summaryrefslogtreecommitdiffstats
path: root/input
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2009-02-18 19:17:50 -0300
committerJohan Hedberg <johan.hedberg@nokia.com>2009-02-19 11:05:10 +0200
commitc95494ee508a9f36096af5ddb1c2ac1579a32b1d (patch)
treef04c45cc65a372d8ae5d953a72ab6156e8215bf1 /input
parent56fe087dfc68f56d84ac41ca390c8a0dc7438e2d (diff)
Make input plugin to use BtIO API.
Diffstat (limited to 'input')
-rw-r--r--input/device.c158
-rw-r--r--input/device.h2
-rw-r--r--input/fakehid.c2
-rw-r--r--input/fakehid.h2
-rw-r--r--input/server.c60
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);