aboutsummaryrefslogtreecommitdiff
path: root/input
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2009-04-17 11:22:38 -0300
committerJohan Hedberg <johan.hedberg@nokia.com>2009-04-17 21:02:54 +0300
commitd31cee86b0b9ebfc99cf0d318c590f5ccdd0f821 (patch)
tree890f552fb9f1f4c29aa6bd43fff082a413b6323a /input
parent3df7c3e66042f266dadace88488e532de92d4da9 (diff)
downloadbluez-d31cee86b0b9ebfc99cf0d318c590f5ccdd0f821.tar.gz
Make input service to use confirm callback.
Diffstat (limited to 'input')
-rw-r--r--input/device.c61
-rw-r--r--input/device.h1
-rw-r--r--input/server.c154
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);