summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2005-11-09 22:54:20 +0000
committerMarcel Holtmann <marcel@holtmann.org>2005-11-09 22:54:20 +0000
commit5a6a10b3e5bcaaa92cacfa09d2aea930eff41205 (patch)
treeb707507b2ff98f0deee3e7a422eeca62758049ec
parentd46119704d437932ce905917b69ce665c1ac0149 (diff)
Handle the D-Bus system "Disconnect" signal
-rw-r--r--hcid/dbus.c106
1 files 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 <stdio.h>
#include <errno.h>
#include <unistd.h>
+#include <signal.h>
#include <string.h>
#include <syslog.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/time.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
@@ -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);
@@ -1156,6 +1161,89 @@ const struct service_data *get_hci_table(void)
}
/*****************************************************************
+ *
+ * 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;
}