diff options
author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2009-02-18 19:17:50 -0300 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2009-02-19 11:05:10 +0200 |
commit | c95494ee508a9f36096af5ddb1c2ac1579a32b1d (patch) | |
tree | f04c45cc65a372d8ae5d953a72ab6156e8215bf1 /input | |
parent | 56fe087dfc68f56d84ac41ca390c8a0dc7438e2d (diff) |
Make input plugin to use BtIO API.
Diffstat (limited to 'input')
-rw-r--r-- | input/device.c | 158 | ||||
-rw-r--r-- | input/device.h | 2 | ||||
-rw-r--r-- | input/fakehid.c | 2 | ||||
-rw-r--r-- | input/fakehid.h | 2 | ||||
-rw-r--r-- | input/server.c | 60 |
5 files changed, 136 insertions, 88 deletions
diff --git a/input/device.c b/input/device.c index a2a3c38d..eb089093 100644 --- a/input/device.c +++ b/input/device.c @@ -59,6 +59,7 @@ #include "error.h" #include "fakehid.h" #include "glib-helper.h" +#include "btio.h" #define INPUT_DEVICE_INTERFACE "org.bluez.Input" @@ -324,22 +325,26 @@ static inline DBusMessage *already_connected(DBusMessage *msg) "Already connected to a device"); } -static inline DBusMessage *connection_attempt_failed(DBusMessage *msg, int err) +static inline DBusMessage *connection_attempt_failed(DBusMessage *msg, + const char *err) { - return g_dbus_create_error(msg, ERROR_INTERFACE ".ConnectionAttemptFailed", - err ? strerror(err) : "Connection attempt failed"); + return g_dbus_create_error(msg, + ERROR_INTERFACE ".ConnectionAttemptFailed", + err ? err : "Connection attempt failed"); } -static void rfcomm_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src, - const bdaddr_t *dst, gpointer user_data) +static void rfcomm_connect_cb(GIOChannel *chan, GError *err, gpointer user_data) { struct input_conn *iconn = user_data; struct input_device *idev = iconn->idev; struct fake_input *fake = iconn->fake; DBusMessage *reply; - if (err < 0) + if (err) { + reply = connection_attempt_failed(iconn->pending_connect, + err->message); goto failed; + } fake->rfcomm = g_io_channel_unix_get_fd(chan); @@ -349,7 +354,9 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src, */ fake->uinput = uinput_create(idev->name); if (fake->uinput < 0) { - err = errno; + g_io_channel_close(chan); + reply = connection_attempt_failed(iconn->pending_connect, + strerror(errno)); goto failed; } @@ -368,26 +375,27 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src, return; failed: - reply = connection_attempt_failed(iconn->pending_connect, err); g_dbus_send_message(idev->conn, reply); - dbus_message_unref(iconn->pending_connect); iconn->pending_connect = NULL; } -static int rfcomm_connect(struct input_conn *iconn) +static gboolean rfcomm_connect(struct input_conn *iconn, GError **err) { struct input_device *idev = iconn->idev; - int err; + GIOChannel *io; - err = bt_rfcomm_connect(&idev->src, &idev->dst, iconn->fake->ch, - rfcomm_connect_cb, iconn); - if (err < 0) { - error("connect() failed: %s (%d)", strerror(-err), -err); - return err; - } + io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, iconn, + NULL, err, + BT_IO_OPT_SOURCE_BDADDR, &idev->src, + BT_IO_OPT_DEST_BDADDR, &idev->dst, + BT_IO_OPT_INVALID); + if (!io) + return FALSE; - return 0; + g_io_channel_unref(io); + + return TRUE; } static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data) @@ -448,11 +456,11 @@ static guint create_watch(int sk, GIOFunc cb, struct input_conn *iconn) return id; } -static gboolean fake_hid_connect(struct input_conn *iconn) +static gboolean fake_hid_connect(struct input_conn *iconn, GError **err) { struct fake_hid *fhid = iconn->fake->priv; - return fhid->connect(iconn->fake); + return fhid->connect(iconn->fake, err); } static int fake_hid_disconnect(struct input_conn *iconn) @@ -588,8 +596,7 @@ cleanup: } static int hidp_add_connection(const struct input_device *idev, - const struct input_conn *iconn) - + const struct input_conn *iconn) { struct hidp_connadd_req *req; struct fake_hid *fake_hid; @@ -663,23 +670,28 @@ cleanup: return err; } -static void interrupt_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src, - const bdaddr_t *dst, gpointer user_data) +static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err, + gpointer user_data) { struct input_conn *iconn = user_data; struct input_device *idev = iconn->idev; DBusMessage *reply; + int err; + const char *err_msg; - if (err < 0) { - error("connect(): %s (%d)", strerror(-err), -err); + if (conn_err) { + err_msg = conn_err->message; goto failed; } - iconn->intr_sk = g_io_channel_unix_get_fd(chan); err = hidp_add_connection(idev, iconn); - - if (err < 0) + if (err < 0) { + err_msg = strerror(-err); + g_io_channel_close(chan); goto failed; + } + + iconn->intr_sk = g_io_channel_unix_get_fd(chan); iconn->intr_watch = create_watch(iconn->intr_sk, intr_watch_cb, iconn); iconn->ctrl_watch = create_watch(iconn->ctrl_sk, ctrl_watch_cb, iconn); @@ -690,7 +702,8 @@ static void interrupt_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src, goto cleanup; failed: - reply = connection_attempt_failed(iconn->pending_connect, -err); + error("%s", err_msg); + reply = connection_attempt_failed(iconn->pending_connect, err_msg); g_dbus_send_message(idev->conn, reply); iconn->intr_sk = -1; @@ -701,34 +714,46 @@ cleanup: iconn->pending_connect = NULL; } -static void control_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src, - const bdaddr_t *dst, gpointer user_data) +static void control_connect_cb(GIOChannel *chan, GError *conn_err, + gpointer user_data) { struct input_conn *iconn = user_data; struct input_device *idev = iconn->idev; DBusMessage *reply; + GIOChannel *io; + GError *err = NULL; - if (err < 0) { - error("connect(): %s (%d)", strerror(-err), -err); + if (conn_err) { + error("%s", conn_err->message); + reply = connection_attempt_failed(iconn->pending_connect, + conn_err->message); goto failed; } - /* Set HID control channel */ - iconn->ctrl_sk = g_io_channel_unix_get_fd(chan); - /* Connect to the HID interrupt channel */ - err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_INTR, 0, - interrupt_connect_cb, iconn); - if (err < 0) { - error("L2CAP connect failed:%s (%d)", strerror(-err), -err); + io = bt_io_connect(BT_IO_L2CAP, interrupt_connect_cb, iconn, + NULL, &err, + BT_IO_OPT_SOURCE_BDADDR, &idev->src, + BT_IO_OPT_DEST_BDADDR, &idev->dst, + BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR, + BT_IO_OPT_INVALID); + if (!io) { + error("%s", err->message); + reply = connection_attempt_failed(iconn->pending_connect, + err->message); + g_clear_error(&err); + g_io_channel_close(chan); goto failed; } + g_io_channel_unref(io); + + /* Set HID control channel */ + iconn->ctrl_sk = g_io_channel_unix_get_fd(chan); + return; failed: - iconn->ctrl_sk = -1; - reply = connection_attempt_failed(iconn->pending_connect, -err); g_dbus_send_message(idev->conn, reply); dbus_message_unref(iconn->pending_connect); iconn->pending_connect = NULL; @@ -873,7 +898,8 @@ static DBusMessage *device_connect(DBusConnection *conn, struct input_device *idev = data; struct input_conn *iconn; struct fake_input *fake; - int err; + DBusMessage *reply; + GError *err = NULL; iconn = find_connection(idev->connections, "HID"); if (!iconn) @@ -888,31 +914,33 @@ static DBusMessage *device_connect(DBusConnection *conn, iconn->pending_connect = dbus_message_ref(msg); fake = iconn->fake; - /* Fake input device */ if (fake) { - if (fake->connect(iconn) < 0) { - int err = errno; - const char *str = strerror(err); - error("Connect failed: %s(%d)", str, err); - dbus_message_unref(iconn->pending_connect); - iconn->pending_connect = NULL; - return connection_attempt_failed(msg, err); - } - fake->flags |= FI_FLAG_CONNECTED; - return NULL; + /* Fake input device */ + if (fake->connect(iconn, &err)) + fake->flags |= FI_FLAG_CONNECTED; + } else { + /* HID devices */ + GIOChannel *io; + + io = bt_io_connect(BT_IO_L2CAP, control_connect_cb, iconn, + NULL, &err, + BT_IO_OPT_SOURCE_BDADDR, &idev->src, + BT_IO_OPT_DEST_BDADDR, &idev->dst, + BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL, + NULL); + if (io) + g_io_channel_unref(io); } - /* HID devices */ - err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_CTRL, - 0, control_connect_cb, iconn); - if (err < 0) { - error("L2CAP connect failed: %s(%d)", strerror(-err), -err); - dbus_message_unref(iconn->pending_connect); - iconn->pending_connect = NULL; - return connection_attempt_failed(msg, -err); - } + if (err == NULL) + return NULL; - return NULL; + error("%s", err->message); + dbus_message_unref(iconn->pending_connect); + iconn->pending_connect = NULL; + reply = connection_attempt_failed(msg, err->message); + g_clear_error(&err); + return reply; } static DBusMessage *create_errno_message(DBusMessage *msg, int err) diff --git a/input/device.h b/input/device.h index c65a5d20..cb305d62 100644 --- a/input/device.h +++ b/input/device.h @@ -36,7 +36,7 @@ struct fake_input { int uinput; /* uinput socket */ int rfcomm; /* RFCOMM socket */ uint8_t ch; /* RFCOMM channel number */ - gboolean (*connect) (struct input_conn *iconn); + gboolean (*connect) (struct input_conn *iconn, GError **err); int (*disconnect) (struct input_conn *iconn); void *priv; }; diff --git a/input/fakehid.c b/input/fakehid.c index 900399d2..077dc21f 100644 --- a/input/fakehid.c +++ b/input/fakehid.c @@ -325,7 +325,7 @@ err: return 1; } -static gboolean fake_hid_common_connect(struct fake_input *fake) +static gboolean fake_hid_common_connect(struct fake_input *fake, GError **err) { return TRUE; } diff --git a/input/fakehid.h b/input/fakehid.h index ced9ed43..e61a7275 100644 --- a/input/fakehid.h +++ b/input/fakehid.h @@ -27,7 +27,7 @@ struct fake_input; struct fake_hid { uint16_t vendor; uint16_t product; - gboolean (*connect) (struct fake_input *fake_input); + gboolean (*connect) (struct fake_input *fake_input, GError **err); int (*disconnect) (struct fake_input *fake_input); gboolean (*event) (GIOChannel *chan, GIOCondition cond, gpointer data); int (*setup_uinput) (struct fake_input *fake, struct fake_hid *fake_hid); diff --git a/input/server.c b/input/server.c index 6e9639f0..fdeac6d5 100644 --- a/input/server.c +++ b/input/server.c @@ -36,6 +36,7 @@ #include "logging.h" #include "glib-helper.h" +#include "btio.h" #include "adapter.h" #include "device.h" #include "server.h" @@ -86,60 +87,76 @@ static int authorize_device(const bdaddr_t *src, const bdaddr_t *dst) auth_callback, auth); } -static void connect_event_cb(GIOChannel *chan, int err, const bdaddr_t *src, - const bdaddr_t *dst, gpointer data) +static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data) { - int sk, psm = GPOINTER_TO_UINT(data); + int sk, psm; + bdaddr_t src, dst; + GError *gerr = NULL; - if (err < 0) { - error("accept: %s (%d)", strerror(-err), -err); + if (err) { + error("%s", err->message); return; } - sk = g_io_channel_unix_get_fd(chan); + bt_io_get(chan, BT_IO_L2CAP, &gerr, + BT_IO_OPT_SOURCE_BDADDR, &src, + BT_IO_OPT_DEST_BDADDR, &dst, + BT_IO_OPT_PSM, &psm, + NULL); + if (gerr) { + error("%s", gerr->message); + g_error_free(gerr); + g_io_channel_close(chan); + return; + } debug("Incoming connection on PSM %d", psm); - if (input_device_set_channel(src, dst, psm, sk) < 0) { + sk = g_io_channel_unix_get_fd(chan); + + if (input_device_set_channel(&src, &dst, psm, sk) < 0) { /* Send unplug virtual cable to unknown devices */ if (psm == L2CAP_PSM_HIDP_CTRL) { unsigned char unplug[] = { 0x15 }; int err; err = write(sk, unplug, sizeof(unplug)); } - close(sk); + g_io_channel_close(chan); return; } - if ((psm == L2CAP_PSM_HIDP_INTR) && (authorize_device(src, dst) < 0)) - input_device_close_channels(src, dst); - - return; + if ((psm == L2CAP_PSM_HIDP_INTR) && (authorize_device(&src, &dst) < 0)) + input_device_close_channels(&src, &dst); } int server_start(const bdaddr_t *src) { struct server *server; GIOChannel *ctrl_io, *intr_io; + GError *err = NULL; - ctrl_io = bt_l2cap_listen(src, L2CAP_PSM_HIDP_CTRL, 0, 0, - connect_event_cb, - GUINT_TO_POINTER(L2CAP_PSM_HIDP_CTRL)); + ctrl_io = bt_io_listen(BT_IO_L2CAP, connect_event_cb, NULL, + NULL, NULL, &err, + BT_IO_OPT_SOURCE_BDADDR, src, + BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL, + BT_IO_OPT_INVALID); if (!ctrl_io) { error("Failed to listen on control channel"); + g_clear_error(&err); return -1; } - g_io_channel_set_close_on_unref(ctrl_io, TRUE); - intr_io = bt_l2cap_listen(src, L2CAP_PSM_HIDP_INTR, 0, 0, - connect_event_cb, - GUINT_TO_POINTER(L2CAP_PSM_HIDP_INTR)); + intr_io = bt_io_listen(BT_IO_L2CAP, connect_event_cb, NULL, + NULL, NULL, &err, + BT_IO_OPT_SOURCE_BDADDR, src, + BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR, + BT_IO_OPT_INVALID); if (!intr_io) { error("Failed to listen on interrupt channel"); g_io_channel_unref(ctrl_io); + g_clear_error(&err); return -1; } - g_io_channel_set_close_on_unref(intr_io, TRUE); server = g_new0(struct server, 1); bacpy(&server->src, src); @@ -162,7 +179,10 @@ void server_stop(const bdaddr_t *src) server = l->data; + g_io_channel_close(server->intr); g_io_channel_unref(server->intr); + + g_io_channel_close(server->ctrl); g_io_channel_unref(server->ctrl); servers = g_slist_remove(servers, server); |