From 5a6a10b3e5bcaaa92cacfa09d2aea930eff41205 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 9 Nov 2005 22:54:20 +0000 Subject: Handle the D-Bus system "Disconnect" signal --- hcid/dbus.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 7 deletions(-) diff --git a/hcid/dbus.c b/hcid/dbus.c index ab1e2fc8..45b101f9 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -28,10 +28,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -47,7 +49,8 @@ static DBusConnection *connection; static int default_dev = -1; -#define TIMEOUT (30 * 1000) /* 30 seconds */ +#define TIMEOUT (30 * 1000) /* 30 seconds */ +#define DBUS_RECONNECT_TIMER (5 * 1000 * 1000) /* 5 sec */ #define MAX_PATH_LENGTH 64 #define MAX_CONN_NUMBER 10 @@ -61,7 +64,7 @@ struct pin_request { bdaddr_t bda; }; -typedef DBusMessage* (service_handler_func_t)(DBusMessage *, void *); +typedef DBusMessage* (service_handler_func_t) (DBusMessage *, void *); struct service_data { const char *name; @@ -898,6 +901,8 @@ gboolean hcid_dbus_init(void) return FALSE; } + dbus_connection_set_exit_on_disconnect(connection, FALSE); + dbus_bus_request_name(connection, BASE_INTERFACE, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error); @@ -1155,6 +1160,89 @@ const struct service_data *get_hci_table(void) return device_hci_services; } +/***************************************************************** + * + * Section reserved to re-connection timer + * + *****************************************************************/ +static void reconnect_timer_handler(int signum) +{ + struct hci_dev_list_req *dl = NULL; + struct hci_dev_req *dr; + int sk; + int i; + + if (hcid_dbus_init() == FALSE) + return; + + /* stop the timer */ + sigaction(SIGALRM, NULL, NULL); + setitimer(ITIMER_REAL, NULL, NULL); + + /* register the device based paths */ + + /* Create and bind HCI socket */ + sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (sk < 0) { + syslog(LOG_ERR, "Can't open HCI socket: %s (%d)", + strerror(errno), errno); + return; + } + + dl = malloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl)); + if (!dl) { + syslog(LOG_ERR, "Can't allocate memory"); + goto failed; + } + + dl->dev_num = HCI_MAX_DEV; + dr = dl->dev_req; + + if (ioctl(sk, HCIGETDEVLIST, (void *) dl) < 0) { + syslog(LOG_INFO, "Can't get device list: %s (%d)", + strerror(errno), errno); + goto failed; + } + + /* reset the default device */ + default_dev = -1; + + for (i = 0; i < dl->dev_num; i++, dr++) { + + hcid_dbus_register_device(dr->dev_id); + + if (hci_test_bit(HCI_UP, &dr->dev_opt)) + hcid_dbus_dev_up(dr->dev_id); + } +failed: + if (sk >= 0) + close(sk); + + if (dl) + free(dl); + +} + +static void reconnect_timer_start(void) +{ + struct sigaction sa; + struct itimerval timer; + + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = &reconnect_timer_handler; + sigaction(SIGALRM, &sa, NULL); + + /* expire after X msec... */ + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = DBUS_RECONNECT_TIMER; + + /* ... and every x msec after that. */ + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = DBUS_RECONNECT_TIMER; + + setitimer(ITIMER_REAL, &timer, NULL); +} + /***************************************************************** * * Section reserved to HCI D-Bus services @@ -1175,14 +1263,18 @@ static DBusHandlerResult hci_signal_filter (DBusConnection *conn, DBusMessage *m iface = dbus_message_get_interface(msg); method = dbus_message_get_member(msg); - if (strcmp(iface, DBUS_INTERFACE_LOCAL) == 0) { - if (strcmp(method, "Disconnected") == 0) - ret = DBUS_HANDLER_RESULT_HANDLED; + if ((strcmp(iface, DBUS_INTERFACE_LOCAL) == 0) && + (strcmp(method, "Disconnected") == 0)) { + syslog(LOG_ERR, "Got disconnected from the system message bus"); + dbus_connection_dispatch(conn); + dbus_connection_close(conn); + dbus_connection_unref(conn); + reconnect_timer_start(); + ret = DBUS_HANDLER_RESULT_HANDLED; } else if (strcmp(iface, DBUS_INTERFACE_DBUS) == 0) { if (strcmp(method, "NameOwnerChanged") == 0) ret = DBUS_HANDLER_RESULT_HANDLED; - - if (strcmp(method, "NameAcquired") == 0) + else if (strcmp(method, "NameAcquired") == 0) ret = DBUS_HANDLER_RESULT_HANDLED; } -- cgit