diff options
-rw-r--r-- | input/device.c | 91 |
1 files changed, 62 insertions, 29 deletions
diff --git a/input/device.c b/input/device.c index 3f78d15a..4c485736 100644 --- a/input/device.c +++ b/input/device.c @@ -32,7 +32,7 @@ #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/socket.h> - + #include <bluetooth/bluetooth.h> #include <bluetooth/hidp.h> #include <bluetooth/l2cap.h> @@ -80,7 +80,8 @@ struct device { char *path; int ctrl_sk; int intr_sk; - guint watch; + guint ctrl_watch; + guint intr_watch; }; GSList *devices = NULL; @@ -402,7 +403,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, goto failed; } - /* + /* * FIXME: Some headsets required a sco connection * first to report volume gain key events */ @@ -425,7 +426,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, path = dbus_message_get_path(idev->pending_connect); dbus_connection_emit_signal(idev->conn, path, INPUT_DEVICE_INTERFACE, "Connected", - DBUS_TYPE_INVALID); + DBUS_TYPE_INVALID); dbus_message_unref(idev->pending_connect); idev->pending_connect = NULL; @@ -511,45 +512,73 @@ failed: return -err; } -static gboolean connection_event(GIOChannel *chan, GIOCondition cond, gpointer data) +static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct device *idev = data; - gboolean ret = TRUE; - - if (cond & G_IO_NVAL) - ret = FALSE; - if (cond & (G_IO_HUP | G_IO_ERR)) { + if (cond & (G_IO_HUP | G_IO_ERR)) g_io_channel_close(chan); - ret = FALSE; + + dbus_connection_emit_signal(idev->conn, + idev->path, + INPUT_DEVICE_INTERFACE, + "Disconnected", + DBUS_TYPE_INVALID); + + g_source_remove(idev->ctrl_watch); + idev->ctrl_watch = 0; + idev->intr_watch = 0; + + /* Close control channel */ + if (idev->ctrl_sk > 0) { + close(idev->ctrl_sk); + idev->ctrl_sk = -1; } - if (ret == FALSE) { - dbus_connection_emit_signal(idev->conn, - idev->path, - INPUT_DEVICE_INTERFACE, - "Disconnected", - DBUS_TYPE_INVALID); - idev->watch = 0; + return FALSE; + +} + +static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data) +{ + struct device *idev = data; + + if (cond & (G_IO_HUP | G_IO_ERR)) + g_io_channel_close(chan); + + dbus_connection_emit_signal(idev->conn, + idev->path, + INPUT_DEVICE_INTERFACE, + "Disconnected", + DBUS_TYPE_INVALID); + + g_source_remove(idev->intr_watch); + idev->intr_watch = 0; + idev->ctrl_watch = 0; + + /* Close interrupt channel */ + if (idev->intr_sk > 0) { + close(idev->intr_sk); + idev->intr_sk = -1; } - return ret; + return FALSE; } -static guint create_watch(int sk, struct device *idev) +static guint create_watch(int sk, GIOFunc cb, struct device *idev) { guint id; GIOChannel *io; io = g_io_channel_unix_new(sk); - id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL, - connection_event, idev); + id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL, cb, idev); g_io_channel_unref(io); return id; } -static int hidp_connadd(bdaddr_t *src, bdaddr_t *dst, int ctrl_sk, int intr_sk, const char *name) +static int hidp_connadd(bdaddr_t *src, bdaddr_t *dst, + int ctrl_sk, int intr_sk, const char *name) { struct hidp_connadd_req req; char addr[18]; @@ -640,7 +669,8 @@ static gboolean interrupt_connect_cb(GIOChannel *chan, if (err < 0) goto failed; - idev->watch = create_watch(idev->ctrl_sk, idev); + idev->intr_watch = create_watch(idev->intr_sk, intr_watch_cb, idev); + idev->ctrl_watch = create_watch(idev->ctrl_sk, ctrl_watch_cb, idev); dbus_connection_emit_signal(idev->conn, idev->path, INPUT_DEVICE_INTERFACE, @@ -1139,9 +1169,11 @@ int input_device_unregister(DBusConnection *conn, const char *path) * to access the D-Bus data assigned to this path * because the object path data was destroyed. */ - if (idev->watch) { - g_source_remove(idev->watch); - idev->watch = 0; + if (idev->ctrl_watch) + g_source_remove(idev->ctrl_watch); + + if (idev->intr_watch) { + g_source_remove(idev->intr_watch); dbus_connection_emit_signal(conn, path, INPUT_DEVICE_INTERFACE, @@ -1154,7 +1186,7 @@ int input_device_unregister(DBusConnection *conn, const char *path) dbus_connection_emit_signal(conn, INPUT_PATH, INPUT_MANAGER_INTERFACE, "DeviceRemoved" , DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); + DBUS_TYPE_INVALID); return 0; } @@ -1302,7 +1334,8 @@ int input_device_connadd(bdaddr_t *src, bdaddr_t *dst) return err; } - idev->watch = create_watch(idev->ctrl_sk, idev); + idev->intr_watch = create_watch(idev->intr_sk, intr_watch_cb, idev); + idev->ctrl_watch = create_watch(idev->ctrl_sk, ctrl_watch_cb, idev); dbus_connection_emit_signal(idev->conn, idev->path, INPUT_DEVICE_INTERFACE, |