summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--input/device.c91
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,