diff options
-rw-r--r-- | hcid/dbus-adapter.c | 35 | ||||
-rw-r--r-- | hcid/dbus.c | 72 |
2 files changed, 70 insertions, 37 deletions
diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index 75232a7b..07583d77 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -1793,7 +1793,6 @@ static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBu { struct hci_dbus_data *dbus_data = data; struct slist *l; - DBusMessage *reply = NULL; DBusError err; bdaddr_t peer_bdaddr; const char *peer_addr; @@ -1831,6 +1830,8 @@ 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); + l = slist_find(dbus_data->active_conn, &peer_bdaddr, active_conn_find_by_bdaddr); if (!l) { @@ -1866,29 +1867,31 @@ static DBusHandlerResult handle_dev_cancel_bonding_req(DBusConnection *conn, DBu return error_failed(conn, msg, bt_error(rp.status)); } - dbus_data->bonding->cancel = dbus_message_ref(msg); + /* + * if the HCI doesn't support cancel create connection cmd let + * the create connection complete event arrives with page timeout. + * Bonding in progress will be returned to requestors. + */ + } else { struct active_conn_info *cinfo = l->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, dbus_data->bonding->rq); - name_listener_remove(conn, dbus_message_get_sender(dbus_data->bonding->rq), - (name_cb_t) create_bond_req_exit, dbus_data); + /* for unlock PIN Code Request */ + hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &peer_bdaddr); - /* disconnect from the remote device */ + /* + * 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_OE_USER_ENDED_CONNECTION, 1000) < 0) + if (hci_disconnect(dd, htobs(cinfo->handle), HCI_AUTHENTICATION_FAILURE, 1000) < 0) error("Disconnect failed"); } - bonding_request_free(dbus_data->bonding); - dbus_data->bonding = NULL; + /* + * If disconnect can't be applied and the PIN Code Request + * was already replied let the Controller's timer to expire + */ } hci_close_dev(dd); diff --git a/hcid/dbus.c b/hcid/dbus.c index c9aca3c5..f356f6ba 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -232,6 +232,7 @@ static DBusMessage *dbus_msg_new_authentication_return(DBusMessage *msg, uint8_t return dbus_message_new_error(msg, ERROR_INTERFACE".RepeatedAttemps", "Repeated Attempts"); + case 0x06: case 0x18: /* pairing not allowed (e.g. gw rejected attempt) */ return dbus_message_new_error(msg, ERROR_INTERFACE".AuthenticationRejected", "Authentication Rejected"); @@ -245,7 +246,6 @@ static DBusMessage *dbus_msg_new_authentication_return(DBusMessage *msg, uint8_t "Authentication Canceled"); case 0x05: /* authentication failure */ - case 0x06: /* pin missing */ case 0x0E: /* rejected due to security reasons - is this auth failure? */ case 0x25: /* encryption mode not acceptable - is this auth failure? */ case 0x26: /* link key cannot be changed - is this auth failure? */ @@ -795,8 +795,19 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const u } } - message = dbus_msg_new_authentication_return(pdata->bonding->rq, status); - send_reply_and_unref(connection, message); + 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); + } name_listener_remove(connection, dbus_message_get_sender(pdata->bonding->rq), (name_cb_t) create_bond_req_exit, pdata); @@ -839,20 +850,15 @@ void hcid_dbus_create_conn_cancel(bdaddr_t *local, void *ptr) goto failed; } - if (!pdata->bonding) + if (!pdata->bonding || !pdata->bonding->cancel || + bacmp(&pdata->bonding->bdaddr, &ret->bdaddr)) goto failed; - if (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)); - - dbus_message_unref(pdata->bonding->cancel); - pdata->bonding->cancel = NULL; + error_failed(connection, pdata->bonding->cancel, bt_error(ret->status)); failed: bt_free(local_addr); @@ -1285,20 +1291,35 @@ 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 */ - if (!pdata->bonding) + if (!pdata->bonding || bacmp(&pdata->bonding->bdaddr, peer)) goto done; /* skip */ - if (bacmp(&pdata->bonding->bdaddr, peer)) - goto done; /* skip */ + dd = hci_open_dev(pdata->dev_id); + if (dd < 0) { + error_no_such_adapter(connection, pdata->bonding->rq); + goto bonding_failed; + } + + 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); + + /* + * When the controller doesn't support cancel create connection, + * disconnect the if the connection has been completed later. + */ + if (!status) + hci_disconnect(dd, htobs(handle), HCI_AUTHENTICATION_FAILURE, 1000); - if (status) { - 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, pdata->bonding->rq); + if (status) { + error_connection_attempt_failed(connection, pdata->bonding->rq, bt_error(status)); goto bonding_failed; } @@ -1404,9 +1425,18 @@ 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); - message = dbus_msg_new_authentication_return(pdata->bonding->rq, HCI_AUTHENTICATION_FAILURE); - 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); + } name_listener_remove(connection, dbus_message_get_sender(pdata->bonding->rq), (name_cb_t) create_bond_req_exit, pdata); |