summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-04-25 20:01:09 +0000
committerLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-04-25 20:01:09 +0000
commit279e85d6da77c74f04e5fc605dd8074bfe56b5a5 (patch)
tree61d3f0496f6ed6d5d479cff01eba992ef795042d
parent90ddd9872e42d11a347de4ec3f3ba47b66ca92e2 (diff)
Make input service to use libbluetooth-glib convenient functions.
-rw-r--r--input/device.c206
-rw-r--r--input/manager.c532
2 files changed, 103 insertions, 635 deletions
diff --git a/input/device.c b/input/device.c
index 46214217..08a1c089 100644
--- a/input/device.c
+++ b/input/device.c
@@ -37,6 +37,7 @@
#include <bluetooth/hidp.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
#include <glib.h>
@@ -53,6 +54,7 @@
#include "manager.h"
#include "storage.h"
#include "fakehid.h"
+#include "glib-helper.h"
#define INPUT_DEVICE_INTERFACE "org.bluez.input.Device"
@@ -368,38 +370,18 @@ failed:
return FALSE;
}
-static gboolean rfcomm_connect_cb(GIOChannel *chan,
- GIOCondition cond, struct device *idev)
+static void rfcomm_connect_cb(GIOChannel *chan, int err, gpointer user_data)
{
+ struct device *idev = user_data;
struct fake_input *fake;
DBusMessage *reply;
const char *path;
- socklen_t len;
- int ret, err;
fake = idev->fake;
fake->rfcomm = g_io_channel_unix_get_fd(chan);
- if (cond & G_IO_NVAL)
- return FALSE;
-
- if (cond & (G_IO_ERR | G_IO_HUP)) {
- err = EIO;
- goto failed;
- }
-
- len = sizeof(ret);
- if (getsockopt(fake->rfcomm, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
- err = errno;
- error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err);
- goto failed;
- }
-
- if (ret != 0) {
- err = ret;
- error("connect(): %s (%d)", strerror(err), err);
+ if (err < 0)
goto failed;
- }
/*
* FIXME: Some headsets required a sco connection
@@ -429,85 +411,27 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan,
dbus_message_unref(idev->pending_connect);
idev->pending_connect = NULL;
- return FALSE;
+ return;
failed:
error_connection_attempt_failed(idev->conn,
idev->pending_connect, err);
dbus_message_unref(idev->pending_connect);
idev->pending_connect = NULL;
-
- g_io_channel_close(chan);
-
- return FALSE;
}
static int rfcomm_connect(struct device *idev)
{
- struct sockaddr_rc addr;
- GIOChannel *io;
- int sk, err;
-
- sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- if (sk < 0) {
- err = errno;
- error("socket: %s (%d)", strerror(err), err);
- return -err;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, &idev->src);
- addr.rc_channel = 0;
-
- if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- err = errno;
- error("bind: %s (%d)", strerror(err), err);
- goto failed;
- }
-
- if (set_nonblocking(sk) < 0) {
- err = errno;
- error("Set non blocking: %s (%d)", strerror(err), err);
- goto failed;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, &idev->dst);
- addr.rc_channel = idev->fake->ch;
-
- io = g_io_channel_unix_new(sk);
- g_io_channel_set_close_on_unref(io, FALSE);
-
- if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- char peer[18]; /* FIXME: debug purpose */
- if (!(errno == EAGAIN || errno == EINPROGRESS)) {
- err = errno;
- error("connect() failed: %s (%d)",
- strerror(err), err);
- g_io_channel_unref(io);
- goto failed;
- }
+ int err;
- ba2str(&idev->dst, peer);
- debug("RFCOMM connection in progress: %s channel:%d", peer, idev->fake->ch);
- g_io_add_watch(io, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- (GIOFunc) rfcomm_connect_cb, idev);
- } else {
- debug("Connect succeeded with first try");
- rfcomm_connect_cb(io, G_IO_OUT, idev);
+ err = bt_rfcomm_connect(&idev->src, &idev->dst, idev->fake->ch,
+ rfcomm_connect_cb, idev);
+ if (err < 0) {
+ error("connect() failed: %s (%d)", strerror(-err), -err);
+ return err;
}
- g_io_channel_unref(io);
-
return 0;
-
-failed:
- close(sk);
- errno = err;
-
- return -err;
}
static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
@@ -628,41 +552,16 @@ cleanup:
return err;
}
-static gboolean interrupt_connect_cb(GIOChannel *chan,
- GIOCondition cond, struct device *idev)
+static void interrupt_connect_cb(GIOChannel *chan, int err, gpointer user_data)
{
- int isk, ret, err;
- socklen_t len;
-
- isk = g_io_channel_unix_get_fd(chan);
-
- if (cond & G_IO_NVAL) {
- err = EHOSTDOWN;
- isk = -1;
- goto failed;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- err = EHOSTDOWN;
- error("Hangup or error on HIDP interrupt socket");
- goto failed;
-
- }
-
- len = sizeof(ret);
- if (getsockopt(isk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
- err = errno;
- error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err);
- goto failed;
- }
+ struct device *idev = user_data;
- if (ret != 0) {
- err = ret;
- error("connect(): %s (%d)", strerror(ret), ret);
+ if (err < 0) {
+ error("connect(): %s (%d)", strerror(-err), -err);
goto failed;
}
- idev->intr_sk = isk;
+ idev->intr_sk = g_io_channel_unix_get_fd(chan);
err = hidp_connadd(&idev->src, &idev->dst,
idev->ctrl_sk, idev->intr_sk, idev->name);
if (err < 0)
@@ -683,78 +582,43 @@ static gboolean interrupt_connect_cb(GIOChannel *chan,
goto cleanup;
failed:
error_connection_attempt_failed(idev->conn,
- idev->pending_connect, err);
- if (isk > 0)
- close(isk);
- close(idev->ctrl_sk);
+ idev->pending_connect, -err);
idev->intr_sk = -1;
idev->ctrl_sk = -1;
cleanup:
dbus_message_unref(idev->pending_connect);
idev->pending_connect = NULL;
-
- return FALSE;
}
-static gboolean control_connect_cb(GIOChannel *chan,
- GIOCondition cond, struct device *idev)
+static void control_connect_cb(GIOChannel *chan, int err, gpointer user_data)
{
- int ret, csk, err;
- socklen_t len;
+ struct device *idev = user_data;
- csk = g_io_channel_unix_get_fd(chan);
-
- if (cond & G_IO_NVAL) {
- err = EHOSTDOWN;
- csk = -1;
- goto failed;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- err = EHOSTDOWN;
- error("Hangup or error on HIDP control socket");
+ if (err < 0) {
+ error("connect(): %s (%d)", strerror(-err), -err);
goto failed;
}
/* Set HID control channel */
- idev->ctrl_sk = csk;
-
- len = sizeof(ret);
- if (getsockopt(csk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
- err = errno;
- error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err);
- goto failed;
- }
-
- if (ret != 0) {
- err = ret;
- error("connect(): %s (%d)", strerror(ret), ret);
- goto failed;
- }
+ idev->ctrl_sk = g_io_channel_unix_get_fd(chan);
/* Connect to the HID interrupt channel */
- if (l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_INTR,
- (GIOFunc) interrupt_connect_cb, idev) < 0) {
-
- err = errno;
- error("L2CAP connect failed:%s (%d)", strerror(errno), errno);
+ err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_INTR,
+ interrupt_connect_cb, idev);
+ if (err < 0) {
+ error("L2CAP connect failed:%s (%d)", strerror(-err), -err);
goto failed;
}
- return FALSE;
+ return;
failed:
- if (csk > 0)
- close(csk);
-
idev->ctrl_sk = -1;
error_connection_attempt_failed(idev->conn,
- idev->pending_connect, err);
+ idev->pending_connect, -err);
dbus_message_unref(idev->pending_connect);
idev->pending_connect = NULL;
-
- return FALSE;
}
static int fake_disconnect(struct device *idev)
@@ -874,6 +738,7 @@ static DBusHandlerResult device_connect(DBusConnection *conn,
{
struct device *idev = data;
struct fake_input *fake = idev->fake;
+ int err;
if (idev->pending_connect)
return error_in_progress(conn, msg,
@@ -900,14 +765,13 @@ static DBusHandlerResult device_connect(DBusConnection *conn,
}
/* HID devices */
- if (l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_CTRL,
- (GIOFunc) control_connect_cb, idev) < 0) {
- int err = errno;
-
- error("L2CAP connect failed: %s(%d)", strerror(err), err);
+ err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_CTRL,
+ control_connect_cb, idev);
+ if (err < 0) {
+ error("L2CAP connect failed: %s(%d)", strerror(-err), -err);
dbus_message_unref(idev->pending_connect);
idev->pending_connect = NULL;
- return error_connection_attempt_failed(conn, msg, err);
+ return error_connection_attempt_failed(conn, msg, -err);
}
return DBUS_HANDLER_RESULT_HANDLED;
diff --git a/input/manager.c b/input/manager.c
index 2e138c6b..4b25843d 100644
--- a/input/manager.c
+++ b/input/manager.c
@@ -52,10 +52,7 @@
#include "error.h"
#include "manager.h"
#include "storage.h"
-
-static const char *pnp_uuid = "00001200-0000-1000-8000-00805f9b34fb";
-static const char *hid_uuid = "00001124-0000-1000-8000-00805f9b34fb";
-static const char *headset_uuid = "00001108-0000-1000-8000-00805f9b34fb";
+#include "glib-helper.h"
struct pending_req {
char *adapter_path; /* Local adapter D-Bus path */
@@ -119,70 +116,6 @@ static void pending_req_free(struct pending_req *pr)
g_free(pr);
}
-static int get_record(struct pending_req *pr, uint32_t handle,
- DBusPendingCallNotifyFunction cb)
-{
- DBusMessage *msg;
- DBusPendingCall *pending;
- char addr[18];
- const char *paddr = addr;
-
- msg = dbus_message_new_method_call("org.bluez", pr->adapter_path,
- "org.bluez.Adapter", "GetRemoteServiceRecord");
- if (!msg)
- return -1;
-
- ba2str(&pr->dst, addr);
- dbus_message_append_args(msg,
- DBUS_TYPE_STRING, &paddr,
- DBUS_TYPE_UINT32, &handle,
- DBUS_TYPE_INVALID);
-
- if (dbus_connection_send_with_reply(pr->conn, msg, &pending, -1) == FALSE) {
- error("Can't send D-Bus message.");
- dbus_message_unref(msg);
- return -1;
- }
-
- dbus_pending_call_set_notify(pending, cb, pr, NULL);
- dbus_pending_call_unref(pending);
- dbus_message_unref(msg);
-
- return 0;
-}
-
-static int get_handles(struct pending_req *pr, const char *uuid,
- DBusPendingCallNotifyFunction cb)
-{
- DBusMessage *msg;
- DBusPendingCall *pending;
- char addr[18];
- const char *paddr = addr;
-
- msg = dbus_message_new_method_call("org.bluez", pr->adapter_path,
- "org.bluez.Adapter", "GetRemoteServiceHandles");
- if (!msg)
- return -1;
-
- ba2str(&pr->dst, addr);
- dbus_message_append_args(msg,
- DBUS_TYPE_STRING, &paddr,
- DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
-
- if (dbus_connection_send_with_reply(pr->conn, msg, &pending, -1) == FALSE) {
- error("Can't send D-Bus message.");
- dbus_message_unref(msg);
- return -1;
- }
-
- dbus_pending_call_set_notify(pending, cb, pr, NULL);
- dbus_pending_call_unref(pending);
- dbus_message_unref(msg);
-
- return 0;
-}
-
static void epox_endian_quirk(unsigned char *data, int size)
{
/* USAGE_PAGE (Keyboard) 05 07
@@ -279,42 +212,17 @@ static void extract_pnp_record(sdp_record_t *rec, struct hidp_connadd_req *req)
req->version = pdlist ? pdlist->val.uint16 : 0x0000;
}
-static gboolean interrupt_connect_cb(GIOChannel *chan,
- GIOCondition cond, struct pending_req *pr)
+static void interrupt_connect_cb(GIOChannel *chan, int err, gpointer user_data)
{
+ struct pending_req *pr = user_data;
struct hidp_connadd_req hidp;
DBusMessage *reply;
const char *path;
- int isk, ret, err;
- socklen_t len;
memset(&hidp, 0, sizeof(hidp));
- isk = g_io_channel_unix_get_fd(chan);
-
- if (cond & G_IO_NVAL) {
- err = EHOSTDOWN;
- isk = -1;
- goto failed;
- }
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- err = EHOSTDOWN;
- error("Hangup or error on HIDP interrupt socket");
- goto failed;
-
- }
-
- len = sizeof(ret);
- if (getsockopt(isk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
- err = errno;
- error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err);
- goto failed;
- }
-
- if (ret != 0) {
- err = ret;
- error("connect(): %s (%d)", strerror(ret), ret);
+ if (err < 0) {
+ error("connect(): %s (%d)", strerror(-err), -err);
goto failed;
}
@@ -351,74 +259,38 @@ failed:
error_connection_attempt_failed(pr->conn, pr->msg, err);
cleanup:
- if (isk >= 0)
- close(isk);
-
close(pr->ctrl_sock);
pending_req_free(pr);
if (hidp.rd_data)
g_free(hidp.rd_data);
-
- return FALSE;
}
-static gboolean control_connect_cb(GIOChannel *chan,
- GIOCondition cond, struct pending_req *pr)
+static void control_connect_cb(GIOChannel *chan, int err, gpointer user_data)
{
- int ret, csk, err;
- socklen_t len;
-
- csk = g_io_channel_unix_get_fd(chan);
-
- if (cond & G_IO_NVAL) {
- err = EHOSTDOWN;
- csk = -1;
- goto failed;
- }
+ struct pending_req *pr = user_data;
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- err = EHOSTDOWN;
- error("Hangup or error on HIDP control socket");
+ if (err < 0) {
+ error("connect(): %s (%d)", strerror(-err), -err);
goto failed;
-
}
/* Set HID control channel */
- pr->ctrl_sock = csk;
-
- len = sizeof(ret);
- if (getsockopt(csk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
- err = errno;
- error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err);
- goto failed;
- }
-
- if (ret != 0) {
- err = ret;
- error("connect(): %s (%d)", strerror(ret), ret);
- goto failed;
- }
+ pr->ctrl_sock = g_io_channel_unix_get_fd(chan);
/* Connect to the HID interrupt channel */
- if (l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_INTR,
- (GIOFunc) interrupt_connect_cb, pr) < 0) {
-
- err = errno;
- error("L2CAP connect failed:%s (%d)", strerror(errno), errno);
+ err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_INTR,
+ interrupt_connect_cb, pr);
+ if (err < 0) {
+ error("L2CAP connect failed:%s (%d)", strerror(-err), -err);
goto failed;
}
- return FALSE;
+ return;
failed:
- if (csk >= 0)
- close(csk);
-
- error_connection_attempt_failed(pr->conn, pr->msg, err);
+ error_connection_attempt_failed(pr->conn, pr->msg, -err);
pending_req_free(pr);
-
- return FALSE;
}
static void create_bonding_reply(DBusPendingCall *call, void *data)
@@ -426,6 +298,7 @@ static void create_bonding_reply(DBusPendingCall *call, void *data)
DBusMessage *reply = dbus_pending_call_steal_reply(call);
struct pending_req *pr = data;
DBusError derr;
+ int err;
dbus_error_init(&derr);
if (dbus_set_error_from_message(&derr, reply)) {
@@ -440,36 +313,15 @@ static void create_bonding_reply(DBusPendingCall *call, void *data)
dbus_message_unref(reply);
- if (l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_CTRL,
- (GIOFunc) control_connect_cb, pr) < 0) {
- int err = errno;
- error_connection_attempt_failed(pr->conn, pr->msg, err);
- error("L2CAP connect failed:%s (%d)", strerror(err), err);
+ err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_CTRL,
+ control_connect_cb, pr);
+ if (err < 0) {
+ error("L2CAP connect failed:%s (%d)", strerror(-err), -err);
+ error_connection_attempt_failed(pr->conn, pr->msg, -err);
pending_req_free(pr);
}
}
-static void finish_sdp_transaction(bdaddr_t *dba)
-{
- char address[18], *addr_ptr = address;
- DBusMessage *msg;
-
- ba2str(dba, address);
-
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0",
- "org.bluez.Adapter",
- "FinishRemoteServiceTransaction");
- if (!msg) {
- error("Unable to allocate new method call");
- return;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &addr_ptr,
- DBUS_TYPE_INVALID);
-
- send_message_and_unref(connection, msg);
-}
-
static int create_bonding(struct pending_req *pr)
{
DBusPendingCall *pending;
@@ -496,53 +348,23 @@ static int create_bonding(struct pending_req *pr)
return 0;
}
-static void hid_record_reply(DBusPendingCall *call, void *data)
+static void hid_record_cb(sdp_list_t *recs, int err, gpointer user_data)
{
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- struct pending_req *pr = data;
- DBusError derr;
- uint8_t *rec_bin;
- int len, scanned;
+ struct pending_req *pr = user_data;
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- /* FIXME : to not try to be clever about
- hcid error but forward as is to the user */
- if (dbus_error_has_name(&derr,
- "org.bluez.Error.ConnectionAttemptFailed"))
- error_connection_attempt_failed(pr->conn,
- pr->msg, EIO);
- else
- error_not_supported(pr->conn, pr->msg);
-
- error("GetRemoteServiceRecord failed: %s(%s)",
- derr.name, derr.message);
- goto fail;
- }
-
- finish_sdp_transaction(&pr->dst);
-
- if (!dbus_message_get_args(reply, &derr,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len,
- DBUS_TYPE_INVALID)) {
+ if (err < 0) {
error_not_supported(pr->conn, pr->msg);
- error("%s: %s", derr.name, derr.message);
+ error("SDP search error: %s (%d)", strerror(-err), -err);
goto fail;
}
- if (len == 0) {
+ if (!recs || !recs->data) {
error_not_supported(pr->conn, pr->msg);
error("Invalid HID service record length");
goto fail;
}
- pr->hid_rec = sdp_extract_pdu(rec_bin, &scanned);
- if (!pr->hid_rec) {
- error_not_supported(pr->conn, pr->msg);
- goto fail;
- }
-
- dbus_message_unref(reply);
+ pr->hid_rec = recs->data;
if (strcmp("CreateSecureDevice", dbus_message_get_member(pr->msg)) == 0) {
sdp_data_t *d;
@@ -564,240 +386,76 @@ static void hid_record_reply(DBusPendingCall *call, void *data)
}
/* No encryption or link key already exists -- connect control channel */
- if (l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_CTRL,
- (GIOFunc) control_connect_cb, pr) < 0) {
- int err = errno;
- error("L2CAP connect failed:%s (%d)", strerror(err), err);
- error_connection_attempt_failed(pr->conn, pr->msg, err);
+ err = bt_l2cap_connect(&pr->src, &pr->dst, L2CAP_PSM_HIDP_CTRL,
+ control_connect_cb, pr);
+ if (err < 0) {
+ error("L2CAP connect failed:%s (%d)", strerror(-err), -err);
+ error_connection_attempt_failed(pr->conn, pr->msg, -err);
goto fail;
}
/* Wait L2CAP connect */
return;
-fail:
- dbus_error_free(&derr);
- pending_req_free(pr);
- dbus_message_unref(reply);
-}
-
-static void hid_handle_reply(DBusPendingCall *call, void *data)
-{
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- struct pending_req *pr = data;
- uint32_t *phandle;
- DBusError derr;
- int len;
-
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- /* FIXME : to not try to be clever about
- hcid error but forward as is to the user */
- if (dbus_error_has_name(&derr,
- "org.bluez.Error.ConnectionAttemptFailed"))
- error_connection_attempt_failed(pr->conn,
- pr->msg, EIO);
- else
- error_not_supported(pr->conn, pr->msg);
-
- error("GetRemoteServiceHandles: %s(%s)",
- derr.name, derr.message);
- goto fail;
- }
-
- if (!dbus_message_get_args(reply, &derr,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len,
- DBUS_TYPE_INVALID)) {
- error_not_supported(pr->conn, pr->msg);
- error("%s: %s", derr.name, derr.message);
- goto fail;
- }
-
- if (len == 0) {
- error_not_supported(pr->conn, pr->msg);
- error("HID record handle not found");
- goto fail;
- }
-
- if (get_record(pr, *phandle, hid_record_reply) < 0) {
- error_not_supported(pr->conn, pr->msg);
- error("HID service attribute request failed");
- goto fail;
- } else {
- /* Wait record reply */
- goto done;
- }
fail:
- dbus_error_free(&derr);
pending_req_free(pr);
-
-done:
- dbus_message_unref(reply);
}
-static void pnp_record_reply(DBusPendingCall *call, void *data)
+static void pnp_record_cb(sdp_list_t *recs, int err, gpointer user_data)
{
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- struct pending_req *pr = data;
- DBusError derr;
- uint8_t *rec_bin;
- int len, scanned;
+ struct pending_req *pr = user_data;
+ uuid_t uuid;
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- /* FIXME : to not try to be clever about
- hcid error but forward as is to the user */
- if (dbus_error_has_name(&derr,
- "org.bluez.Error.ConnectionAttemptFailed"))
- error_connection_attempt_failed(pr->conn, pr->msg,
- EIO);
- else
- error_not_supported(pr->conn, pr->msg);
-
- error("GetRemoteServiceRecord: %s(%s)",
- derr.name, derr.message);
- goto fail;
- }
-
- if (!dbus_message_get_args(reply, &derr,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len,
- DBUS_TYPE_INVALID)) {
+ if (err < 0) {
error_not_supported(pr->conn, pr->msg);
- error("%s: %s", derr.name, derr.message);
+ error("SDP search error: %s (%d)", strerror(-err), -err);
goto fail;
}
- if (len == 0) {
+ if (!recs || !recs->data) {
error_not_supported(pr->conn, pr->msg);
error("Invalid PnP service record length");
goto fail;
}
- pr->pnp_rec = sdp_extract_pdu(rec_bin, &scanned);
- if (get_handles(pr, hid_uuid, hid_handle_reply) < 0) {
+ pr->pnp_rec = recs->data;
+ sdp_uuid16_create(&uuid, HID_SVCLASS_ID);
+ err = bt_search_service(&pr->src, &pr->dst, &uuid, hid_record_cb,
+ pr, NULL);
+ if (err < 0) {
error_not_supported(pr->conn, pr->msg);
error("HID service search request failed");
goto fail;
- } else {
- /* Wait handle reply */
- goto done;
}
-fail:
- dbus_error_free(&derr);
- pending_req_free(pr);
-
-done:
- dbus_message_unref(reply);
-}
-
-static void pnp_handle_reply(DBusPendingCall *call, void *data)
-{
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- struct pending_req *pr = data;
- DBusError derr;
- uint32_t *phandle;
- int len;
-
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- /* FIXME : to not try to be clever about
- hcid error but forward as is to the user */
- if (dbus_error_has_name(&derr,
- "org.bluez.Error.ConnectionAttemptFailed"))
- error_connection_attempt_failed(pr->conn, pr->msg,
- EIO);
- else
- error_not_supported(pr->conn, pr->msg);
-
- error("GetRemoteServiceHandles: %s(%s)",
- derr.name, derr.message);
- goto fail;
- }
-
- if (!dbus_message_get_args(reply, &derr,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len,
- DBUS_TYPE_INVALID)) {
- error_not_supported(pr->conn, pr->msg);
- error("%s: %s", derr.name, derr.message);
- goto fail;
- }
-
- if (len == 0) {
- /* PnP is optional: Ignore it and request the HID handle */
- if (get_handles(pr, hid_uuid, hid_handle_reply) < 0) {
- error_not_supported(pr->conn, pr->msg);
- error("HID service search request failed");
- goto fail;
- }
- } else {
- /* Request PnP record */
- if (get_record(pr, *phandle, pnp_record_reply) < 0) {
- error_not_supported(pr->conn, pr->msg);
- error("PnP service attribute request failed");
- goto fail;
- }
- }
-
- /* Wait HID handle reply or PnP record reply */
- goto done;
+ return;
fail:
- dbus_error_free(&derr);
pending_req_free(pr);
-
-done:
- dbus_message_unref(reply);
}
-static void headset_record_reply(DBusPendingCall *call, void *data)
+static void headset_record_cb(sdp_list_t *recs, int err, gpointer user_data)
{
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- DBusMessage *pr_reply;
- DBusError derr;
- struct pending_req *pr = data;
- uint8_t *rec_bin;
+ struct pending_req *pr = user_data;
+ DBusMessage *reply;
sdp_record_t *rec;
sdp_list_t *protos;
const char *path;
- int len, scanned;
uint8_t ch;
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- /* FIXME : to not try to be clever about
- hcid error but forward as is to the user */
- if (dbus_error_has_name(&derr,
- "org.bluez.Error.ConnectionAttemptFailed"))
- error_connection_attempt_failed(pr->conn, pr->msg,
- EIO);
- else
- error_not_supported(pr->conn, pr->msg);
-
- error("GetRemoteServiceRecord: %s(%s)",
- derr.name, derr.message);
- goto fail;
- }
-
- if (!dbus_message_get_args(reply, &derr,
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len,
- DBUS_TYPE_INVALID)) {
+ if (err < 0) {
error_not_supported(pr->conn, pr->msg);
- error("%s: %s", derr.name, derr.message);
+ error("SDP search error: %s (%d)", strerror(-err), -err);
goto fail;
}
- if (len == 0) {
+ if (!recs || !recs->data) {
error_not_supported(pr->conn, pr->msg);
error("Invalid headset service record length");
goto fail;
}
- rec = sdp_extract_pdu(rec_bin, &scanned);
- if (!rec) {
- error_not_supported(pr->conn, pr->msg);
- goto fail;
- }
+ rec = recs->data;
if (sdp_get_access_protos(rec, &protos) < 0) {
error_not_supported(pr->conn, pr->msg);
@@ -830,73 +488,16 @@ static void headset_record_reply(DBusPendingCall *call, void *data)
device_paths = g_slist_append(device_paths, g_strdup(path));
- pr_reply = dbus_message_new_method_return(pr->msg);
+ reply = dbus_message_new_method_return(pr->msg);
- dbus_message_append_args(pr_reply,
+ dbus_message_append_args(reply,
DBUS_TYPE_STRING, &path,
DBUS_TYPE_INVALID);
- send_message_and_unref(pr->conn, pr_reply);
-
-fail:
- dbus_error_free(&derr);
- pending_req_free(pr);
- dbus_message_unref(reply);
-}
-
-static void headset_handle_reply(DBusPendingCall *call, void *data)
-{
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- struct pending_req *pr = data;
- DBusError derr;
- uint32_t *phandle;
- int len;
-
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- /* FIXME : to not try to be clever about
- hcid error but forward as is to the user */
- if (dbus_error_has_name(&derr,
- "org.bluez.Error.ConnectionAttemptFailed"))
- error_connection_attempt_failed(pr->conn, pr->msg,
- EIO);
- else
- error_not_supported(pr->conn, pr->msg);
-
- error("GetRemoteServiceHandles: %s(%s)",
- derr.name, derr.message);
- goto fail;
- }
-
- if (!dbus_message_get_args(reply, &derr,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len,
- DBUS_TYPE_INVALID)) {
- error_not_supported(pr->conn, pr->msg);
- error("%s: %s", derr.name, derr.message);
- goto fail;
- }
-
- if (len == 0) {
- error_not_supported(pr->conn, pr->msg);
- error("Headset record handle not found");
- goto fail;
- }
-
- if (get_record(pr, *phandle, headset_record_reply) < 0) {
- error_not_supported(pr->conn, pr->msg);
- error("Headset service attribute request failed");
- goto fail;
- } else {
- /* Wait record reply */
- goto done;
- }
+ send_message_and_unref(pr->conn, reply);
fail:
- dbus_error_free(&derr);
pending_req_free(pr);
-
-done:
- dbus_message_unref(reply);
}
static DBusHandlerResult create_device(DBusConnection *conn,
@@ -907,7 +508,9 @@ static DBusHandlerResult create_device(DBusConnection *conn,
const char *addr;
bdaddr_t src, dst;
uint32_t cls = 0;
- int dev_id;
+ int dev_id, err;
+ uuid_t uuid;
+ bt_callback_t cb;
dbus_error_init(&derr);
if (!dbus_message_get_args(msg, &derr,
@@ -946,23 +549,24 @@ static DBusHandlerResult create_device(DBusConnection *conn,
switch (cls & 0x1f00) {
case 0x0500: /* Peripheral */
case 0x0200: /* Phone */
- if (get_handles(pr, pnp_uuid, pnp_handle_reply) < 0) {
- pending_req_free(pr);
- return error_not_supported(conn, msg);
- }
+ sdp_uuid16_create(&uuid, PNP_INFO_SVCLASS_ID);
+ cb = pnp_record_cb;
break;
case 0x0400: /* Fake input */
- if (get_handles(pr, headset_uuid,
- headset_handle_reply) < 0) {
- pending_req_free(pr);
- return error_not_supported(conn, msg);
- }
+ sdp_uuid16_create(&uuid, HEADSET_SVCLASS_ID);
+ cb = headset_record_cb;
break;
default:
pending_req_free(pr);
return error_not_supported(conn, msg);
}
+ err = bt_search_service(&src, &dst, &uuid, cb, pr, NULL);
+ if (err < 0) {
+ pending_req_free(pr);
+ return error_not_supported(conn, msg);
+ }
+
return DBUS_HANDLER_RESULT_HANDLED;
}