使用低级API调用方法和接收信号

时间:2013-08-09 15:20:03

标签: api methods signals dbus

我正在尝试使用dbus低级API调用方法ReadLocalBdAddrReq并在dbus上接收其信号ReadLocalBdAddrCfm

我在一些论坛帖子和dbus教程的帮助下编写了以下代码。

问题是,我无法收到信号。代码在某些地方是不完整的,因为我不知道应该做什么。

所以请帮助我,以便我可以收到所谓方法的信号。 这里是我写的代码。请更正我所犯的任何错误。

#include <stdlib.h>
#include <stdio.h>
#include <dbus/dbus.h>

#define OBJ_PATH "/bt/cm"


static dbus_bool_t add_watch(DBusWatch *watch, void *data)
{
    if (!dbus_watch_get_enabled(watch))
    return TRUE;

int fd = dbus_watch_get_unix_fd(watch);
unsigned int flags = dbus_watch_get_flags(watch);
int f = 0;;

if (flags & DBUS_WATCH_READABLE) {
    f |= DBUS_WATCH_READABLE;
    printf("Readable\n");
}
if (flags & DBUS_WATCH_WRITABLE) {
    printf("Writeable\n");
    f |= DBUS_WATCH_WRITABLE;
}
/* this should not be here */
if (dbus_watch_handle(watch, f) == FALSE)
        printf("dbus_watch_handle() failed\n");
return TRUE;
}

static void remove_watch(DBusWatch *watch, void *data)
{
printf("In remove watch with fd = [%d]\n",dbus_watch_get_unix_fd(watch));
}

static void toggel_watch(DBusWatch *watch, void *data)
{
printf("In toggel watch\n");
/*
if (dbus_watch_get_enabled(watch))
    add_watch(watch, data);
else
    remove_watch(watch, data);
*/
}


 /* timeout functions */
static dbus_bool_t add_time(DBusTimeout *timeout, void *data)
{
/* Incomplete */
printf("In add_time\n");
if (!dbus_timeout_get_enabled(timeout))
    return TRUE;

//dbus_timeout_handle(timeout);
return 0;
}
static void remove_time(DBusTimeout *timeout, void *data)
{
/* Incomplete */
printf("In remove_time\n");
}
static void toggel_time(DBusTimeout *timeout, void *data)
{
/* Incomplete */
printf("In toggel_time\n");
/*
if (dbus_timeout_get_enabled(timeout))
    add_timeout(timeout, data);
else
    remove_timeout(timeout, data);
*/
}

/* message filter --    handlers to run on all  incoming messages*/
static DBusHandlerResult filter (DBusConnection *connection, DBusMessage *message, void *user_data)
{
printf("In filter\n");
char *deviceaddr;
if (dbus_message_is_signal(message, "com.bluegiga.v2.bt.cm", "ReadLocalBdAddrCfm")) {
    printf("Signal received is  ReadLocalBdAddrCfm\n");
    if ((dbus_message_get_args(message,NULL,DBUS_TYPE_STRING, &deviceaddr,DBUS_TYPE_INVALID) == FALSE))
    {
        printf("Could not get the arguments from the message received\n");
        return -2;
    }
    printf("Got Signal and device address is [%s]\n", deviceaddr);
}
return 0;
}

 /* dispatch function-- simply save an indication that messages should be dispatched later, when the main loop is re-entered*/
static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_status, void *data)
{
printf("In dispatch_status\n");
if (new_status == DBUS_DISPATCH_DATA_REMAINS)
{
    printf("new dbus dispatch status: DBUS_DISPATCH_DATA_REMAINS [%d]",new_status);
}

}

/* unregister function */
void unregister_func(DBusConnection *connection, void *user_data)
{

}
/* message function -  Called when a message is sent to a registered object path. */
static DBusHandlerResult message_func(DBusConnection *connection, DBusMessage *message, void *data)
{
printf("Message [%s] is sent to [%s] from interface [%s] on path [%s] \n",dbus_message_get_member(message),dbus_message_get_destination(message),
dbus_message_get_interface(message),dbus_message_get_path(message));                                                    return 0;
}
DBusObjectPathVTable table  = {
    .unregister_function = unregister_func,
    .message_function = message_func,
};

int main(void) {
DBusMessage* msg;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
DBusPendingCall* pending;
int ret;
//unsigned int  level;
char* appHandle = NULL;
//int *context;
int msg_serial;
int open;
char *deviceaddr;

dbus_error_init(&err);

// connect to the system bus and check for errors
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 (NULL == conn) {
    exit(1);
}


if (!dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggel_watch, NULL, NULL))
{
    printf("Error in dbus_set_watch_functions\n");
    dbus_connection_unref(conn);
    return -1;
}


/* These functions are responsible for making the application's main loop aware of timeouts */
if (!dbus_connection_set_timeout_functions(conn, add_time, remove_time, toggel_time, NULL, NULL))
{
    printf("Error in dbus_set_timeout_functions\n");
    dbus_connection_unref(conn);
    return -1;
}
/* Used to register the handler functions run on incoming messages*/
if (!dbus_connection_add_filter(conn, filter, NULL, NULL))
{
    printf("Error in adding filter\n");
    dbus_connection_unref(conn);
    return -1;
}
/* Filter added for incoming messages */

/* Set a function to be invoked when the dispatch status changes */
dbus_connection_set_dispatch_status_function(conn, dispatch_status, NULL ,NULL);

/* Register a handler for messages sent to a given path */
if(!dbus_connection_register_object_path(conn, OBJ_PATH, &table, NULL))
{
    printf("Error in registering object\n");
    return -1;
}


/* sending messages to the outgoing queue */
msg = dbus_message_new_method_call("com.bluegiga.v2.bt.cm", // target for the method call
                                    OBJ_PATH, // object to call on
                                  "com.bluegiga.v2.bt.cm", // interface to call on
                                  "ReadLocalBdAddrReq"); // method name
if (NULL == msg) {
  fprintf(stderr, "Message Null\n");
  exit(1);
}
dbus_message_iter_init_append(msg, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT16,&appHandle)) {
  fprintf(stderr, "Out Of Memory!\n");
  exit(1);
}

fprintf(stderr, "Sending the connections\n");
// send message and get a handle for a reply
if (!dbus_connection_send (conn, msg, &msg_serial)) {
  fprintf(stderr, "Out Of Memory!\n");
  exit(1);
}

fprintf(stderr, "Connection sent and the msg serial is  %d\n",msg_serial);
/* Message sent over */

/* not sure whether this should be here or above watch */
while (dbus_connection_get_dispatch_status(conn) == DBUS_DISPATCH_DATA_REMAINS)
{
    //printf("Entered in dispatch\n");
    /* Processes any incoming data. will call the filters registered by add_filer*/
        dbus_connection_dispatch(conn);
}
    return 0;
}

运行此程序后,它具有以下输出:

  

可读

     

发送连接

     

已发送连接且msg序列为   2(DBUS_MESSAGE_TYPE_METHOD_RETURN)

如果连接已发送到对象路径,那么应该正确调用message_func,但它永远不会被调用。发送方法调用时有错误吗?

1 个答案:

答案 0 :(得分:0)

如果您选择使用其中一个绑定,则缺少事件循环,否则默认情况下该循环可用。当您调用add_watch时,libdbus希望应用程序将附加IO处理程序。应用程序添加的IOHandler将监视为手表查询的fd(filedescriptor)上的活动。只要该文件描述符上有活动,IOHandler就会在调用dbus_watch_handle之前触发带有适当标志的回调,然后转换为DBUS标志。

如果您不知道如何使用事件循环,建议您使用glib。如果我使用libUV或libEV作为低占用空间事件循环,我能够得到它。