diff options
Diffstat (limited to 'hcid/dbus.c')
-rw-r--r-- | hcid/dbus.c | 189 |
1 files changed, 92 insertions, 97 deletions
diff --git a/hcid/dbus.c b/hcid/dbus.c index b9525ae1..f58697e2 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -108,16 +108,14 @@ void disc_device_info_free(void *data, void *user_data) } } -void bonding_request_info_free(void *data, void *user_data) +void bonding_request_free(struct bonding_request_info *dev ) { - struct bonding_request_info *dev = data; - if (dev) { free(dev->bdaddr); - if (dev->req_msg) - dbus_message_unref(dev->req_msg); - if (dev->cancel_msg) - dbus_message_unref(dev->cancel_msg); + if (dev->rq) + dbus_message_unref(dev->rq); + if (dev->cancel) + dbus_message_unref(dev->cancel); free(dev); } } @@ -132,18 +130,7 @@ static void active_conn_info_free(void *data, void *user_data) } } -int bonding_requests_find(const void *data, const void *user_data) -{ - const struct bonding_request_info *dev = data; - const bdaddr_t *bdaddr = user_data; - - if (memcmp(dev->bdaddr, bdaddr, sizeof(*bdaddr)) == 0) - return 0; - - return -1; -} - -int disc_device_find_by_bdaddr(const void *data, const void *user_data) +static int disc_device_find_by_bdaddr(const void *data, const void *user_data) { const struct discovered_dev_info *dev = data; const bdaddr_t *bdaddr = user_data; @@ -212,6 +199,17 @@ static int disc_device_remove(struct slist **list, bdaddr_t *bdaddr) return ret_val; } +int active_conn_find_by_bdaddr(const void *data, const void *user_data) +{ + const struct active_conn_info *con = data; + const bdaddr_t *bdaddr = user_data; + + if (memcmp(con->bdaddr, bdaddr, sizeof(*bdaddr)) == 0) + return 0; + + return -1; +} + static int active_conn_find_by_handle(const void *data, const void *user_data) { const struct active_conn_info *dev = data; @@ -442,10 +440,9 @@ static gboolean unregister_dbus_path(const char *path) pdata->disc_devices = NULL; } - if (pdata->bonding_requests) { - slist_foreach(pdata->bonding_requests, bonding_request_info_free, NULL); - slist_free(pdata->bonding_requests); - pdata->bonding_requests = NULL; + if (pdata->bonding) { + bonding_request_free(pdata->bonding); + pdata->bonding = NULL; } if (pdata->active_conn) { @@ -632,8 +629,6 @@ void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const u struct hci_dbus_data *pdata; DBusMessage *msg_reply = NULL; DBusMessage *msg_signal = NULL; - struct bonding_request_info *dev = NULL; - struct slist *l; char *local_addr, *peer_addr; const char *name; bdaddr_t tmp; @@ -681,23 +676,36 @@ void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const u goto failed; } - l = slist_find(pdata->bonding_requests, peer, bonding_requests_find); - - if (!l) - goto failed; - - dev = l->data; + if (!pdata->bonding) + goto failed; /* skip: no bonding req pending */ - msg_reply = dbus_msg_new_authentication_return(dev->req_msg, status); + msg_reply = dbus_msg_new_authentication_return(pdata->bonding->rq, status); if (dbus_connection_send(connection, msg_reply, NULL) == FALSE) { error("Can't send D-Bus reply for create bonding request"); goto failed; } /* FIXME: disconnect if required */ + if (pdata->bonding->disconnect) { + struct slist *l; + + l = slist_find(pdata->active_conn, peer, active_conn_find_by_bdaddr); + if (l) { + struct active_conn_info *con = l->data; + int dd = hci_open_dev(pdata->dev_id); + /* Send the HCI disconnect command */ + if (hci_disconnect(dd, con->handle, HCI_OE_USER_ENDED_CONNECTION, 100) < 0) { + error("Disconnect failed"); + } + hci_close_dev(dd); + } + } + + bonding_request_free(pdata->bonding); + pdata->bonding = NULL; - pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev); - bonding_request_info_free(dev, NULL); + free(pdata->requestor_name); + pdata->requestor_name = NULL; failed: if (msg_signal) @@ -720,10 +728,8 @@ void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr) char path[MAX_PATH_LENGTH]; bdaddr_t tmp; ret_param_conn_cancel *ret = ptr + sizeof(evt_cmd_complete); - struct bonding_request_info *dev = NULL; DBusMessage *reply; char *local_addr, *peer_addr; - struct slist *l; struct hci_dbus_data *pdata; int id; @@ -742,24 +748,20 @@ void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr) goto failed; } - l = slist_find(pdata->bonding_requests, &ret->bdaddr, bonding_requests_find); - - if (!l) + if (!pdata->bonding) goto failed; - dev = l->data; - + if (memcmp(pdata->bonding->bdaddr, &ret->bdaddr, sizeof(bdaddr_t))) + goto failed; + if (!ret->status) { - reply = dbus_message_new_method_return(dev->cancel_msg); + reply = dbus_message_new_method_return(pdata->bonding->cancel); send_reply_and_unref(connection, reply); } else - error_failed(connection, dev->cancel_msg, bt_error(ret->status)); + error_failed(connection, pdata->bonding->cancel, bt_error(ret->status)); - dbus_message_unref(dev->cancel_msg); - dev->cancel_msg = NULL; - /* Don't remove from the list. It will be necessary - * to return the reply for create bonding request - */ + dbus_message_unref(pdata->bonding->cancel); + pdata->bonding->cancel = NULL; failed: bt_free(local_addr); @@ -768,6 +770,7 @@ failed: void hcid_dbus_inquiry_start(bdaddr_t *local) { + struct hci_dbus_data *pdata; DBusMessage *message = NULL; char path[MAX_PATH_LENGTH]; char *local_addr; @@ -784,6 +787,9 @@ void hcid_dbus_inquiry_start(bdaddr_t *local) snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); + if (dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) + pdata->discover_state = STATE_DISCOVER; + message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "DiscoveryStarted"); if (message == NULL) { @@ -919,12 +925,14 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local) snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); if (dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { - if (!disc_device_req_name(pdata)) { - pdata->discover_state = RESOLVING_NAMES; - goto failed; /* skip - there is name to resolve */ - } - pdata->discover_state = DISCOVER_OFF; + if (pdata->discover_type == RESOLVE_NAMES) { + if (!disc_device_req_name(pdata)) { + pdata->discover_state = STATE_RESOLVING_NAMES; + goto failed; /* skip - there is name to resolve */ + } + } + pdata->discover_state = STATE_IDLE; /* free discovered devices list */ slist_foreach(pdata->disc_devices, disc_device_info_free, NULL); @@ -1063,26 +1071,13 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i free(name); name_status = NAME_SENT; - - /* - * Add in the discovered devices list to avoid - * multiple remote name update signals - */ - switch (pdata->discover_state) { - case DISCOVER_RUNNING_WITH_NAMES: - case DISCOVER_RUNNING: - disc_device_append(&pdata->disc_devices, peer, name_status); - break; - default: /* ignore */ - break; - } + } + /* queue only results triggered by D-Bus clients */ + if (pdata->requestor_name) + disc_device_append(&pdata->disc_devices, peer, name_status); - } else { - /* check if the remote name needs be requested */ - if (pdata->discover_state == DISCOVER_RUNNING_WITH_NAMES) - disc_device_append(&pdata->disc_devices, peer, name_status); - } + disc_device_append(&pdata->disc_devices, peer, name_status); failed: if (signal_device) @@ -1133,12 +1128,14 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char if (!disc_device_req_name(pdata)) goto failed; /* skip if a new request has been sent */ + pdata->discover_state = STATE_IDLE; + /* free discovered devices list */ slist_foreach(pdata->disc_devices, disc_device_info_free, NULL); slist_free(pdata->disc_devices); pdata->disc_devices = NULL; - if (pdata->discover_state != DISCOVER_OFF) { + if (pdata->discover_type == RESOLVE_NAMES) { message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "DiscoveryCompleted"); @@ -1148,8 +1145,6 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char free(pdata->requestor_name); pdata->requestor_name = NULL; } - - pdata->discover_state = DISCOVER_OFF; } failed: @@ -1165,8 +1160,6 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b evt_cmd_status rp; auth_requested_cp cp; struct hci_dbus_data *pdata = NULL; - const struct slist *l; - struct bonding_request_info *dev = NULL; char *local_addr, *peer_addr; bdaddr_t tmp; int dd = -1, id; @@ -1177,14 +1170,14 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b id = hci_devid(local_addr); if (id < 0) { error("No matching device id for %s", local_addr); - goto failed; + goto done; } snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { error("Getting %s path data failed!", path); - goto failed; + goto done; } if (!status) { @@ -1202,21 +1195,21 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b } /* check if this connection request was requested by a bonding procedure */ - l = slist_find(pdata->bonding_requests, peer, bonding_requests_find); - if (!l) - goto failed; + if (!pdata->bonding) + goto done; /* skip */ - dev = l->data; + if (memcmp(pdata->bonding->bdaddr, peer, sizeof(bdaddr_t))) + goto done; /* skip */ if (status) { - error_connection_attempt_failed(connection, dev->req_msg, bt_error(status)); - goto failed; + error_connection_attempt_failed(connection, pdata->bonding->rq, bt_error(status)); + goto bonding_failed; } dd = hci_open_dev(pdata->dev_id); if (dd < 0) { - error_no_such_adapter(connection, dev->req_msg); - goto failed; + error_no_such_adapter(connection, pdata->bonding->rq); + goto bonding_failed; } /* request authentication */ @@ -1237,22 +1230,24 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b if (hci_send_req(dd, &rq, 100) < 0) { error("Unable to send the HCI request: %s (%d)", strerror(errno), errno); - error_failed(connection, dev->req_msg, errno); - goto failed; + error_failed(connection, pdata->bonding->rq, errno); + goto bonding_failed; } if (rp.status) { error("Failed with status 0x%02x", rp.status); - error_failed(connection, dev->req_msg, bt_error(rp.status)); - goto failed; - } - goto done; -failed: - /* remove from the list if the HCI pairing request was not sent */ - if (dev) { - pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev); - bonding_request_info_free(dev, NULL); + error_failed(connection, pdata->bonding->rq, bt_error(rp.status)); + goto bonding_failed; } + + goto done; /* skip: authentication requested */ + +bonding_failed: + /* free bonding request if the HCI pairing request was not sent */ + bonding_request_free(pdata->bonding); + pdata->bonding = NULL; + free(pdata->requestor_name); + pdata->requestor_name = NULL; done: hci_close_dev(dd); |