diff options
author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2009-04-17 11:22:38 -0300 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2009-04-17 21:02:54 +0300 |
commit | d31cee86b0b9ebfc99cf0d318c590f5ccdd0f821 (patch) | |
tree | 890f552fb9f1f4c29aa6bd43fff082a413b6323a /input | |
parent | 3df7c3e66042f266dadace88488e532de92d4da9 (diff) | |
download | bluez-d31cee86b0b9ebfc99cf0d318c590f5ccdd0f821.tar.gz |
Make input service to use confirm callback.
Diffstat (limited to 'input')
-rw-r--r-- | input/device.c | 61 | ||||
-rw-r--r-- | input/device.h | 1 | ||||
-rw-r--r-- | input/server.c | 154 |
3 files changed, 125 insertions, 91 deletions
diff --git a/input/device.c b/input/device.c index ad944e66..8f344649 100644 --- a/input/device.c +++ b/input/device.c @@ -1185,6 +1185,29 @@ int input_device_unregister(const char *path, const char *uuid) return 0; } +static int input_device_connadd(struct input_device *idev, + struct input_conn *iconn) +{ + int err; + + err = input_device_connected(idev, iconn); + if (err == 0) + return 0; + + if (iconn->ctrl_io) { + g_io_channel_shutdown(iconn->ctrl_io, FALSE, NULL); + g_io_channel_unref(iconn->ctrl_io); + iconn->ctrl_io = NULL; + } + if (iconn->intr_io) { + g_io_channel_shutdown(iconn->intr_io, FALSE, NULL); + g_io_channel_unref(iconn->intr_io); + iconn->intr_io = NULL; + } + + return err; +} + int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, GIOChannel *io) { @@ -1211,6 +1234,9 @@ int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, break; } + if (iconn->intr_io && iconn->ctrl_io) + input_device_connadd(idev, iconn); + return 0; } @@ -1234,38 +1260,3 @@ int input_device_close_channels(const bdaddr_t *src, const bdaddr_t *dst) return 0; } - -int input_device_connadd(const bdaddr_t *src, const bdaddr_t *dst) -{ - struct input_device *idev; - struct input_conn *iconn; - int err; - - idev = find_device(src, dst); - if (!idev) - return -ENOENT; - - iconn = find_connection(idev->connections, "hid"); - if (!iconn) - return -ENOENT; - - err = input_device_connected(idev, iconn); - if (err < 0) - goto error; - - return 0; - -error: - if (iconn->ctrl_io) { - g_io_channel_shutdown(iconn->ctrl_io, FALSE, NULL); - g_io_channel_unref(iconn->ctrl_io); - iconn->ctrl_io = NULL; - } - if (iconn->intr_io) { - g_io_channel_shutdown(iconn->intr_io, FALSE, NULL); - g_io_channel_unref(iconn->intr_io); - iconn->intr_io = NULL; - } - - return err; -} diff --git a/input/device.h b/input/device.h index 237b09af..a1a8803c 100644 --- a/input/device.h +++ b/input/device.h @@ -51,4 +51,3 @@ int input_device_unregister(const char *path, const char *uuid); int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, GIOChannel *io); int input_device_close_channels(const bdaddr_t *src, const bdaddr_t *dst); -int input_device_connadd(const bdaddr_t *src, const bdaddr_t *dst); diff --git a/input/server.c b/input/server.c index af15282f..5ae9f8c3 100644 --- a/input/server.c +++ b/input/server.c @@ -43,39 +43,21 @@ #include "server.h" static GSList *servers = NULL; -struct server { +struct input_server { bdaddr_t src; GIOChannel *ctrl; GIOChannel *intr; -}; - -struct authorization_data { - bdaddr_t src; - bdaddr_t dst; + GIOChannel *confirm; }; static gint server_cmp(gconstpointer s, gconstpointer user_data) { - const struct server *server = s; + const struct input_server *server = s; const bdaddr_t *src = user_data; return bacmp(&server->src, src); } -static void auth_callback(DBusError *derr, void *user_data) -{ - struct authorization_data *auth = user_data; - - if (derr) { - error("Access denied: %s", derr->message); - - input_device_close_channels(&auth->src, &auth->dst); - } else - input_device_connadd(&auth->src, &auth->dst); - - g_free(auth); -} - static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data) { uint16_t psm; @@ -103,67 +85,129 @@ static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data) debug("Incoming connection on PSM %d", psm); ret = input_device_set_channel(&src, &dst, psm, chan); - if (ret < 0) { - /* Send unplug virtual cable to unknown devices */ - if (ret == -ENOENT && psm == L2CAP_PSM_HIDP_CTRL) { - unsigned char unplug = 0x15; - int err, sk = g_io_channel_unix_get_fd(chan); - err = write(sk, &unplug, sizeof(unplug)); - } - g_io_channel_shutdown(chan, TRUE, NULL); + if (ret == 0) return; + + /* Send unplug virtual cable to unknown devices */ + if (ret == -ENOENT && psm == L2CAP_PSM_HIDP_CTRL) { + unsigned char unplug = 0x15; + int err, sk = g_io_channel_unix_get_fd(chan); + err = write(sk, &unplug, sizeof(unplug)); + } + + g_io_channel_shutdown(chan, TRUE, NULL); +} + +static void auth_callback(DBusError *derr, void *user_data) +{ + struct input_server *server = user_data; + bdaddr_t src, dst; + GError *err = NULL; + + bt_io_get(server->confirm, BT_IO_L2CAP, &err, + BT_IO_OPT_SOURCE_BDADDR, &src, + BT_IO_OPT_DEST_BDADDR, &dst, + BT_IO_OPT_INVALID); + if (err) { + error("%s", err->message); + g_error_free(err); + goto reject; + } + + if (derr) { + error("Access denied: %s", derr->message); + goto reject; + } + + if (!bt_io_accept(server->confirm, connect_event_cb, server, + NULL, &err)) { + error("bt_io_accept: %s", err->message); + g_error_free(err); + goto reject; } - if (psm == L2CAP_PSM_HIDP_INTR) { - struct authorization_data *auth; + g_io_channel_unref(server->confirm); + server->confirm = NULL; - auth = g_new0(struct authorization_data, 1); - bacpy(&auth->src, &src); - bacpy(&auth->dst, &dst); + return; + +reject: + g_io_channel_shutdown(server->confirm, TRUE, NULL); + g_io_channel_unref(server->confirm); + server->confirm = NULL; + input_device_close_channels(&src, &dst); +} + +static void confirm_event_cb(GIOChannel *chan, gpointer user_data) +{ + struct input_server *server = user_data; + bdaddr_t src, dst; + GError *err = NULL; + int ret; + + bt_io_get(chan, BT_IO_L2CAP, &err, + BT_IO_OPT_SOURCE_BDADDR, &src, + BT_IO_OPT_DEST_BDADDR, &dst, + BT_IO_OPT_INVALID); + if (err) { + error("%s", err->message); + g_error_free(err); + goto drop; + } - ret = btd_request_authorization(&src, &dst, HID_UUID, - auth_callback, auth); - if (ret < 0) { - g_free(auth); - input_device_close_channels(&src, &dst); - } + if (server->confirm) { + error("Refusing connection: setup in progress"); + goto drop; } + + server->confirm = g_io_channel_ref(chan); + + ret = btd_request_authorization(&src, &dst, HID_UUID, + auth_callback, server); + if (ret == 0) + return; + + g_io_channel_unref(server->confirm); + server->confirm = NULL; + +drop: + input_device_close_channels(&src, &dst); + g_io_channel_shutdown(chan, TRUE, NULL); } int server_start(const bdaddr_t *src) { - struct server *server; - GIOChannel *ctrl_io, *intr_io; + struct input_server *server; GError *err = NULL; - ctrl_io = bt_io_listen(BT_IO_L2CAP, connect_event_cb, NULL, - NULL, NULL, &err, + server = g_new0(struct input_server, 1); + bacpy(&server->src, src); + + server->ctrl = bt_io_listen(BT_IO_L2CAP, connect_event_cb, NULL, + server, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL, BT_IO_OPT_INVALID); - if (!ctrl_io) { + if (!server->ctrl) { error("Failed to listen on control channel"); g_error_free(err); + g_free(server); return -1; } - intr_io = bt_io_listen(BT_IO_L2CAP, connect_event_cb, NULL, - NULL, NULL, &err, + server->intr = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event_cb, + server, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR, BT_IO_OPT_INVALID); - if (!intr_io) { + if (!server->intr) { error("Failed to listen on interrupt channel"); - g_io_channel_unref(ctrl_io); + g_io_channel_unref(server->ctrl); g_error_free(err); + g_free(server); return -1; } - server = g_new0(struct server, 1); - bacpy(&server->src, src); - server->ctrl = ctrl_io; - server->intr = intr_io; - servers = g_slist_append(servers, server); return 0; @@ -171,7 +215,7 @@ int server_start(const bdaddr_t *src) void server_stop(const bdaddr_t *src) { - struct server *server; + struct input_server *server; GSList *l; l = g_slist_find_custom(servers, src, server_cmp); |