summaryrefslogtreecommitdiffstats
path: root/hcid
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-04-08 22:35:49 +0000
committerLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2008-04-08 22:35:49 +0000
commit3d9966f38f1d6ca12c9e9e2eace5181ba04844b4 (patch)
treeb1fa4bfbf4675e9ddd97b95e2b12b5812b49120c /hcid
parenta6bf5ec452e5426906fc9991d738e3a5ae27050c (diff)
Fix CreatePairedDevice and CreateDevice behavior.
Diffstat (limited to 'hcid')
-rw-r--r--hcid/adapter.c243
-rw-r--r--hcid/adapter.h5
-rw-r--r--hcid/dbus-hci.c98
-rw-r--r--hcid/device.c107
-rw-r--r--hcid/device.h8
5 files changed, 213 insertions, 248 deletions
diff --git a/hcid/adapter.c b/hcid/adapter.c
index 1ffce314..12e92695 100644
--- a/hcid/adapter.c
+++ b/hcid/adapter.c
@@ -69,14 +69,6 @@
#define NUM_ELEMENTS(table) (sizeof(table)/sizeof(const char *))
-struct create_device_req {
- char address[18]; /* Destination address */
- DBusConnection *conn; /* Connection reference */
- DBusMessage *msg; /* Message reference */
- guint id; /* Listener id */
- char *agent_path; /* Agent object path */
-};
-
struct mode_req {
struct adapter *adapter;
DBusConnection *conn; /* Connection reference */
@@ -239,18 +231,26 @@ int pending_remote_name_cancel(struct adapter *adapter)
return err;
}
-static struct bonding_request_info *bonding_request_new(bdaddr_t *peer,
- DBusConnection *conn,
- DBusMessage *msg)
+static struct bonding_request_info *bonding_request_new(DBusConnection *conn,
+ DBusMessage *msg,
+ struct adapter *adapter,
+ const char *address)
{
struct bonding_request_info *bonding;
+ struct device *device;
bonding = g_new0(struct bonding_request_info, 1);
- bacpy(&bonding->bdaddr, peer);
-
bonding->conn = dbus_connection_ref(conn);
- bonding->rq = dbus_message_ref(msg);
+ bonding->msg = dbus_message_ref(msg);
+
+ /* FIXME: should be removed on 4.0 */
+ if (hcid_dbus_use_experimental()) {
+ device = adapter_get_device(conn, adapter, address);
+ device->temporary = TRUE;
+ }
+
+ str2ba(address, &bonding->bdaddr);
return bonding;
}
@@ -2254,19 +2254,11 @@ static void reply_authentication_failure(struct bonding_request_info *bonding)
status = bonding->hci_status ?
bonding->hci_status : HCI_AUTHENTICATION_FAILURE;
- reply = new_authentication_return(bonding->rq, status);
+ reply = new_authentication_return(bonding->msg, status);
if (reply)
send_message_and_unref(bonding->conn, reply);
}
-static void create_device_req_free(struct create_device_req *create)
-{
- dbus_connection_unref(create->conn);
- dbus_message_unref(create->msg);
- g_free(create->agent_path);
- g_free(create);
-}
-
struct device *adapter_find_device(struct adapter *adapter, const char *dest)
{
struct device *device;
@@ -2334,7 +2326,7 @@ static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,
if (cond & G_IO_NVAL) {
error_authentication_canceled(adapter->bonding->conn,
- adapter->bonding->rq);
+ adapter->bonding->msg);
goto cleanup;
}
@@ -2343,7 +2335,7 @@ static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,
if (!adapter->bonding->auth_active)
error_connection_attempt_failed(adapter->bonding->conn,
- adapter->bonding->rq,
+ adapter->bonding->msg,
ENETDOWN);
else
reply_authentication_failure(adapter->bonding);
@@ -2357,7 +2349,7 @@ static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,
if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {
error("Can't get socket error: %s (%d)",
strerror(errno), errno);
- error_failed_errno(adapter->bonding->conn, adapter->bonding->rq,
+ error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,
errno);
goto failed;
}
@@ -2367,7 +2359,7 @@ static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,
reply_authentication_failure(adapter->bonding);
else
error_connection_attempt_failed(adapter->bonding->conn,
- adapter->bonding->rq,
+ adapter->bonding->msg,
ret);
goto failed;
}
@@ -2376,7 +2368,7 @@ static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,
if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &cinfo, &len) < 0) {
error("Can't get connection info: %s (%d)",
strerror(errno), errno);
- error_failed_errno(adapter->bonding->conn, adapter->bonding->rq,
+ error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,
errno);
goto failed;
}
@@ -2384,7 +2376,7 @@ static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,
dd = hci_open_dev(adapter->dev_id);
if (dd < 0) {
error_no_such_adapter(adapter->bonding->conn,
- adapter->bonding->rq);
+ adapter->bonding->msg);
goto failed;
}
@@ -2405,7 +2397,7 @@ static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,
if (hci_send_req(dd, &rq, 500) < 0) {
error("Unable to send HCI request: %s (%d)",
strerror(errno), errno);
- error_failed_errno(adapter->bonding->conn, adapter->bonding->rq,
+ error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,
errno);
hci_close_dev(dd);
goto failed;
@@ -2414,7 +2406,7 @@ static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,
if (rp.status) {
error("HCI_Authentication_Requested failed with status 0x%02x",
rp.status);
- error_failed_errno(adapter->bonding->conn, adapter->bonding->rq,
+ error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,
bt_error(rp.status));
hci_close_dev(dd);
goto failed;
@@ -2436,18 +2428,12 @@ failed:
cleanup:
name_listener_remove(adapter->bonding->conn,
- dbus_message_get_sender(adapter->bonding->rq),
+ dbus_message_get_sender(adapter->bonding->msg),
(name_cb_t) create_bond_req_exit, adapter);
bonding_request_free(adapter->bonding);
adapter->bonding = NULL;
- if (adapter->create) {
- name_listener_id_remove(adapter->create->id);
- create_device_req_free(adapter->create);
- adapter->create = NULL;
- }
-
return FALSE;
}
@@ -2489,7 +2475,7 @@ static DBusHandlerResult create_bonding(DBusConnection *conn, DBusMessage *msg,
if (sk < 0)
return error_connection_attempt_failed(conn, msg, 0);
- adapter->bonding = bonding_request_new(&bdaddr, conn, msg);
+ adapter->bonding = bonding_request_new(conn, msg, adapter, address);
if (!adapter->bonding) {
close(sk);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
@@ -2532,33 +2518,33 @@ static DBusHandlerResult adapter_cancel_bonding(DBusConnection *conn,
{
struct adapter *adapter = data;
DBusMessage *reply;
- bdaddr_t peer_bdaddr;
- const char *peer_addr;
+ const char *address;
+ bdaddr_t bdaddr;
GSList *l;
+ struct bonding_request_info *bonding = adapter->bonding;
if (!adapter->up)
return error_not_ready(conn, msg);
if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &peer_addr,
+ DBUS_TYPE_STRING, &address,
DBUS_TYPE_INVALID))
return error_invalid_arguments(conn, msg, NULL);
- if (check_address(peer_addr) < 0)
+ if (check_address(address) < 0)
return error_invalid_arguments(conn, msg, NULL);
- str2ba(peer_addr, &peer_bdaddr);
-
- if (!adapter->bonding || bacmp(&adapter->bonding->bdaddr, &peer_bdaddr))
+ str2ba(address, &bdaddr);
+ if (!bonding || bacmp(&bonding->bdaddr, &bdaddr))
return error_bonding_not_in_progress(conn, msg);
- if (strcmp(dbus_message_get_sender(adapter->bonding->rq),
+ if (strcmp(dbus_message_get_sender(adapter->bonding->msg),
dbus_message_get_sender(msg)))
return error_not_authorized(conn, msg);
adapter->bonding->cancel = 1;
- l = g_slist_find_custom(adapter->pin_reqs, &peer_bdaddr, pin_req_cmp);
+ l = g_slist_find_custom(adapter->pin_reqs, &bdaddr, pin_req_cmp);
if (l) {
struct pending_pin_info *pin_req = l->data;
@@ -2579,7 +2565,7 @@ static DBusHandlerResult adapter_cancel_bonding(DBusConnection *conn,
}
hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY,
- 6, &peer_bdaddr);
+ 6, &bdaddr);
hci_close_dev(dd);
}
@@ -3688,77 +3674,29 @@ static DBusHandlerResult list_devices(DBusConnection *conn,
return send_message_and_unref(conn, reply);
}
-static void create_device_exit(const char *name, struct adapter *adapter)
-{
- create_device_req_free(adapter->create);
- adapter->create = NULL;
-}
-
-static void discover_services_cb(gpointer user_data, sdp_list_t *recs, int err)
+static DBusHandlerResult create_device(DBusConnection *conn,
+ DBusMessage *msg, void *data)
{
- sdp_list_t *seq, *next, *svcclass;
- struct adapter *adapter = user_data;
+ struct adapter *adapter = data;
struct device *device;
- DBusMessage *reply;
- GSList *uuids;
- bdaddr_t src, dst;
-
- /* Onwer exitted? */
- if (!adapter->create) {
- sdp_list_free(recs, (sdp_free_func_t) sdp_record_free);
- return;
- }
-
- if (err < 0) {
- error_connection_attempt_failed(adapter->create->conn,
- adapter->create->msg, -err);
- goto failed;
- }
-
- uuids = NULL;
- for (seq = recs; seq; seq = next) {
- sdp_record_t *rec = (sdp_record_t *) seq->data;
-
- if (!rec)
- break;
-
- svcclass = NULL;
- if (sdp_get_service_classes(rec, &svcclass) == 0) {
- /* Extract the first element and skip the remainning */
- gchar *uuid_str = bt_uuid2string(svcclass->data);
- if (uuid_str) {
- if (!g_slist_find_custom(uuids, uuid_str,
- (GCompareFunc) strcmp))
- uuids = g_slist_insert_sorted(uuids,
- uuid_str, (GCompareFunc) strcmp);
- else
- g_free(uuid_str);
- }
- sdp_list_free(svcclass, free);
- }
+ const gchar *address;
- next = seq->next;
- }
+ if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
+ DBUS_TYPE_INVALID) == FALSE)
+ return error_invalid_arguments(conn, msg, NULL);
- sdp_list_free(recs, (sdp_free_func_t) sdp_record_free);
+ if (adapter_find_device(adapter, address))
+ return error_already_exists(conn, msg, "Device already exists");
- device = device_create(adapter->create->conn, adapter,
- adapter->create->address, uuids);
+ device = device_create(conn, adapter, address, NULL);
if (!device)
- goto failed;
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
device->temporary = FALSE;
- /* Reply create device request */
- reply = dbus_message_new_method_return(adapter->create->msg);
- if (!reply)
- goto failed;
- dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &device->path,
- DBUS_TYPE_INVALID);
- send_message_and_unref(adapter->create->conn, reply);
+ device_browse(device, conn, msg);
- dbus_connection_emit_signal(adapter->create->conn,
- dbus_message_get_path(adapter->create->msg),
+ dbus_connection_emit_signal(conn, dbus_message_get_path(msg),
ADAPTER_INTERFACE,
"DeviceCreated",
DBUS_TYPE_OBJECT_PATH, &device->path,
@@ -3766,90 +3704,9 @@ static void discover_services_cb(gpointer user_data, sdp_list_t *recs, int err)
adapter->devices = g_slist_append(adapter->devices, device);
- /* Store the device's profiles in the filesystem */
- str2ba(adapter->address, &src);
- str2ba(adapter->create->address, &dst);
- if (uuids) {
- gchar *str = bt_list2string(uuids);
- write_device_profiles(&src, &dst, str);
- g_free(str);
- } else
- write_device_profiles(&src, &dst, "");
-
- if (adapter->create->agent_path)
- create_bonding(adapter->create->conn, adapter->create->msg,
- adapter->create->address,
- adapter->create->agent_path, adapter);
-
-failed:
- name_listener_id_remove(adapter->create->id);
- create_device_req_free(adapter->create);
- adapter->create = NULL;
-}
-
-static DBusHandlerResult discover_services(DBusConnection *conn,
- DBusMessage *msg, const char *address,
- const char *agent_path, void *data)
-{
- struct adapter *adapter = data;
- struct create_device_req *create;
- bdaddr_t src, dst;
- int err;
- GSList *l;
-
- if (check_address(address) < 0)
- return error_invalid_arguments(conn, msg, NULL);
-
- l = g_slist_find_custom(adapter->devices, address,
- (GCompareFunc) device_address_cmp);
- if (l && agent_path)
- return create_bonding(conn, msg, address, agent_path, data);
- else if (l && !agent_path)
- return error_already_exists(conn, msg, "Device already exists");
-
- if (adapter->create) {
- adapter->create->agent_path = g_strdup(agent_path);
- return DBUS_HANDLER_RESULT_HANDLED;
- }
-
- str2ba(adapter->address, &src);
- str2ba(address, &dst);
- err = bt_discover_services(&src, &dst,
- discover_services_cb, adapter, NULL);
- if (err < 0) {
- error("Discover services failed!");
- return error_connection_attempt_failed(conn, msg, -err);
- }
-
- create = g_new0(struct create_device_req, 1);
- create->conn = dbus_connection_ref(conn);
- create->msg = dbus_message_ref(msg);
- create->id = name_listener_add(conn,
- dbus_message_get_sender(msg),
- (name_cb_t) create_device_exit, adapter);
- strcpy(create->address, address);
- create->agent_path = g_strdup(agent_path);
- adapter->create = create;
-
return DBUS_HANDLER_RESULT_HANDLED;
}
-static DBusHandlerResult create_device(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct adapter *adapter = data;
- const gchar *address;
-
- if (adapter->create)
- return error_in_progress(conn, msg, "CreateDevice in progress");
-
- if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
- DBUS_TYPE_INVALID) == FALSE)
- return error_invalid_arguments(conn, msg, NULL);
-
- return discover_services(conn, msg, address, NULL, data);
-}
-
static DBusHandlerResult create_paired_device(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -3861,7 +3718,7 @@ static DBusHandlerResult create_paired_device(DBusConnection *conn,
DBUS_TYPE_INVALID) == FALSE)
return error_invalid_arguments(conn, msg, NULL);
- return discover_services(conn, msg, address, agent_path, data);
+ return create_bonding(conn, msg, address, agent_path, data);
}
static gint device_path_cmp(struct device *device, const gchar *path)
@@ -3905,7 +3762,7 @@ static DBusHandlerResult remove_device(DBusConnection *conn,
DBUS_TYPE_OBJECT_PATH, &device->path,
DBUS_TYPE_INVALID);
- device_destroy(device, conn);
+ device_remove(device, conn);
adapter->devices = g_slist_remove(adapter->devices, device);
return send_message_and_unref(conn, reply);
diff --git a/hcid/adapter.h b/hcid/adapter.h
index b02c6ccb..3449aec4 100644
--- a/hcid/adapter.h
+++ b/hcid/adapter.h
@@ -53,9 +53,9 @@ struct remote_dev_info {
};
struct bonding_request_info {
- bdaddr_t bdaddr;
DBusConnection *conn;
- DBusMessage *rq;
+ DBusMessage *msg;
+ bdaddr_t bdaddr;
GIOChannel *io;
guint io_id;
int hci_status;
@@ -107,7 +107,6 @@ struct adapter {
struct bonding_request_info *bonding;
GSList *pin_reqs;
struct pending_dc_info *pending_dc;
- struct create_device_req *create;
GSList *devices; /* Devices structure pointers */
GSList *sessions; /* Request Mode sessions */
};
diff --git a/hcid/dbus-hci.c b/hcid/dbus-hci.c
index 0cc3af6a..e27df03f 100644
--- a/hcid/dbus-hci.c
+++ b/hcid/dbus-hci.c
@@ -69,8 +69,8 @@ void bonding_request_free(struct bonding_request_info *bonding)
if (!bonding)
return;
- if (bonding->rq)
- dbus_message_unref(bonding->rq);
+ if (bonding->msg)
+ dbus_message_unref(bonding->msg);
if (bonding->conn)
dbus_connection_unref(bonding->conn);
@@ -332,9 +332,9 @@ static void reply_pending_requests(const char *path, struct adapter *adapter)
/* pending bonding */
if (adapter->bonding) {
- error_authentication_canceled(connection, adapter->bonding->rq);
+ error_authentication_canceled(connection, adapter->bonding->msg);
name_listener_remove(connection,
- dbus_message_get_sender(adapter->bonding->rq),
+ dbus_message_get_sender(adapter->bonding->msg),
(name_cb_t) create_bond_req_exit,
adapter);
if (adapter->bonding->io_id)
@@ -471,7 +471,7 @@ int unregister_adapter_path(const char *path)
if (adapter->devices) {
g_slist_foreach(adapter->devices,
- (GFunc) device_destroy, connection);
+ (GFunc) device_remove, connection);
g_slist_free(adapter->devices);
}
@@ -956,8 +956,7 @@ static void passkey_cb(struct agent *agent, DBusError *err, const char *passkey,
str2ba(device->address, &dba);
if (err) {
- if (device->temporary)
- device_remove(connection, device);
+
hci_send_cmd(dev, OGF_LINK_CTL,
OCF_PIN_CODE_NEG_REPLY, 6, &dba);
goto done;
@@ -1050,6 +1049,10 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
const char *paddr = peer_addr;
GSList *l;
int id;
+ DBusMessage *reply;
+ struct device *device;
+ struct bonding_request_info *bonding;
+ void *d;
ba2str(local, local_addr);
ba2str(peer, peer_addr);
@@ -1074,50 +1077,60 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
peer);
l = g_slist_find_custom(adapter->pin_reqs, peer, pin_req_cmp);
- if (l) {
- void *d = l->data;
- adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, l->data);
- g_free(d);
+ if (!l || status)
+ goto proceed;
- if (!status) {
- send_adapter_signal(connection, adapter->dev_id,
- "BondingCreated",
- DBUS_TYPE_STRING, &paddr,
- DBUS_TYPE_INVALID);
+ d = l->data;
+ adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, l->data);
+ g_free(d);
- if (hcid_dbus_use_experimental()) {
- struct device *device;
- gboolean paired = TRUE;
+ send_adapter_signal(connection, adapter->dev_id, "BondingCreated",
+ DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID);
- device = adapter_get_device(connection, adapter, paddr);
- if (device) {
- device->temporary = FALSE;
- dbus_connection_emit_property_changed(connection,
- device->path, DEVICE_INTERFACE,
- "Paired", DBUS_TYPE_BOOLEAN, &paired);
- }
- }
+ if (hcid_dbus_use_experimental()) {
+ struct device *device;
+ gboolean paired = TRUE;
+
+ device = adapter_get_device(connection, adapter, paddr);
+ if (device) {
+ dbus_connection_emit_property_changed(connection,
+ device->path, DEVICE_INTERFACE,
+ "Paired", DBUS_TYPE_BOOLEAN, &paired);
}
}
+proceed:
+
release_passkey_agents(adapter, peer);
- if (!adapter->bonding || bacmp(&adapter->bonding->bdaddr, peer))
+ bonding = adapter->bonding;
+ if (!bonding || bacmp(&bonding->bdaddr, peer))
return; /* skip: no bonding req pending */
- if (adapter->bonding->cancel) {
+ if (bonding->cancel) {
/* reply authentication canceled */
- error_authentication_canceled(connection, adapter->bonding->rq);
- } else {
- DBusMessage *reply;
- /* reply authentication success or an error */
- reply = new_authentication_return(adapter->bonding->rq,
- status);
+ error_authentication_canceled(connection, bonding->msg);
+ goto cleanup;
+ }
+
+ /* reply authentication success or an error */
+ if (dbus_message_is_method_call(bonding->msg, ADAPTER_INTERFACE,
+ "CreateBonding")) {
+ reply = new_authentication_return(bonding->msg, status);
send_message_and_unref(connection, reply);
+ } else if ((device = adapter_find_device(adapter, paddr))) {
+ if (status) {
+ reply = new_authentication_return(bonding->msg, status);
+ send_message_and_unref(connection, reply);
+ } else {
+ device->temporary = FALSE;
+ device_browse(device, bonding->conn, bonding->msg);
+ }
}
+cleanup:
name_listener_remove(connection,
- dbus_message_get_sender(adapter->bonding->rq),
+ dbus_message_get_sender(adapter->bonding->msg),
(name_cb_t) create_bond_req_exit, adapter);
if (adapter->bonding->io_id)
@@ -1996,15 +2009,15 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status,
if (adapter->bonding->cancel) {
/* reply authentication canceled */
error_authentication_canceled(connection,
- adapter->bonding->rq);
+ adapter->bonding->msg);
} else {
- reply = new_authentication_return(adapter->bonding->rq,
+ reply = new_authentication_return(adapter->bonding->msg,
HCI_AUTHENTICATION_FAILURE);
send_message_and_unref(connection, reply);
}
name_listener_remove(connection,
- dbus_message_get_sender(adapter->bonding->rq),
+ dbus_message_get_sender(adapter->bonding->msg),
(name_cb_t) create_bond_req_exit,
adapter);
if (adapter->bonding->io_id)
@@ -2042,8 +2055,11 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status,
device->path, DEVICE_INTERFACE,
"Connected", DBUS_TYPE_BOOLEAN,
&connected);
- if (device->temporary)
- device_remove(connection, device);
+ if (device->temporary) {
+ adapter->devices = g_slist_remove(adapter->devices,
+ device);
+ device_remove(device, connection);
+ }
}
}
diff --git a/hcid/device.c b/hcid/device.c
index b0532712..32567851 100644
--- a/hcid/device.c
+++ b/hcid/device.c
@@ -59,11 +59,18 @@
#include "dbus-common.h"
#include "dbus-hci.h"
#include "error.h"
+#include "glib-helper.h"
#define MAX_DEVICES 16
#define DEVICE_INTERFACE "org.bluez.Device"
+struct browse_req {
+ DBusConnection *conn;
+ DBusMessage *msg;
+ struct device *device;
+};
+
struct hci_peer {
struct timeval lastseen;
struct timeval lastused;
@@ -1035,13 +1042,7 @@ struct device *device_create(DBusConnection *conn, struct adapter *adapter,
return device;
}
-void device_remove(DBusConnection *conn, struct device *device)
-{
- device_destroy(device, conn);
- device_free(device);
-}
-
-void device_destroy(struct device *device, DBusConnection *conn)
+void device_remove(struct device *device, DBusConnection *conn)
{
debug("Removing device %s", device->path);
@@ -1052,3 +1053,95 @@ gint device_address_cmp(struct device *device, const gchar *address)
{
return strcasecmp(device->address, address);
}
+
+static void browse_cb(gpointer user_data, sdp_list_t *recs, int err)
+{
+ sdp_list_t *seq, *next, *svcclass;
+ struct browse_req *req = user_data;
+ struct device *device = req->device;
+ struct adapter *adapter = device->adapter;
+ bdaddr_t src, dst;
+ char **uuids;
+ int i;
+ GSList *l;
+ DBusMessage *reply;
+
+ if (err < 0)
+ return;
+
+ for (seq = recs; seq; seq = next) {
+ sdp_record_t *rec = (sdp_record_t *) seq->data;
+
+ if (!rec)
+ break;
+
+ svcclass = NULL;
+ if (sdp_get_service_classes(rec, &svcclass) == 0) {
+ /* Extract the first element and skip the remainning */
+ gchar *uuid_str = bt_uuid2string(svcclass->data);
+ if (uuid_str) {
+ if (!g_slist_find_custom(device->uuids, uuid_str,
+ (GCompareFunc) strcmp))
+ device->uuids = g_slist_insert_sorted(device->uuids,
+ uuid_str, (GCompareFunc) strcmp);
+ else
+ g_free(uuid_str);
+ }
+ sdp_list_free(svcclass, free);
+ }
+
+ next = seq->next;
+ }
+
+ sdp_list_free(recs, (sdp_free_func_t) sdp_record_free);
+
+ /* Store the device's profiles in the filesystem */
+ str2ba(adapter->address, &src);
+ str2ba(device->address, &dst);
+ if (device->uuids) {
+ gchar *str = bt_list2string(device->uuids);
+ write_device_profiles(&src, &dst, str);
+ g_free(str);
+ } else
+ write_device_profiles(&src, &dst, "");
+
+ uuids = g_new0(char *, g_slist_length(device->uuids) + 1);
+ for (i = 0, l = device->uuids; l; l = l->next, i++)
+ uuids[i] = l->data;
+
+ dbus_connection_emit_property_changed(req->conn, device->path,
+ DEVICE_INTERFACE, "UUIDs",
+ DBUS_TYPE_ARRAY, &uuids);
+ g_free(uuids);
+
+ /* Reply create device request */
+ reply = dbus_message_new_method_return(req->msg);
+ if (!reply)
+ return;
+
+ dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &device->path,
+ DBUS_TYPE_INVALID);
+
+ send_message_and_unref(req->conn, reply);
+
+ dbus_message_unref(req->msg);
+ dbus_connection_unref(req->conn);
+ g_free(req);
+}
+
+int device_browse(struct device *device, DBusConnection *conn,
+ DBusMessage *msg)
+{
+ struct adapter *adapter = device->adapter;
+ struct browse_req *req;
+ bdaddr_t src, dst;
+
+ req = g_new0(struct browse_req, 1);
+ req->conn = dbus_connection_ref(conn);
+ req->msg = dbus_message_ref(msg);
+ req->device = device;
+
+ str2ba(adapter->address, &src);
+ str2ba(device->address, &dst);
+ return bt_discover_services(&src, &dst, browse_cb, req, NULL);
+}
diff --git a/hcid/device.h b/hcid/device.h
index 318b2470..273d23d5 100644
--- a/hcid/device.h
+++ b/hcid/device.h
@@ -33,8 +33,8 @@ struct device {
};
struct device *device_create(DBusConnection *conn, struct adapter *adapter,
- const gchar *address, GSList *uuids);
-
-void device_remove(DBusConnection *conn, struct device *device);
-void device_destroy(struct device *device, DBusConnection *conn);
+ const gchar *address, GSList *uuids);
+void device_remove(struct device *device, DBusConnection *conn);
gint device_address_cmp(struct device *device, const gchar *address);
+int device_browse(struct device *device, DBusConnection *conn,
+ DBusMessage *msg);