* [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands
@ 2020-01-28 20:13 Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 2/6] monitor: Add decoding of ISO related Link Layer PDUs Luiz Augusto von Dentz
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2020-01-28 20:13 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds parsing of ISO related commands.
---
monitor/bt.h | 307 ++++++++++++++++++++++
monitor/packet.c | 661 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 968 insertions(+)
diff --git a/monitor/bt.h b/monitor/bt.h
index b31e6c5c5..48901d7cd 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -24,6 +24,10 @@
#include <stdint.h>
+#define BT_HCI_CMD_5_2 0x2060
+#define BT_HCI_BIT_5_2 (8 * 41) + 5
+#define BT_HCI_SUBEVT_5_2 0x19
+
struct bt_ll_hdr {
uint8_t preamble;
uint32_t access_addr;
@@ -443,6 +447,7 @@ struct bt_lmp_power_control_res {
#define BT_H4_ACL_PKT 0x02
#define BT_H4_SCO_PKT 0x03
#define BT_H4_EVT_PKT 0x04
+#define BT_H4_ISO_PKT 0x05
struct bt_hci_cmd_hdr {
uint16_t opcode;
@@ -459,6 +464,16 @@ struct bt_hci_sco_hdr {
uint8_t dlen;
} __attribute__ ((packed));
+struct bt_hci_iso_hdr {
+ uint16_t handle;
+ uint8_t dlen;
+} __attribute__ ((packed));
+
+struct bt_hci_iso_data_start {
+ uint16_t sn;
+ uint16_t slen;
+} __attribute__ ((packed));
+
struct bt_hci_evt_hdr {
uint8_t evt;
uint8_t plen;
@@ -2498,6 +2513,231 @@ struct bt_hci_cmd_default_periodic_adv_sync_trans_params {
uint8_t cte_type;
} __attribute__ ((packed));
+#define BT_HCI_CMD_LE_READ_BUFFER_SIZE_V2 BT_HCI_CMD_5_2
+#define BT_HCI_BIT_LE_READ_BUFFER_SIZE_V2 BT_HCI_BIT_5_2
+struct bt_hci_rsp_le_read_buffer_size_v2 {
+ uint8_t status;
+ uint16_t acl_mtu;
+ uint8_t acl_max_pkt;
+ uint16_t iso_mtu;
+ uint8_t iso_max_pkt;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_READ_ISO_TX_SYNC BT_HCI_CMD_5_2 + 1
+#define BT_HCI_BIT_LE_READ_ISO_TX_SYNC BT_HCI_BIT_5_2 + 1
+struct bt_hci_cmd_le_read_iso_tx_sync {
+ uint16_t handle;
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_read_iso_tx_sync {
+ uint8_t status;
+ uint16_t handle;
+ uint16_t seq;
+ uint32_t timestamp;
+ uint8_t offset[3];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_CIG_PARAMS BT_HCI_CMD_5_2 + 2
+#define BT_HCI_BIT_LE_SET_CIG_PARAMS BT_HCI_BIT_5_2 + 2
+struct bt_hci_cis_params {
+ uint8_t cis_id;
+ uint16_t m_sdu;
+ uint16_t s_sdu;
+ uint8_t m_phy;
+ uint8_t s_phy;
+ uint8_t m_rtn;
+ uint8_t s_rtn;
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_set_cig_params {
+ uint8_t cig_id;
+ uint8_t m_interval[3];
+ uint8_t s_interval[3];
+ uint8_t sca;
+ uint8_t packing;
+ uint8_t framing;
+ uint16_t m_latency;
+ uint16_t s_latency;
+ uint8_t num_cis;
+ struct bt_hci_cis_params cis[0];
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_set_cig_params {
+ uint8_t status;
+ uint8_t cig_id;
+ uint8_t num_handles;
+ uint16_t handle[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_CIG_PARAMS_TEST BT_HCI_CMD_5_2 + 3
+#define BT_HCI_BIT_LE_SET_CIG_PARAMS_TEST BT_HCI_BIT_5_2 + 3
+struct bt_hci_cis_params_test {
+ uint8_t cis_id;
+ uint8_t nse;
+ uint16_t m_sdu;
+ uint16_t s_sdu;
+ uint8_t m_pdu;
+ uint8_t s_pdu;
+ uint8_t m_phy;
+ uint8_t s_phy;
+ uint8_t m_bn;
+ uint8_t s_bn;
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_set_cig_params_test {
+ uint8_t cig_id;
+ uint8_t m_interval[3];
+ uint8_t s_interval[3];
+ uint8_t m_ft;
+ uint8_t s_ft;
+ uint16_t iso_interval;
+ uint8_t sca;
+ uint8_t packing;
+ uint8_t framing;
+ uint8_t num_cis;
+ struct bt_hci_cis_params_test cis[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_CREATE_CIS BT_HCI_CMD_5_2 + 4
+#define BT_HCI_BIT_LE_CREATE_CIS BT_HCI_BIT_5_2 + 4
+struct bt_hci_cis {
+ uint16_t cis_handle;
+ uint16_t acl_handle;
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_create_cis {
+ uint8_t num_cis;
+ struct bt_hci_cis cis[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_REMOVE_CIG BT_HCI_CMD_5_2 + 5
+#define BT_HCI_BIT_LE_REMOVE_CIG BT_HCI_BIT_5_2 + 5
+struct bt_hci_cmd_le_remove_cig {
+ uint8_t cig_id;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_ACCEPT_CIS BT_HCI_CMD_5_2 + 6
+#define BT_HCI_BIT_LE_ACCEPT_CIS BT_HCI_BIT_5_2 + 6
+struct bt_hci_cmd_le_accept_cis {
+ uint16_t handle;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_REJECT_CIS BT_HCI_CMD_5_2 + 7
+#define BT_HCI_BIT_LE_REJECT_CIS BT_HCI_BIT_5_2 + 7
+struct bt_hci_cmd_le_reject_cis {
+ uint16_t handle;
+ uint8_t reason;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_CREATE_BIG BT_HCI_CMD_5_2 + 8
+#define BT_HCI_BIT_LE_CREATE_BIG BT_HCI_BIT_5_2 + 8
+struct bt_hci_bis {
+ uint8_t sdu_interval[3];
+ uint16_t sdu;
+ uint16_t latency;
+ uint8_t rtn;
+ uint8_t phy;
+ uint8_t packing;
+ uint8_t framing;
+ uint8_t encryption;
+ uint8_t bcode[16];
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_create_big {
+ uint8_t big_id;
+ uint8_t adv_handle;
+ uint8_t num_bis;
+ struct bt_hci_bis bis[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_CREATE_BIG_TEST BT_HCI_CMD_5_2 + 9
+#define BT_HCI_BIT_LE_CREATE_BIG_TEST BT_HCI_BIT_5_2 + 9
+struct bt_hci_bis_test {
+ uint8_t sdu_interval[3];
+ uint16_t iso_interval;
+ uint8_t nse;
+ uint16_t sdu;
+ uint8_t pdu;
+ uint8_t phy;
+ uint8_t packing;
+ uint8_t framing;
+ uint8_t bn;
+ uint8_t irc;
+ uint8_t pto;
+ uint8_t adv_handle;
+ uint8_t encryption;
+ uint8_t bcode[16];
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_create_big_test {
+ uint8_t big_id;
+ uint8_t adv_handle;
+ uint8_t num_bis;
+ struct bt_hci_bis_test bis[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_TERM_BIG BT_HCI_CMD_5_2 + 10
+#define BT_HCI_BIT_LE_TERM_BIG BT_HCI_BIT_5_2 + 10
+struct bt_hci_cmd_le_term_big {
+ uint8_t big_id;
+ uint8_t reason;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_BIG_CREATE_SYNC BT_HCI_CMD_5_2 + 11
+#define BT_HCI_BIT_LE_BIG_CREATE_SYNC BT_HCI_BIT_5_2 + 11
+struct bt_hci_bis_sync {
+} __attribute__ ((packed));
+
+struct bt_hci_cmd_le_big_create_sync {
+ uint8_t big_id;
+ uint16_t sync_handle;
+ uint8_t num_bis;
+ uint8_t encryption;
+ uint8_t bcode[16];
+ uint8_t mse;
+ uint16_t timeout;
+ struct bt_hci_bis_sync bis[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_BIG_TERM_SYNC BT_HCI_CMD_5_2 + 12
+#define BT_HCI_BIT_LE_BIG_TERM_SYNC BT_HCI_BIT_5_2 + 12
+struct bt_hci_cmd_le_big_term_sync {
+ uint8_t big_id;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_REQ_PEER_SCA BT_HCI_CMD_5_2 + 13
+#define BT_HCI_BIT_LE_REQ_PEER_SCA BT_HCI_BIT_5_2 + 13
+struct bt_hci_cmd_le_req_peer_sca {
+ uint16_t handle;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SETUP_ISO_PATH BT_HCI_CMD_5_2 + 14
+#define BT_HCI_BIT_LE_SETUP_ISO_PATH BT_HCI_BIT_5_2 + 14
+struct bt_hci_cmd_le_setup_iso_path {
+ uint16_t handle;
+ uint8_t input_path;
+ uint8_t output_path;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_REMOVE_ISO_PATH BT_HCI_CMD_5_2 + 15
+#define BT_HCI_BIT_LE_REMOVE_ISO_PATH BT_HCI_BIT_5_2 + 15
+struct bt_hci_cmd_le_remove_iso_path {
+ uint16_t handle;
+ uint8_t path_dir;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_ISO_TX_TEST BT_HCI_CMD_5_2 + 16
+#define BT_HCI_BIT_LE_ISO_TX_TEST BT_HCI_BIT_5_2 + 16
+
+#define BT_HCI_CMD_LE_ISO_RX_TEST BT_HCI_CMD_5_2 + 17
+#define BT_HCI_BIT_LE_ISO_RX_TEST BT_HCI_BIT_5_2 + 17
+
+#define BT_HCI_CMD_LE_ISO_READ_TEST_COUNTER BT_HCI_CMD_5_2 + 18
+#define BT_HCI_BIT_LE_ISO_READ_TEST_COUNTER BT_HCI_BIT_5_2 + 18
+
+#define BT_HCI_CMD_LE_ISO_TEST_END BT_HCI_CMD_5_2 + 19
+#define BT_HCI_BIT_LE_ISO_TEST_END BT_HCI_BIT_5_2 + 19
+
#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
struct bt_hci_evt_inquiry_complete {
uint8_t status;
@@ -3197,6 +3437,73 @@ struct bt_hci_evt_le_per_adv_sync_trans_rec {
uint8_t clock_accuracy;
} __attribute__ ((packed));
+#define BT_HCI_EVT_LE_CIS_ESTABLISHED BT_HCI_SUBEVT_5_2
+struct bt_hci_evt_le_cis_established {
+ uint8_t status;
+ uint16_t conn_handle;
+ uint8_t cig_sync_delay[3];
+ uint8_t cis_sync_delay[3];
+ uint8_t m_latency[3];
+ uint8_t s_latency[3];
+ uint8_t m_phy;
+ uint8_t s_phy;
+ uint8_t nse;
+ uint8_t m_bn;
+ uint8_t s_bn;
+ uint8_t m_ft;
+ uint8_t s_ft;
+ uint16_t m_mtu;
+ uint16_t s_mtu;
+ uint16_t interval;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_CIS_REQ BT_HCI_SUBEVT_5_2 + 1
+struct bt_hci_evt_le_cis_req {
+ uint16_t acl_handle;
+ uint16_t cis_handle;
+ uint8_t cig_id;
+ uint8_t cis_id;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_BIG_COMPLETE BT_HCI_SUBEVT_5_2 + 2
+struct bt_hci_evt_le_big_complete {
+ uint8_t status;
+ uint8_t big_id;
+ uint8_t sync_delay[3];
+ uint8_t latency[3];
+ uint8_t phy;
+ uint8_t num_bis;
+ uint16_t handle[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_BIG_TERMINATE BT_HCI_SUBEVT_5_2 + 3
+struct bt_hci_evt_le_big_terminate {
+ uint8_t reason;
+ uint8_t big_id;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_BIG_SYNC_ESTABILISHED BT_HCI_SUBEVT_5_2 + 4
+struct bt_hci_evt_le_big_sync_estabilished {
+ uint8_t status;
+ uint8_t big_id;
+ uint8_t latency[3];
+ uint8_t num_bis;
+ uint16_t handle[0];
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_BIG_SYNC_LOST BT_HCI_SUBEVT_5_2 + 5
+struct bt_hci_evt_le_big_sync_lost {
+ uint8_t big_id;
+ uint8_t reason;
+} __attribute__ ((packed));
+
+#define BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE BT_HCI_SUBEVT_5_2 + 6
+struct bt_hci_evt_le_req_peer_sca_complete {
+ uint8_t status;
+ uint16_t handle;
+ uint8_t sca;
+} __attribute__ ((packed));
+
#define BT_HCI_ERR_SUCCESS 0x00
#define BT_HCI_ERR_UNKNOWN_COMMAND 0x01
#define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02
diff --git a/monitor/packet.c b/monitor/packet.c
index 6e7cc5e85..007887181 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -2617,6 +2617,11 @@ static const struct bitfield_data features_le[] = {
{ 25, "Periodic Advertising Sync Transfer - Recipient" },
{ 26, "Sleep Clock Accuracy Updates" },
{ 27, "Remote Public Key Validation" },
+ { 28, "Connected Isochronous Stream - Master" },
+ { 29, "Connected Isochronous Stream - Slave" },
+ { 30, "Isochronous Broadcaster" },
+ { 31, "Synchronized Receiver" },
+ { 32, "Isochronous Channels (Host Support)" },
{ }
};
@@ -2977,6 +2982,12 @@ static const struct bitfield_data events_le_table[] = {
{ 17, "LE Extended Advertising Set Terminated" },
{ 18, "LE Scan Request Received" },
{ 19, "LE Channel Selection Algorithm" },
+ { 24, "LE CIS Established" },
+ { 25, "LE CIS Request" },
+ { 26, "LE Create BIG Complete" },
+ { 27, "LE Terminate BIG Complete" },
+ { 28, "LE BIG Sync Estabilished Complete" },
+ { 29, "LE BIG Sync Lost" },
{ }
};
@@ -7666,6 +7677,437 @@ static void le_set_default_periodic_adv_sync_trans_params(const void *data,
print_create_sync_cte_type(cmd->cte_type);
}
+static void print_sca(uint8_t sca)
+{
+ switch (sca) {
+ case 0x00:
+ print_field("SCA: 201 - 500 ppm (0x%2.2x)", sca);
+ return;
+ case 0x01:
+ print_field("SCA: 151 - 200 ppm (0x%2.2x)", sca);
+ return;
+ case 0x02:
+ print_field("SCA: 101 - 150 ppm (0x%2.2x)", sca);
+ return;
+ case 0x03:
+ print_field("SCA: 76 - 100 ppm (0x%2.2x)", sca);
+ return;
+ case 0x04:
+ print_field("SCA: 51 - 75 ppm (0x%2.2x)", sca);
+ return;
+ case 0x05:
+ print_field("SCA: 31 - 50 ppm (0x%2.2x)", sca);
+ return;
+ case 0x06:
+ print_field("SCA: 21 - 30 ppm (0x%2.2x)", sca);
+ return;
+ case 0x07:
+ print_field("SCA: 0 - 20 ppm (0x%2.2x)", sca);
+ return;
+ default:
+ print_field("SCA: Reserved (0x%2.2x)", sca);
+ }
+}
+
+static void print_packing(uint8_t value)
+{
+ switch (value) {
+ case 0x00:
+ print_field("Packing: Sequential (0x%2.2x)", value);
+ return;
+ case 0x01:
+ print_field("Packing: Interleaved (0x%2.2x)", value);
+ return;
+ default:
+ print_field("Packing: Reserved (0x%2.2x)", value);
+ }
+}
+
+static void print_framing(uint8_t value)
+{
+ switch (value) {
+ case 0x00:
+ print_field("Framing: Unframed (0x%2.2x)", value);
+ return;
+ case 0x01:
+ print_field("Framing: Framed (0x%2.2x)", value);
+ return;
+ default:
+ print_field("Packing: Reserved (0x%2.2x)", value);
+ }
+}
+
+static void le_read_buffer_size_v2_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_read_buffer_size_v2 *rsp = data;
+
+ print_status(rsp->status);
+
+ if (size == 1)
+ return;
+
+ print_field("ACL MTU: %d", le16_to_cpu(rsp->acl_mtu));
+ print_field("ACL max packet: %d", rsp->acl_max_pkt);
+ print_field("ISO MTU: %d", le16_to_cpu(rsp->iso_mtu));
+ print_field("ISO max packet: %d", rsp->iso_max_pkt);
+}
+
+static void le_read_iso_tx_sync_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_read_iso_tx_sync *cmd = data;
+
+ print_field("Handle: %d", le16_to_cpu(cmd->handle));
+}
+
+static void le_read_iso_tx_sync_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_read_iso_tx_sync *rsp = data;
+ uint32_t offset = 0;
+
+ print_status(rsp->status);
+
+ if (size == 1)
+ return;
+
+ print_field("Handle: %d", le16_to_cpu(rsp->handle));
+ print_field("Sequence Number: %d", le16_to_cpu(rsp->seq));
+ print_field("Timestamp: %d", le32_to_cpu(rsp->timestamp));
+
+ memcpy(&offset, rsp->offset, sizeof(rsp->offset));
+
+ print_field("Offset: %d", le32_to_cpu(offset));
+}
+
+static void print_cis_params(const void *data)
+{
+ const struct bt_hci_cis_params *cis = data;
+
+ print_field("CIS ID: 0x%2.2x", cis->cis_id);
+ print_field("Master to Slave Maximum SDU Size: %u",
+ le16_to_cpu(cis->m_sdu));
+ print_field("Slave to Master Maximum SDU Size: %u",
+ le16_to_cpu(cis->s_sdu));
+ print_le_phy("Master to Slave PHY", cis->m_phy);
+ print_le_phy("Slave to Master PHY", cis->s_phy);
+ print_field("Master to Slave Retransmission attempts: 0x%2.2x",
+ cis->m_rtn);
+ print_field("Slave to Master Retransmission attempts: 0x%2.2x",
+ cis->s_rtn);
+}
+
+static void print_list(const void *data, uint8_t size, int num_items,
+ size_t item_size, void (*callback)(const void *data))
+{
+ while (size >= item_size && num_items) {
+ callback(data);
+ data += item_size;
+ size -= item_size;
+ num_items--;
+ }
+
+ if (num_items)
+ print_hex_field("", data, size);
+}
+
+static void print_usec_interval(const char *prefix, const uint8_t interval[3])
+{
+ uint32_t u24 = 0;
+
+ memcpy(&u24, interval, 3);
+ print_field("%s: %u us (0x%6.6x)", prefix, le32_to_cpu(u24),
+ le32_to_cpu(u24));
+}
+
+static void le_set_cig_params_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_cig_params *cmd = data;
+
+ print_field("CIG ID: 0x%2.2x", cmd->cig_id);
+ print_usec_interval("Master to Slave SDU Interval", cmd->m_interval);
+ print_usec_interval("Slave to Master SDU Interval", cmd->s_interval);
+ print_sca(cmd->sca);
+ print_packing(cmd->packing);
+ print_framing(cmd->framing);
+ print_field("Master to Slave Maximum Latency: %d ms (0x%4.4x)",
+ le16_to_cpu(cmd->m_latency), le16_to_cpu(cmd->m_latency));
+ print_field("Slave to Master Maximum Latency: %d ms (0x%4.4x)",
+ le16_to_cpu(cmd->s_latency), le16_to_cpu(cmd->s_latency));
+ print_field("Number of CIS: %u", cmd->num_cis);
+
+ size -= sizeof(*cmd);
+
+ print_list(cmd->cis, size, cmd->num_cis, sizeof(*cmd->cis),
+ print_cis_params);
+}
+
+static void print_cis_params_test(const void *data)
+{
+ const struct bt_hci_cis_params_test *cis = data;
+
+ print_field("CIS ID: 0x%2.2x", cis->cis_id);
+ print_field("NSE: 0x%2.2x", cis->nse);
+ print_field("Master to Slave Maximum SDU: 0x%4.4x", cis->m_sdu);
+ print_field("Slave to Master Maximum SDU: 0x%4.4x",
+ le16_to_cpu(cis->s_sdu));
+ print_field("Master to Slave Maximum PDU: 0x%2.2x",
+ le16_to_cpu(cis->m_pdu));
+ print_field("Slave to Master Maximum PDU: 0x%2.2x", cis->s_pdu);
+ print_le_phy("Master to Slave PHY", cis->m_phy);
+ print_le_phy("Slave to Master PHY", cis->s_phy);
+ print_field("Master to Slave Burst Number: 0x%2.2x", cis->m_bn);
+ print_field("Slave to Master Burst Number: 0x%2.2x", cis->s_bn);
+}
+
+static void le_set_cig_params_test_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_cig_params_test *cmd = data;
+
+ print_field("CIG ID: 0x%2.2x", cmd->cig_id);
+ print_usec_interval("Master to Slave SDU Interval", cmd->m_interval);
+ print_usec_interval("Master to Slave SDU Interval", cmd->s_interval);
+ print_field("Master to Slave Flush Timeout: 0x%2.2x", cmd->m_ft);
+ print_field("Slave to Master Flush Timeout: 0x%2.2x", cmd->s_ft);
+ print_field("ISO Interval: %.2f ms (0x%4.4x)",
+ le16_to_cpu(cmd->iso_interval) * 1.25,
+ le16_to_cpu(cmd->iso_interval));
+ print_sca(cmd->sca);
+ print_packing(cmd->packing);
+ print_framing(cmd->framing);
+ print_field("Number of CIS: %u", cmd->num_cis);
+
+ size -= sizeof(*cmd);
+
+ print_list(cmd->cis, size, cmd->num_cis, sizeof(*cmd->cis),
+ print_cis_params_test);
+}
+
+static void print_cig_handle(const void *data)
+{
+ const uint16_t *handle = data;
+
+ print_field("Connection Handle: %d", le16_to_cpu(*handle));
+}
+
+static void le_set_cig_params_rsp(const void *data, uint8_t size)
+{
+ const struct bt_hci_rsp_le_set_cig_params *rsp = data;
+
+ print_status(rsp->status);
+
+ if (size == 1)
+ return;
+
+ print_field("CIG ID: 0x%2.2x", rsp->cig_id);
+ print_field("Number of Handles: %u", rsp->num_handles);
+
+ size -= sizeof(*rsp);
+
+ print_list(rsp->handle, size, rsp->num_handles, sizeof(*rsp->handle),
+ print_cig_handle);
+}
+
+static void print_cis(const void *data)
+{
+ const struct bt_hci_cis *cis = data;
+
+ print_field("CIS Handle: %d", cis->cis_handle);
+ print_field("ACL Handle: %d", cis->acl_handle);
+}
+
+static void le_create_cis_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_create_cis *cmd = data;
+
+ print_field("Number of CIS: %u", cmd->num_cis);
+
+ size -= sizeof(*cmd);
+
+ print_list(cmd->cis, size, cmd->num_cis, sizeof(*cmd->cis), print_cis);
+}
+
+static void le_remove_cig_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_remove_cig *cmd = data;
+
+ print_field("CIG ID: 0x%02x", cmd->cig_id);
+}
+
+static void le_accept_cis_req_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_accept_cis *cmd = data;
+
+ print_field("CIS Handle: %d", le16_to_cpu(cmd->handle));
+}
+
+static void le_reject_cis_req_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_reject_cis *cmd = data;
+
+ print_field("CIS Handle: %d", le16_to_cpu(cmd->handle));
+ print_reason(cmd->reason);
+}
+
+static void print_bis(const void *data)
+{
+ const struct bt_hci_bis *bis = data;
+
+ print_usec_interval("SDU Interval", bis->sdu_interval);
+ print_field("Maximum SDU size: %u", le16_to_cpu(bis->sdu));
+ print_field("Maximum Latency: %u ms (0x%4.4x)",
+ le16_to_cpu(bis->latency), le16_to_cpu(bis->latency));
+ print_field("RTN: 0x%2.2x", bis->rtn);
+ print_le_phy("PHY", bis->phy);
+ print_packing(bis->packing);
+ print_framing(bis->framing);
+ print_field("Encryption: 0x%2.2x", bis->encryption);
+ print_hex_field("Broadcast Code", bis->bcode, 16);
+}
+
+static void le_create_big_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_create_big *cmd = data;
+
+ print_field("BIG ID: 0x%2.2x", cmd->big_id);
+ print_field("Advertising Handle: 0x%2.2x", cmd->adv_handle);
+ print_field("Number of BIS: %u", cmd->num_bis);
+
+ size -= sizeof(*cmd);
+
+ print_list(cmd->bis, size, cmd->num_bis, sizeof(*cmd->bis), print_bis);
+}
+
+static void print_bis_test(const void *data)
+{
+ const struct bt_hci_bis_test *bis = data;
+
+ print_usec_interval("SDU Interval", bis->sdu_interval);
+ print_field("ISO Interval: %.2f ms (0x%4.4x)",
+ le16_to_cpu(bis->iso_interval) * 1.25,
+ le16_to_cpu(bis->iso_interval));
+ print_field("Number of Subevents: %u", bis->nse);
+ print_field("Maximum SDU: %u", bis->sdu);
+ print_field("Maximum PDU: %u", bis->pdu);
+ print_packing(bis->packing);
+ print_framing(bis->framing);
+ print_le_phy("PHY", bis->phy);
+ print_field("Burst Number: %u", bis->bn);
+ print_field("Immediate Repetition Count: %u", bis->irc);
+ print_field("Pre Transmission Offset: 0x%2.2x", bis->pto);
+ print_field("Encryption: 0x%2.2x", bis->encryption);
+ print_hex_field("Broadcast Code", bis->bcode, 16);
+}
+
+static void le_create_big_cmd_test_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_create_big_test *cmd = data;
+
+ print_field("BIG ID: 0x%2.2x", cmd->big_id);
+ print_field("Advertising Handle: 0x%2.2x", cmd->adv_handle);
+ print_field("Number of BIS: %u", cmd->num_bis);
+
+ size -= sizeof(*cmd);
+
+ print_list(cmd->bis, size, cmd->num_bis, sizeof(*cmd->bis),
+ print_bis_test);
+}
+
+static void le_terminate_big_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_term_big *cmd = data;
+
+ print_field("BIG ID: 0x%2.2x", cmd->big_id);
+ print_reason(cmd->reason);
+}
+
+static void print_bis_sync(const void *data)
+{
+ const uint8_t *bis_id = data;
+
+ print_field("BIS ID: 0x%2.2x", *bis_id);
+}
+
+static void le_big_create_sync_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_big_create_sync *cmd = data;
+
+ print_field("BIG ID: 0x%2.2x", cmd->big_id);
+ print_field("Number of BIS: %u", cmd->num_bis);
+ print_field("Encryption: 0x%2.2x", cmd->encryption);
+ print_hex_field("Broadcast Code", cmd->bcode, 16);
+ print_field("Number Subevents: 0x%2.2x", cmd->mse);
+ print_field("Timeout: %d ms (0x%4.4x)", le16_to_cpu(cmd->timeout) * 10,
+ le16_to_cpu(cmd->timeout));
+
+ size -= sizeof(*cmd);
+
+ print_list(cmd->bis, size, cmd->num_bis, sizeof(*cmd->bis),
+ print_bis_sync);
+}
+
+static void le_big_term_sync_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_big_term_sync *cmd = data;
+
+ print_field("BIG ID: 0x%2.2x", cmd->big_id);
+}
+
+static void print_iso_path(const char *prefix, uint8_t path)
+{
+ switch (path) {
+ case 0x00:
+ print_field("%s Data Path: Disabled (0x%2.2x)", prefix, path);
+ return;
+ case 0x01:
+ print_field("%s Data Path: HCI (0x%2.2x)", prefix, path);
+ return;
+ case 0xff:
+ print_field("%s Data Path: Test Mode (0x%2.2x)", prefix, path);
+ return;
+ default:
+ print_field("%s Data Path: Logical Channel Number (0x%2.2x)",
+ prefix, path);
+ }
+}
+
+static void le_setup_iso_path_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_setup_iso_path *cmd = data;
+
+ print_field("Handle: %d", le16_to_cpu(cmd->handle));
+ print_iso_path("Input", cmd->input_path);
+ print_iso_path("Output", cmd->output_path);
+}
+
+static void print_iso_dir(uint8_t path_dir)
+{
+ switch (path_dir) {
+ case 0x00:
+ print_field("Data Path Direction: Input (0x%2.2x)", path_dir);
+ return;
+ case 0x01:
+ print_field("Data Path Direction: Output (0x%2.2x)", path_dir);
+ return;
+ default:
+ print_field("Data Path Direction: Reserved (0x%2.2x)",
+ path_dir);
+ }
+}
+
+static void le_remove_iso_path_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_remove_iso_path *cmd = data;
+
+ print_field("Connection Handle: %d", le16_to_cpu(cmd->handle));
+ print_iso_dir(cmd->path_dir);
+}
+
+static void le_req_peer_sca_cmd(const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_req_peer_sca *cmd = data;
+
+ print_field("Connection Handle: %d", le16_to_cpu(cmd->handle));
+}
+
struct opcode_data {
uint16_t opcode;
int bit;
@@ -8475,6 +8917,107 @@ static const struct opcode_data opcode_table[] = {
"Parameters",
le_set_default_periodic_adv_sync_trans_params,
6, true, status_rsp, 1, true},
+ { BT_HCI_CMD_LE_READ_BUFFER_SIZE_V2,
+ BT_HCI_BIT_LE_READ_BUFFER_SIZE_V2,
+ "LE Read Buffer v2",
+ null_cmd, 0, true,
+ le_read_buffer_size_v2_rsp,
+ sizeof(
+ struct bt_hci_rsp_le_read_buffer_size_v2),
+ true },
+ { BT_HCI_CMD_LE_READ_ISO_TX_SYNC,
+ BT_HCI_BIT_LE_READ_ISO_TX_SYNC,
+ "LE Read ISO TX Sync",
+ le_read_iso_tx_sync_cmd,
+ sizeof(struct bt_hci_cmd_le_read_iso_tx_sync),
+ true,
+ le_read_iso_tx_sync_rsp,
+ sizeof(struct bt_hci_rsp_le_read_iso_tx_sync),
+ true },
+ { BT_HCI_CMD_LE_SET_CIG_PARAMS, BT_HCI_BIT_LE_SET_CIG_PARAMS,
+ "LE Set Connected Isochronous Group Parameters",
+ le_set_cig_params_cmd,
+ sizeof(struct bt_hci_cmd_le_set_cig_params),
+ false,
+ le_set_cig_params_rsp,
+ sizeof(struct bt_hci_rsp_le_set_cig_params),
+ false },
+ { BT_HCI_CMD_LE_SET_CIG_PARAMS_TEST, BT_HCI_BIT_LE_SET_CIG_PARAMS_TEST,
+ "LE Set Connected Isochronous Group Parameters"
+ " Test", le_set_cig_params_test_cmd,
+ sizeof(
+ struct bt_hci_cmd_le_set_cig_params_test),
+ false,
+ le_set_cig_params_rsp,
+ sizeof(struct bt_hci_rsp_le_set_cig_params),
+ false },
+ { BT_HCI_CMD_LE_CREATE_CIS, BT_HCI_BIT_LE_CREATE_CIS,
+ "LE Create Connected Isochronous Stream",
+ le_create_cis_cmd,
+ sizeof(struct bt_hci_cmd_le_create_cis),
+ false },
+ { BT_HCI_CMD_LE_REMOVE_CIG, BT_HCI_BIT_LE_REMOVE_CIG,
+ "LE Remove Connected Isochronous Group",
+ le_remove_cig_cmd,
+ sizeof(struct bt_hci_cmd_le_remove_cig), false,
+ status_rsp, 1, true },
+ { BT_HCI_CMD_LE_ACCEPT_CIS, BT_HCI_BIT_LE_ACCEPT_CIS,
+ "LE Accept Connected Isochronous Stream Request",
+ le_accept_cis_req_cmd,
+ sizeof(struct bt_hci_cmd_le_accept_cis), true },
+ { BT_HCI_CMD_LE_REJECT_CIS, BT_HCI_BIT_LE_REJECT_CIS,
+ "LE Reject Connected Isochronous Stream Request",
+ le_reject_cis_req_cmd,
+ sizeof(struct bt_hci_cmd_le_reject_cis), true,
+ status_rsp, 1, true },
+ { BT_HCI_CMD_LE_CREATE_BIG, BT_HCI_BIT_LE_CREATE_BIG,
+ "LE Create Broadcast Isochronous Group",
+ le_create_big_cmd },
+ { BT_HCI_CMD_LE_CREATE_BIG_TEST, BT_HCI_BIT_LE_CREATE_BIG_TEST,
+ "LE Create Broadcast Isochronous Group Test",
+ le_create_big_cmd_test_cmd },
+ { BT_HCI_CMD_LE_TERM_BIG, BT_HCI_BIT_LE_TERM_BIG,
+ "LE Terminate Broadcast Isochronous Group",
+ le_terminate_big_cmd,
+ sizeof(struct bt_hci_cmd_le_term_big), true,
+ status_rsp, 1, true},
+ { BT_HCI_CMD_LE_BIG_CREATE_SYNC, BT_HCI_BIT_LE_BIG_CREATE_SYNC,
+ "LE Broadcast Isochronous Group Create Sync",
+ le_big_create_sync_cmd,
+ sizeof(struct bt_hci_cmd_le_big_create_sync),
+ true },
+ { BT_HCI_CMD_LE_BIG_TERM_SYNC, BT_HCI_BIT_LE_BIG_TERM_SYNC,
+ "LE Broadcast Isochronous Group Terminate Sync",
+ le_big_term_sync_cmd,
+ sizeof(struct bt_hci_cmd_le_big_term_sync),
+ true },
+ { BT_HCI_CMD_LE_REQ_PEER_SCA, BT_HCI_BIT_LE_REQ_PEER_SCA,
+ "LE Request Peer SCA", le_req_peer_sca_cmd,
+ sizeof(struct bt_hci_cmd_le_req_peer_sca),
+ true },
+ { BT_HCI_CMD_LE_SETUP_ISO_PATH, BT_HCI_BIT_LE_SETUP_ISO_PATH,
+ "LE Setup Isochronous Data Path",
+ le_setup_iso_path_cmd,
+ sizeof(struct bt_hci_cmd_le_setup_iso_path),
+ true, status_rsp, 1, true },
+ { BT_HCI_CMD_LE_REMOVE_ISO_PATH, BT_HCI_BIT_LE_REMOVE_ISO_PATH,
+ "LE Remove Isochronous Data Path",
+ le_remove_iso_path_cmd,
+ sizeof(struct bt_hci_cmd_le_remove_iso_path),
+ true, status_rsp, 1, true },
+ { BT_HCI_CMD_LE_ISO_TX_TEST, BT_HCI_BIT_LE_ISO_TX_TEST,
+ "LE Isochronous Transmit Test", NULL, 0,
+ false },
+ { BT_HCI_CMD_LE_ISO_RX_TEST, BT_HCI_BIT_LE_ISO_RX_TEST,
+ "LE Isochronous Receive Test", NULL, 0,
+ false },
+ { BT_HCI_CMD_LE_ISO_READ_TEST_COUNTER,
+ BT_HCI_BIT_LE_ISO_READ_TEST_COUNTER,
+ "LE Isochronous Read Test Counters", NULL, 0,
+ false },
+ { BT_HCI_CMD_LE_ISO_TEST_END, BT_HCI_BIT_LE_ISO_TEST_END,
+ "LE Isochronous Read Test Counters", NULL, 0,
+ false },
{ }
};
@@ -9912,6 +10455,94 @@ static void le_per_adv_sync_trans_rec_evt(const void *data, uint8_t size)
print_clock_accuracy(evt->clock_accuracy);
}
+static void le_cis_established_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_cis_established *evt = data;
+
+ print_status(evt->status);
+ print_field("Connection Handle: %d", le16_to_cpu(evt->conn_handle));
+ print_usec_interval("CIG Synchronization Delay", evt->cig_sync_delay);
+ print_usec_interval("CIS Synchronization Delay", evt->cis_sync_delay);
+ print_usec_interval("Master to Slave Latency", evt->m_latency);
+ print_usec_interval("Slave to Master Latency", evt->s_latency);
+ print_le_phy("Master to Slave PHY", evt->m_phy);
+ print_le_phy("Slave to Master PHY", evt->s_phy);
+ print_field("Number of Subevents: %u", evt->nse);
+ print_field("Master to Slave Burst Number: %u", evt->m_bn);
+ print_field("Slave to Master Burst Number: %u", evt->s_bn);
+ print_field("Master to Slave Flush Timeout: %u", evt->m_ft);
+ print_field("Slave to Master Flush Timeout: %u", evt->s_ft);
+ print_field("Master to Slave MTU: %u", le16_to_cpu(evt->m_mtu));
+ print_field("Slave to Master MTU: %u", le16_to_cpu(evt->s_mtu));
+ print_field("ISO Interval: %u", le16_to_cpu(evt->interval));
+}
+
+static void le_req_cis_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_cis_req *evt = data;
+
+ print_field("ACL Handle: %d", le16_to_cpu(evt->acl_handle));
+ print_field("CIS Handle: %d", le16_to_cpu(evt->cis_handle));
+ print_field("CIG ID: 0x%2.2x", evt->cig_id);
+ print_field("CIS ID: 0x%2.2x", evt->cis_id);
+}
+
+static void print_bis_handle(const void *data)
+{
+ const uint16_t *handle = data;
+
+ print_field("Connection Handle: %d", le16_to_cpu(*handle));
+}
+
+static void le_big_complete_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_big_complete *evt = data;
+
+ print_status(evt->status);
+ print_field("BIG ID: 0x%2.2x", evt->big_id);
+ print_usec_interval("BIG Synchronization Delay", evt->sync_delay);
+ print_usec_interval("Transport Latency", evt->latency);
+ print_le_phy("PHY", evt->phy);
+ print_list(evt->handle, size, evt->num_bis, sizeof(*evt->handle),
+ print_bis_handle);
+}
+
+static void le_big_terminate_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_big_terminate *evt = data;
+
+ print_reason(evt->reason);
+ print_field("BIG ID: 0x%2.2x", evt->big_id);
+}
+
+static void le_big_sync_estabilished_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_big_sync_estabilished *evt = data;
+
+ print_status(evt->status);
+ print_field("BIG ID: 0x%2.2x", evt->big_id);
+ print_usec_interval("Transport Latency", evt->latency);
+ print_list(evt->handle, size, evt->num_bis, sizeof(*evt->handle),
+ print_bis_handle);
+}
+
+static void le_big_sync_lost_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_big_sync_lost *evt = data;
+
+ print_field("BIG ID: 0x%2.2x", evt->big_id);
+ print_reason(evt->reason);
+}
+
+static void le_req_sca_complete_evt(const void *data, uint8_t size)
+{
+ const struct bt_hci_evt_le_req_peer_sca_complete *evt = data;
+
+ print_status(evt->status);
+ print_field("Connection Handle: %d", le16_to_cpu(evt->handle));
+ print_sca(evt->sca);
+}
+
struct subevent_data {
uint8_t subevent;
const char *str;
@@ -10000,6 +10631,36 @@ static const struct subevent_data le_meta_event_table[] = {
{ 0x18, "LE Periodic Advertising Sync Transfer Received",
le_per_adv_sync_trans_rec_evt, 19,
true},
+ { BT_HCI_EVT_LE_CIS_ESTABLISHED,
+ "LE Connected Isochronous Stream Established",
+ le_cis_established_evt,
+ sizeof(struct bt_hci_evt_le_cis_established),
+ true },
+ { BT_HCI_EVT_LE_CIS_REQ, "LE Connected Isochronous Stream Request",
+ le_req_cis_evt,
+ sizeof(struct bt_hci_evt_le_cis_req),
+ true },
+ { BT_HCI_EVT_LE_BIG_COMPLETE,
+ "LE Broadcast Isochronous Group Complete",
+ le_big_complete_evt,
+ sizeof(struct bt_hci_evt_le_big_complete) },
+ { BT_HCI_EVT_LE_BIG_TERMINATE,
+ "LE Broadcast Isochronous Group Terminate",
+ le_big_terminate_evt,
+ sizeof(struct bt_hci_evt_le_big_terminate) },
+ { BT_HCI_EVT_LE_BIG_SYNC_ESTABILISHED,
+ "LE Broadcast Isochronous Group Sync "
+ "Estabilished", le_big_sync_estabilished_evt,
+ sizeof(struct bt_hci_evt_le_big_sync_lost) },
+ { BT_HCI_EVT_LE_BIG_SYNC_LOST,
+ "LE Broadcast Isochronous Group Sync Lost",
+ le_big_sync_lost_evt,
+ sizeof(struct bt_hci_evt_le_big_sync_lost) },
+ { BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE,
+ "LE Request Peer SCA Complete",
+ le_req_sca_complete_evt,
+ sizeof(
+ struct bt_hci_evt_le_req_peer_sca_complete)},
{ }
};
--
2.21.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 2/6] monitor: Add decoding of ISO related Link Layer PDUs
2020-01-28 20:13 [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
@ 2020-01-28 20:13 ` Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 3/6] monitor: Add support for ISO packets Luiz Augusto von Dentz
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2020-01-28 20:13 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds the decoding of ISO related Link Layer PDUs
---
monitor/bt.h | 48 +++++++++++++++++++++++++
monitor/ll.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 148 insertions(+)
diff --git a/monitor/bt.h b/monitor/bt.h
index 48901d7cd..b1b24afeb 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -28,6 +28,8 @@
#define BT_HCI_BIT_5_2 (8 * 41) + 5
#define BT_HCI_SUBEVT_5_2 0x19
+#define BT_LL_CMD_5_2 0x1f
+
struct bt_ll_hdr {
uint8_t preamble;
uint32_t access_addr;
@@ -179,6 +181,52 @@ struct bt_ll_clock_acc {
#define BT_LL_CLOCK_ACCURACY_RSP 0x1e
+#define BT_LL_CIS_REQ BT_LL_CMD_5_2
+struct bt_ll_cis_req {
+ uint8_t cig;
+ uint8_t cis;
+ uint8_t m_phy;
+ uint8_t s_phy;
+ uint16_t m_sdu;
+ uint16_t s_sdu;
+ uint8_t m_interval[3];
+ uint8_t s_interval[3];
+ uint8_t m_pdu;
+ uint8_t s_pdu;
+ uint8_t nse;
+ uint8_t sub_interval[3];
+ uint8_t bn;
+ uint8_t m_ft;
+ uint8_t s_ft;
+ uint16_t iso_interval;
+ uint8_t offset_min[3];
+ uint8_t offset_max[3];
+ uint16_t conn_event_count;
+} __attribute__ ((packed));
+
+#define BT_LL_CIS_RSP BT_LL_CMD_5_2 + 1
+struct bt_ll_cis_rsp {
+ uint8_t offset_min[3];
+ uint8_t offset_max[3];
+ uint16_t conn_event_count;
+} __attribute__ ((packed));
+
+#define BT_LL_CIS_IND BT_LL_CMD_5_2 + 2
+struct bt_ll_cis_ind {
+ uint32_t addr;
+ uint8_t cis_offset[3];
+ uint8_t cig_sync_delay[3];
+ uint8_t cis_sync_delay[3];
+ uint16_t conn_event_count;
+} __attribute__ ((packed));
+
+#define BT_LL_CIS_TERMINATE_IND BT_LL_CMD_5_2 + 3
+struct bt_ll_cis_term_ind {
+ uint8_t cig;
+ uint8_t cis;
+ uint8_t reason;
+} __attribute__ ((packed));
+
#define LMP_ESC4(x) ((127 << 8) | (x))
#define BT_LMP_NAME_REQ 1
diff --git a/monitor/ll.c b/monitor/ll.c
index 5141f2be6..4b3f567bd 100644
--- a/monitor/ll.c
+++ b/monitor/ll.c
@@ -601,6 +601,97 @@ static void clock_acc_req_rsp(const void *data, uint8_t size)
print_field("SCA: 0x%2.2x", pdu->sca);
}
+static void cis_req(const void *data, uint8_t size)
+{
+ const struct bt_ll_cis_req *cmd = data;
+ uint32_t interval;
+ uint8_t mask;
+
+ print_field("CIG ID: 0x%2.2x", cmd->cig);
+ print_field("CIS ID: 0x%2.2x", cmd->cis);
+ print_field("Master to Slave PHY: 0x%2.2x", cmd->m_phy);
+
+ mask = print_bitfield(2, cmd->m_phy, le_phys);
+ if (mask)
+ print_text(COLOR_UNKNOWN_OPTIONS_BIT, " Reserved"
+ " (0x%2.2x)", mask);
+
+ print_field("Slave To Master PHY: 0x%2.2x", cmd->s_phy);
+
+ mask = print_bitfield(2, cmd->s_phy, le_phys);
+ if (mask)
+ print_text(COLOR_UNKNOWN_OPTIONS_BIT, " Reserved"
+ " (0x%2.2x)", mask);
+
+ print_field("Master to Slave Maximum SDU: %u", cmd->m_sdu);
+ print_field("Slave to Master Maximum SDU: %u", cmd->s_sdu);
+
+ memcpy(&interval, cmd->m_interval, sizeof(cmd->m_interval));
+ print_field("Master to Slave Interval: 0x%6.6x", le32_to_cpu(interval));
+ memcpy(&interval, cmd->s_interval, sizeof(cmd->s_interval));
+ print_field("Slave to Master Interval: 0x%6.6x", le32_to_cpu(interval));
+
+ print_field("Master to Slave Maximum PDU: %u", cmd->m_pdu);
+ print_field("Slave to Master Maximum PDU: %u", cmd->s_pdu);
+
+ print_field("Burst Number: %u us", cmd->bn);
+
+ memcpy(&interval, cmd->sub_interval, sizeof(cmd->sub_interval));
+ print_field("Sub-Interval: 0x%6.6x", le32_to_cpu(interval));
+
+ print_field("Master to Slave Flush Timeout: %u", cmd->m_ft);
+ print_field("Slave to Master Flush Timeout: %u", cmd->s_ft);
+
+ print_field("ISO Interval: 0x%4.4x", le16_to_cpu(cmd->iso_interval));
+
+ memcpy(&interval, cmd->offset_min, sizeof(cmd->offset_min));
+ print_field("CIS Offset Minimum: 0x%6.6x", le32_to_cpu(interval));
+ memcpy(&interval, cmd->offset_max, sizeof(cmd->offset_max));
+ print_field("CIS Offset Maximum: 0x%6.6x", le32_to_cpu(interval));
+
+ print_field("Connection Event Count: %u", cmd->conn_event_count);
+}
+
+static void cis_rsp(const void *data, uint8_t size)
+{
+ const struct bt_ll_cis_rsp *rsp = data;
+ uint32_t interval;
+
+ memcpy(&interval, rsp->offset_min, sizeof(rsp->offset_min));
+ print_field("CIS Offset Minimum: 0x%6.6x", le32_to_cpu(interval));
+ memcpy(&interval, rsp->offset_max, sizeof(rsp->offset_max));
+ print_field("CIS Offset Maximum: 0x%6.6x", le32_to_cpu(interval));
+
+ print_field("Connection Event Count: %u", rsp->conn_event_count);
+}
+
+static void cis_ind(const void *data, uint8_t size)
+{
+ const struct bt_ll_cis_ind *ind = data;
+ uint32_t interval;
+
+ print_field("CIS Access Address: 0x%4.4x", le32_to_cpu(ind->addr));
+ memcpy(&interval, ind->cis_offset, sizeof(ind->cis_offset));
+ print_field("CIS Offset: 0x%6.6x", le32_to_cpu(interval));
+
+ memcpy(&interval, ind->cig_sync_delay, sizeof(ind->cig_sync_delay));
+ print_field("CIG Synchronization Delay: 0x%6.6x",
+ le32_to_cpu(interval));
+ memcpy(&interval, ind->cis_sync_delay, sizeof(ind->cis_sync_delay));
+ print_field("CIS Synchronization Delay: %u us",
+ le32_to_cpu(interval));
+ print_field("Connection Event Count: %u", ind->conn_event_count);
+}
+
+static void cis_term_ind(const void *data, uint8_t size)
+{
+ const struct bt_ll_cis_term_ind *ind = data;
+
+ print_field("CIG ID: 0x%2.2x", ind->cig);
+ print_field("CIS ID: 0x%2.2x", ind->cis);
+ packet_print_error("Reason", ind->reason);
+}
+
struct llcp_data {
uint8_t opcode;
const char *str;
@@ -641,6 +732,15 @@ static const struct llcp_data llcp_table[] = {
{ 0x1c, "LL_PERIODIC_SYNC_IND", periodic_sync_ind, 34, true },
{ 0x1d, "LL_CLOCK_ACCURACY_REQ", clock_acc_req_rsp, 1, true },
{ 0x1e, "LL_CLOCK_ACCURACY_RSP", clock_acc_req_rsp, 1, true },
+ { BT_LL_CIS_REQ, "LL_CIS_REQ", cis_req,
+ sizeof(struct bt_ll_cis_req), true },
+ { BT_LL_CIS_RSP, "LL_CIS_RSP", cis_rsp,
+ sizeof(struct bt_ll_cis_rsp), true },
+ { BT_LL_CIS_IND, "LL_CIS_IND", cis_ind,
+ sizeof(struct bt_ll_cis_ind), true },
+ { BT_LL_CIS_TERMINATE_IND, "LL_CIS_TERMINATE_IND", cis_term_ind,
+ sizeof(struct bt_ll_cis_term_ind),
+ true },
{ }
};
--
2.21.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 3/6] monitor: Add support for ISO packets
2020-01-28 20:13 [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 2/6] monitor: Add decoding of ISO related Link Layer PDUs Luiz Augusto von Dentz
@ 2020-01-28 20:13 ` Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 4/6] monitor: Add decoding for L2CAP Enhanced Credit Based PDUs Luiz Augusto von Dentz
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2020-01-28 20:13 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This enables decoding of ISO packets.
---
monitor/bt.h | 2 +-
monitor/packet.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
monitor/packet.h | 2 ++
src/shared/btsnoop.h | 2 ++
4 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/monitor/bt.h b/monitor/bt.h
index b1b24afeb..c2e6964ff 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -514,7 +514,7 @@ struct bt_hci_sco_hdr {
struct bt_hci_iso_hdr {
uint16_t handle;
- uint8_t dlen;
+ uint16_t dlen;
} __attribute__ ((packed));
struct bt_hci_iso_data_start {
diff --git a/monitor/packet.c b/monitor/packet.c
index 007887181..a6d958910 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -3934,6 +3934,12 @@ void packet_monitor(struct timeval *tv, struct ucred *cred,
case BTSNOOP_OPCODE_SCO_RX_PKT:
packet_hci_scodata(tv, cred, index, true, data, size);
break;
+ case BTSNOOP_OPCODE_ISO_TX_PKT:
+ packet_hci_isodata(tv, cred, index, false, data, size);
+ break;
+ case BTSNOOP_OPCODE_ISO_RX_PKT:
+ packet_hci_isodata(tv, cred, index, true, data, size);
+ break;
case BTSNOOP_OPCODE_OPEN_INDEX:
if (index < MAX_INDEX)
addr2str(index_list[index].bdaddr, str);
@@ -11336,6 +11342,53 @@ void packet_hci_scodata(struct timeval *tv, struct ucred *cred, uint16_t index,
packet_hexdump(data, size);
}
+void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index,
+ bool in, const void *data, uint16_t size)
+{
+ const struct bt_hci_iso_hdr *hdr = data;
+ uint16_t handle = le16_to_cpu(hdr->handle);
+ uint8_t flags = acl_flags(handle);
+ char handle_str[16], extra_str[32];
+
+ if (index > MAX_INDEX) {
+ print_field("Invalid index (%d).", index);
+ return;
+ }
+
+ index_list[index].frame++;
+
+ if (size < sizeof(*hdr)) {
+ if (in)
+ print_packet(tv, cred, '*', index, NULL, COLOR_ERROR,
+ "Malformed ISO Data RX packet", NULL, NULL);
+ else
+ print_packet(tv, cred, '*', index, NULL, COLOR_ERROR,
+ "Malformed ISO Data TX packet", NULL, NULL);
+ packet_hexdump(data, size);
+ return;
+ }
+
+ data += sizeof(*hdr);
+ size -= sizeof(*hdr);
+
+ sprintf(handle_str, "Handle %d", acl_handle(handle));
+ sprintf(extra_str, "flags 0x%2.2x dlen %d", flags, hdr->dlen);
+
+ print_packet(tv, cred, in ? '>' : '<', index, NULL, COLOR_HCI_SCODATA,
+ in ? "ISO Data RX" : "ISO Data TX",
+ handle_str, extra_str);
+
+ if (size != hdr->dlen) {
+ print_text(COLOR_ERROR, "invalid packet size (%d != %d)",
+ size, hdr->dlen);
+ packet_hexdump(data, size);
+ return;
+ }
+
+ if (filter_mask & PACKET_FILTER_SHOW_SCO_DATA)
+ packet_hexdump(data, size);
+}
+
void packet_ctrl_open(struct timeval *tv, struct ucred *cred, uint16_t index,
const void *data, uint16_t size)
{
diff --git a/monitor/packet.h b/monitor/packet.h
index 199e15e58..19ea04c68 100644
--- a/monitor/packet.h
+++ b/monitor/packet.h
@@ -94,6 +94,8 @@ void packet_hci_acldata(struct timeval *tv, struct ucred *cred, uint16_t index,
bool in, const void *data, uint16_t size);
void packet_hci_scodata(struct timeval *tv, struct ucred *cred, uint16_t index,
bool in, const void *data, uint16_t size);
+void packet_hci_isodata(struct timeval *tv, struct ucred *cred, uint16_t index,
+ bool in, const void *data, uint16_t size);
void packet_ctrl_open(struct timeval *tv, struct ucred *cred, uint16_t index,
const void *data, uint16_t size);
diff --git a/src/shared/btsnoop.h b/src/shared/btsnoop.h
index 3043d33e2..5fb084aa2 100644
--- a/src/shared/btsnoop.h
+++ b/src/shared/btsnoop.h
@@ -53,6 +53,8 @@
#define BTSNOOP_OPCODE_CTRL_CLOSE 15
#define BTSNOOP_OPCODE_CTRL_COMMAND 16
#define BTSNOOP_OPCODE_CTRL_EVENT 17
+#define BTSNOOP_OPCODE_ISO_TX_PKT 18
+#define BTSNOOP_OPCODE_ISO_RX_PKT 19
#define BTSNOOP_MAX_PACKET_SIZE (1486 + 4)
--
2.21.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 4/6] monitor: Add decoding for L2CAP Enhanced Credit Based PDUs
2020-01-28 20:13 [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 2/6] monitor: Add decoding of ISO related Link Layer PDUs Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 3/6] monitor: Add support for ISO packets Luiz Augusto von Dentz
@ 2020-01-28 20:13 ` Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 5/6] emulator: Add initial support for BT 5.2 Luiz Augusto von Dentz
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2020-01-28 20:13 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Enhanced Credit Based Flow Control Mode is used for L2CAP
connection-oriented channels on LE and BR/EDR with flow control using
a credit-based scheme for L2CAP data.
---
monitor/bt.h | 30 ++++++++++
monitor/l2cap.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 183 insertions(+)
diff --git a/monitor/bt.h b/monitor/bt.h
index c2e6964ff..d989f5b94 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -3712,6 +3712,36 @@ struct bt_l2cap_pdu_le_flowctl_creds {
uint16_t credits;
} __attribute__ ((packed));
+#define BT_L2CAP_PDU_ECRED_CONN_REQ 0x17
+struct bt_l2cap_pdu_ecred_conn_req {
+ uint16_t psm;
+ uint16_t mtu;
+ uint16_t mps;
+ uint16_t credits;
+ uint16_t scid[0];
+} __attribute__ ((packed));
+
+#define BT_L2CAP_PDU_ECRED_CONN_RSP 0x18
+struct bt_l2cap_pdu_ecred_conn_rsp {
+ uint16_t mtu;
+ uint16_t mps;
+ uint16_t credits;
+ uint16_t result;
+ uint16_t dcid[0];
+} __attribute__ ((packed));
+
+#define BT_L2CAP_PDU_ECRED_RECONF_REQ 0x19
+struct bt_l2cap_pdu_ecred_reconf_req {
+ uint16_t mtu;
+ uint16_t mps;
+ uint16_t scid[0];
+} __attribute__ ((packed));
+
+#define BT_L2CAP_PDU_ECRED_RECONF_RSP 0x1a
+struct bt_l2cap_pdu_ecred_reconf_rsp {
+ uint16_t result;
+} __attribute__ ((packed));
+
struct bt_l2cap_hdr_connless {
uint16_t psm;
} __attribute__ ((packed));
diff --git a/monitor/l2cap.c b/monitor/l2cap.c
index d4feca451..3b2b25f24 100644
--- a/monitor/l2cap.c
+++ b/monitor/l2cap.c
@@ -54,6 +54,7 @@
#define L2CAP_MODE_ERTM 0x03
#define L2CAP_MODE_STREAMING 0x04
#define L2CAP_MODE_LE_FLOWCTL 0x80
+#define L2CAP_MODE_ECRED 0x81
/* L2CAP Control Field bit masks */
#define L2CAP_CTRL_SAR_MASK 0xC000
@@ -121,6 +122,9 @@ static void assign_scid(const struct l2cap_frame *frame, uint16_t scid,
int i, n = -1;
uint8_t seq_num = 1;
+ if (!scid)
+ return;
+
for (i = 0; i < MAX_CHAN; i++) {
if (n < 0 && chan_list[i].handle == 0x0000) {
n = i;
@@ -417,6 +421,8 @@ static char *mode2str(uint8_t mode)
return "Streaming";
case L2CAP_MODE_LE_FLOWCTL:
return "LE Flow Control";
+ case L2CAP_MODE_ECRED:
+ return "Enhanced Credit";
default:
return "Unknown";
}
@@ -1333,6 +1339,132 @@ static void sig_le_flowctl_creds(const struct l2cap_frame *frame)
print_field("Credits: %u", le16_to_cpu(pdu->credits));
}
+static void sig_ecred_conn_req(const struct l2cap_frame *frame)
+{
+ const struct bt_l2cap_pdu_ecred_conn_req *pdu = frame->data;
+ uint16_t scid;
+
+ l2cap_frame_pull((void *)frame, frame, sizeof(pdu));
+
+ print_psm(pdu->psm);
+ print_field("MTU: %u", le16_to_cpu(pdu->mtu));
+ print_field("MPS: %u", le16_to_cpu(pdu->mps));
+ print_field("Credits: %u", le16_to_cpu(pdu->credits));
+
+ while (l2cap_frame_get_le16((void *)frame, &scid)) {
+ print_cid("Source", scid);
+ assign_scid(frame, scid, le16_to_cpu(pdu->psm),
+ L2CAP_MODE_ECRED, 0);
+ }
+}
+
+static void print_ecred_conn_result(uint16_t result)
+{
+ const char *str;
+
+ switch (le16_to_cpu(result)) {
+ case 0x0000:
+ str = "Connection successful";
+ break;
+ case 0x0002:
+ str = "Connection refused - PSM not supported";
+ break;
+ case 0x0004:
+ str = "Some connections refused – not enough resources "
+ "available";
+ break;
+ case 0x0005:
+ str = "All Connections refused - insufficient authentication";
+ break;
+ case 0x0006:
+ str = "All Connections refused - insufficient authorization";
+ break;
+ case 0x0007:
+ str = "All Connection refused - insufficient encryption key "
+ "size";
+ break;
+ case 0x0008:
+ str = "All Connections refused - insufficient encryption";
+ break;
+ case 0x0009:
+ str = "Some Connections refused - Invalid Source CID";
+ break;
+ case 0x000a:
+ str = "Some Connections refused - Source CID already allocated";
+ break;
+ case 0x000b:
+ str = "All Connections refused - unacceptable parameters";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Result: %s (0x%4.4x)", str, le16_to_cpu(result));
+}
+
+static void sig_ecred_conn_rsp(const struct l2cap_frame *frame)
+{
+ const struct bt_l2cap_pdu_ecred_conn_rsp *pdu = frame->data;
+ uint16_t dcid;
+
+ l2cap_frame_pull((void *)frame, frame, sizeof(pdu));
+
+ print_field("MTU: %u", le16_to_cpu(pdu->mtu));
+ print_field("MPS: %u", le16_to_cpu(pdu->mps));
+ print_field("Credits: %u", le16_to_cpu(pdu->credits));
+ print_ecred_conn_result(pdu->result);
+
+ while (l2cap_frame_get_le16((void *)frame, &dcid)) {
+ print_cid("Destination", dcid);
+ assign_dcid(frame, dcid, 0);
+ }
+}
+
+static void sig_ecred_reconf_req(const struct l2cap_frame *frame)
+{
+ const struct bt_l2cap_pdu_ecred_reconf_req *pdu = frame->data;
+ uint16_t scid;
+
+ l2cap_frame_pull((void *)frame, frame, sizeof(pdu));
+
+ print_field("MTU: %u", le16_to_cpu(pdu->mtu));
+ print_field("MPS: %u", le16_to_cpu(pdu->mps));
+
+ while (l2cap_frame_get_le16((void *)frame, &scid))
+ print_cid("Source", scid);
+}
+
+static void print_ecred_reconf_result(uint16_t result)
+{
+ const char *str;
+
+ switch (le16_to_cpu(result)) {
+ case 0x0000:
+ str = "Reconfiguration successful";
+ break;
+ case 0x0001:
+ str = "Reconfiguration failed - reduction in size of MTU not "
+ "allowed";
+ break;
+ case 0x0002:
+ str = "Reconfiguration failed - reduction in size of MPS not "
+ "allowed for more than one channel at a time";
+ break;
+ default:
+ str = "Reserved";
+ }
+
+ print_field("Result: %s (0x%4.4x)", str, le16_to_cpu(result));
+}
+
+static void sig_ecred_reconf_rsp(const struct l2cap_frame *frame)
+{
+ const struct bt_l2cap_pdu_ecred_reconf_rsp *pdu = frame->data;
+
+ print_ecred_reconf_result(pdu->result);
+}
+
struct sig_opcode_data {
uint8_t opcode;
const char *str;
@@ -1341,6 +1473,24 @@ struct sig_opcode_data {
bool fixed;
};
+#define SIG_ECRED \
+ { BT_L2CAP_PDU_ECRED_CONN_REQ, \
+ "Enhanced Credit Connection Request", \
+ sig_ecred_conn_req, sizeof(struct bt_l2cap_pdu_ecred_conn_req), \
+ false }, \
+ { BT_L2CAP_PDU_ECRED_CONN_RSP, \
+ "Enhanced Credit Connection Response", \
+ sig_ecred_conn_rsp, sizeof(struct bt_l2cap_pdu_ecred_conn_rsp), \
+ false }, \
+ { BT_L2CAP_PDU_ECRED_RECONF_REQ, \
+ "Enhanced Credit Reconfigure Request", \
+ sig_ecred_reconf_req, sizeof(struct bt_l2cap_pdu_ecred_reconf_req), \
+ false }, \
+ { BT_L2CAP_PDU_ECRED_RECONF_RSP, \
+ "Enhanced Credit Reconfigure Respond", \
+ sig_ecred_reconf_rsp, sizeof(struct bt_l2cap_pdu_ecred_reconf_rsp), \
+ true },
+
static const struct sig_opcode_data bredr_sig_opcode_table[] = {
{ 0x01, "Command Reject",
sig_cmd_reject, 2, false },
@@ -1376,6 +1526,7 @@ static const struct sig_opcode_data bredr_sig_opcode_table[] = {
sig_move_chan_cfm, 4, true },
{ 0x11, "Move Channel Confirmation Response",
sig_move_chan_cfm_rsp, 2, true },
+ SIG_ECRED
{ },
};
@@ -1396,6 +1547,7 @@ static const struct sig_opcode_data le_sig_opcode_table[] = {
sig_le_conn_rsp, 10, true },
{ 0x16, "LE Flow Control Credit",
sig_le_flowctl_creds, 4, true },
+ SIG_ECRED
{ },
};
@@ -3066,6 +3218,7 @@ void l2cap_frame(uint16_t index, bool in, uint16_t handle, uint16_t cid,
switch (frame.mode) {
case L2CAP_MODE_LE_FLOWCTL:
+ case L2CAP_MODE_ECRED:
chan = get_chan(&frame);
if (!chan->sdu) {
if (!l2cap_frame_get_le16(&frame, &chan->sdu))
--
2.21.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 5/6] emulator: Add initial support for BT 5.2
2020-01-28 20:13 [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
` (2 preceding siblings ...)
2020-01-28 20:13 ` [PATCH BlueZ 4/6] monitor: Add decoding for L2CAP Enhanced Credit Based PDUs Luiz Augusto von Dentz
@ 2020-01-28 20:13 ` Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 6/6] tools/btproxy: Add support for ISO packets Luiz Augusto von Dentz
2020-02-03 21:30 ` [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2020-01-28 20:13 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds the initial command/event decoding for 5.2.
---
emulator/btdev.c | 293 +++++++++++++++++++++++++++++++++++++++-------
emulator/btdev.h | 1 +
emulator/hciemu.c | 3 +
emulator/hciemu.h | 1 +
emulator/vhci.c | 3 +-
5 files changed, 258 insertions(+), 43 deletions(-)
diff --git a/emulator/btdev.c b/emulator/btdev.c
index 38d5b3b1f..0de273e53 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -47,6 +47,9 @@
#define has_bredr(btdev) (!((btdev)->features[4] & 0x20))
#define has_le(btdev) (!!((btdev)->features[4] & 0x40))
+#define ACL_HANDLE 42
+#define ISO_HANDLE 44
+
struct hook {
btdev_hook_func handler;
void *user_data;
@@ -92,6 +95,8 @@ struct btdev {
uint8_t feat_page_2[8];
uint16_t acl_mtu;
uint16_t acl_max_pkt;
+ uint16_t iso_mtu;
+ uint16_t iso_max_pkt;
uint8_t country_code;
uint8_t bdaddr[6];
uint8_t random_addr[6];
@@ -139,6 +144,10 @@ struct btdev {
uint8_t le_filter_dup;
uint8_t le_adv_enable;
uint8_t le_ltk[16];
+ struct {
+ struct bt_hci_cmd_le_set_cig_params params;
+ struct bt_hci_cis_params cis;
+ } __attribute__ ((packed)) le_cig;
uint8_t le_local_sk256[32];
@@ -438,6 +447,30 @@ static void set_le_50_commands(struct btdev *btdev)
btdev->commands[38] |= 0x40; /* LE Read Periodic Adv List Size */
}
+static void set_le_60_commands(struct btdev *btdev)
+{
+ btdev->commands[41] |= 0x20; /* LE Read Buffer Size v2 */
+ btdev->commands[41] |= 0x40; /* LE Read ISO TX Sync */
+ btdev->commands[41] |= 0x80; /* LE Set CIG Parameters */
+ btdev->commands[42] |= 0x01; /* LE Set CIG Parameters Test */
+ btdev->commands[42] |= 0x02; /* LE Create CIS */
+ btdev->commands[42] |= 0x04; /* LE Remove CIG */
+ btdev->commands[42] |= 0x08; /* LE Accept CIS */
+ btdev->commands[42] |= 0x10; /* LE Reject CIS */
+ btdev->commands[42] |= 0x20; /* LE Create BIG */
+ btdev->commands[42] |= 0x40; /* LE Create BIG Test */
+ btdev->commands[42] |= 0x80; /* LE Terminate BIG */
+ btdev->commands[43] |= 0x01; /* LE BIG Create Sync */
+ btdev->commands[43] |= 0x02; /* LE BIG Terminate Sync */
+ btdev->commands[43] |= 0x04; /* LE Request Peer SCA */
+ btdev->commands[43] |= 0x08; /* LE Setup ISO Path */
+ btdev->commands[43] |= 0x10; /* LE Remove ISO Path */
+ btdev->commands[43] |= 0x20; /* LE ISO TX Test */
+ btdev->commands[43] |= 0x40; /* LE ISO RX Test */
+ btdev->commands[43] |= 0x80; /* LE ISO Read Test Counter */
+ btdev->commands[44] |= 0x01; /* LE ISO Test End */
+}
+
static void set_le_commands(struct btdev *btdev)
{
set_common_commands_all(btdev);
@@ -482,6 +515,10 @@ static void set_le_commands(struct btdev *btdev)
/* Extra LE commands for >= 5.0 adapters */
if (btdev->type >= BTDEV_TYPE_BREDRLE50)
set_le_50_commands(btdev);
+
+ /* Extra LE commands for >= 6.0 adapters */
+ if (btdev->type >= BTDEV_TYPE_BREDRLE60)
+ set_le_60_commands(btdev);
}
static void set_bredrle_commands(struct btdev *btdev)
@@ -550,6 +587,14 @@ static void set_bredrle_features(struct btdev *btdev)
btdev->le_features[1] |= 0x10; /* LE EXT ADV */
}
+ if (btdev->type >= BTDEV_TYPE_BREDRLE60) {
+ btdev->le_features[3] |= 0x10; /* LE CIS Master */
+ btdev->le_features[3] |= 0x20; /* LE CIS Slave */
+ btdev->le_features[3] |= 0x40; /* LE ISO Broadcaster */
+ btdev->le_features[3] |= 0x80; /* LE Synchronized Receiver */
+ btdev->le_features[4] |= 0x01; /* LE ISO channels */
+ }
+
btdev->feat_page_2[0] |= 0x01; /* CSB - Master Operation */
btdev->feat_page_2[0] |= 0x02; /* CSB - Slave Operation */
btdev->feat_page_2[0] |= 0x04; /* Synchronization Train */
@@ -644,8 +689,9 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
memset(btdev, 0, sizeof(*btdev));
- if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE
- || type == BTDEV_TYPE_BREDRLE50) {
+ if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE ||
+ type == BTDEV_TYPE_BREDRLE50 ||
+ type == BTDEV_TYPE_BREDRLE60) {
btdev->crypto = bt_crypto_new();
if (!btdev->crypto) {
free(btdev);
@@ -661,6 +707,7 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
switch (btdev->type) {
case BTDEV_TYPE_BREDRLE:
case BTDEV_TYPE_BREDRLE50:
+ case BTDEV_TYPE_BREDRLE60:
btdev->version = 0x09;
set_bredrle_features(btdev);
set_bredrle_commands(btdev);
@@ -700,6 +747,9 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
btdev->acl_mtu = 192;
btdev->acl_max_pkt = 1;
+ btdev->iso_mtu = 251;
+ btdev->iso_max_pkt = 1;
+
btdev->country_code = 0x00;
index = add_btdev(btdev);
@@ -893,13 +943,13 @@ static void le_meta_event(struct btdev *btdev, uint8_t event,
send_event(btdev, BT_HCI_EVT_LE_META_EVENT, pkt_data, 1 + len);
}
-static void num_completed_packets(struct btdev *btdev)
+static void num_completed_packets(struct btdev *btdev, uint16_t handle)
{
if (btdev->conn) {
struct bt_hci_evt_num_completed_packets ncp;
ncp.num_handles = 1;
- ncp.handle = cpu_to_le16(42);
+ ncp.handle = cpu_to_le16(handle);
ncp.count = cpu_to_le16(1);
send_event(btdev, BT_HCI_EVT_NUM_COMPLETED_PACKETS,
@@ -1106,12 +1156,12 @@ static void conn_complete(struct btdev *btdev,
memcpy(cc.bdaddr, btdev->bdaddr, 6);
cc.encr_mode = 0x00;
- cc.handle = cpu_to_le16(42);
+ cc.handle = cpu_to_le16(ACL_HANDLE);
cc.link_type = 0x01;
send_event(remote, BT_HCI_EVT_CONN_COMPLETE, &cc, sizeof(cc));
- cc.handle = cpu_to_le16(42);
+ cc.handle = cpu_to_le16(ACL_HANDLE);
cc.link_type = 0x01;
} else {
cc.handle = cpu_to_le16(0x0000);
@@ -1208,7 +1258,7 @@ static void le_conn_complete(struct btdev *btdev,
memcpy(cc->peer_addr, btdev->bdaddr, 6);
cc->role = 0x01;
- cc->handle = cpu_to_le16(42);
+ cc->handle = cpu_to_le16(ACL_HANDLE);
cc->interval = lecc->max_interval;
cc->latency = lecc->latency;
cc->supv_timeout = lecc->supv_timeout;
@@ -1255,7 +1305,7 @@ static void le_ext_conn_complete(struct btdev *btdev,
memcpy(cc->peer_addr, btdev->bdaddr, 6);
cc->role = 0x01;
- cc->handle = cpu_to_le16(42);
+ cc->handle = cpu_to_le16(ACL_HANDLE);
cc->interval = lecc->max_interval;
cc->latency = lecc->latency;
cc->supv_timeout = lecc->supv_timeout;
@@ -1356,6 +1406,63 @@ static void le_ext_conn_request(struct btdev *btdev,
BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH);
}
+static void le_cis_estabilished(struct btdev *dev, uint8_t status)
+{
+ struct bt_hci_evt_le_cis_established evt;
+
+ memset(&evt, 0, sizeof(evt));
+
+ evt.status = status;
+
+ if (!evt.status) {
+ evt.conn_handle = cpu_to_le16(ISO_HANDLE);
+ /* TODO: Figure out if these values makes sense */
+ memcpy(evt.cig_sync_delay, dev->le_cig.params.m_interval,
+ sizeof(dev->le_cig.params.m_interval));
+ memcpy(evt.cis_sync_delay, dev->le_cig.params.s_interval,
+ sizeof(dev->le_cig.params.s_interval));
+ memcpy(evt.m_latency, &dev->le_cig.params.m_latency,
+ sizeof(dev->le_cig.params.m_latency));
+ memcpy(evt.s_latency, &dev->le_cig.params.s_latency,
+ sizeof(dev->le_cig.params.s_latency));
+ evt.m_phy = dev->le_cig.cis.m_phy;
+ evt.s_phy = dev->le_cig.cis.s_phy;
+ evt.nse = 0x01;
+ evt.m_bn = 0x01;
+ evt.s_bn = 0x01;
+ evt.m_ft = 0x01;
+ evt.s_ft = 0x01;
+ evt.m_mtu = dev->iso_mtu;
+ evt.s_mtu = dev->iso_mtu;
+ evt.interval = dev->le_cig.params.m_latency;
+ }
+
+ le_meta_event(dev, BT_HCI_EVT_LE_CIS_ESTABLISHED, &evt, sizeof(evt));
+
+ if (dev->conn)
+ le_meta_event(dev->conn, BT_HCI_EVT_LE_CIS_ESTABLISHED, &evt,
+ sizeof(evt));
+}
+
+static void le_cis_request(struct btdev *dev,
+ const struct bt_hci_cmd_le_create_cis *leccis)
+{
+ struct btdev *remote = dev->conn;
+
+ if (remote) {
+ struct bt_hci_evt_le_cis_req evt;
+
+ evt.acl_handle = cpu_to_le16(ACL_HANDLE);
+ evt.cis_handle = cpu_to_le16(ISO_HANDLE);
+ evt.cis_id = 0x00;
+ evt.cis_id = 0x00;
+
+ le_meta_event(remote, BT_HCI_EVT_LE_CIS_REQ, &evt, sizeof(evt));
+ } else {
+ le_cis_estabilished(dev, BT_HCI_ERR_UNKNOWN_CONN_ID);
+ }
+}
+
static void conn_request(struct btdev *btdev, const uint8_t *bdaddr)
{
struct btdev *remote = find_btdev_by_bdaddr(bdaddr);
@@ -1464,8 +1571,10 @@ static void disconnect_complete(struct btdev *btdev, uint16_t handle,
dc.handle = cpu_to_le16(handle);
dc.reason = reason;
- btdev->conn = NULL;
- remote->conn = NULL;
+ if (dc.handle == ACL_HANDLE) {
+ btdev->conn = NULL;
+ remote->conn = NULL;
+ }
send_event(btdev, BT_HCI_EVT_DISCONNECT_COMPLETE, &dc, sizeof(dc));
send_event(remote, BT_HCI_EVT_DISCONNECT_COMPLETE, &dc, sizeof(dc));
@@ -1492,7 +1601,7 @@ static void link_key_req_reply_complete(struct btdev *btdev,
return;
}
- ev.handle = cpu_to_le16(42);
+ ev.handle = cpu_to_le16(ACL_HANDLE);
if (!memcmp(btdev->link_key, remote->link_key, 16))
ev.status = BT_HCI_ERR_SUCCESS;
@@ -1587,7 +1696,7 @@ static void encrypt_change(struct btdev *btdev, uint8_t mode, uint8_t status)
struct bt_hci_evt_encrypt_change ev;
ev.status = status;
- ev.handle = cpu_to_le16(42);
+ ev.handle = cpu_to_le16(ACL_HANDLE);
ev.encr_mode = mode;
send_event(btdev, BT_HCI_EVT_ENCRYPT_CHANGE, &ev, sizeof(ev));
@@ -1628,7 +1737,7 @@ static void pin_code_req_reply_complete(struct btdev *btdev,
}
if (remote->conn) {
- ev.handle = cpu_to_le16(42);
+ ev.handle = cpu_to_le16(ACL_HANDLE);
send_event(remote, BT_HCI_EVT_AUTH_COMPLETE, &ev, sizeof(ev));
} else {
conn_complete(remote, btdev->bdaddr, ev.status);
@@ -1651,7 +1760,7 @@ static void pin_code_req_neg_reply_complete(struct btdev *btdev,
}
ev.status = BT_HCI_ERR_PIN_OR_KEY_MISSING;
- ev.handle = cpu_to_le16(42);
+ ev.handle = cpu_to_le16(ACL_HANDLE);
if (btdev->conn)
send_event(btdev, BT_HCI_EVT_AUTH_COMPLETE, &ev, sizeof(ev));
@@ -1944,7 +2053,7 @@ static void ssp_complete(struct btdev *btdev, const uint8_t *bdaddr,
}
auth.status = status;
- auth.handle = cpu_to_le16(42);
+ auth.handle = cpu_to_le16(ACL_HANDLE);
send_event(init, BT_HCI_EVT_AUTH_COMPLETE, &auth, sizeof(auth));
}
@@ -2207,7 +2316,7 @@ static void le_read_remote_features_complete(struct btdev *btdev)
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);
+ ev->handle = cpu_to_le16(ACL_HANDLE);
memcpy(ev->features, remote->le_features, 8);
send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
@@ -2230,7 +2339,7 @@ static void le_start_encrypt_complete(struct btdev *btdev, uint16_t ediv,
memset(buf, 0, sizeof(buf));
buf[0] = BT_HCI_EVT_LE_LONG_TERM_KEY_REQUEST;
- ev->handle = cpu_to_le16(42);
+ ev->handle = cpu_to_le16(ACL_HANDLE);
ev->ediv = ediv;
ev->rand = rand;
@@ -2244,7 +2353,7 @@ static void le_encrypt_complete(struct btdev *btdev)
struct btdev *remote = btdev->conn;
memset(&rp, 0, sizeof(rp));
- rp.handle = cpu_to_le16(42);
+ rp.handle = cpu_to_le16(ACL_HANDLE);
if (!remote) {
rp.status = BT_HCI_ERR_UNKNOWN_CONN_ID;
@@ -2266,7 +2375,7 @@ static void le_encrypt_complete(struct btdev *btdev)
ev.encr_mode = 0x01;
}
- ev.handle = cpu_to_le16(42);
+ ev.handle = cpu_to_le16(ACL_HANDLE);
send_event(btdev, BT_HCI_EVT_ENCRYPT_CHANGE, &ev, sizeof(ev));
send_event(remote, BT_HCI_EVT_ENCRYPT_CHANGE, &ev, sizeof(ev));
@@ -2279,7 +2388,7 @@ static void ltk_neg_reply_complete(struct btdev *btdev)
struct btdev *remote = btdev->conn;
memset(&rp, 0, sizeof(rp));
- rp.handle = cpu_to_le16(42);
+ rp.handle = cpu_to_le16(ACL_HANDLE);
if (!remote) {
rp.status = BT_HCI_ERR_UNKNOWN_CONN_ID;
@@ -2293,7 +2402,7 @@ static void ltk_neg_reply_complete(struct btdev *btdev)
memset(&ev, 0, sizeof(ev));
ev.status = BT_HCI_ERR_PIN_OR_KEY_MISSING;
- ev.handle = cpu_to_le16(42);
+ ev.handle = cpu_to_le16(ACL_HANDLE);
send_event(remote, BT_HCI_EVT_ENCRYPT_CHANGE, &ev, sizeof(ev));
}
@@ -2364,6 +2473,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_set_ext_scan_params *lsesp;
const struct bt_hci_le_scan_phy *lsp;
const struct bt_hci_cmd_le_set_ext_scan_enable *lsese;
+ const struct bt_hci_cmd_le_reject_cis *lrcis;
struct bt_hci_rsp_read_default_link_policy rdlp;
struct bt_hci_rsp_read_stored_link_key rslk;
struct bt_hci_rsp_write_stored_link_key wslk;
@@ -2425,6 +2535,11 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
struct bt_hci_evt_le_generate_dhkey_complete dh_evt;
struct bt_hci_rsp_le_read_num_supported_adv_sets rlrnsas;
struct bt_hci_rsp_le_set_ext_adv_params rlseap;
+ struct bt_hci_rsp_le_read_buffer_size_v2 lrbsv2;
+ struct lescp {
+ struct bt_hci_rsp_le_set_cig_params params;
+ uint16_t handle;
+ } __attribute__ ((packed)) lscp;
uint8_t status, page;
switch (opcode) {
@@ -2960,7 +3075,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_READ_LE_HOST_SUPPORTED:
if (btdev->type != BTDEV_TYPE_BREDRLE &&
- btdev->type != BTDEV_TYPE_BREDRLE50)
+ btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
rlhs.status = BT_HCI_ERR_SUCCESS;
rlhs.supported = btdev->le_supported;
@@ -2971,7 +3087,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_WRITE_LE_HOST_SUPPORTED:
if (btdev->type != BTDEV_TYPE_BREDRLE &&
btdev->type != BTDEV_TYPE_LE &&
- btdev->type != BTDEV_TYPE_BREDRLE50)
+ btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
wlhs = data;
btdev->le_supported = wlhs->supported;
@@ -2982,7 +3099,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_READ_SECURE_CONN_SUPPORT:
if (btdev->type != BTDEV_TYPE_BREDRLE &&
- btdev->type != BTDEV_TYPE_BREDRLE50)
+ btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
rscs.status = BT_HCI_ERR_SUCCESS;
rscs.support = btdev->secure_conn_support;
@@ -2991,7 +3109,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_WRITE_SECURE_CONN_SUPPORT:
if (btdev->type != BTDEV_TYPE_BREDRLE &&
- btdev->type != BTDEV_TYPE_BREDRLE50)
+ btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
wscs = data;
btdev->secure_conn_support = wscs->support;
@@ -3001,7 +3120,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_READ_LOCAL_OOB_EXT_DATA:
if (btdev->type != BTDEV_TYPE_BREDRLE &&
- btdev->type != BTDEV_TYPE_BREDRLE50)
+ btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
rloed.status = BT_HCI_ERR_SUCCESS;
cmd_complete(btdev, opcode, &rloed, sizeof(rloed));
@@ -3009,7 +3129,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_READ_SYNC_TRAIN_PARAMS:
if (btdev->type != BTDEV_TYPE_BREDRLE &&
- btdev->type != BTDEV_TYPE_BREDRLE50)
+ btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
rstp.status = BT_HCI_ERR_SUCCESS;
rstp.interval = cpu_to_le16(btdev->sync_train_interval);
@@ -3160,7 +3281,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_READ_ENCRYPT_KEY_SIZE:
if (btdev->type != BTDEV_TYPE_BREDRLE &&
btdev->type != BTDEV_TYPE_BREDR &&
- btdev->type != BTDEV_TYPE_BREDRLE50)
+ btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
reks = data;
read_enc_key_size_complete(btdev, le16_to_cpu(reks->handle));
@@ -3535,7 +3657,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &lcprnr_rsp, sizeof(lcprnr_rsp));
break;
case BT_HCI_CMD_LE_READ_NUM_SUPPORTED_ADV_SETS:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
rlrnsas.status = BT_HCI_ERR_SUCCESS;
@@ -3544,7 +3667,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &rlrnsas, sizeof(rlrnsas));
break;
case BT_HCI_CMD_LE_SET_ADV_SET_RAND_ADDR:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
lsasra = data;
@@ -3553,7 +3677,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
case BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
if (btdev->le_adv_enable) {
@@ -3573,7 +3698,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &rlseap, sizeof(rlseap));
break;
case BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
lseae = data;
@@ -3588,7 +3714,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
le_set_ext_adv_enable_complete(btdev);
break;
case BT_HCI_CMD_LE_SET_EXT_ADV_DATA:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
lsead = data;
@@ -3598,7 +3725,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
case BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
lsesrd = data;
@@ -3608,14 +3736,16 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
case BT_HCI_CMD_LE_REMOVE_ADV_SET:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
status = BT_HCI_ERR_SUCCESS;
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
case BT_HCI_CMD_LE_CLEAR_ADV_SETS:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
status = BT_HCI_ERR_SUCCESS;
@@ -3636,7 +3766,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
case BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
lsesp = data;
@@ -3658,7 +3789,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
case BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
lsese = data;
@@ -3672,11 +3804,63 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
case BT_HCI_CMD_LE_EXT_CREATE_CONN:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
goto unsupported;
cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode);
break;
+
+ case BT_HCI_CMD_LE_READ_BUFFER_SIZE_V2:
+ if (btdev->type != BTDEV_TYPE_BREDRLE60)
+ goto unsupported;
+ lrbsv2.status = BT_HCI_ERR_SUCCESS;
+ lrbsv2.acl_mtu = cpu_to_le16(btdev->acl_mtu);
+ lrbsv2.acl_max_pkt = btdev->acl_max_pkt;
+ lrbsv2.iso_mtu = cpu_to_le16(btdev->iso_mtu);
+ lrbsv2.iso_max_pkt = btdev->iso_max_pkt;
+ cmd_complete(btdev, opcode, &lrbsv2, sizeof(lrbsv2));
+ break;
+
+ case BT_HCI_CMD_LE_SET_CIG_PARAMS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE60)
+ goto unsupported;
+ memcpy(&btdev->le_cig, data, len);
+ lscp.params.status = BT_HCI_ERR_SUCCESS;
+ lscp.params.cig_id = 0x00;
+ lscp.params.num_handles = 1;
+ lscp.handle = cpu_to_le16(ISO_HANDLE);
+ cmd_complete(btdev, opcode, &lscp, sizeof(lscp));
+ break;
+
+ case BT_HCI_CMD_LE_CREATE_CIS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE60)
+ goto unsupported;
+
+ cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode);
+
+ break;
+
+ case BT_HCI_CMD_LE_ACCEPT_CIS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE60)
+ goto unsupported;
+
+ cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode);
+ le_cis_estabilished(btdev, BT_HCI_ERR_SUCCESS);
+
+ break;
+
+ case BT_HCI_CMD_LE_REJECT_CIS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE60)
+ goto unsupported;
+
+ cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode);
+
+ lrcis = data;
+ le_cis_estabilished(btdev, lrcis->reason);
+
+ break;
+
default:
goto unsupported;
}
@@ -3716,6 +3900,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_set_scan_enable *lsse;
const struct bt_hci_cmd_le_set_ext_scan_enable *lsese;
const struct bt_hci_cmd_le_ext_create_conn *leecc;
+ const struct bt_hci_cmd_le_create_cis *leccis;
switch (opcode) {
case BT_HCI_CMD_INQUIRY:
@@ -3912,19 +4097,28 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
le_set_scan_enable_complete(btdev);
break;
case BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
return;
lsese = data;
if (btdev->le_scan_enable && lsese->enable)
le_set_ext_scan_enable_complete(btdev);
break;
case BT_HCI_CMD_LE_EXT_CREATE_CONN:
- if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
return;
leecc = data;
btdev->le_scan_own_addr_type = leecc->own_addr_type;
le_ext_conn_request(btdev, leecc);
break;
+ case BT_HCI_CMD_LE_CREATE_CIS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50 &&
+ btdev->type != BTDEV_TYPE_BREDRLE60)
+ return;
+ leccis = data;
+ le_cis_request(btdev, leccis);
+ break;
}
}
@@ -4033,6 +4227,16 @@ static void send_acl(struct btdev *conn, const void *data, uint16_t len)
send_packet(conn, iov, 3);
}
+static void send_iso(struct btdev *conn, const void *data, uint16_t len)
+{
+ struct iovec iov;
+
+ iov.iov_base = (void *) (data);
+ iov.iov_len = len;
+
+ send_packet(conn, &iov, 1);
+}
+
void btdev_receive_h4(struct btdev *btdev, const void *data, uint16_t len)
{
uint8_t pkt_type;
@@ -4052,7 +4256,12 @@ void btdev_receive_h4(struct btdev *btdev, const void *data, uint16_t len)
case BT_H4_ACL_PKT:
if (btdev->conn)
send_acl(btdev->conn, data, len);
- num_completed_packets(btdev);
+ num_completed_packets(btdev, ACL_HANDLE);
+ break;
+ case BT_H4_ISO_PKT:
+ num_completed_packets(btdev, ISO_HANDLE);
+ if (btdev->conn)
+ send_iso(btdev->conn, data, len);
break;
default:
printf("Unsupported packet 0x%2.2x\n", pkt_type);
diff --git a/emulator/btdev.h b/emulator/btdev.h
index 362d1e7a2..b535930de 100644
--- a/emulator/btdev.h
+++ b/emulator/btdev.h
@@ -64,6 +64,7 @@ enum btdev_type {
BTDEV_TYPE_AMP,
BTDEV_TYPE_BREDR20,
BTDEV_TYPE_BREDRLE50,
+ BTDEV_TYPE_BREDRLE60,
};
enum btdev_hook_type {
diff --git a/emulator/hciemu.c b/emulator/hciemu.c
index 1045043f1..23891a2ee 100644
--- a/emulator/hciemu.c
+++ b/emulator/hciemu.c
@@ -335,6 +335,9 @@ struct hciemu *hciemu_new(enum hciemu_type type)
case HCIEMU_TYPE_BREDRLE50:
hciemu->btdev_type = BTDEV_TYPE_BREDRLE50;
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 e37c069e1..6f651cb98 100644
--- a/emulator/hciemu.h
+++ b/emulator/hciemu.h
@@ -32,6 +32,7 @@ enum hciemu_type {
HCIEMU_TYPE_LE,
HCIEMU_TYPE_LEGACY,
HCIEMU_TYPE_BREDRLE50,
+ HCIEMU_TYPE_BREDRLE60,
};
enum hciemu_hook_type {
diff --git a/emulator/vhci.c b/emulator/vhci.c
index 8dec20a08..7a69b484e 100644
--- a/emulator/vhci.c
+++ b/emulator/vhci.c
@@ -89,6 +89,7 @@ static void vhci_read_callback(int fd, uint32_t events, void *user_data)
case BT_H4_CMD_PKT:
case BT_H4_ACL_PKT:
case BT_H4_SCO_PKT:
+ case BT_H4_ISO_PKT:
btdev_receive_h4(vhci->btdev, buf, len);
break;
}
@@ -104,7 +105,7 @@ struct vhci *vhci_open(enum vhci_type type)
switch (type) {
case VHCI_TYPE_BREDRLE:
- btdev_type = BTDEV_TYPE_BREDRLE;
+ btdev_type = BTDEV_TYPE_BREDRLE60;
ctrl_type = HCI_PRIMARY;
break;
case VHCI_TYPE_BREDR:
--
2.21.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 6/6] tools/btproxy: Add support for ISO packets
2020-01-28 20:13 [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
` (3 preceding siblings ...)
2020-01-28 20:13 ` [PATCH BlueZ 5/6] emulator: Add initial support for BT 5.2 Luiz Augusto von Dentz
@ 2020-01-28 20:13 ` Luiz Augusto von Dentz
2020-02-03 21:30 ` [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2020-01-28 20:13 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This enables proxing ISO packets.
---
tools/btproxy.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/tools/btproxy.c b/tools/btproxy.c
index fb67a5735..a98bbb73f 100644
--- a/tools/btproxy.c
+++ b/tools/btproxy.c
@@ -73,14 +73,14 @@ static void hexdump_print(const char *str, void *user_data)
}
struct proxy {
- /* Receive commands, ACL and SCO data */
+ /* Receive commands, ACL, SCO and ISO data */
int host_fd;
uint8_t host_buf[4096];
uint16_t host_len;
bool host_shutdown;
bool host_skip_first_zero;
- /* Receive events, ACL and SCO data */
+ /* Receive events, ACL, SCO and ISO data */
int dev_fd;
uint8_t dev_buf[4096];
uint16_t dev_len;
@@ -296,6 +296,7 @@ static void host_read_callback(int fd, uint32_t events, void *user_data)
struct bt_hci_cmd_hdr *cmd_hdr;
struct bt_hci_acl_hdr *acl_hdr;
struct bt_hci_sco_hdr *sco_hdr;
+ struct bt_hci_iso_hdr *iso_hdr;
ssize_t len;
uint16_t pktlen;
@@ -364,6 +365,13 @@ process_packet:
sco_hdr = (void *) (proxy->host_buf + 1);
pktlen = 1 + sizeof(*sco_hdr) + sco_hdr->dlen;
break;
+ case BT_H4_ISO_PKT:
+ if (proxy->host_len < 1 + sizeof(*iso_hdr))
+ return;
+
+ iso_hdr = (void *) (proxy->host_buf + 1);
+ pktlen = 1 + sizeof(*iso_hdr) + cpu_to_le16(iso_hdr->dlen);
+ break;
case 0xff:
/* Notification packet from /dev/vhci - ignore */
proxy->host_len = 0;
@@ -418,6 +426,7 @@ static void dev_read_callback(int fd, uint32_t events, void *user_data)
struct bt_hci_evt_hdr *evt_hdr;
struct bt_hci_acl_hdr *acl_hdr;
struct bt_hci_sco_hdr *sco_hdr;
+ struct bt_hci_iso_hdr *iso_hdr;
ssize_t len;
uint16_t pktlen;
@@ -476,6 +485,13 @@ process_packet:
sco_hdr = (void *) (proxy->dev_buf + 1);
pktlen = 1 + sizeof(*sco_hdr) + sco_hdr->dlen;
break;
+ case BT_H4_ISO_PKT:
+ if (proxy->dev_len < 1 + sizeof(*iso_hdr))
+ return;
+
+ iso_hdr = (void *) (proxy->dev_buf + 1);
+ pktlen = 1 + sizeof(*iso_hdr) + cpu_to_le16(iso_hdr->dlen);
+ break;
default:
fprintf(stderr, "Received unknown device packet type 0x%02x\n",
proxy->dev_buf[0]);
--
2.21.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands
2020-01-28 20:13 [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
` (4 preceding siblings ...)
2020-01-28 20:13 ` [PATCH BlueZ 6/6] tools/btproxy: Add support for ISO packets Luiz Augusto von Dentz
@ 2020-02-03 21:30 ` Luiz Augusto von Dentz
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2020-02-03 21:30 UTC (permalink / raw)
To: linux-bluetooth
Hi,
On Tue, Jan 28, 2020 at 12:13 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This adds parsing of ISO related commands.
> ---
> monitor/bt.h | 307 ++++++++++++++++++++++
> monitor/packet.c | 661 +++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 968 insertions(+)
>
> diff --git a/monitor/bt.h b/monitor/bt.h
> index b31e6c5c5..48901d7cd 100644
> --- a/monitor/bt.h
> +++ b/monitor/bt.h
> @@ -24,6 +24,10 @@
>
> #include <stdint.h>
>
> +#define BT_HCI_CMD_5_2 0x2060
> +#define BT_HCI_BIT_5_2 (8 * 41) + 5
> +#define BT_HCI_SUBEVT_5_2 0x19
> +
> struct bt_ll_hdr {
> uint8_t preamble;
> uint32_t access_addr;
> @@ -443,6 +447,7 @@ struct bt_lmp_power_control_res {
> #define BT_H4_ACL_PKT 0x02
> #define BT_H4_SCO_PKT 0x03
> #define BT_H4_EVT_PKT 0x04
> +#define BT_H4_ISO_PKT 0x05
>
> struct bt_hci_cmd_hdr {
> uint16_t opcode;
> @@ -459,6 +464,16 @@ struct bt_hci_sco_hdr {
> uint8_t dlen;
> } __attribute__ ((packed));
>
> +struct bt_hci_iso_hdr {
> + uint16_t handle;
> + uint8_t dlen;
> +} __attribute__ ((packed));
> +
> +struct bt_hci_iso_data_start {
> + uint16_t sn;
> + uint16_t slen;
> +} __attribute__ ((packed));
> +
> struct bt_hci_evt_hdr {
> uint8_t evt;
> uint8_t plen;
> @@ -2498,6 +2513,231 @@ struct bt_hci_cmd_default_periodic_adv_sync_trans_params {
> uint8_t cte_type;
> } __attribute__ ((packed));
>
> +#define BT_HCI_CMD_LE_READ_BUFFER_SIZE_V2 BT_HCI_CMD_5_2
> +#define BT_HCI_BIT_LE_READ_BUFFER_SIZE_V2 BT_HCI_BIT_5_2
> +struct bt_hci_rsp_le_read_buffer_size_v2 {
> + uint8_t status;
> + uint16_t acl_mtu;
> + uint8_t acl_max_pkt;
> + uint16_t iso_mtu;
> + uint8_t iso_max_pkt;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_READ_ISO_TX_SYNC BT_HCI_CMD_5_2 + 1
> +#define BT_HCI_BIT_LE_READ_ISO_TX_SYNC BT_HCI_BIT_5_2 + 1
> +struct bt_hci_cmd_le_read_iso_tx_sync {
> + uint16_t handle;
> +} __attribute__ ((packed));
> +
> +struct bt_hci_rsp_le_read_iso_tx_sync {
> + uint8_t status;
> + uint16_t handle;
> + uint16_t seq;
> + uint32_t timestamp;
> + uint8_t offset[3];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_SET_CIG_PARAMS BT_HCI_CMD_5_2 + 2
> +#define BT_HCI_BIT_LE_SET_CIG_PARAMS BT_HCI_BIT_5_2 + 2
> +struct bt_hci_cis_params {
> + uint8_t cis_id;
> + uint16_t m_sdu;
> + uint16_t s_sdu;
> + uint8_t m_phy;
> + uint8_t s_phy;
> + uint8_t m_rtn;
> + uint8_t s_rtn;
> +} __attribute__ ((packed));
> +
> +struct bt_hci_cmd_le_set_cig_params {
> + uint8_t cig_id;
> + uint8_t m_interval[3];
> + uint8_t s_interval[3];
> + uint8_t sca;
> + uint8_t packing;
> + uint8_t framing;
> + uint16_t m_latency;
> + uint16_t s_latency;
> + uint8_t num_cis;
> + struct bt_hci_cis_params cis[0];
> +} __attribute__ ((packed));
> +
> +struct bt_hci_rsp_le_set_cig_params {
> + uint8_t status;
> + uint8_t cig_id;
> + uint8_t num_handles;
> + uint16_t handle[0];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_SET_CIG_PARAMS_TEST BT_HCI_CMD_5_2 + 3
> +#define BT_HCI_BIT_LE_SET_CIG_PARAMS_TEST BT_HCI_BIT_5_2 + 3
> +struct bt_hci_cis_params_test {
> + uint8_t cis_id;
> + uint8_t nse;
> + uint16_t m_sdu;
> + uint16_t s_sdu;
> + uint8_t m_pdu;
> + uint8_t s_pdu;
> + uint8_t m_phy;
> + uint8_t s_phy;
> + uint8_t m_bn;
> + uint8_t s_bn;
> +} __attribute__ ((packed));
> +
> +struct bt_hci_cmd_le_set_cig_params_test {
> + uint8_t cig_id;
> + uint8_t m_interval[3];
> + uint8_t s_interval[3];
> + uint8_t m_ft;
> + uint8_t s_ft;
> + uint16_t iso_interval;
> + uint8_t sca;
> + uint8_t packing;
> + uint8_t framing;
> + uint8_t num_cis;
> + struct bt_hci_cis_params_test cis[0];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_CREATE_CIS BT_HCI_CMD_5_2 + 4
> +#define BT_HCI_BIT_LE_CREATE_CIS BT_HCI_BIT_5_2 + 4
> +struct bt_hci_cis {
> + uint16_t cis_handle;
> + uint16_t acl_handle;
> +} __attribute__ ((packed));
> +
> +struct bt_hci_cmd_le_create_cis {
> + uint8_t num_cis;
> + struct bt_hci_cis cis[0];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_REMOVE_CIG BT_HCI_CMD_5_2 + 5
> +#define BT_HCI_BIT_LE_REMOVE_CIG BT_HCI_BIT_5_2 + 5
> +struct bt_hci_cmd_le_remove_cig {
> + uint8_t cig_id;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_ACCEPT_CIS BT_HCI_CMD_5_2 + 6
> +#define BT_HCI_BIT_LE_ACCEPT_CIS BT_HCI_BIT_5_2 + 6
> +struct bt_hci_cmd_le_accept_cis {
> + uint16_t handle;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_REJECT_CIS BT_HCI_CMD_5_2 + 7
> +#define BT_HCI_BIT_LE_REJECT_CIS BT_HCI_BIT_5_2 + 7
> +struct bt_hci_cmd_le_reject_cis {
> + uint16_t handle;
> + uint8_t reason;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_CREATE_BIG BT_HCI_CMD_5_2 + 8
> +#define BT_HCI_BIT_LE_CREATE_BIG BT_HCI_BIT_5_2 + 8
> +struct bt_hci_bis {
> + uint8_t sdu_interval[3];
> + uint16_t sdu;
> + uint16_t latency;
> + uint8_t rtn;
> + uint8_t phy;
> + uint8_t packing;
> + uint8_t framing;
> + uint8_t encryption;
> + uint8_t bcode[16];
> +} __attribute__ ((packed));
> +
> +struct bt_hci_cmd_le_create_big {
> + uint8_t big_id;
> + uint8_t adv_handle;
> + uint8_t num_bis;
> + struct bt_hci_bis bis[0];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_CREATE_BIG_TEST BT_HCI_CMD_5_2 + 9
> +#define BT_HCI_BIT_LE_CREATE_BIG_TEST BT_HCI_BIT_5_2 + 9
> +struct bt_hci_bis_test {
> + uint8_t sdu_interval[3];
> + uint16_t iso_interval;
> + uint8_t nse;
> + uint16_t sdu;
> + uint8_t pdu;
> + uint8_t phy;
> + uint8_t packing;
> + uint8_t framing;
> + uint8_t bn;
> + uint8_t irc;
> + uint8_t pto;
> + uint8_t adv_handle;
> + uint8_t encryption;
> + uint8_t bcode[16];
> +} __attribute__ ((packed));
> +
> +struct bt_hci_cmd_le_create_big_test {
> + uint8_t big_id;
> + uint8_t adv_handle;
> + uint8_t num_bis;
> + struct bt_hci_bis_test bis[0];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_TERM_BIG BT_HCI_CMD_5_2 + 10
> +#define BT_HCI_BIT_LE_TERM_BIG BT_HCI_BIT_5_2 + 10
> +struct bt_hci_cmd_le_term_big {
> + uint8_t big_id;
> + uint8_t reason;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_BIG_CREATE_SYNC BT_HCI_CMD_5_2 + 11
> +#define BT_HCI_BIT_LE_BIG_CREATE_SYNC BT_HCI_BIT_5_2 + 11
> +struct bt_hci_bis_sync {
> +} __attribute__ ((packed));
> +
> +struct bt_hci_cmd_le_big_create_sync {
> + uint8_t big_id;
> + uint16_t sync_handle;
> + uint8_t num_bis;
> + uint8_t encryption;
> + uint8_t bcode[16];
> + uint8_t mse;
> + uint16_t timeout;
> + struct bt_hci_bis_sync bis[0];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_BIG_TERM_SYNC BT_HCI_CMD_5_2 + 12
> +#define BT_HCI_BIT_LE_BIG_TERM_SYNC BT_HCI_BIT_5_2 + 12
> +struct bt_hci_cmd_le_big_term_sync {
> + uint8_t big_id;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_REQ_PEER_SCA BT_HCI_CMD_5_2 + 13
> +#define BT_HCI_BIT_LE_REQ_PEER_SCA BT_HCI_BIT_5_2 + 13
> +struct bt_hci_cmd_le_req_peer_sca {
> + uint16_t handle;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_SETUP_ISO_PATH BT_HCI_CMD_5_2 + 14
> +#define BT_HCI_BIT_LE_SETUP_ISO_PATH BT_HCI_BIT_5_2 + 14
> +struct bt_hci_cmd_le_setup_iso_path {
> + uint16_t handle;
> + uint8_t input_path;
> + uint8_t output_path;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_REMOVE_ISO_PATH BT_HCI_CMD_5_2 + 15
> +#define BT_HCI_BIT_LE_REMOVE_ISO_PATH BT_HCI_BIT_5_2 + 15
> +struct bt_hci_cmd_le_remove_iso_path {
> + uint16_t handle;
> + uint8_t path_dir;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_CMD_LE_ISO_TX_TEST BT_HCI_CMD_5_2 + 16
> +#define BT_HCI_BIT_LE_ISO_TX_TEST BT_HCI_BIT_5_2 + 16
> +
> +#define BT_HCI_CMD_LE_ISO_RX_TEST BT_HCI_CMD_5_2 + 17
> +#define BT_HCI_BIT_LE_ISO_RX_TEST BT_HCI_BIT_5_2 + 17
> +
> +#define BT_HCI_CMD_LE_ISO_READ_TEST_COUNTER BT_HCI_CMD_5_2 + 18
> +#define BT_HCI_BIT_LE_ISO_READ_TEST_COUNTER BT_HCI_BIT_5_2 + 18
> +
> +#define BT_HCI_CMD_LE_ISO_TEST_END BT_HCI_CMD_5_2 + 19
> +#define BT_HCI_BIT_LE_ISO_TEST_END BT_HCI_BIT_5_2 + 19
> +
> #define BT_HCI_EVT_INQUIRY_COMPLETE 0x01
> struct bt_hci_evt_inquiry_complete {
> uint8_t status;
> @@ -3197,6 +3437,73 @@ struct bt_hci_evt_le_per_adv_sync_trans_rec {
> uint8_t clock_accuracy;
> } __attribute__ ((packed));
>
> +#define BT_HCI_EVT_LE_CIS_ESTABLISHED BT_HCI_SUBEVT_5_2
> +struct bt_hci_evt_le_cis_established {
> + uint8_t status;
> + uint16_t conn_handle;
> + uint8_t cig_sync_delay[3];
> + uint8_t cis_sync_delay[3];
> + uint8_t m_latency[3];
> + uint8_t s_latency[3];
> + uint8_t m_phy;
> + uint8_t s_phy;
> + uint8_t nse;
> + uint8_t m_bn;
> + uint8_t s_bn;
> + uint8_t m_ft;
> + uint8_t s_ft;
> + uint16_t m_mtu;
> + uint16_t s_mtu;
> + uint16_t interval;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_EVT_LE_CIS_REQ BT_HCI_SUBEVT_5_2 + 1
> +struct bt_hci_evt_le_cis_req {
> + uint16_t acl_handle;
> + uint16_t cis_handle;
> + uint8_t cig_id;
> + uint8_t cis_id;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_EVT_LE_BIG_COMPLETE BT_HCI_SUBEVT_5_2 + 2
> +struct bt_hci_evt_le_big_complete {
> + uint8_t status;
> + uint8_t big_id;
> + uint8_t sync_delay[3];
> + uint8_t latency[3];
> + uint8_t phy;
> + uint8_t num_bis;
> + uint16_t handle[0];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_EVT_LE_BIG_TERMINATE BT_HCI_SUBEVT_5_2 + 3
> +struct bt_hci_evt_le_big_terminate {
> + uint8_t reason;
> + uint8_t big_id;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_EVT_LE_BIG_SYNC_ESTABILISHED BT_HCI_SUBEVT_5_2 + 4
> +struct bt_hci_evt_le_big_sync_estabilished {
> + uint8_t status;
> + uint8_t big_id;
> + uint8_t latency[3];
> + uint8_t num_bis;
> + uint16_t handle[0];
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_EVT_LE_BIG_SYNC_LOST BT_HCI_SUBEVT_5_2 + 5
> +struct bt_hci_evt_le_big_sync_lost {
> + uint8_t big_id;
> + uint8_t reason;
> +} __attribute__ ((packed));
> +
> +#define BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE BT_HCI_SUBEVT_5_2 + 6
> +struct bt_hci_evt_le_req_peer_sca_complete {
> + uint8_t status;
> + uint16_t handle;
> + uint8_t sca;
> +} __attribute__ ((packed));
> +
> #define BT_HCI_ERR_SUCCESS 0x00
> #define BT_HCI_ERR_UNKNOWN_COMMAND 0x01
> #define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02
> diff --git a/monitor/packet.c b/monitor/packet.c
> index 6e7cc5e85..007887181 100644
> --- a/monitor/packet.c
> +++ b/monitor/packet.c
> @@ -2617,6 +2617,11 @@ static const struct bitfield_data features_le[] = {
> { 25, "Periodic Advertising Sync Transfer - Recipient" },
> { 26, "Sleep Clock Accuracy Updates" },
> { 27, "Remote Public Key Validation" },
> + { 28, "Connected Isochronous Stream - Master" },
> + { 29, "Connected Isochronous Stream - Slave" },
> + { 30, "Isochronous Broadcaster" },
> + { 31, "Synchronized Receiver" },
> + { 32, "Isochronous Channels (Host Support)" },
> { }
> };
>
> @@ -2977,6 +2982,12 @@ static const struct bitfield_data events_le_table[] = {
> { 17, "LE Extended Advertising Set Terminated" },
> { 18, "LE Scan Request Received" },
> { 19, "LE Channel Selection Algorithm" },
> + { 24, "LE CIS Established" },
> + { 25, "LE CIS Request" },
> + { 26, "LE Create BIG Complete" },
> + { 27, "LE Terminate BIG Complete" },
> + { 28, "LE BIG Sync Estabilished Complete" },
> + { 29, "LE BIG Sync Lost" },
> { }
> };
>
> @@ -7666,6 +7677,437 @@ static void le_set_default_periodic_adv_sync_trans_params(const void *data,
> print_create_sync_cte_type(cmd->cte_type);
> }
>
> +static void print_sca(uint8_t sca)
> +{
> + switch (sca) {
> + case 0x00:
> + print_field("SCA: 201 - 500 ppm (0x%2.2x)", sca);
> + return;
> + case 0x01:
> + print_field("SCA: 151 - 200 ppm (0x%2.2x)", sca);
> + return;
> + case 0x02:
> + print_field("SCA: 101 - 150 ppm (0x%2.2x)", sca);
> + return;
> + case 0x03:
> + print_field("SCA: 76 - 100 ppm (0x%2.2x)", sca);
> + return;
> + case 0x04:
> + print_field("SCA: 51 - 75 ppm (0x%2.2x)", sca);
> + return;
> + case 0x05:
> + print_field("SCA: 31 - 50 ppm (0x%2.2x)", sca);
> + return;
> + case 0x06:
> + print_field("SCA: 21 - 30 ppm (0x%2.2x)", sca);
> + return;
> + case 0x07:
> + print_field("SCA: 0 - 20 ppm (0x%2.2x)", sca);
> + return;
> + default:
> + print_field("SCA: Reserved (0x%2.2x)", sca);
> + }
> +}
> +
> +static void print_packing(uint8_t value)
> +{
> + switch (value) {
> + case 0x00:
> + print_field("Packing: Sequential (0x%2.2x)", value);
> + return;
> + case 0x01:
> + print_field("Packing: Interleaved (0x%2.2x)", value);
> + return;
> + default:
> + print_field("Packing: Reserved (0x%2.2x)", value);
> + }
> +}
> +
> +static void print_framing(uint8_t value)
> +{
> + switch (value) {
> + case 0x00:
> + print_field("Framing: Unframed (0x%2.2x)", value);
> + return;
> + case 0x01:
> + print_field("Framing: Framed (0x%2.2x)", value);
> + return;
> + default:
> + print_field("Packing: Reserved (0x%2.2x)", value);
> + }
> +}
> +
> +static void le_read_buffer_size_v2_rsp(const void *data, uint8_t size)
> +{
> + const struct bt_hci_rsp_le_read_buffer_size_v2 *rsp = data;
> +
> + print_status(rsp->status);
> +
> + if (size == 1)
> + return;
> +
> + print_field("ACL MTU: %d", le16_to_cpu(rsp->acl_mtu));
> + print_field("ACL max packet: %d", rsp->acl_max_pkt);
> + print_field("ISO MTU: %d", le16_to_cpu(rsp->iso_mtu));
> + print_field("ISO max packet: %d", rsp->iso_max_pkt);
> +}
> +
> +static void le_read_iso_tx_sync_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_read_iso_tx_sync *cmd = data;
> +
> + print_field("Handle: %d", le16_to_cpu(cmd->handle));
> +}
> +
> +static void le_read_iso_tx_sync_rsp(const void *data, uint8_t size)
> +{
> + const struct bt_hci_rsp_le_read_iso_tx_sync *rsp = data;
> + uint32_t offset = 0;
> +
> + print_status(rsp->status);
> +
> + if (size == 1)
> + return;
> +
> + print_field("Handle: %d", le16_to_cpu(rsp->handle));
> + print_field("Sequence Number: %d", le16_to_cpu(rsp->seq));
> + print_field("Timestamp: %d", le32_to_cpu(rsp->timestamp));
> +
> + memcpy(&offset, rsp->offset, sizeof(rsp->offset));
> +
> + print_field("Offset: %d", le32_to_cpu(offset));
> +}
> +
> +static void print_cis_params(const void *data)
> +{
> + const struct bt_hci_cis_params *cis = data;
> +
> + print_field("CIS ID: 0x%2.2x", cis->cis_id);
> + print_field("Master to Slave Maximum SDU Size: %u",
> + le16_to_cpu(cis->m_sdu));
> + print_field("Slave to Master Maximum SDU Size: %u",
> + le16_to_cpu(cis->s_sdu));
> + print_le_phy("Master to Slave PHY", cis->m_phy);
> + print_le_phy("Slave to Master PHY", cis->s_phy);
> + print_field("Master to Slave Retransmission attempts: 0x%2.2x",
> + cis->m_rtn);
> + print_field("Slave to Master Retransmission attempts: 0x%2.2x",
> + cis->s_rtn);
> +}
> +
> +static void print_list(const void *data, uint8_t size, int num_items,
> + size_t item_size, void (*callback)(const void *data))
> +{
> + while (size >= item_size && num_items) {
> + callback(data);
> + data += item_size;
> + size -= item_size;
> + num_items--;
> + }
> +
> + if (num_items)
> + print_hex_field("", data, size);
> +}
> +
> +static void print_usec_interval(const char *prefix, const uint8_t interval[3])
> +{
> + uint32_t u24 = 0;
> +
> + memcpy(&u24, interval, 3);
> + print_field("%s: %u us (0x%6.6x)", prefix, le32_to_cpu(u24),
> + le32_to_cpu(u24));
> +}
> +
> +static void le_set_cig_params_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_set_cig_params *cmd = data;
> +
> + print_field("CIG ID: 0x%2.2x", cmd->cig_id);
> + print_usec_interval("Master to Slave SDU Interval", cmd->m_interval);
> + print_usec_interval("Slave to Master SDU Interval", cmd->s_interval);
> + print_sca(cmd->sca);
> + print_packing(cmd->packing);
> + print_framing(cmd->framing);
> + print_field("Master to Slave Maximum Latency: %d ms (0x%4.4x)",
> + le16_to_cpu(cmd->m_latency), le16_to_cpu(cmd->m_latency));
> + print_field("Slave to Master Maximum Latency: %d ms (0x%4.4x)",
> + le16_to_cpu(cmd->s_latency), le16_to_cpu(cmd->s_latency));
> + print_field("Number of CIS: %u", cmd->num_cis);
> +
> + size -= sizeof(*cmd);
> +
> + print_list(cmd->cis, size, cmd->num_cis, sizeof(*cmd->cis),
> + print_cis_params);
> +}
> +
> +static void print_cis_params_test(const void *data)
> +{
> + const struct bt_hci_cis_params_test *cis = data;
> +
> + print_field("CIS ID: 0x%2.2x", cis->cis_id);
> + print_field("NSE: 0x%2.2x", cis->nse);
> + print_field("Master to Slave Maximum SDU: 0x%4.4x", cis->m_sdu);
> + print_field("Slave to Master Maximum SDU: 0x%4.4x",
> + le16_to_cpu(cis->s_sdu));
> + print_field("Master to Slave Maximum PDU: 0x%2.2x",
> + le16_to_cpu(cis->m_pdu));
> + print_field("Slave to Master Maximum PDU: 0x%2.2x", cis->s_pdu);
> + print_le_phy("Master to Slave PHY", cis->m_phy);
> + print_le_phy("Slave to Master PHY", cis->s_phy);
> + print_field("Master to Slave Burst Number: 0x%2.2x", cis->m_bn);
> + print_field("Slave to Master Burst Number: 0x%2.2x", cis->s_bn);
> +}
> +
> +static void le_set_cig_params_test_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_set_cig_params_test *cmd = data;
> +
> + print_field("CIG ID: 0x%2.2x", cmd->cig_id);
> + print_usec_interval("Master to Slave SDU Interval", cmd->m_interval);
> + print_usec_interval("Master to Slave SDU Interval", cmd->s_interval);
> + print_field("Master to Slave Flush Timeout: 0x%2.2x", cmd->m_ft);
> + print_field("Slave to Master Flush Timeout: 0x%2.2x", cmd->s_ft);
> + print_field("ISO Interval: %.2f ms (0x%4.4x)",
> + le16_to_cpu(cmd->iso_interval) * 1.25,
> + le16_to_cpu(cmd->iso_interval));
> + print_sca(cmd->sca);
> + print_packing(cmd->packing);
> + print_framing(cmd->framing);
> + print_field("Number of CIS: %u", cmd->num_cis);
> +
> + size -= sizeof(*cmd);
> +
> + print_list(cmd->cis, size, cmd->num_cis, sizeof(*cmd->cis),
> + print_cis_params_test);
> +}
> +
> +static void print_cig_handle(const void *data)
> +{
> + const uint16_t *handle = data;
> +
> + print_field("Connection Handle: %d", le16_to_cpu(*handle));
> +}
> +
> +static void le_set_cig_params_rsp(const void *data, uint8_t size)
> +{
> + const struct bt_hci_rsp_le_set_cig_params *rsp = data;
> +
> + print_status(rsp->status);
> +
> + if (size == 1)
> + return;
> +
> + print_field("CIG ID: 0x%2.2x", rsp->cig_id);
> + print_field("Number of Handles: %u", rsp->num_handles);
> +
> + size -= sizeof(*rsp);
> +
> + print_list(rsp->handle, size, rsp->num_handles, sizeof(*rsp->handle),
> + print_cig_handle);
> +}
> +
> +static void print_cis(const void *data)
> +{
> + const struct bt_hci_cis *cis = data;
> +
> + print_field("CIS Handle: %d", cis->cis_handle);
> + print_field("ACL Handle: %d", cis->acl_handle);
> +}
> +
> +static void le_create_cis_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_create_cis *cmd = data;
> +
> + print_field("Number of CIS: %u", cmd->num_cis);
> +
> + size -= sizeof(*cmd);
> +
> + print_list(cmd->cis, size, cmd->num_cis, sizeof(*cmd->cis), print_cis);
> +}
> +
> +static void le_remove_cig_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_remove_cig *cmd = data;
> +
> + print_field("CIG ID: 0x%02x", cmd->cig_id);
> +}
> +
> +static void le_accept_cis_req_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_accept_cis *cmd = data;
> +
> + print_field("CIS Handle: %d", le16_to_cpu(cmd->handle));
> +}
> +
> +static void le_reject_cis_req_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_reject_cis *cmd = data;
> +
> + print_field("CIS Handle: %d", le16_to_cpu(cmd->handle));
> + print_reason(cmd->reason);
> +}
> +
> +static void print_bis(const void *data)
> +{
> + const struct bt_hci_bis *bis = data;
> +
> + print_usec_interval("SDU Interval", bis->sdu_interval);
> + print_field("Maximum SDU size: %u", le16_to_cpu(bis->sdu));
> + print_field("Maximum Latency: %u ms (0x%4.4x)",
> + le16_to_cpu(bis->latency), le16_to_cpu(bis->latency));
> + print_field("RTN: 0x%2.2x", bis->rtn);
> + print_le_phy("PHY", bis->phy);
> + print_packing(bis->packing);
> + print_framing(bis->framing);
> + print_field("Encryption: 0x%2.2x", bis->encryption);
> + print_hex_field("Broadcast Code", bis->bcode, 16);
> +}
> +
> +static void le_create_big_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_create_big *cmd = data;
> +
> + print_field("BIG ID: 0x%2.2x", cmd->big_id);
> + print_field("Advertising Handle: 0x%2.2x", cmd->adv_handle);
> + print_field("Number of BIS: %u", cmd->num_bis);
> +
> + size -= sizeof(*cmd);
> +
> + print_list(cmd->bis, size, cmd->num_bis, sizeof(*cmd->bis), print_bis);
> +}
> +
> +static void print_bis_test(const void *data)
> +{
> + const struct bt_hci_bis_test *bis = data;
> +
> + print_usec_interval("SDU Interval", bis->sdu_interval);
> + print_field("ISO Interval: %.2f ms (0x%4.4x)",
> + le16_to_cpu(bis->iso_interval) * 1.25,
> + le16_to_cpu(bis->iso_interval));
> + print_field("Number of Subevents: %u", bis->nse);
> + print_field("Maximum SDU: %u", bis->sdu);
> + print_field("Maximum PDU: %u", bis->pdu);
> + print_packing(bis->packing);
> + print_framing(bis->framing);
> + print_le_phy("PHY", bis->phy);
> + print_field("Burst Number: %u", bis->bn);
> + print_field("Immediate Repetition Count: %u", bis->irc);
> + print_field("Pre Transmission Offset: 0x%2.2x", bis->pto);
> + print_field("Encryption: 0x%2.2x", bis->encryption);
> + print_hex_field("Broadcast Code", bis->bcode, 16);
> +}
> +
> +static void le_create_big_cmd_test_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_create_big_test *cmd = data;
> +
> + print_field("BIG ID: 0x%2.2x", cmd->big_id);
> + print_field("Advertising Handle: 0x%2.2x", cmd->adv_handle);
> + print_field("Number of BIS: %u", cmd->num_bis);
> +
> + size -= sizeof(*cmd);
> +
> + print_list(cmd->bis, size, cmd->num_bis, sizeof(*cmd->bis),
> + print_bis_test);
> +}
> +
> +static void le_terminate_big_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_term_big *cmd = data;
> +
> + print_field("BIG ID: 0x%2.2x", cmd->big_id);
> + print_reason(cmd->reason);
> +}
> +
> +static void print_bis_sync(const void *data)
> +{
> + const uint8_t *bis_id = data;
> +
> + print_field("BIS ID: 0x%2.2x", *bis_id);
> +}
> +
> +static void le_big_create_sync_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_big_create_sync *cmd = data;
> +
> + print_field("BIG ID: 0x%2.2x", cmd->big_id);
> + print_field("Number of BIS: %u", cmd->num_bis);
> + print_field("Encryption: 0x%2.2x", cmd->encryption);
> + print_hex_field("Broadcast Code", cmd->bcode, 16);
> + print_field("Number Subevents: 0x%2.2x", cmd->mse);
> + print_field("Timeout: %d ms (0x%4.4x)", le16_to_cpu(cmd->timeout) * 10,
> + le16_to_cpu(cmd->timeout));
> +
> + size -= sizeof(*cmd);
> +
> + print_list(cmd->bis, size, cmd->num_bis, sizeof(*cmd->bis),
> + print_bis_sync);
> +}
> +
> +static void le_big_term_sync_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_big_term_sync *cmd = data;
> +
> + print_field("BIG ID: 0x%2.2x", cmd->big_id);
> +}
> +
> +static void print_iso_path(const char *prefix, uint8_t path)
> +{
> + switch (path) {
> + case 0x00:
> + print_field("%s Data Path: Disabled (0x%2.2x)", prefix, path);
> + return;
> + case 0x01:
> + print_field("%s Data Path: HCI (0x%2.2x)", prefix, path);
> + return;
> + case 0xff:
> + print_field("%s Data Path: Test Mode (0x%2.2x)", prefix, path);
> + return;
> + default:
> + print_field("%s Data Path: Logical Channel Number (0x%2.2x)",
> + prefix, path);
> + }
> +}
> +
> +static void le_setup_iso_path_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_setup_iso_path *cmd = data;
> +
> + print_field("Handle: %d", le16_to_cpu(cmd->handle));
> + print_iso_path("Input", cmd->input_path);
> + print_iso_path("Output", cmd->output_path);
> +}
> +
> +static void print_iso_dir(uint8_t path_dir)
> +{
> + switch (path_dir) {
> + case 0x00:
> + print_field("Data Path Direction: Input (0x%2.2x)", path_dir);
> + return;
> + case 0x01:
> + print_field("Data Path Direction: Output (0x%2.2x)", path_dir);
> + return;
> + default:
> + print_field("Data Path Direction: Reserved (0x%2.2x)",
> + path_dir);
> + }
> +}
> +
> +static void le_remove_iso_path_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_remove_iso_path *cmd = data;
> +
> + print_field("Connection Handle: %d", le16_to_cpu(cmd->handle));
> + print_iso_dir(cmd->path_dir);
> +}
> +
> +static void le_req_peer_sca_cmd(const void *data, uint8_t size)
> +{
> + const struct bt_hci_cmd_le_req_peer_sca *cmd = data;
> +
> + print_field("Connection Handle: %d", le16_to_cpu(cmd->handle));
> +}
> +
> struct opcode_data {
> uint16_t opcode;
> int bit;
> @@ -8475,6 +8917,107 @@ static const struct opcode_data opcode_table[] = {
> "Parameters",
> le_set_default_periodic_adv_sync_trans_params,
> 6, true, status_rsp, 1, true},
> + { BT_HCI_CMD_LE_READ_BUFFER_SIZE_V2,
> + BT_HCI_BIT_LE_READ_BUFFER_SIZE_V2,
> + "LE Read Buffer v2",
> + null_cmd, 0, true,
> + le_read_buffer_size_v2_rsp,
> + sizeof(
> + struct bt_hci_rsp_le_read_buffer_size_v2),
> + true },
> + { BT_HCI_CMD_LE_READ_ISO_TX_SYNC,
> + BT_HCI_BIT_LE_READ_ISO_TX_SYNC,
> + "LE Read ISO TX Sync",
> + le_read_iso_tx_sync_cmd,
> + sizeof(struct bt_hci_cmd_le_read_iso_tx_sync),
> + true,
> + le_read_iso_tx_sync_rsp,
> + sizeof(struct bt_hci_rsp_le_read_iso_tx_sync),
> + true },
> + { BT_HCI_CMD_LE_SET_CIG_PARAMS, BT_HCI_BIT_LE_SET_CIG_PARAMS,
> + "LE Set Connected Isochronous Group Parameters",
> + le_set_cig_params_cmd,
> + sizeof(struct bt_hci_cmd_le_set_cig_params),
> + false,
> + le_set_cig_params_rsp,
> + sizeof(struct bt_hci_rsp_le_set_cig_params),
> + false },
> + { BT_HCI_CMD_LE_SET_CIG_PARAMS_TEST, BT_HCI_BIT_LE_SET_CIG_PARAMS_TEST,
> + "LE Set Connected Isochronous Group Parameters"
> + " Test", le_set_cig_params_test_cmd,
> + sizeof(
> + struct bt_hci_cmd_le_set_cig_params_test),
> + false,
> + le_set_cig_params_rsp,
> + sizeof(struct bt_hci_rsp_le_set_cig_params),
> + false },
> + { BT_HCI_CMD_LE_CREATE_CIS, BT_HCI_BIT_LE_CREATE_CIS,
> + "LE Create Connected Isochronous Stream",
> + le_create_cis_cmd,
> + sizeof(struct bt_hci_cmd_le_create_cis),
> + false },
> + { BT_HCI_CMD_LE_REMOVE_CIG, BT_HCI_BIT_LE_REMOVE_CIG,
> + "LE Remove Connected Isochronous Group",
> + le_remove_cig_cmd,
> + sizeof(struct bt_hci_cmd_le_remove_cig), false,
> + status_rsp, 1, true },
> + { BT_HCI_CMD_LE_ACCEPT_CIS, BT_HCI_BIT_LE_ACCEPT_CIS,
> + "LE Accept Connected Isochronous Stream Request",
> + le_accept_cis_req_cmd,
> + sizeof(struct bt_hci_cmd_le_accept_cis), true },
> + { BT_HCI_CMD_LE_REJECT_CIS, BT_HCI_BIT_LE_REJECT_CIS,
> + "LE Reject Connected Isochronous Stream Request",
> + le_reject_cis_req_cmd,
> + sizeof(struct bt_hci_cmd_le_reject_cis), true,
> + status_rsp, 1, true },
> + { BT_HCI_CMD_LE_CREATE_BIG, BT_HCI_BIT_LE_CREATE_BIG,
> + "LE Create Broadcast Isochronous Group",
> + le_create_big_cmd },
> + { BT_HCI_CMD_LE_CREATE_BIG_TEST, BT_HCI_BIT_LE_CREATE_BIG_TEST,
> + "LE Create Broadcast Isochronous Group Test",
> + le_create_big_cmd_test_cmd },
> + { BT_HCI_CMD_LE_TERM_BIG, BT_HCI_BIT_LE_TERM_BIG,
> + "LE Terminate Broadcast Isochronous Group",
> + le_terminate_big_cmd,
> + sizeof(struct bt_hci_cmd_le_term_big), true,
> + status_rsp, 1, true},
> + { BT_HCI_CMD_LE_BIG_CREATE_SYNC, BT_HCI_BIT_LE_BIG_CREATE_SYNC,
> + "LE Broadcast Isochronous Group Create Sync",
> + le_big_create_sync_cmd,
> + sizeof(struct bt_hci_cmd_le_big_create_sync),
> + true },
> + { BT_HCI_CMD_LE_BIG_TERM_SYNC, BT_HCI_BIT_LE_BIG_TERM_SYNC,
> + "LE Broadcast Isochronous Group Terminate Sync",
> + le_big_term_sync_cmd,
> + sizeof(struct bt_hci_cmd_le_big_term_sync),
> + true },
> + { BT_HCI_CMD_LE_REQ_PEER_SCA, BT_HCI_BIT_LE_REQ_PEER_SCA,
> + "LE Request Peer SCA", le_req_peer_sca_cmd,
> + sizeof(struct bt_hci_cmd_le_req_peer_sca),
> + true },
> + { BT_HCI_CMD_LE_SETUP_ISO_PATH, BT_HCI_BIT_LE_SETUP_ISO_PATH,
> + "LE Setup Isochronous Data Path",
> + le_setup_iso_path_cmd,
> + sizeof(struct bt_hci_cmd_le_setup_iso_path),
> + true, status_rsp, 1, true },
> + { BT_HCI_CMD_LE_REMOVE_ISO_PATH, BT_HCI_BIT_LE_REMOVE_ISO_PATH,
> + "LE Remove Isochronous Data Path",
> + le_remove_iso_path_cmd,
> + sizeof(struct bt_hci_cmd_le_remove_iso_path),
> + true, status_rsp, 1, true },
> + { BT_HCI_CMD_LE_ISO_TX_TEST, BT_HCI_BIT_LE_ISO_TX_TEST,
> + "LE Isochronous Transmit Test", NULL, 0,
> + false },
> + { BT_HCI_CMD_LE_ISO_RX_TEST, BT_HCI_BIT_LE_ISO_RX_TEST,
> + "LE Isochronous Receive Test", NULL, 0,
> + false },
> + { BT_HCI_CMD_LE_ISO_READ_TEST_COUNTER,
> + BT_HCI_BIT_LE_ISO_READ_TEST_COUNTER,
> + "LE Isochronous Read Test Counters", NULL, 0,
> + false },
> + { BT_HCI_CMD_LE_ISO_TEST_END, BT_HCI_BIT_LE_ISO_TEST_END,
> + "LE Isochronous Read Test Counters", NULL, 0,
> + false },
> { }
> };
>
> @@ -9912,6 +10455,94 @@ static void le_per_adv_sync_trans_rec_evt(const void *data, uint8_t size)
> print_clock_accuracy(evt->clock_accuracy);
> }
>
> +static void le_cis_established_evt(const void *data, uint8_t size)
> +{
> + const struct bt_hci_evt_le_cis_established *evt = data;
> +
> + print_status(evt->status);
> + print_field("Connection Handle: %d", le16_to_cpu(evt->conn_handle));
> + print_usec_interval("CIG Synchronization Delay", evt->cig_sync_delay);
> + print_usec_interval("CIS Synchronization Delay", evt->cis_sync_delay);
> + print_usec_interval("Master to Slave Latency", evt->m_latency);
> + print_usec_interval("Slave to Master Latency", evt->s_latency);
> + print_le_phy("Master to Slave PHY", evt->m_phy);
> + print_le_phy("Slave to Master PHY", evt->s_phy);
> + print_field("Number of Subevents: %u", evt->nse);
> + print_field("Master to Slave Burst Number: %u", evt->m_bn);
> + print_field("Slave to Master Burst Number: %u", evt->s_bn);
> + print_field("Master to Slave Flush Timeout: %u", evt->m_ft);
> + print_field("Slave to Master Flush Timeout: %u", evt->s_ft);
> + print_field("Master to Slave MTU: %u", le16_to_cpu(evt->m_mtu));
> + print_field("Slave to Master MTU: %u", le16_to_cpu(evt->s_mtu));
> + print_field("ISO Interval: %u", le16_to_cpu(evt->interval));
> +}
> +
> +static void le_req_cis_evt(const void *data, uint8_t size)
> +{
> + const struct bt_hci_evt_le_cis_req *evt = data;
> +
> + print_field("ACL Handle: %d", le16_to_cpu(evt->acl_handle));
> + print_field("CIS Handle: %d", le16_to_cpu(evt->cis_handle));
> + print_field("CIG ID: 0x%2.2x", evt->cig_id);
> + print_field("CIS ID: 0x%2.2x", evt->cis_id);
> +}
> +
> +static void print_bis_handle(const void *data)
> +{
> + const uint16_t *handle = data;
> +
> + print_field("Connection Handle: %d", le16_to_cpu(*handle));
> +}
> +
> +static void le_big_complete_evt(const void *data, uint8_t size)
> +{
> + const struct bt_hci_evt_le_big_complete *evt = data;
> +
> + print_status(evt->status);
> + print_field("BIG ID: 0x%2.2x", evt->big_id);
> + print_usec_interval("BIG Synchronization Delay", evt->sync_delay);
> + print_usec_interval("Transport Latency", evt->latency);
> + print_le_phy("PHY", evt->phy);
> + print_list(evt->handle, size, evt->num_bis, sizeof(*evt->handle),
> + print_bis_handle);
> +}
> +
> +static void le_big_terminate_evt(const void *data, uint8_t size)
> +{
> + const struct bt_hci_evt_le_big_terminate *evt = data;
> +
> + print_reason(evt->reason);
> + print_field("BIG ID: 0x%2.2x", evt->big_id);
> +}
> +
> +static void le_big_sync_estabilished_evt(const void *data, uint8_t size)
> +{
> + const struct bt_hci_evt_le_big_sync_estabilished *evt = data;
> +
> + print_status(evt->status);
> + print_field("BIG ID: 0x%2.2x", evt->big_id);
> + print_usec_interval("Transport Latency", evt->latency);
> + print_list(evt->handle, size, evt->num_bis, sizeof(*evt->handle),
> + print_bis_handle);
> +}
> +
> +static void le_big_sync_lost_evt(const void *data, uint8_t size)
> +{
> + const struct bt_hci_evt_le_big_sync_lost *evt = data;
> +
> + print_field("BIG ID: 0x%2.2x", evt->big_id);
> + print_reason(evt->reason);
> +}
> +
> +static void le_req_sca_complete_evt(const void *data, uint8_t size)
> +{
> + const struct bt_hci_evt_le_req_peer_sca_complete *evt = data;
> +
> + print_status(evt->status);
> + print_field("Connection Handle: %d", le16_to_cpu(evt->handle));
> + print_sca(evt->sca);
> +}
> +
> struct subevent_data {
> uint8_t subevent;
> const char *str;
> @@ -10000,6 +10631,36 @@ static const struct subevent_data le_meta_event_table[] = {
> { 0x18, "LE Periodic Advertising Sync Transfer Received",
> le_per_adv_sync_trans_rec_evt, 19,
> true},
> + { BT_HCI_EVT_LE_CIS_ESTABLISHED,
> + "LE Connected Isochronous Stream Established",
> + le_cis_established_evt,
> + sizeof(struct bt_hci_evt_le_cis_established),
> + true },
> + { BT_HCI_EVT_LE_CIS_REQ, "LE Connected Isochronous Stream Request",
> + le_req_cis_evt,
> + sizeof(struct bt_hci_evt_le_cis_req),
> + true },
> + { BT_HCI_EVT_LE_BIG_COMPLETE,
> + "LE Broadcast Isochronous Group Complete",
> + le_big_complete_evt,
> + sizeof(struct bt_hci_evt_le_big_complete) },
> + { BT_HCI_EVT_LE_BIG_TERMINATE,
> + "LE Broadcast Isochronous Group Terminate",
> + le_big_terminate_evt,
> + sizeof(struct bt_hci_evt_le_big_terminate) },
> + { BT_HCI_EVT_LE_BIG_SYNC_ESTABILISHED,
> + "LE Broadcast Isochronous Group Sync "
> + "Estabilished", le_big_sync_estabilished_evt,
> + sizeof(struct bt_hci_evt_le_big_sync_lost) },
> + { BT_HCI_EVT_LE_BIG_SYNC_LOST,
> + "LE Broadcast Isochronous Group Sync Lost",
> + le_big_sync_lost_evt,
> + sizeof(struct bt_hci_evt_le_big_sync_lost) },
> + { BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE,
> + "LE Request Peer SCA Complete",
> + le_req_sca_complete_evt,
> + sizeof(
> + struct bt_hci_evt_le_req_peer_sca_complete)},
> { }
> };
>
> --
> 2.21.0
Applied.
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-02-03 21:30 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-28 20:13 [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 2/6] monitor: Add decoding of ISO related Link Layer PDUs Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 3/6] monitor: Add support for ISO packets Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 4/6] monitor: Add decoding for L2CAP Enhanced Credit Based PDUs Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 5/6] emulator: Add initial support for BT 5.2 Luiz Augusto von Dentz
2020-01-28 20:13 ` [PATCH BlueZ 6/6] tools/btproxy: Add support for ISO packets Luiz Augusto von Dentz
2020-02-03 21:30 ` [PATCH BlueZ 1/6] monitor: Add support for decoding ISO related commands Luiz Augusto von Dentz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).