summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaudio Takahasi <claudio.takahasi@openbossa.org>2006-04-05 14:03:53 +0000
committerClaudio Takahasi <claudio.takahasi@openbossa.org>2006-04-05 14:03:53 +0000
commit8fa8629fa44075dfa41b1bff96a7951dd40cfb0a (patch)
tree1d7ef94b106dd33c796af7e80929d073b8ecbd05
parent737b2a1a36c13e575d3cfb21f7e42553407cb6d2 (diff)
added timeout new function
-rw-r--r--common/glib-ectomy.c175
-rw-r--r--common/glib-ectomy.h27
-rw-r--r--hcid/dbus.c128
-rw-r--r--hcid/dbus.h6
-rw-r--r--hcid/main.c3
-rw-r--r--test/Makefile.am5
6 files changed, 222 insertions, 122 deletions
diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c
index 463d0aee..f1d79e7f 100644
--- a/common/glib-ectomy.c
+++ b/common/glib-ectomy.c
@@ -10,8 +10,11 @@
#include <malloc.h>
#include <string.h>
#include <limits.h>
+#include <sys/time.h>
+#include <time.h>
#include "glib-ectomy.h"
+#include "list.h"
GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read)
{
@@ -89,6 +92,7 @@ struct watch {
};
static struct watch watch_head = { .id = 0, .next = 0 };
+static GMainContext *default_context = NULL;
void g_io_remove_watch(guint id)
{
@@ -129,6 +133,23 @@ guint g_io_add_watch(GIOChannel *channel, GIOCondition condition,
func, user_data, NULL);
}
+static GMainContext *g_main_context_default()
+{
+
+ if (default_context)
+ return default_context;
+
+ default_context = malloc(sizeof(GMainContext));
+ if (!default_context)
+ return NULL;
+
+ memset(default_context, 0, sizeof(GMainContext));
+
+ default_context->timeout = -1;
+
+ return default_context;
+}
+
GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running)
{
GMainLoop *ml;
@@ -137,11 +158,80 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running)
if (!ml)
return NULL;
- ml->bail = 0;
+ memset(ml, 0, sizeof(GMainLoop));
+
+ if (!context)
+ ml->context = g_main_context_default();
+ else
+ ml->context = context;
+ ml->bail = 0;
return ml;
}
+static void timeout_handlers_prepare(GMainContext *context)
+{
+ struct slist *l = context->ltimeout;
+ struct timeout *t;
+ struct timeval tv;
+ glong msec, timeout = LONG_MAX;
+
+ gettimeofday(&tv, NULL);
+
+ while (l) {
+ t = l->data;
+ l = l->next;
+
+ /* calculate the remainning time */
+ msec = (t->expiration.tv_sec - tv.tv_sec) * 1000 +
+ (t->expiration.tv_usec - tv.tv_usec) / 1000;
+ if (msec < 0)
+ msec = 0;
+
+ timeout = MIN_TIMEOUT(timeout, msec);
+ }
+
+ /* set to min value found or NO timeout */
+ context->timeout = (timeout != LONG_MAX ? timeout: -1);
+}
+
+static void timeout_handlers_check(GMainContext *context)
+{
+ struct slist *l = context->ltimeout;
+ struct timeout *t;
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ while (l) {
+ t = l->data;
+ l = l->next;
+
+ if ((tv.tv_sec < t->expiration.tv_sec) ||
+ (tv.tv_sec == t->expiration.tv_sec &&
+ tv.tv_usec < t->expiration.tv_usec))
+ continue;
+
+ if (t->func(t->data)) {
+ /* if false/expired: remove it from the list */
+ context->ltimeout = slist_remove(context->ltimeout, t);
+ free(t);
+ } else {
+ glong secs, msecs;
+ /* update the next expiration time */
+ secs = t->interval / 1000;
+ msecs = t->interval - secs * 1000;
+
+ t->expiration.tv_sec = tv.tv_sec + secs;
+ t->expiration.tv_usec = tv.tv_usec + msecs * 1000;
+ if (t->expiration.tv_usec >= 1000000) {
+ t->expiration.tv_usec -= 1000000;
+ t->expiration.tv_sec++;
+ }
+ }
+ }
+}
+
void g_main_loop_run(GMainLoop *loop)
{
int open_max = sysconf(_SC_OPEN_MAX);
@@ -163,7 +253,10 @@ void g_main_loop_run(GMainLoop *loop)
nfds++;
}
- rc = poll(ufds, nfds, -1);
+ /* calculate the next timeout */
+ timeout_handlers_prepare(loop->context);
+
+ rc = poll(ufds, nfds, loop->context->timeout);
if (rc < 0)
continue;
@@ -190,6 +283,9 @@ void g_main_loop_run(GMainLoop *loop)
w = w->next;
i++;
}
+
+ /* check expired timers */
+ timeout_handlers_check(loop->context);
}
free(ufds);
@@ -208,3 +304,78 @@ void g_main_loop_quit(GMainLoop *loop)
free(w);
}
}
+
+void g_main_loop_unref(GMainLoop *loop)
+{
+ if (!loop->context)
+ return;
+
+ slist_free(loop->context->ltimeout);
+ free(loop->context);
+}
+
+guint g_timeout_add(guint interval, timeout_func_t *func, void *data)
+{
+ struct timeval tv;
+ guint secs;
+ guint msecs;
+ struct timeout *t;
+
+ if (!default_context || !func)
+ return 0;
+
+ t = malloc(sizeof(*t));
+
+ if (!t)
+ return 0;
+
+ t->interval = interval;
+ t->func = func;
+ t->data = data;
+
+ gettimeofday(&tv, NULL);
+
+ secs = interval /1000;
+ msecs = interval - secs * 1000;
+
+ t->expiration.tv_sec = tv.tv_sec + secs;
+ t->expiration.tv_usec = tv.tv_usec + msecs * 1000;
+
+ if (t->expiration.tv_usec >= 1000000) {
+ t->expiration.tv_usec -= 1000000;
+ t->expiration.tv_sec++;
+ }
+
+ /* attach the timeout the default context */
+ t->id = ++default_context->next_id;
+ default_context->ltimeout = slist_append(default_context->ltimeout, t);
+
+ return t->id;
+}
+
+gint g_timeout_remove(const guint id)
+{
+ struct slist *l;
+ struct timeout *t;
+
+ if (!default_context)
+ return -1;
+
+ l = default_context->ltimeout;
+
+ while (l) {
+ t = l->data;
+ l = l->next;
+
+ if (t->id != id)
+ continue;
+
+ default_context->ltimeout = slist_remove(default_context->ltimeout, t);
+ free(t);
+
+ return 0;
+ }
+
+ return -1;
+}
+
diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h
index e921b40d..56dac08b 100644
--- a/common/glib-ectomy.h
+++ b/common/glib-ectomy.h
@@ -28,16 +28,36 @@ typedef ssize_t gssize;
#define SSIZE_MAX INT_MAX
#endif
+#define MIN_TIMEOUT(a, b) (((a) < (b)) ? (a) : (b))
+
typedef struct _GIOChannel {
int fd;
} GIOChannel;
+typedef int (timeout_func_t)(void *data);
+
+typedef struct {
+ glong tv_sec;
+ glong tv_usec;
+} time_val_t;
+
+struct timeout {
+ guint id;
+ guint interval;
+ time_val_t expiration;
+ void *data;
+ timeout_func_t *func;
+};
+
typedef struct _GMainContext {
- int dummy;
+ guint next_id;
+ glong timeout;
+ struct slist *ltimeout;
} GMainContext;
typedef struct _GMainLoop {
int bail;
+ GMainContext *context;
} GMainLoop;
typedef enum {
@@ -89,9 +109,14 @@ void g_io_remove_watch(guint id);
GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running);
void g_main_loop_run(GMainLoop *loop);
void g_main_loop_quit(GMainLoop *loop);
+void g_main_loop_unref(GMainLoop *loop);
+guint g_timeout_add(guint interval, timeout_func_t *func, void *data);
+gint g_timeout_remove(const guint id);
+
#define g_main_new(is_running) g_main_loop_new(NULL, is_running);
#define g_main_run(loop) g_main_loop_run(loop)
#define g_main_quit(loop) g_main_loop_quit(loop)
+#define g_main_unref(loop) g_main_loop_unref(loop)
#endif /* __GLIB_ECTOMY_H */
diff --git a/hcid/dbus.c b/hcid/dbus.c
index 6ed5b6a4..c1abd71b 100644
--- a/hcid/dbus.c
+++ b/hcid/dbus.c
@@ -28,9 +28,7 @@
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
-#include <signal.h>
#include <string.h>
-#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -50,9 +48,9 @@
static DBusConnection *connection;
static int default_dev = -1;
-static volatile sig_atomic_t __timeout_active = 0;
#define MAX_CONN_NUMBER 10
+#define RECONNECT_RETRY_TIMEOUT 5000
static const char *services_cls[] = {
"positioning",
@@ -289,8 +287,6 @@ static DBusMessage *dbus_msg_new_authentication_return(DBusMessage *msg, uint8_t
/*
* Timeout functions Protypes
*/
-static int discoverable_timeout_handler(void *data);
-
DBusConnection *get_dbus_connection(void)
{
return connection;
@@ -496,13 +492,6 @@ gboolean hcid_dbus_register_device(uint16_t id)
else
pdata->mode = rp.enable; /* Keep the current scan status */
- /*
- * Enable timeout to address dbus daemon restart, where
- * register the device paths is required due connection lost.
- */
- if (pdata->mode & SCAN_INQUIRY)
- pdata->timeout_handler = &discoverable_timeout_handler;
-
message = dbus_message_new_signal(MANAGER_PATH, MANAGER_INTERFACE,
"AdapterAdded");
if (message == NULL) {
@@ -1055,7 +1044,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i
name = textfile_get(filename, peer_addr);
if (name) {
- signal_name = dev_signal_factory(pdata->dev_id, "RemoteNameUpdate",
+ signal_name = dev_signal_factory(pdata->dev_id, "RemoteNameUpdated",
DBUS_TYPE_STRING, &peer_addr,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID);
@@ -1475,7 +1464,7 @@ static int discoverable_timeout_handler(void *data)
dd = hci_open_dev(dbus_data->dev_id);
if (dd < 0) {
error("HCI device open failed: hci%d", dbus_data->dev_id);
- return -1;
+ return 0;
}
memset(&rq, 0, sizeof(rq));
@@ -1489,15 +1478,14 @@ static int discoverable_timeout_handler(void *data)
if (hci_send_req(dd, &rq, 100) < 0) {
error("Sending write scan enable command to hci%d failed: %s (%d)",
dbus_data->dev_id, strerror(errno), errno);
- retval = -1;
goto failed;
}
if (status) {
error("Setting scan enable failed with status 0x%02x", status);
- retval = -1;
goto failed;
}
+ retval = -1;
failed:
if (dd >= 0)
close(dd);
@@ -1505,22 +1493,24 @@ failed:
return retval;
}
-static void system_bus_reconnect(void)
+static int system_bus_reconnect(void *data)
{
struct hci_dev_list_req *dl = NULL;
struct hci_dev_req *dr;
- int sk;
- int i;
+ int sk, i, ret_val = 0;
+
+ if (dbus_connection_get_is_connected(connection))
+ return -1;
if (hcid_dbus_init() == FALSE)
- return;
+ return 0;
/* Create and bind HCI socket */
sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (sk < 0) {
error("Can't open HCI socket: %s (%d)",
strerror(errno), errno);
- return;
+ return 0;
}
dl = malloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl));
@@ -1544,98 +1534,15 @@ static void system_bus_reconnect(void)
for (i = 0; i < dl->dev_num; i++, dr++)
hcid_dbus_register_device(dr->dev_id);
+ ret_val = -1;
failed:
if (sk >= 0)
close(sk);
if (dl)
free(dl);
-}
-
-static void sigalarm_handler(int signum)
-{
- struct hci_dbus_data *pdata = NULL;
- char device_path[MAX_PATH_LENGTH];
- char **device = NULL;
- int active_handlers = 0;
- int i = 0;
-
- if (!dbus_connection_get_is_connected(connection)) {
- /* it is not connected */
- system_bus_reconnect();
- return;
- }
-
- if (!dbus_connection_list_registered(connection, ADAPTER_PATH, &device))
- goto done;
-
- /* check the timer for each registered path */
- for (; device[i]; i++) {
-
- snprintf(device_path, sizeof(device_path), "%s/%s", ADAPTER_PATH, device[i]);
-
- if (!dbus_connection_get_object_path_data(connection, device_path, (void *) &pdata)){
- error("Getting %s path data failed!", device_path);
- continue;
- }
-
- if (pdata->timeout_handler == NULL)
- continue;
-
- if (!(pdata->mode & SCAN_INQUIRY)) {
- pdata->timeout_hits = 0;
- continue;
- }
-
- active_handlers++;
-
- if (!pdata->discoverable_timeout)
- continue; /* skip if discoverable always: timeout zero */
-
- if ((++(pdata->timeout_hits) % pdata->discoverable_timeout) != 0)
- continue;
-
- if (!pdata->timeout_handler(pdata)) {
- /* Remove from the timeout queue */
- pdata->timeout_handler = NULL;
- pdata->timeout_hits = 0;
- active_handlers--;
- }
- }
-
- dbus_free_string_array(device);
-
-done:
- if (!active_handlers) {
- sigaction(SIGALRM, NULL, NULL);
- setitimer(ITIMER_REAL, NULL, NULL);
- __timeout_active = 0;
- }
-}
-
-static void bluez_timeout_start(void)
-{
- struct sigaction sa;
- struct itimerval timer;
-
- if (__timeout_active)
- return;
-
- __timeout_active = 1;
-
- memset (&sa, 0, sizeof (sa));
- sa.sa_handler = &sigalarm_handler;
- sigaction(SIGALRM, &sa, NULL);
- /* expire after 1 sec... */
- timer.it_value.tv_sec = 1;
- timer.it_value.tv_usec = 0;
-
- /* ... and every 1 sec after that. */
- timer.it_interval.tv_sec = 1;
- timer.it_interval.tv_usec = 0;
-
- setitimer(ITIMER_REAL, &timer, NULL);
+ return ret_val;
}
/*****************************************************************
@@ -1662,8 +1569,7 @@ static DBusHandlerResult hci_dbus_signal_filter(DBusConnection *conn, DBusMessag
(strcmp(method, "Disconnected") == 0)) {
error("Got disconnected from the system message bus");
dbus_connection_unref(conn);
- bluez_timeout_start();
- ret = DBUS_HANDLER_RESULT_HANDLED;
+ g_timeout_add(RECONNECT_RETRY_TIMEOUT, system_bus_reconnect, NULL);
}
return ret;
@@ -1802,13 +1708,11 @@ void hcid_dbus_setscan_enable_complete(bdaddr_t *local)
break;
case (SCAN_PAGE | SCAN_INQUIRY):
scan_mode = MODE_DISCOVERABLE;
- pdata->timeout_handler = &discoverable_timeout_handler;
- bluez_timeout_start();
+ g_timeout_add(pdata->discoverable_timeout, discoverable_timeout_handler, pdata);
break;
case SCAN_INQUIRY:
/* Address the scenario where another app changed the scan mode */
- pdata->timeout_handler = &discoverable_timeout_handler;
- bluez_timeout_start();
+ g_timeout_add(pdata->discoverable_timeout, discoverable_timeout_handler, pdata);
/* ignore, this event should not be sent*/
default:
/* ignore, reserved */
diff --git a/hcid/dbus.h b/hcid/dbus.h
index 61817090..f6f0b6d8 100644
--- a/hcid/dbus.h
+++ b/hcid/dbus.h
@@ -70,8 +70,6 @@ struct service_data {
service_handler_func_t handler_func;
};
-typedef int (timeout_handler_func_t) (void *data);
-
typedef enum {
STATE_IDLE,
STATE_DISCOVER,
@@ -108,8 +106,6 @@ struct hci_dbus_data {
uint16_t dev_id;
uint16_t path_id;
uint32_t discoverable_timeout;
- uint32_t timeout_hits;
- timeout_handler_func_t *timeout_handler;
uint8_t mode; /* scan mode */
discover_state_t discover_state; /* discover states */
int discover_type; /* with/without name resolving */
@@ -211,7 +207,7 @@ int disc_device_req_name(struct hci_dbus_data *dbus_data);
#define MODE_DISCOVERABLE "discoverable"
#define MODE_UNKNOWN "unknown"
-#define DFT_DISCOVERABLE_TIMEOUT 180 /* 3 seconds */
+#define DFT_DISCOVERABLE_TIMEOUT 180*1000 /* 3 seconds */
#define DISCOVERABLE_TIMEOUT_OFF 0
#endif /* __H_BLUEZ_DBUS_H__ */
diff --git a/hcid/main.c b/hcid/main.c
index a449f37b..6a6b382c 100644
--- a/hcid/main.c
+++ b/hcid/main.c
@@ -34,7 +34,6 @@
#include <stdlib.h>
#include <string.h>
#include <signal.h>
-#include <sys/time.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -660,6 +659,8 @@ int main(int argc, char *argv[], char *env[])
/* Start event processor */
g_main_run(event_loop);
+ g_main_unref(event_loop);
+
if (sdp)
stop_sdp_server();
diff --git a/test/Makefile.am b/test/Makefile.am
index 751fa50c..32b32b33 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -6,7 +6,10 @@ bin_PROGRAMS = l2test rctest
noinst_PROGRAMS = scotest attest hstest bdaddr
-hciemu_LDADD = @BLUEZ_LIBS@ $(top_builddir)/common/libglib-ectomy.a
+hciemu_LDADD = @BLUEZ_LIBS@ \
+ $(top_builddir)/common/libglib-ectomy.a \
+ $(top_builddir)/common/liblist.a
+
l2test_LDADD = @BLUEZ_LIBS@