diff mbox series

[BlueZ,2/2] monitor: Detect LE-ACL connections

Message ID 20230816223147.2787284-2-luiz.dentz@gmail.com
State New
Headers show
Series [BlueZ,1/2] monitor: Fix not printing latency information with -r | expand

Commit Message

Luiz Augusto von Dentz Aug. 16, 2023, 10:31 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This enables LE-ACL connections to be detected by processing its events
otherwise they would be assumed to be BR-ACL. Also make sure that LE-ISO
address is set based on its ACL link.
---
 monitor/analyze.c | 88 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 84 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/monitor/analyze.c b/monitor/analyze.c
index 608ef4d77c85..3cc482cd9227 100644
--- a/monitor/analyze.c
+++ b/monitor/analyze.c
@@ -71,6 +71,7 @@  struct hci_stats {
 
 struct hci_conn {
 	uint16_t handle;
+	uint16_t link;
 	uint8_t type;
 	uint8_t bdaddr[6];
 	bool setup_seen;
@@ -290,6 +291,20 @@  static struct hci_conn *conn_lookup(struct hci_dev *dev, uint16_t handle)
 						UINT_TO_PTR(handle));
 }
 
+static bool link_match_handle(const void *a, const void *b)
+{
+	const struct hci_conn *conn = a;
+	uint16_t handle = PTR_TO_UINT(b);
+
+	return (conn->link == handle && !conn->terminated);
+}
+
+static struct hci_conn *link_lookup(struct hci_dev *dev, uint16_t handle)
+{
+	return queue_find(dev->conn_list, link_match_handle,
+						UINT_TO_PTR(handle));
+}
+
 static struct hci_conn *conn_lookup_type(struct hci_dev *dev, uint16_t handle,
 								uint8_t type)
 {
@@ -297,7 +312,7 @@  static struct hci_conn *conn_lookup_type(struct hci_dev *dev, uint16_t handle,
 
 	conn = queue_find(dev->conn_list, conn_match_handle,
 						UINT_TO_PTR(handle));
-	if (!conn || conn->type != type) {
+	if (!conn || (type && conn->type != type)) {
 		conn = conn_alloc(dev, handle, type);
 		queue_push_tail(dev->conn_list, conn);
 	}
@@ -542,6 +557,42 @@  static void plot_add(struct queue *queue, struct timeval *latency,
 	queue_push_tail(queue, plot);
 }
 
+static void evt_le_conn_complete(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_conn_complete *evt;
+	struct hci_conn *conn;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt || evt->status)
+		return;
+
+	conn = conn_lookup_type(dev, le16_to_cpu(evt->handle), CONN_LE_ACL);
+	if (!conn)
+		return;
+
+	memcpy(conn->bdaddr, evt->peer_addr, 6);
+	conn->setup_seen = true;
+}
+
+static void evt_le_enh_conn_complete(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_enhanced_conn_complete *evt;
+	struct hci_conn *conn;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt || evt->status)
+		return;
+
+	conn = conn_lookup_type(dev, le16_to_cpu(evt->handle), CONN_LE_ACL);
+	if (!conn)
+		return;
+
+	memcpy(conn->bdaddr, evt->peer_addr, 6);
+	conn->setup_seen = true;
+}
+
 static void evt_num_completed_packets(struct hci_dev *dev, struct timeval *tv,
 					const void *data, uint16_t size)
 {
@@ -612,7 +663,7 @@  static void evt_le_cis_established(struct hci_dev *dev, struct timeval *tv,
 					struct iovec *iov)
 {
 	const struct bt_hci_evt_le_cis_established *evt;
-	struct hci_conn *conn;
+	struct hci_conn *conn, *link;
 
 	evt = util_iov_pull_mem(iov, sizeof(*evt));
 	if (!evt || evt->status)
@@ -624,6 +675,27 @@  static void evt_le_cis_established(struct hci_dev *dev, struct timeval *tv,
 		return;
 
 	conn->setup_seen = true;
+
+	link = link_lookup(dev, conn->handle);
+	if (link)
+		memcpy(conn->bdaddr, link->bdaddr, 6);
+}
+
+static void evt_le_cis_req(struct hci_dev *dev, struct timeval *tv,
+					struct iovec *iov)
+{
+	const struct bt_hci_evt_le_cis_req *evt;
+	struct hci_conn *conn;
+
+	evt = util_iov_pull_mem(iov, sizeof(*evt));
+	if (!evt)
+		return;
+
+	conn = conn_lookup(dev, le16_to_cpu(evt->acl_handle));
+	if (!conn)
+		return;
+
+	conn->link = le16_to_cpu(evt->cis_handle);
 }
 
 static void evt_le_big_complete(struct hci_dev *dev, struct timeval *tv,
@@ -685,9 +757,18 @@  static void evt_le_meta_event(struct hci_dev *dev, struct timeval *tv,
 		return;
 
 	switch (subevt) {
+	case BT_HCI_EVT_LE_CONN_COMPLETE:
+		evt_le_conn_complete(dev, tv, &iov);
+		break;
+	case BT_HCI_EVT_LE_ENHANCED_CONN_COMPLETE:
+		evt_le_enh_conn_complete(dev, tv, &iov);
+		break;
 	case BT_HCI_EVT_LE_CIS_ESTABLISHED:
 		evt_le_cis_established(dev, tv, &iov);
 		break;
+	case BT_HCI_EVT_LE_CIS_REQ:
+		evt_le_cis_req(dev, tv, &iov);
+		break;
 	case BT_HCI_EVT_LE_BIG_COMPLETE:
 		evt_le_big_complete(dev, tv, &iov);
 		break;
@@ -811,8 +892,7 @@  static void acl_pkt(struct timeval *tv, uint16_t index, bool out,
 	dev->num_hci++;
 	dev->num_acl++;
 
-	conn = conn_lookup_type(dev, le16_to_cpu(hdr->handle) & 0x0fff,
-								CONN_BR_ACL);
+	conn = conn_lookup_type(dev, le16_to_cpu(hdr->handle) & 0x0fff, 0x00);
 	if (!conn)
 		return;