mor*_*ndg 17 linux embedded dbus
我正在尝试编写一些代码来使用DBUS与wpa_supplicant进行通信.当我在嵌入式系统(ARM)中工作时,我想避免使用Python或GLib.我想知道我是不是很愚蠢,因为我真的觉得没有关于D-Bus的清晰文档.即使使用官方文档,我发现文档的级别太高,或者显示的示例都使用了Glib!我看过的文档:http://www.freedesktop.org/wiki/Software/dbus
我发现了一篇关于在C中使用D-Bus的好文章:http://www.matthew.ath.cx/articles/dbus
但是,这篇文章已经很老了,还不够完整!我也找到了c ++ - dbus API,但在这里,我找不到任何文档!我一直在深入研究wpa_supplicant和NetworkManager源代码,但这真是一场噩梦!我一直在研究"低级D-Bus API",但这并没有告诉我如何从D-Bus消息中提取字符串参数!http://dbus.freedesktop.org/doc/api/html/index.html
下面是我编写的一些代码来测试,但我真的很难提取字符串值.很抱歉有很长的源代码,但如果有人想尝试...我的D-Bus配置似乎很好,因为它"已经"从wpa_supplicant捕获"StateChanged"信号,但无法打印状态:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <dbus/dbus.h>
//#include "wpa_supp_dbus.h"
/* Content of wpa_supp_dbus.h */
#define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant"
#define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant"
#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant"
#define WPAS_DBUS_PATH_INTERFACES WPAS_DBUS_PATH "/Interfaces"
#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface"
#define WPAS_DBUS_NETWORKS_PART "Networks"
#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network"
#define WPAS_DBUS_BSSIDS_PART "BSSIDs"
#define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID"
int running = 1;
void stopLoop(int sig)
{
running = 0;
}
void sendScan()
{
// TODO !
}
void loop(DBusConnection* conn)
{
DBusMessage* msg;
DBusMessageIter args;
DBusMessageIter subArgs;
int argType;
int i;
int buffSize = 1024;
char strValue[buffSize];
const char* member = 0;
sendScan();
while (running)
{
// non blocking read of the next available message
dbus_connection_read_write(conn, 0);
msg = dbus_connection_pop_message(conn);
// loop again if we haven't read a message
if (!msg)
{
printf("No message received, waiting a little ...\n");
sleep(1);
continue;
}
else printf("Got a message, will analyze it ...\n");
// Print the message member
printf("Got message for interface %s\n",
dbus_message_get_interface(msg));
member = dbus_message_get_member(msg);
if(member) printf("Got message member %s\n", member);
// Check has argument
if (!dbus_message_iter_init(msg, &args))
{
printf("Message has no argument\n");
continue;
}
else
{
// Go through arguments
while(1)
{
argType = dbus_message_iter_get_arg_type(&args);
if (argType == DBUS_TYPE_STRING)
{
printf("Got string argument, extracting ...\n");
/* FIXME : got weird characters
dbus_message_iter_get_basic(&args, &strValue);
*/
/* FIXME : segmentation fault !
dbus_message_iter_get_fixed_array(
&args, &strValue, buffSize);
*/
/* FIXME : segmentation fault !
dbus_message_iter_recurse(&args, &subArgs);
*/
/* FIXME : deprecated!
if(dbus_message_iter_get_array_len(&args) > buffSize)
printf("message content to big for local buffer!");
*/
//printf("String value was %s\n", strValue);
}
else
printf("Arg type not implemented yet !\n");
if(dbus_message_iter_has_next(&args))
dbus_message_iter_next(&args);
else break;
}
printf("No more arguments!\n");
}
// free the message
dbus_message_unref(msg);
}
}
int main(int argc, char* argv[])
{
DBusError err;
DBusConnection* conn;
int ret;
char signalDesc[1024]; // Signal description as string
// Signal handling
signal(SIGKILL, stopLoop);
signal(SIGTERM, stopLoop);
// Initialize err struct
dbus_error_init(&err);
// connect to the bus
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (!conn)
{
exit(1);
}
// request a name on the bus
ret = dbus_bus_request_name(conn, WPAS_DBUS_SERVICE, 0, &err);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Name Error (%s)\n", err.message);
dbus_error_free(&err);
}
/* Connect to signal */
// Interface signal ..
sprintf(signalDesc, "type='signal',interface='%s'",
WPAS_DBUS_IFACE_INTERFACE);
dbus_bus_add_match(conn, signalDesc, &err);
dbus_connection_flush(conn);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Match Error (%s)\n", err.message);
exit(1);
}
// Network signal ..
sprintf(signalDesc, "type='signal',interface='%s'",
WPAS_DBUS_IFACE_NETWORK);
dbus_bus_add_match(conn, signalDesc, &err);
dbus_connection_flush(conn);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Match Error (%s)\n", err.message);
exit(1);
}
// Bssid signal ..
sprintf(signalDesc, "type='signal',interface='%s'",
WPAS_DBUS_IFACE_BSSID);
dbus_bus_add_match(conn, signalDesc, &err);
dbus_connection_flush(conn);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Match Error (%s)\n", err.message);
exit(1);
}
// Do main loop
loop(conn);
// Main loop exited
printf("Main loop stopped, exiting ...\n");
dbus_connection_close(conn);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
任何指向任何漂亮,完整,低级C教程的指针都非常感谢!我也打算做一些远程方法调用,所以如果教程涵盖了这个主题,那就太棒了!说我不是很聪明,因为我没有用官方教程得到它也很感激:-p!
或者是否有另一种与wpa_supplicant通信的方式(除了使用wpa_cli)?
编辑1:
使用'qdbusviewer'和内省功能,这有助于我发现wpa_supplicant使用dbus的工作原理和方式.跳这个会帮助别人!
编辑2:
当我找到一种在D-Bus上读取字符串值的方法时,可能会来!
您已经放弃了可以帮助您更轻松地学习 D-Bus 的工具,而正在使用低级别的 libdbus 实现,所以也许您应该感到痛苦。顺便说一句,您是在谈论 ARM,就像手机 ARM 一样吗?可能有 500 Mhz 和 256 MB RAM?在这种情况下,处理器非常适合使用 glib、Qt 甚至 python。当您编写异步事件驱动代码时,D-Bus 最有用,例如来自 glib 的集成主循环,即使您使用低级 libdbus(它具有连接到 glib 主循环的功能,例如)。
由于您使用的是低级库,因此文档就是您已经拥有的:
http://dbus.freedesktop.org/doc/api/html/index.html
此外,libdbus 源代码也是文档的一部分:
http://dbus.freedesktop.org/doc/api/html/files.html
文档的主要入口点是模块页面(特别是公共 API 部分):
http://dbus.freedesktop.org/doc/api/html/modules.html
对于消息处理,DBusMessage 部分是相关的: DBusMessage
那里有解析项目值的函数的文档。在您的情况下,您从 dbus_message_iter_get_basic 开始。如文档中所述,检索字符串需要一个 const char ** 变量,因为返回的值将指向接收到的消息中预先分配的字符串:
因此,对于 int32,它应该是“dbus_int32_t*”,而对于字符串,它应该是“const char**”。返回值是通过引用,不应被释放。
所以你不能定义一个数组,因为 libdbus 不会将文本复制到你的数组中。如果需要保存字符串,先获取常量字符串引用,然后strcpy到自己的数组。
然后您尝试在不移动迭代器的情况下获得固定数组。您需要在基本字符串和固定数组之间调用下一个迭代器 (dbus_message_iter_next)。在递归到子迭代器之前相同。
最后,您不调用 get_array_len 来获取数组上的元素数。从文档中,它只返回字节数。相反,您使用 iter_next 循环遍历子迭代器,就像您应该使用主迭代器一样。遍历数组末尾后,dbus_message_iter_get_arg_type 将返回 DBUS_TYPE_INVALID。
有关更多信息,请阅读参考手册,不要寻找教程。或者只是使用合理的 d-bus 实现:
https://developer.gnome.org/gio/2.36/gdbus-codegen.html
GIO 的 GDBus 会自动为您的 d-bus 调用创建包装器。
http://qt-project.org/doc/qt-4.8/intro-to-dbus.html
http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html
等等。
如果您只需要编写一个 C 程序来与 wpa_supplicant 通信,则不需要使用/理解 dbus 的工作原理。我对 wpa_cli 的源代码进行了逆向工程。完成了它的实现并使用了 wpa_ctrl.h/c 中提供的函数。这个实现会处理所有事情。您可以使用/修改任何您想要的内容,构建可执行文件,然后就完成了!
这是 wpa_supplicant 的 ctrl_interface 的官方链接: http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html