summaryrefslogtreecommitdiffstats
path: root/hcid/adapter.c
diff options
context:
space:
mode:
Diffstat (limited to 'hcid/adapter.c')
-rw-r--r--hcid/adapter.c243
1 files changed, 50 insertions, 193 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);