diff options
author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-23 21:03:31 +0000 |
---|---|---|
committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-23 21:03:31 +0000 |
commit | 923976d833265decd9a3dd2b3aa7fca7c843c93a (patch) | |
tree | 38bf2e1fb11fe3b8389c3670f068ab6940c32f36 | |
parent | b7fb0f9b9054c138a82e0843a8c82f550c6922eb (diff) |
Removed create bonding queue, disconnect after the bonding finishes and code cleanup
-rw-r--r-- | hcid/dbus-adapter.c | 251 | ||||
-rw-r--r-- | hcid/dbus.c | 189 | ||||
-rw-r--r-- | hcid/dbus.h | 31 |
3 files changed, 217 insertions, 254 deletions
diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index e3484c88..ad1d12c1 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -112,35 +112,21 @@ static int check_address(const char *addr) return 0; } -int active_conn_find_by_bdaddr(const void *data, const void *user_data) +static struct bonding_request_info *bonding_request_new(bdaddr_t *peer) { - 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 bonding_requests_append(struct slist **list, bdaddr_t *bdaddr, DBusMessage *msg, int disconnect) -{ - struct bonding_request_info *dev; - - dev = malloc(sizeof(*dev)); + struct bonding_request_info *bonding; + + bonding = malloc(sizeof(*bonding)); - if (!dev) - return -1; + if (!bonding) + return NULL; - memset(dev, 0, sizeof(*dev)); - dev->bdaddr = malloc(sizeof(*dev->bdaddr)); - bacpy(dev->bdaddr, bdaddr); - dev->req_msg = msg; - dev->disconnect = disconnect; + memset(bonding, 0, sizeof(*bonding)); - *list = slist_append(*list, dev); + bonding->bdaddr = malloc(sizeof(*bonding->bdaddr)); + bacpy(bonding->bdaddr, peer); - return 0; + return bonding; } static DBusHandlerResult handle_dev_get_address_req(DBusConnection *conn, DBusMessage *msg, void *data) @@ -974,9 +960,14 @@ static DBusHandlerResult handle_dev_get_remote_name_req(DBusConnection *conn, DB str2ba(peer_addr, &peer_bdaddr); disc_device_append(&dbus_data->disc_devices, &peer_bdaddr, NAME_PENDING); - /* check if there is a discover process running */ - if (dbus_data->discover_state == DISCOVER_OFF) - disc_device_req_name(dbus_data); + /* + * if there is a discover process running, just queue the request. + * Otherwise, send the HCI cmd to get the remote name + */ + if (dbus_data->discover_state == STATE_IDLE) { + if (!disc_device_req_name(dbus_data)) + dbus_data->discover_state = STATE_RESOLVING_NAMES; + } return error_request_deferred(conn, msg); } @@ -1232,8 +1223,7 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu char *peer_addr = NULL; char *str; struct hci_dbus_data *dbus_data = data; - struct slist *lbon; - struct slist *lconn; + struct slist *l; bdaddr_t peer_bdaddr; int dd, ecode, disconnect; @@ -1254,12 +1244,11 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu str2ba(peer_addr, &peer_bdaddr); /* check if there is a pending bonding request */ - lbon = slist_find(dbus_data->bonding_requests, &peer_bdaddr, bonding_requests_find); - - if (lbon) + if (dbus_data->bonding) return error_bonding_in_progress(conn, msg); - if (dbus_data->requestor_name) + /* check if there is a pending discover */ + if (dbus_data->discover_state != STATE_IDLE || dbus_data->requestor_name) return error_discover_in_progress(conn, msg); ecode = get_device_address(dbus_data->dev_id, local_addr, sizeof(local_addr)); @@ -1296,9 +1285,9 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu rq.rlen = EVT_CMD_STATUS_SIZE; /* check if there is an active connection */ - lconn = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr); + l = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr); - if (!lconn) { + if (!l) { memset(&cc_cp, 0, sizeof(cc_cp)); /* create a new connection */ bacpy(&cc_cp.bdaddr, &peer_bdaddr); @@ -1312,12 +1301,11 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu rq.clen = CREATE_CONN_CP_SIZE; disconnect = 1; } else { - struct active_conn_info *dev = lconn->data; + struct active_conn_info *dev = l->data; + memset(&ar_cp, 0, sizeof(ar_cp)); - /* active connection found */ ar_cp.handle = dev->handle; - rq.ocf = OCF_AUTH_REQUESTED; rq.cparam = &ar_cp; rq.clen = AUTH_REQUESTED_CP_SIZE; @@ -1337,9 +1325,11 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu return error_failed(conn, msg, bt_error(rp.status)); } - /* add in the bonding requests list */ - bonding_requests_append(&dbus_data->bonding_requests, &peer_bdaddr, - dbus_message_ref(msg), disconnect); + dbus_data->bonding = bonding_request_new(&peer_bdaddr); + dbus_data->bonding->disconnect = disconnect; + dbus_data->bonding->rq = dbus_message_ref(msg); + + dbus_data->requestor_name = strdup(dbus_message_get_sender(msg)); hci_close_dev(dd); @@ -1349,14 +1339,8 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBusMessage *msg, void *data) { struct hci_dbus_data *dbus_data = data; - struct bonding_request_info *dev; - struct slist *lconn; - struct slist *lbon; + struct slist *l; DBusMessage *reply = NULL; - struct hci_request rq; - create_conn_cancel_cp cc_cp; - disconnect_cp dc_cp; - evt_cmd_status rp; DBusError err; bdaddr_t peer_bdaddr; const char *peer_addr; @@ -1376,43 +1360,60 @@ static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBu if (check_address(peer_addr) < 0) return error_invalid_arguments(conn, msg); - /* FIXME: check authorization */ - str2ba(peer_addr, &peer_bdaddr); /* check if there is a pending bonding request */ - lbon = slist_find(dbus_data->bonding_requests, &peer_bdaddr, bonding_requests_find); - - if (!lbon) { + if ((!dbus_data->bonding) || + (memcmp(dbus_data->bonding->bdaddr, &peer_bdaddr, sizeof(bdaddr_t)))) { error("No bonding request pending."); return error_unknown_address(conn, msg); } - lconn = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr); - - dev = lbon->data; + if (strcmp(dbus_data->requestor_name, dbus_message_get_sender(msg))) + return error_not_authorized(conn, msg); dd = hci_open_dev(dbus_data->dev_id); if (dd < 0) return error_no_such_adapter(conn, msg); - memset(&rq, 0, sizeof(rq)); - rq.ogf = OGF_LINK_CTL; - rq.rparam = &rp; - rq.rlen = EVT_CMD_STATUS_SIZE; - rq.event = EVT_CMD_STATUS; + l = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr); - if (!lconn) { + if (!l) { /* connection request is pending */ - memset(&cc_cp, 0, sizeof(cc_cp)); - bacpy(&cc_cp.bdaddr, dev->bdaddr); - rq.ocf = OCF_CREATE_CONN_CANCEL; - rq.cparam = &cc_cp; - rq.clen = CREATE_CONN_CANCEL_CP_SIZE; + struct hci_request rq; + create_conn_cancel_cp cp; + evt_cmd_status rp; - dev->cancel_msg = dbus_message_ref(msg); + memset(&rq, 0, sizeof(rq)); + memset(&cp, 0, sizeof(cp)); + memset(&rp, 0, sizeof(rp)); + + bacpy(&cp.bdaddr, dbus_data->bonding->bdaddr); + + rq.ogf = OGF_LINK_CTL; + rq.ocf = OCF_CREATE_CONN_CANCEL; + rq.rparam = &rp; + rq.rlen = EVT_CMD_STATUS_SIZE; + rq.event = EVT_CMD_STATUS; + rq.cparam = &cp; + rq.clen = CREATE_CONN_CANCEL_CP_SIZE; + + if (hci_send_req(dd, &rq, 100) < 0) { + error("Cancel bonding - unable to send the HCI request: %s (%d)", + strerror(errno), errno); + hci_close_dev(dd); + return error_failed(conn, msg, errno); + } + + if (rp.status) { + error("Cancel bonding - Failed with status 0x%02x", rp.status); + hci_close_dev(dd); + return error_failed(conn, msg, bt_error(rp.status)); + } + + dbus_data->bonding->cancel = dbus_message_ref(msg); } else { - struct active_conn_info *cinfo = lconn->data; + struct active_conn_info *cinfo = l->data; /* FIXME: if waiting remote PIN, which HCI cmd must be sent? */ /* reply to cancel bonding */ @@ -1420,36 +1421,16 @@ static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBu send_reply_and_unref(conn, reply); /* Reply to the create bonding request */ - error_authentication_canceled(conn, dev->req_msg); - - dbus_data->bonding_requests = slist_remove(dbus_data->bonding_requests, dev); - bonding_request_info_free(dev, NULL); + error_authentication_canceled(conn, dbus_data->bonding->rq); /* disconnect from the remote device */ + if (dbus_data->bonding->disconnect) { + if (hci_disconnect(dd, htobs(cinfo->handle), HCI_OE_USER_ENDED_CONNECTION, 1000) < 0) + error("Disconnect failed"); + } - /* FIXME: send the disconnect if the connection was created by a create - * bonding procedure only. Otherwise, keep the connection active. - */ - memset(&dc_cp, 0, sizeof(dc_cp)); - dc_cp.handle = cinfo->handle; - dc_cp.reason = 0x05; - rq.ocf = OCF_DISCONNECT; - rq.cparam = &dc_cp; - rq.clen = DISCONNECT_CP_SIZE; - } - - if (hci_send_req(dd, &rq, 100) < 0) { - - error("Cancel bonding - unable to send the HCI request: %s (%d)", - strerror(errno), errno); - hci_close_dev(dd); - return error_failed(conn, msg, errno); - } - - if (rp.status) { - error("Cancel bonding - Failed with status 0x%02x", rp.status); - hci_close_dev(dd); - return error_failed(conn, msg, bt_error(rp.status)); + bonding_request_free(dbus_data->bonding); + dbus_data->bonding = NULL; } hci_close_dev(dd); @@ -1459,13 +1440,13 @@ static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBu static DBusHandlerResult handle_dev_remove_bonding_req(DBusConnection *conn, DBusMessage *msg, void *data) { struct hci_dbus_data *dbus_data = data; + struct slist *l; DBusConnection *connection = get_dbus_connection(); DBusMessage *reply; DBusMessage *signal; DBusError err; char filename[PATH_MAX + 1]; char addr[18], *addr_ptr; - struct hci_conn_info_req *cr; bdaddr_t bdaddr; int dd; @@ -1500,29 +1481,16 @@ static DBusHandlerResult handle_dev_remove_bonding_req(DBusConnection *conn, DBu /* Delete the link key from the Bluetooth chip */ hci_delete_stored_link_key(dd, &bdaddr, 0, 1000); - /* Close active connections for the remote device */ - cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); - if (!cr) { - error("Can't allocate memory"); - hci_close_dev(dd); - return error_out_of_memory(conn, msg); - } - - bacpy(&cr->bdaddr, &bdaddr); - cr->type = ACL_LINK; - if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { - /* Ignore when there isn't active connections, return success */ - hci_close_dev(dd); - free(cr); - return send_reply_and_unref(conn, dbus_message_new_method_return(msg)); - } - - /* Send the HCI disconnect command */ - if (hci_disconnect(dd, htobs(cr->conn_info->handle), HCI_OE_USER_ENDED_CONNECTION, 1000) < 0) { - error("Disconnect failed"); - free(cr); - hci_close_dev(dd); - return error_failed(conn, msg, errno); + /* find the connection */ + l = slist_find(dbus_data->active_conn, &bdaddr, active_conn_find_by_bdaddr); + if (l) { + struct active_conn_info *con = l->data; + /* Send the HCI disconnect command */ + if (hci_disconnect(dd, htobs(con->handle), HCI_OE_USER_ENDED_CONNECTION, 1000) < 0) { + error("Disconnect failed"); + hci_close_dev(dd); + return error_failed(conn, msg, errno); + } } /* FIXME: which condition must be verified before send the signal */ @@ -1537,8 +1505,6 @@ static DBusHandlerResult handle_dev_remove_bonding_req(DBusConnection *conn, DBu reply = dbus_message_new_method_return(msg); - free(cr); - hci_close_dev(dd); return send_reply_and_unref(conn, reply); @@ -1715,7 +1681,6 @@ static DBusHandlerResult handle_dev_get_encryption_key_size_req(DBusConnection * static DBusHandlerResult handle_dev_discover_devices_req(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply = NULL; - const char *requestor_name; const char *method; inquiry_cp cp; evt_cmd_status rp; @@ -1725,15 +1690,12 @@ static DBusHandlerResult handle_dev_discover_devices_req(DBusConnection *conn, D uint32_t lap = 0x9e8b33; int dd; - if (dbus_data->requestor_name) + if (dbus_data->discover_state != STATE_IDLE) return error_discover_in_progress(conn, msg); - method = dbus_message_get_member(msg); - if (strcmp("DiscoverDevicesWithoutNameResolving", method) == 0) - dbus_data->discover_state = DISCOVER_RUNNING; - else - dbus_data->discover_state = DISCOVER_RUNNING_WITH_NAMES; - + if (dbus_data->bonding) + return error_bonding_in_progress(conn, msg); + dd = hci_open_dev(dbus_data->dev_id); if (dd < 0) return error_no_such_adapter(conn, msg); @@ -1757,7 +1719,6 @@ static DBusHandlerResult handle_dev_discover_devices_req(DBusConnection *conn, D if (hci_send_req(dd, &rq, 100) < 0) { error("Unable to start inquiry: %s (%d)", strerror(errno), errno); - dbus_data->discover_state = DISCOVER_OFF; hci_close_dev(dd); return error_failed(conn, msg, errno); } @@ -1768,8 +1729,13 @@ static DBusHandlerResult handle_dev_discover_devices_req(DBusConnection *conn, D return error_failed(conn, msg, bt_error(rp.status)); } - requestor_name = dbus_message_get_sender(msg); - dbus_data->requestor_name = strdup(requestor_name); + method = dbus_message_get_member(msg); + if (strcmp("DiscoverDevicesWithoutNameResolving", method) == 0) + dbus_data->discover_type = WITHOUT_NAME_RESOLVING; + else + dbus_data->discover_type = RESOLVE_NAMES; + + dbus_data->requestor_name = strdup(dbus_message_get_sender(msg)); reply = dbus_message_new_method_return(msg); @@ -1792,8 +1758,9 @@ static DBusHandlerResult handle_dev_cancel_discovery_req(DBusConnection *conn, D requestor_name = dbus_message_get_sender(msg); /* is there discover pending? */ - if (!dbus_data->requestor_name) - return error_not_authorized(conn, msg); + if (dbus_data->discover_state != STATE_DISCOVER && + dbus_data->discover_state != STATE_RESOLVING_NAMES) + return error_not_authorized(conn, msg); /* FIXME: find a better error name */ /* only the discover requestor can cancel the inquiry process */ if (strcmp(dbus_data->requestor_name, requestor_name)) @@ -1810,9 +1777,7 @@ static DBusHandlerResult handle_dev_cancel_discovery_req(DBusConnection *conn, D rq.rlen = sizeof(status); switch (dbus_data->discover_state) { - case DISCOVER_OFF: - goto failed; - case RESOLVING_NAMES: + case STATE_RESOLVING_NAMES: /* get the first element */ dev = (struct discovered_dev_info *) (dbus_data->disc_devices)->data; @@ -1823,8 +1788,7 @@ static DBusHandlerResult handle_dev_cancel_discovery_req(DBusConnection *conn, D rq.clen = REMOTE_NAME_REQ_CANCEL_CP_SIZE; rq.event = EVT_CMD_STATUS; break; - case DISCOVER_RUNNING: - case DISCOVER_RUNNING_WITH_NAMES: + default: /* STATE_DISCOVER */ rq.ocf = OCF_INQUIRY_CANCEL; break; } @@ -1843,13 +1807,14 @@ static DBusHandlerResult handle_dev_cancel_discovery_req(DBusConnection *conn, D return error_failed(conn, msg, bt_error(status)); } -failed: slist_foreach(dbus_data->disc_devices, disc_device_info_free, NULL); slist_free(dbus_data->disc_devices); dbus_data->disc_devices = NULL; - free(dbus_data->requestor_name); - dbus_data->requestor_name = NULL; + if (dbus_data->requestor_name) { + free(dbus_data->requestor_name); + dbus_data->requestor_name = NULL; + } reply = dbus_message_new_method_return(msg); 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); diff --git a/hcid/dbus.h b/hcid/dbus.h index c745fbee..da2d3af0 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -73,11 +73,14 @@ struct service_data { typedef int (timeout_handler_func_t) (void *data); typedef enum { - DISCOVER_OFF, - DISCOVER_RUNNING, - DISCOVER_RUNNING_WITH_NAMES, - RESOLVING_NAMES -} discover_state_t; + STATE_IDLE, + STATE_DISCOVER, + STATE_RESOLVING_NAMES +}discover_state_t; + +/* discover type */ +#define WITHOUT_NAME_RESOLVING 0 +#define RESOLVE_NAMES 1 typedef enum { NAME_PENDING, @@ -91,8 +94,8 @@ struct discovered_dev_info { struct bonding_request_info { bdaddr_t *bdaddr; - DBusMessage *req_msg; - DBusMessage *cancel_msg; + DBusMessage *rq; + DBusMessage *cancel; int disconnect; /* disconnect after finish */ }; @@ -107,12 +110,13 @@ struct hci_dbus_data { uint32_t discoverable_timeout; uint32_t timeout_hits; timeout_handler_func_t *timeout_handler; - uint8_t mode; /* scan mode */ - discover_state_t discover_state; + uint8_t mode; /* scan mode */ + discover_state_t discover_state; /* discover states */ + int discover_type; /* with/without name resolving */ struct slist *disc_devices; - char *requestor_name; /* requestor unique name */ + char *requestor_name; /* requestor unique name */ struct slist *passkey_agents; - struct slist *bonding_requests; + struct bonding_request_info *bonding; struct slist *active_conn; }; @@ -187,10 +191,9 @@ static inline DBusHandlerResult send_reply_and_unref(DBusConnection *conn, DBusM return DBUS_HANDLER_RESULT_HANDLED; } +int active_conn_find_by_bdaddr(const void *data, const void *user_data); +void bonding_request_free(struct bonding_request_info *dev); void disc_device_info_free(void *data, void *user_data); -void bonding_request_info_free(void *data, void *user_data); -int bonding_requests_find(const void *data, const void *user_data); -int disc_device_find_by_bdaddr(const void *data, const void *user_data); int disc_device_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name_status); int disc_device_req_name(struct hci_dbus_data *dbus_data); |