diff --git a/emulator/btdev.c b/emulator/btdev.c
index e34be71..f4ed94d 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
struct btdev *conn;
+ uint8_t link_key[16];
+
btdev_command_func command_handler;
void *command_data;
#define MAX_BTDEV_ENTRIES 16
+static const uint8_t LINK_KEY_NONE[16] = { 0 };
+
static struct btdev *btdev_list[MAX_BTDEV_ENTRIES] = { };
static int get_hook_index(struct btdev *btdev, enum btdev_hook_type type,
btdev->commands[0] |= 0x80; /* Cancel Create Connection */
btdev->commands[1] |= 0x01; /* Accept Connection Request */
btdev->commands[1] |= 0x02; /* Reject Connection Request */
+ btdev->commands[1] |= 0x04; /* Link Key Request Reply */
btdev->commands[1] |= 0x08; /* Link Key Request Negative Reply */
btdev->commands[1] |= 0x20; /* PIN Code Request Negative Reply */
btdev->commands[1] |= 0x80; /* Authentication Requested */
send_event(remote, BT_HCI_EVT_DISCONNECT_COMPLETE, &dc, sizeof(dc));
}
+static void link_key_req_reply_complete(struct btdev *btdev,
+ const uint8_t *bdaddr,
+ const uint8_t *link_key)
+{
+ struct btdev *remote = btdev->conn;
+ struct bt_hci_evt_auth_complete ev;
+
+ memcpy(btdev->link_key, link_key, 16);
+
+ if (!remote)
+ return;
+
+ if (!memcmp(remote->link_key, LINK_KEY_NONE, 16)) {
+ send_event(remote, BT_HCI_EVT_LINK_KEY_REQUEST,
+ btdev->bdaddr, 6);
+ return;
+ }
+
+ ev.handle = cpu_to_le16(42);
+
+ if (!memcmp(btdev->link_key, remote->link_key, 16))
+ ev.status = BT_HCI_ERR_SUCCESS;
+ else
+ ev.status = BT_HCI_ERR_AUTH_FAILURE;
+
+ send_event(btdev, BT_HCI_EVT_AUTH_COMPLETE, &ev, sizeof(ev));
+ send_event(remote, BT_HCI_EVT_AUTH_COMPLETE, &ev, sizeof(ev));
+}
+
static void link_key_req_neg_reply_complete(struct btdev *btdev,
const uint8_t *bdaddr)
{
}
send_event(btdev, BT_HCI_EVT_LINK_KEY_REQUEST, remote->bdaddr, 6);
- send_event(remote, BT_HCI_EVT_LINK_KEY_REQUEST, btdev->bdaddr, 6);
}
static void name_request_complete(struct btdev *btdev,
struct bt_hci_rsp_le_rand lr;
struct bt_hci_rsp_le_test_end lte;
struct bt_hci_rsp_remote_name_request_cancel rnrc_rsp;
+ struct bt_hci_rsp_link_key_request_reply lkrr_rsp;
struct bt_hci_rsp_link_key_request_neg_reply lkrnr_rsp;
struct bt_hci_rsp_pin_code_request_neg_reply pcrnr_rsp;
uint8_t status, page;
cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode);
break;
+ case BT_HCI_CMD_LINK_KEY_REQUEST_REPLY:
+ if (btdev->type == BTDEV_TYPE_LE)
+ goto unsupported;
+ lkrr_rsp.status = BT_HCI_ERR_SUCCESS;
+ memcpy(lkrr_rsp.bdaddr, data, 6);
+ cmd_complete(btdev, opcode, &lkrr_rsp, sizeof(lkrr_rsp));
+ break;
+
case BT_HCI_CMD_LINK_KEY_REQUEST_NEG_REPLY:
if (btdev->type == BTDEV_TYPE_LE)
goto unsupported;
const struct bt_hci_cmd_accept_conn_request *acr;
const struct bt_hci_cmd_reject_conn_request *rcr;
const struct bt_hci_cmd_auth_requested *ar;
+ const struct bt_hci_cmd_link_key_request_reply *lkrr;
const struct bt_hci_cmd_link_key_request_neg_reply *lkrnr;
const struct bt_hci_cmd_pin_code_request_neg_reply *pcrnr;
const struct bt_hci_cmd_remote_name_request *rnr;
conn_complete(btdev, rcr->bdaddr, BT_HCI_ERR_UNKNOWN_CONN_ID);
break;
+ case BT_HCI_CMD_LINK_KEY_REQUEST_REPLY:
+ if (btdev->type == BTDEV_TYPE_LE)
+ return;
+ lkrr = data;
+ link_key_req_reply_complete(btdev, lkrr->bdaddr, lkrr->link_key);
+ break;
+
case BT_HCI_CMD_LINK_KEY_REQUEST_NEG_REPLY:
if (btdev->type == BTDEV_TYPE_LE)
return;