monitor: Detect LE-ACL connections
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 16 Aug 2023 22:28:41 +0000 (15:28 -0700)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 5 Jan 2024 13:34:03 +0000 (19:04 +0530)
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

index 7d0d6dd..a7df077 100755 (executable)
@@ -73,6 +73,7 @@ struct hci_stats {
 
 struct hci_conn {
        uint16_t handle;
+       uint16_t link;
        uint8_t type;
        uint8_t bdaddr[6];
        bool setup_seen;
@@ -292,6 +293,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)
 {
@@ -299,7 +314,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);
        }
@@ -544,6 +559,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)
 {
@@ -614,7 +665,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)
@@ -626,6 +677,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,
@@ -687,9 +759,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;
@@ -813,8 +894,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;