diff --git a/emulator/btdev.c b/emulator/btdev.c
index c53db70..839b494 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
uint8_t country_code;
uint8_t bdaddr[6];
uint8_t random_addr[6];
- uint8_t le_features[8];
+ uint8_t le_features[248];
uint8_t le_states[8];
const struct btdev_cmd *cmds;
uint16_t msft_opcode;
{}
};
+static int cmd_le_read_all_local_features(struct btdev *dev, const void *data,
+ uint8_t len)
+{
+ struct bt_hci_rsp_le_read_all_local_features rsp;
+
+ memset(&rsp, 0, sizeof(rsp));
+ rsp.status = BT_HCI_ERR_SUCCESS;
+ memcpy(rsp.features, dev->le_features, 248);
+
+ cmd_complete(dev, BT_HCI_CMD_LE_READ_ALL_LOCAL_FEATURES, &rsp,
+ sizeof(rsp));
+
+ return 0;
+}
+
+static int cmd_le_read_all_remote_features(struct btdev *dev, const void *data,
+ uint8_t len)
+{
+ const struct bt_hci_cmd_le_read_all_remote_features *cmd = data;
+ struct bt_hci_evt_le_read_all_remote_features_complete ev;
+ struct btdev_conn *conn;
+ uint8_t status = BT_HCI_ERR_SUCCESS;
+
+ conn = queue_find(dev->conns, match_handle,
+ UINT_TO_PTR(le16_to_cpu(cmd->handle)));
+ if (!conn)
+ status = BT_HCI_ERR_UNKNOWN_CONN_ID;
+
+ cmd_status(dev, status, BT_HCI_CMD_LE_READ_ALL_REMOTE_FEATURES);
+
+ if (status)
+ return 0;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.status = BT_HCI_ERR_SUCCESS;
+ ev.handle = cpu_to_le16(conn->handle);
+ ev.max_pages = 1;
+ ev.valid_pages = 1;
+ memcpy(ev.features, conn->link->dev->le_features, 248);
+
+ le_meta_event(dev, BT_HCI_EVT_LE_READ_ALL_REMOTE_FEATURES_COMPLETE, &ev,
+ sizeof(ev));
+
+ return 0;
+}
+
+#define CMD_LE_60 \
+ CMD(BT_HCI_CMD_LE_READ_ALL_LOCAL_FEATURES, \
+ cmd_le_read_all_local_features, NULL), \
+ CMD(BT_HCI_CMD_LE_READ_ALL_REMOTE_FEATURES, \
+ cmd_le_read_all_remote_features, NULL)
+
+static const struct btdev_cmd cmd_le_6_0[] = {
+ CMD_COMMON_ALL,
+ CMD_COMMON_BREDR_LE,
+ CMD_LE,
+ CMD_LE_50,
+ CMD_LE_52,
+ CMD_LE_60,
+ {}
+};
+
+static void set_le_60_commands(struct btdev *btdev)
+{
+ btdev->commands[47] |= BIT(2); /* LE Read All Local Features */
+ btdev->commands[47] |= BIT(3); /* LE Read All Remote Features */
+ btdev->cmds = cmd_le_6_0;
+}
+
static void set_le_commands(struct btdev *btdev)
{
set_common_commands_all(btdev);
set_le_52_commands(btdev);
btdev->cmds = cmd_le_5_2;
}
+
+ /* Extra LE commands for >= 6.0 adapters */
+ if (btdev->type >= BTDEV_TYPE_BREDRLE52) {
+ set_le_60_commands(btdev);
+ btdev->cmds = cmd_le_6_0;
+ }
}
static int cmd_set_event_mask_2(struct btdev *dev, const void *data,
}
if (btdev->type >= BTDEV_TYPE_BREDRLE52) {
+ btdev->version = 0x0b;
btdev->le_features[1] |= 0x20; /* LE PER ADV */
btdev->le_features[3] |= BIT(0); /* LE PAST Sender */
btdev->le_features[3] |= BIT(1); /* LE PAST Receiver */
btdev->le_features[4] |= 0x01; /* LE ISO channels */
}
+ if (btdev->type >= BTDEV_TYPE_BREDRLE60) {
+ btdev->version = 0x0e;
+ btdev->le_features[7] |= BIT(7); /* LL Extended Features */
+ }
+
btdev->feat_page_2[0] |= 0x01; /* CPB - Central Operation */
btdev->feat_page_2[0] |= 0x02; /* CPB - Peripheral Operation */
btdev->feat_page_2[0] |= 0x04; /* Synchronization Train */
memset(btdev, 0, sizeof(*btdev));
- if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE ||
- type == BTDEV_TYPE_BREDRLE50 ||
- type == BTDEV_TYPE_BREDRLE52) {
+ switch (type) {
+ case BTDEV_TYPE_BREDRLE:
+ case BTDEV_TYPE_LE:
+ case BTDEV_TYPE_BREDRLE50:
+ case BTDEV_TYPE_BREDRLE52:
+ case BTDEV_TYPE_BREDRLE60:
btdev->crypto = bt_crypto_new();
if (!btdev->crypto) {
free(btdev);
return NULL;
}
+ break;
+ case BTDEV_TYPE_BREDR:
+ case BTDEV_TYPE_BREDR20:
+ case BTDEV_TYPE_AMP:
+ default:
+ break;
}
btdev->type = type;
case BTDEV_TYPE_BREDRLE:
case BTDEV_TYPE_BREDRLE50:
case BTDEV_TYPE_BREDRLE52:
+ case BTDEV_TYPE_BREDRLE60:
btdev->version = 0x09;
set_bredrle_features(btdev);
set_bredrle_commands(btdev);
case BTDEV_TYPE_BREDRLE:
case BTDEV_TYPE_BREDRLE50:
case BTDEV_TYPE_BREDRLE52:
+ case BTDEV_TYPE_BREDRLE60:
btdev->msft_opcode = opcode;
btdev->msft_cmds = cmd_msft;
return 0;
case BTDEV_TYPE_BREDRLE:
case BTDEV_TYPE_BREDRLE50:
case BTDEV_TYPE_BREDRLE52:
+ case BTDEV_TYPE_BREDRLE60:
btdev->emu_opcode = opcode;
btdev->emu_cmds = cmd_emu;
return 0;
diff --git a/emulator/btdev.h b/emulator/btdev.h
index c7b3b46..d473bd4 100644
--- a/emulator/btdev.h
+++ b/emulator/btdev.h
BTDEV_TYPE_BREDR20,
BTDEV_TYPE_BREDRLE50,
BTDEV_TYPE_BREDRLE52,
+ BTDEV_TYPE_BREDRLE60,
};
enum btdev_hook_type {
diff --git a/emulator/hciemu.c b/emulator/hciemu.c
index 3521e99..8c73a07 100644
--- a/emulator/hciemu.c
+++ b/emulator/hciemu.c
case HCIEMU_TYPE_BREDRLE52:
hciemu->btdev_type = BTDEV_TYPE_BREDRLE52;
break;
+ case HCIEMU_TYPE_BREDRLE60:
+ hciemu->btdev_type = BTDEV_TYPE_BREDRLE60;
+ break;
default:
return NULL;
}
diff --git a/emulator/hciemu.h b/emulator/hciemu.h
index 9fbe343..1164be6 100644
--- a/emulator/hciemu.h
+++ b/emulator/hciemu.h
HCIEMU_TYPE_LEGACY,
HCIEMU_TYPE_BREDRLE50,
HCIEMU_TYPE_BREDRLE52,
+ HCIEMU_TYPE_BREDRLE60,
};
enum hciemu_hook_type {
diff --git a/emulator/main.c b/emulator/main.c
index bdc2f0d..456fcd9 100644
--- a/emulator/main.c
+++ b/emulator/main.c
bool serial_enabled = false;
int letest_count = 0;
int vhci_count = 0;
- enum btdev_type type = BTDEV_TYPE_BREDRLE52;
+ enum btdev_type type = BTDEV_TYPE_BREDRLE60;
int i;
mainloop_init();