From 10dcd5fa6f6978b1ea76f370e87dc3f14e46ac0c Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 25 Aug 2006 14:03:52 +0000 Subject: Reduced CancelBonding reply time --- hcid/dbus-adapter.c | 57 ++++++++++++++++--------- hcid/dbus.c | 120 +++++++++++++++++++++++----------------------------- hcid/dbus.h | 11 ++++- hcid/hcid.h | 2 +- hcid/security.c | 8 ++-- 5 files changed, 106 insertions(+), 92 deletions(-) (limited to 'hcid') diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index 07583d77..749dad6f 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -1792,7 +1792,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 slist *l; + struct slist *la; + DBusMessage *reply; DBusError err; bdaddr_t peer_bdaddr; const char *peer_addr; @@ -1830,11 +1831,11 @@ static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBu if (dd < 0) return error_no_such_adapter(conn, msg); - dbus_data->bonding->cancel = dbus_message_ref(msg); + dbus_data->bonding->cancel = 1; - l = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr); + la = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr); - if (!l) { + if (!la) { /* connection request is pending */ struct hci_request rq; create_conn_cancel_cp cp; @@ -1874,26 +1875,44 @@ static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBu */ } else { - struct active_conn_info *cinfo = l->data; - - /* for unlock PIN Code Request */ - hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &peer_bdaddr); + struct slist *lb; + struct active_conn_info *cinfo = la->data; /* - * Disconnect from the remote device for safety, maybe the - * Controller already received the reply for PIN Code Request - */ - if (dbus_data->bonding->disconnect) { - if (hci_disconnect(dd, htobs(cinfo->handle), HCI_AUTHENTICATION_FAILURE, 1000) < 0) - error("Disconnect failed"); + * It is already connected, search in the pending passkey requests to + * figure out the current stage(waiting host passkey/remote passkey) + */ + lb = slist_find(dbus_data->pending_bondings, &peer_bdaddr, pending_bonding_cmp); + if (lb) { + struct pending_bonding_info *pb = lb->data; + /* 0: waiting host passkey 1: waiting remote passkey */ + if (pb->step) { + if (dbus_data->bonding->disconnect) { + + /* disconnect and let disconnect handler reply create bonding */ + if (hci_disconnect(dd, htobs(cinfo->handle), HCI_AUTHENTICATION_FAILURE, 1000) < 0) + error("Disconnect failed"); + } else { + /* + * If disconnect can't be applied and the PIN Code Request + * was already replied it doesn't make sense cancel the + * remote passkey: return not authorized. + */ + + error_not_authorized(conn, msg); + goto failed; + } + } else { + + /* for unlock PIN Code Request */ + hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &peer_bdaddr); + } } - - /* - * If disconnect can't be applied and the PIN Code Request - * was already replied let the Controller's timer to expire - */ } + reply = dbus_message_new_method_return(msg); + send_reply_and_unref(conn, reply); +failed: hci_close_dev(dd); return DBUS_HANDLER_RESULT_HANDLED; diff --git a/hcid/dbus.c b/hcid/dbus.c index f356f6ba..fc778757 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -77,8 +77,6 @@ void bonding_request_free(struct bonding_request_info *dev ) if (dev) { if (dev->rq) dbus_message_unref(dev->rq); - if (dev->cancel) - dbus_message_unref(dev->cancel); free(dev); } } @@ -675,16 +673,19 @@ int hcid_dbus_stop_device(uint16_t id) return 0; } -static int pending_bonding_cmp(const void *p1, const void *p2) +int pending_bonding_cmp(const void *p1, const void *p2) { - return p2 ? bacmp(p1, p2) : -1; + const struct pending_bonding_info *pb1 = p1; + const struct pending_bonding_info *pb2 = p2; + + return p2 ? bacmp(&pb1->bdaddr, &pb2->bdaddr) : -1; } void hcid_dbus_pending_bonding_add(bdaddr_t *sba, bdaddr_t *dba) { char path[MAX_PATH_LENGTH], addr[18]; struct hci_dbus_data *pdata; - bdaddr_t *peer; + struct pending_bonding_info *peer; ba2str(sba, addr); @@ -695,8 +696,10 @@ void hcid_dbus_pending_bonding_add(bdaddr_t *sba, bdaddr_t *dba) return; } - peer = malloc(sizeof(bdaddr_t)); - bacpy(peer, dba); + peer = malloc(sizeof(*peer)); + memset(peer, 0, sizeof(*peer)); + + bacpy(&peer->bdaddr, dba); pdata->pending_bondings = slist_append(pdata->pending_bondings, peer); } @@ -796,14 +799,9 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const u } if (pdata->bonding->cancel) { - /* reply the cancel bonding */ - message = dbus_message_new_method_return(pdata->bonding->cancel); - send_reply_and_unref(connection, message); - /* reply authentication canceled */ error_authentication_canceled(connection, pdata->bonding->rq); } else { - /* reply authentication success or an error */ message = dbus_msg_new_authentication_return(pdata->bonding->rq, status); send_reply_and_unref(connection, message); @@ -820,51 +818,6 @@ 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); - DBusMessage *reply; - char *local_addr, *peer_addr; - 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", BASE_PATH, id); - if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { - error("Getting %s path data failed!", path); - goto failed; - } - - if (!pdata->bonding || !pdata->bonding->cancel || - bacmp(&pdata->bonding->bdaddr, &ret->bdaddr)) - goto failed; - - if (!ret->status) { - reply = dbus_message_new_method_return(pdata->bonding->cancel); - send_reply_and_unref(connection, reply); - } else - error_failed(connection, pdata->bonding->cancel, bt_error(ret->status)); - -failed: - bt_free(local_addr); - bt_free(peer_addr); -} - void hcid_dbus_inquiry_start(bdaddr_t *local) { struct hci_dbus_data *pdata; @@ -1301,11 +1254,6 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, b } if (pdata->bonding->cancel) { - /* - * reply to cancel bonding was done in the cancel create connection - * handler or in the beginning if the controller doesn't support - * cancel cmd. Reply authentication canceled only. - */ error_authentication_canceled(connection, pdata->bonding->rq); /* @@ -1426,14 +1374,9 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle send_reply_and_unref(connection, message); #endif if (pdata->bonding->cancel) { - /* reply the cancel bonding */ - message = dbus_message_new_method_return(pdata->bonding->cancel); - send_reply_and_unref(connection, message); - /* reply authentication canceled */ error_authentication_canceled(connection, pdata->bonding->rq); } else { - message = dbus_msg_new_authentication_return(pdata->bonding->rq, HCI_AUTHENTICATION_FAILURE); send_reply_and_unref(connection, message); } @@ -2007,6 +1950,49 @@ failed: bt_free(local_addr); } +void hcid_dbus_pin_code_reply(bdaddr_t *local, void *ptr) +{ + + typedef struct { + uint8_t status; + bdaddr_t bdaddr; + } __attribute__ ((packed)) ret_pin_code_req_reply; + + struct hci_dbus_data *pdata; + char *local_addr; + ret_pin_code_req_reply *ret = ptr + sizeof(evt_cmd_complete); + struct slist *l; + char path[MAX_PATH_LENGTH]; + bdaddr_t tmp; + int id; + + baswap(&tmp, local); local_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", BASE_PATH, id); + + if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { + error("Getting %s path data failed!", path); + goto failed; + } + + if (!pdata->pending_bondings) + goto failed; + + l = slist_find(pdata->pending_bondings, &ret->bdaddr, pending_bonding_cmp); + if (l) { + struct pending_bonding_info *p = l->data; + p->step = 1; + } + +failed: + bt_free(local_addr); +} + void create_bond_req_exit(const char *name, struct hci_dbus_data *pdata) { char path[MAX_PATH_LENGTH]; diff --git a/hcid/dbus.h b/hcid/dbus.h index 0e0e95bb..90d7b325 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -86,10 +86,16 @@ struct discovered_dev_info { struct bonding_request_info { bdaddr_t bdaddr; DBusMessage *rq; - DBusMessage *cancel; + int cancel; int disconnect; /* disconnect after finish */ }; +struct pending_bonding_info { + bdaddr_t bdaddr; + int step; /* 0: waiting host passkey 1:waiting remote passkey */ + +}; + struct active_conn_info { bdaddr_t bdaddr; uint16_t handle; @@ -109,7 +115,7 @@ struct hci_dbus_data { struct slist *passkey_agents; struct bonding_request_info *bonding; struct slist *active_conn; - struct slist *pending_bondings; + struct slist *pending_bondings; /* track D-Bus and non D-Bus requests */ }; struct passkey_agent { @@ -214,6 +220,7 @@ static inline DBusHandlerResult send_reply_and_unref(DBusConnection *conn, DBusM int active_conn_find_by_bdaddr(const void *data, const void *user_data); void bonding_request_free(struct bonding_request_info *dev); +int pending_bonding_cmp(const void *p1, const void *p2); int disc_device_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name_status, int discover_type); int disc_device_req_name(struct hci_dbus_data *dbus_data); diff --git a/hcid/hcid.h b/hcid/hcid.h index c7208222..7eb231f9 100644 --- a/hcid/hcid.h +++ b/hcid/hcid.h @@ -159,9 +159,9 @@ 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_process_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); +void hcid_dbus_pin_code_reply(bdaddr_t *local, void *ptr); void init_devices(void); int add_device(uint16_t dev_id); diff --git a/hcid/security.c b/hcid/security.c index 98c00ca8..b5eca651 100644 --- a/hcid/security.c +++ b/hcid/security.c @@ -431,15 +431,17 @@ 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; case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE): hcid_dbus_setscan_enable_complete(sba); break; + case cmd_opcode_pack(OGF_LINK_CTL, OCF_PIN_CODE_REPLY): + case cmd_opcode_pack(OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY): + hcid_dbus_pin_code_reply(sba, ptr); + break; + }; } -- cgit