linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).