diff options
author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-22 20:34:29 +0000 |
---|---|---|
committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-22 20:34:29 +0000 |
commit | 2fb80f9451af2993dfbd350ce272c7b106312553 (patch) | |
tree | ba33aba2693cf4ccf941c22976d5bf7760921f1c /hcid | |
parent | b2b1d151eae38ccaf0e326ca382158c5d1f58ffb (diff) |
Added cancel bonding and fixed minor issues of create bonding
Diffstat (limited to 'hcid')
-rw-r--r-- | hcid/dbus-adapter.c | 230 | ||||
-rw-r--r-- | hcid/dbus-error.c | 6 | ||||
-rw-r--r-- | hcid/dbus.c | 150 | ||||
-rw-r--r-- | hcid/dbus.h | 12 | ||||
-rw-r--r-- | hcid/hcid.h | 2 | ||||
-rw-r--r-- | hcid/security.c | 3 |
6 files changed, 284 insertions, 119 deletions
diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index 3c2e9c5c..2f242d74 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -74,7 +74,7 @@ static const char *phone_minor_cls[] = { "isdn" }; -static int is_valid_address(const char *addr) +static int check_address(const char *addr) { char tmp[18]; char *ptr = tmp; @@ -87,7 +87,7 @@ static int is_valid_address(const char *addr) memcpy(tmp, addr, 18); - while (ptr) { + while (*ptr) { *ptr = toupper(*ptr); if (*ptr < '0'|| (*ptr > '9' && *ptr < 'A') || *ptr > 'F') @@ -111,28 +111,6 @@ static int is_valid_address(const char *addr) return 0; } -int find_connection_handle(int dd, bdaddr_t *peer) -{ - struct hci_conn_info_req *cr; - int handle = -1; - - cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); - if (!cr) - return -1; - - bacpy(&cr->bdaddr, peer); - cr->type = ACL_LINK; - - if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { - free(cr); - return -1; - } - - handle = cr->conn_info->handle; - free(cr); - - return handle; -} int active_conn_find_by_bdaddr(const void *data, const void *user_data) { @@ -145,18 +123,20 @@ int active_conn_find_by_bdaddr(const void *data, const void *user_data) return -1; } -static int bonding_requests_append(struct slist **list, bdaddr_t *bdaddr, DBusMessage *msg, bonding_state_t bonding_state) +static int bonding_requests_append(struct slist **list, bdaddr_t *bdaddr, DBusMessage *msg, int disconnect) { struct bonding_request_info *dev; dev = malloc(sizeof(*dev)); + if (!dev) return -1; + memset(dev, 0, sizeof(*dev)); dev->bdaddr = malloc(sizeof(*dev->bdaddr)); bacpy(dev->bdaddr, bdaddr); - dev->msg = msg; - dev->bonding_state = bonding_state; + dev->req_msg = msg; + dev->disconnect = disconnect; *list = slist_append(*list, dev); @@ -480,7 +460,7 @@ static DBusHandlerResult handle_dev_is_connected_req(DBusConnection *conn, DBusM return error_invalid_arguments(conn, msg); } - if (is_valid_address(peer_addr) < 0) + if (check_address(peer_addr) < 0) return error_invalid_arguments(conn, msg); str2ba(peer_addr, &peer_bdaddr); @@ -953,7 +933,7 @@ static DBusHandlerResult handle_dev_get_remote_name_req(DBusConnection *conn, DB return error_invalid_arguments(conn, msg); } - if (is_valid_address(peer_addr) < 0) + if (check_address(peer_addr) < 0) return error_invalid_arguments(conn, msg); ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr)); @@ -1021,7 +1001,7 @@ static DBusHandlerResult handle_dev_get_remote_alias_req(DBusConnection *conn, D return error_invalid_arguments(conn, msg); } - if (is_valid_address(addr_ptr) < 0) + if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg); str2ba(addr_ptr, &bdaddr); @@ -1062,7 +1042,7 @@ static DBusHandlerResult handle_dev_set_remote_alias_req(DBusConnection *conn, D return error_invalid_arguments(conn, msg); } - if ((strlen(str_ptr) == 0) || (is_valid_address(addr_ptr) < 0)) { + if ((strlen(str_ptr) == 0) || (check_address(addr_ptr) < 0)) { error("Alias change failed: Invalid parameter"); return error_invalid_arguments(conn, msg); } @@ -1110,7 +1090,7 @@ static DBusHandlerResult handle_dev_last_seen_req(DBusConnection *conn, DBusMess return error_invalid_arguments(conn, msg); } - if (is_valid_address(addr_ptr) < 0) + if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg); ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr)); @@ -1157,7 +1137,7 @@ static DBusHandlerResult handle_dev_last_used_req(DBusConnection *conn, DBusMess return error_invalid_arguments(conn, msg); } - if (is_valid_address(addr_ptr) < 0) + if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg); ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr)); @@ -1190,15 +1170,17 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu char filename[PATH_MAX + 1]; char local_addr[18]; struct hci_request rq; + create_conn_cp cc_cp; + auth_requested_cp ar_cp; evt_cmd_status rp; DBusError err; char *peer_addr = NULL; char *str; struct hci_dbus_data *dbus_data = data; - struct slist *l; + struct slist *lbon; + struct slist *lconn; bdaddr_t peer_bdaddr; - int dd, handle, ecode; - bonding_state_t bonding_state; + int dd, ecode, disconnect; dbus_error_init(&err); dbus_message_get_args(msg, &err, @@ -1211,17 +1193,20 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu return error_invalid_arguments(conn, msg); } - if (is_valid_address(peer_addr) < 0) + if (check_address(peer_addr) < 0) return error_invalid_arguments(conn, msg); str2ba(peer_addr, &peer_bdaddr); - + /* check if there is a pending bonding request */ - l = slist_find(dbus_data->bonding_requests, &peer_bdaddr, bonding_requests_find); + lbon = slist_find(dbus_data->bonding_requests, &peer_bdaddr, bonding_requests_find); - if (l) + if (lbon) return error_bonding_in_progress(conn, msg); + if (dbus_data->requestor_name) + return error_discover_in_progress(conn, msg); + ecode = get_device_address(dbus_data->dev_id, local_addr, sizeof(local_addr)); if (ecode < 0) return error_failed(conn, msg, -ecode); @@ -1256,38 +1241,32 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu rq.rlen = EVT_CMD_STATUS_SIZE; /* check if there is an active connection */ - handle = find_connection_handle(dd, &peer_bdaddr); + lconn = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr); - if (handle < 0 ) { - create_conn_cp cp; - - memset(&cp, 0, sizeof(cp)); + if (!lconn) { + memset(&cc_cp, 0, sizeof(cc_cp)); /* create a new connection */ - bonding_state = CONNECTING; - - bacpy(&cp.bdaddr, &peer_bdaddr); - cp.pkt_type = htobs(HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5); - cp.pscan_rep_mode = 0x02; - cp.clock_offset = htobs(0x0000); - cp.role_switch = 0x01; + bacpy(&cc_cp.bdaddr, &peer_bdaddr); + cc_cp.pkt_type = htobs(HCI_DM1); + cc_cp.pscan_rep_mode = 0x02; + cc_cp.clock_offset = htobs(0x0000); + cc_cp.role_switch = 0x01; rq.ocf = OCF_CREATE_CONN; - rq.cparam = &cp; + rq.cparam = &cc_cp; rq.clen = CREATE_CONN_CP_SIZE; + disconnect = 1; } else { - /* connection found */ - auth_requested_cp cp; - - memset(&cp, 0, sizeof(cp)); + struct active_conn_info *dev = lconn->data; + memset(&ar_cp, 0, sizeof(ar_cp)); /* active connection found */ - bonding_state = PAIRING; - - cp.handle = handle; + ar_cp.handle = dev->handle; rq.ocf = OCF_AUTH_REQUESTED; - rq.cparam = &cp; + rq.cparam = &ar_cp; rq.clen = AUTH_REQUESTED_CP_SIZE; + disconnect = 0; } if (hci_send_req(dd, &rq, 100) < 0) { @@ -1304,14 +1283,124 @@ static DBusHandlerResult handle_dev_create_bonding_req(DBusConnection *conn, DBu } /* add in the bonding requests list */ - bonding_requests_append(&dbus_data->bonding_requests, &peer_bdaddr, msg, bonding_state); + bonding_requests_append(&dbus_data->bonding_requests, &peer_bdaddr, + dbus_message_ref(msg), disconnect); - dbus_message_ref(msg); hci_close_dev(dd); return DBUS_HANDLER_RESULT_HANDLED; } +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; + 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; + int dd = -1; + + dbus_error_init(&err); + dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &peer_addr, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + error("Can't extract message arguments:%s", err.message); + dbus_error_free(&err); + return error_invalid_arguments(conn, msg); + } + + 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) { + 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; + + 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; + + if (!lconn) { + /* 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; + + dev->cancel_msg = dbus_message_ref(msg); + } else { + struct active_conn_info *cinfo = lconn->data; + /* FIXME: if waiting remote PIN, which HCI cmd must be sent? */ + + /* reply to cancel bonding */ + reply = dbus_message_new_method_return(msg); + 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); + + /* disconnect from the remote device */ + + /* 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)); + } + + hci_close_dev(dd); + return DBUS_HANDLER_RESULT_HANDLED; +} + static DBusHandlerResult handle_dev_remove_bonding_req(DBusConnection *conn, DBusMessage *msg, void *data) { struct hci_dbus_data *dbus_data = data; @@ -1336,7 +1425,7 @@ static DBusHandlerResult handle_dev_remove_bonding_req(DBusConnection *conn, DBu return error_invalid_arguments(conn, msg); } - if (is_valid_address(addr_ptr) < 0) + if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg); dd = hci_open_dev(dbus_data->dev_id); @@ -1421,7 +1510,7 @@ static DBusHandlerResult handle_dev_has_bonding_req(DBusConnection *conn, DBusMe return error_invalid_arguments(conn, msg); } - if (is_valid_address(addr_ptr) < 0) + if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg); ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr)); @@ -1503,7 +1592,7 @@ static DBusHandlerResult handle_dev_get_pin_code_length_req(DBusConnection *conn return error_invalid_arguments(conn, msg); } - if (is_valid_address(addr_ptr) < 0) + if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg); ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr)); @@ -1549,7 +1638,7 @@ static DBusHandlerResult handle_dev_get_encryption_key_size_req(DBusConnection * return error_invalid_arguments(conn, msg); } - if (is_valid_address(addr_ptr) < 0) + if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg); str2ba(addr_ptr, &bdaddr); @@ -1618,6 +1707,12 @@ static DBusHandlerResult handle_dev_discover_devices_req(DBusConnection *conn, D return error_failed(conn, msg, errno); } + if (rp.status) { + error("Failed with status 0x%02x", rp.status); + hci_close_dev(dd); + return error_failed(conn, msg, bt_error(rp.status)); + } + requestor_name = dbus_message_get_sender(msg); dbus_data->requestor_name = strdup(requestor_name); @@ -1740,6 +1835,7 @@ static struct service_data dev_services[] = { { "LastUsed", handle_dev_last_used_req, }, { "CreateBonding", handle_dev_create_bonding_req, }, + { "CancelBonding", handle_dev_cancel_bonding_req }, { "RemoveBonding", handle_dev_remove_bonding_req, }, { "HasBonding", handle_dev_has_bonding_req, }, { "ListBondings", handle_dev_list_bondings_req, }, diff --git a/hcid/dbus-error.c b/hcid/dbus-error.c index 375456bd..5407da15 100644 --- a/hcid/dbus-error.c +++ b/hcid/dbus-error.c @@ -168,6 +168,12 @@ DBusHandlerResult error_bonding_in_progress(DBusConnection *conn, DBusMessage *m return error_in_progress(conn, msg, "Bonding in progress"); } +DBusHandlerResult error_authentication_canceled(DBusConnection *conn, DBusMessage *msg) +{ + return send_reply_and_unref(conn, + dbus_message_new_error(msg, ERROR_INTERFACE ".AuthenticationCanceled", + "Authentication Canceled")); +} DBusHandlerResult error_discover_in_progress(DBusConnection *conn, DBusMessage *msg) { return error_in_progress(conn, msg, "Discover in progress"); diff --git a/hcid/dbus.c b/hcid/dbus.c index 63da099a..b9525ae1 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -108,13 +108,16 @@ void disc_device_info_free(void *data, void *user_data) } } -static void bonding_request_info_free(void *data, void *user_data) +void bonding_request_info_free(void *data, void *user_data) { struct bonding_request_info *dev = data; if (dev) { free(dev->bdaddr); - dbus_message_unref(dev->msg); + if (dev->req_msg) + dbus_message_unref(dev->req_msg); + if (dev->cancel_msg) + dbus_message_unref(dev->cancel_msg); free(dev); } } @@ -181,6 +184,7 @@ int disc_device_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name if (!dev) return -1; + memset(dev, 0, sizeof(*dev)); dev->bdaddr = malloc(sizeof(*dev->bdaddr)); bacpy(dev->bdaddr, bdaddr); dev->name_status = name_status; @@ -227,6 +231,7 @@ static int active_conn_append(struct slist **list, bdaddr_t *bdaddr, uint16_t ha if (!dev) return -1; + memset(dev, 0 , sizeof(*dev)); dev->bdaddr = malloc(sizeof(*dev->bdaddr)); bacpy(dev->bdaddr, bdaddr); dev->handle = handle; @@ -504,7 +509,7 @@ gboolean hcid_dbus_register_device(uint16_t id) } if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) - error("Getting path data failed!"); + error("Getting %s path data failed!", path); else pdata->mode = rp.enable; /* Keep the current scan status */ @@ -627,6 +632,8 @@ 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; @@ -658,8 +665,8 @@ void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const u } dbus_message_append_args(msg_signal, - DBUS_TYPE_STRING, &peer_addr, - DBUS_TYPE_INVALID); + DBUS_TYPE_STRING, &peer_addr, + DBUS_TYPE_INVALID); if (dbus_connection_send(connection, msg_signal, NULL) == FALSE) { error("Can't send D-Bus bonding created signal"); @@ -669,27 +676,29 @@ void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const u dbus_connection_flush(connection); /* create the authentication reply */ - if (dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { - struct slist *l; + if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { + error("Getting %s path data failed!", path); + goto failed; + } - l = slist_find(pdata->bonding_requests, peer, bonding_requests_find); + l = slist_find(pdata->bonding_requests, peer, bonding_requests_find); - if (l) { - struct bonding_request_info *dev = l->data; + if (!l) + goto failed; - msg_reply = dbus_msg_new_authentication_return(dev->msg, status); - if (dbus_connection_send(connection, msg_reply, NULL) == FALSE) { - error("Can't send D-Bus reply for create bonding request"); - goto failed; - } + dev = l->data; - dbus_message_unref(dev->msg); - pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev); - free(dev->bdaddr); - free(dev); - } + msg_reply = dbus_msg_new_authentication_return(dev->req_msg, 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 */ + + pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev); + bonding_request_info_free(dev, NULL); + failed: if (msg_signal) dbus_message_unref(msg_signal); @@ -701,6 +710,62 @@ failed: bt_free(peer_addr); } +void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr) +{ + typedef struct { + uint8_t status; + bdaddr_t bdaddr; + }__attribute__ ((packed)) ret_param_conn_cancel; + + 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; + + baswap(&tmp, local); local_addr = batostr(&tmp); + baswap(&tmp, &ret->bdaddr); peer_addr = batostr(&tmp); + + id = hci_devid(local_addr); + if (id < 0) { + error("No matching device id for %s", local_addr); + goto failed; + } + + 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; + } + + l = slist_find(pdata->bonding_requests, &ret->bdaddr, bonding_requests_find); + + if (!l) + goto failed; + + dev = l->data; + + if (!ret->status) { + reply = dbus_message_new_method_return(dev->cancel_msg); + send_reply_and_unref(connection, reply); + } else + error_failed(connection, dev->cancel_msg, 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 + */ + +failed: + bt_free(local_addr); + bt_free(peer_addr); +} + void hcid_dbus_inquiry_start(bdaddr_t *local) { DBusMessage *message = NULL; @@ -1117,6 +1182,11 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b 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; + } + if (!status) { /* Sent the remote device connected signal */ message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteDeviceConnected"); @@ -1126,13 +1196,10 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b DBUS_TYPE_INVALID); send_reply_and_unref(connection, message); - } - - if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) - goto failed; - /* add in the active connetions list */ - active_conn_append(&pdata->active_conn, peer, handle); + /* add in the active connetions list */ + active_conn_append(&pdata->active_conn, peer, handle); + } /* check if this connection request was requested by a bonding procedure */ l = slist_find(pdata->bonding_requests, peer, bonding_requests_find); @@ -1142,16 +1209,13 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b dev = l->data; if (status) { - error_connection_attempt_failed(connection, dev->msg, bt_error(status)); + error_connection_attempt_failed(connection, dev->req_msg, bt_error(status)); goto failed; } - if (dev->bonding_state != CONNECTING) - goto failed; - dd = hci_open_dev(pdata->dev_id); if (dd < 0) { - error_no_such_adapter(connection, dev->msg); + error_no_such_adapter(connection, dev->req_msg); goto failed; } @@ -1173,29 +1237,23 @@ 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->msg, errno); + error_failed(connection, dev->req_msg, errno); goto failed; } if (rp.status) { error("Failed with status 0x%02x", rp.status); - error_failed(connection, dev->msg, bt_error(rp.status)); + error_failed(connection, dev->req_msg, bt_error(rp.status)); goto failed; } - /* request sent properly */ - dev->bonding_state = PAIRING; - + goto done; failed: /* remove from the list if the HCI pairing request was not sent */ if (dev) { - if (dev->bonding_state != PAIRING) { - dbus_message_unref(dev->msg); - pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev); - free(dev->bdaddr); - free(dev); - } + pdata->bonding_requests = slist_remove(pdata->bonding_requests, dev); + bonding_request_info_free(dev, NULL); } - +done: hci_close_dev(dd); bt_free(local_addr); @@ -1223,8 +1281,10 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); - if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) + if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { + error("Getting %s path data failed!", path); goto failed; + } l = slist_find(pdata->active_conn, &handle, active_conn_find_by_handle); @@ -1739,7 +1799,7 @@ void hcid_dbus_setscan_enable_complete(bdaddr_t *local) } if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { - error("Getting path data failed!"); + error("Getting %s path data failed!", path); goto failed; } diff --git a/hcid/dbus.h b/hcid/dbus.h index 92a673e8..c745fbee 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -89,15 +89,11 @@ struct discovered_dev_info { name_status_t name_status; }; -typedef enum { - CONNECTING, - PAIRING -} bonding_state_t; - struct bonding_request_info { bdaddr_t *bdaddr; - DBusMessage *msg; - bonding_state_t bonding_state; + DBusMessage *req_msg; + DBusMessage *cancel_msg; + int disconnect; /* disconnect after finish */ }; struct active_conn_info { @@ -155,6 +151,7 @@ DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn, DBusMess DBusHandlerResult error_bonding_already_exists(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult error_bonding_does_not_exist(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult error_bonding_in_progress(DBusConnection *conn, DBusMessage *msg); +DBusHandlerResult error_authentication_canceled(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult error_discover_in_progress(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult error_connect_in_progress(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult error_connect_not_in_progress(DBusConnection *conn, DBusMessage *msg); @@ -191,6 +188,7 @@ static inline DBusHandlerResult send_reply_and_unref(DBusConnection *conn, DBusM } 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); diff --git a/hcid/hcid.h b/hcid/hcid.h index 71389a62..80357937 100644 --- a/hcid/hcid.h +++ b/hcid/hcid.h @@ -119,6 +119,7 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, bdaddr_t *peer); void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, uint8_t reason); void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status); +void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr); void hcid_dbus_setname_complete(bdaddr_t *local); void hcid_dbus_setscan_enable_complete(bdaddr_t *local); #else @@ -129,6 +130,7 @@ static inline void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_ static inline void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, bdaddr_t *peer) {} static inline void hcid_dbus_disconn_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t reason) {} static inline void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status) {} +static inline void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr) {} static inline void hcid_dbus_setname_complete(bdaddr_t *local) {} static inline void hcid_dbus_setscan_enable_complete(bdaddr_t *local) {} #endif diff --git a/hcid/security.c b/hcid/security.c index ba1fb0a1..8946b1c5 100644 --- a/hcid/security.c +++ b/hcid/security.c @@ -312,6 +312,9 @@ static inline void cmd_complete(int dev, bdaddr_t *sba, void *ptr) case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL): hcid_dbus_inquiry_complete(sba); break; + case cmd_opcode_pack(OGF_LINK_CTL, OCF_CREATE_CONN_CANCEL): + hcid_dbus_create_conn_cancel(sba, ptr); + break; case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME): hcid_dbus_setname_complete(sba); break; |