diff --git a/emulator/btdev.c b/emulator/btdev.c index 9642e8668..ad65cf899 100644 --- a/emulator/btdev.c +++ b/emulator/btdev.c @@ -533,6 +533,8 @@ static void set_le_features(struct btdev *btdev) btdev->features[4] |= 0x40; /* LE Supported */ btdev->max_page = 1; + + btdev->le_features[0] |= 0x01; /* LE Encryption */ } static void set_amp_features(struct btdev *btdev) @@ -1764,6 +1766,30 @@ static void le_set_scan_enable_complete(struct btdev *btdev) } } +static void le_read_remote_features_complete(struct btdev *btdev) +{ + char buf[1 + sizeof(struct bt_hci_evt_le_remote_features_complete)]; + struct bt_hci_evt_le_remote_features_complete *ev = (void *) &buf[1]; + struct btdev *remote = btdev->conn; + + if (!remote) { + cmd_status(btdev, BT_HCI_ERR_UNKNOWN_CONN_ID, + BT_HCI_CMD_LE_READ_REMOTE_FEATURES); + return; + } + + cmd_status(btdev, BT_HCI_ERR_SUCCESS, + BT_HCI_CMD_LE_READ_REMOTE_FEATURES); + + memset(buf, 0, sizeof(buf)); + buf[0] = BT_HCI_EVT_LE_REMOTE_FEATURES_COMPLETE; + ev->status = BT_HCI_ERR_SUCCESS; + ev->handle = cpu_to_le16(42); + memcpy(ev->features, remote->le_features, 8); + + send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf)); +} + static void le_start_encrypt_complete(struct btdev *btdev) { char buf[1 + sizeof(struct bt_hci_evt_le_long_term_key_request)]; @@ -2870,6 +2896,12 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode, cmd_complete(btdev, opcode, &lr, sizeof(lr)); break; + case BT_HCI_CMD_LE_READ_REMOTE_FEATURES: + if (btdev->type == BTDEV_TYPE_BREDR) + goto unsupported; + le_read_remote_features_complete(btdev); + break; + case BT_HCI_CMD_LE_START_ENCRYPT: if (btdev->type == BTDEV_TYPE_BREDR) goto unsupported; diff --git a/emulator/bthost.c b/emulator/bthost.c index 73cf9ac70..2b48ad8f6 100644 --- a/emulator/bthost.c +++ b/emulator/bthost.c @@ -1173,6 +1173,18 @@ static void evt_le_conn_update_complete(struct bthost *bthost, const void *data, return; } +static void evt_le_remote_features_complete(struct bthost *bthost, + const void *data, uint8_t len) +{ + const struct bt_hci_evt_le_remote_features_complete *ev = data; + + if (len < sizeof(*ev)) + return; + + if (ev->status) + return; +} + static void evt_le_ltk_request(struct bthost *bthost, const void *data, uint8_t len) { @@ -1222,6 +1234,9 @@ static void evt_le_meta_event(struct bthost *bthost, const void *data, case BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE: evt_le_conn_update_complete(bthost, evt_data, len - 1); break; + case BT_HCI_EVT_LE_REMOTE_FEATURES_COMPLETE: + evt_le_remote_features_complete(bthost, evt_data, len - 1); + break; case BT_HCI_EVT_LE_LONG_TERM_KEY_REQUEST: evt_le_ltk_request(bthost, evt_data, len - 1); break;