]> git.ipfire.org Git - thirdparty/kernel/linux.git/blobdiff - net/bluetooth/hci_event.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
[thirdparty/kernel/linux.git] / net / bluetooth / hci_event.c
index d72d238c1656ed442aa89c3026dbafb9ac1cdf6b..a487f9df81450fe92b58b67503e9c9fddc888c14 100644 (file)
@@ -1,7 +1,7 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
-   Copyright 2023 NXP
+   Copyright 2023-2024 NXP
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -913,21 +913,6 @@ static u8 hci_cc_read_local_ext_features(struct hci_dev *hdev, void *data,
        return rp->status;
 }
 
-static u8 hci_cc_read_flow_control_mode(struct hci_dev *hdev, void *data,
-                                       struct sk_buff *skb)
-{
-       struct hci_rp_read_flow_control_mode *rp = data;
-
-       bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
-
-       if (rp->status)
-               return rp->status;
-
-       hdev->flow_ctl_mode = rp->mode;
-
-       return rp->status;
-}
-
 static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data,
                                  struct sk_buff *skb)
 {
@@ -954,6 +939,9 @@ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data,
        BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
               hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
 
+       if (!hdev->acl_mtu || !hdev->acl_pkts)
+               return HCI_ERROR_INVALID_PARAMETERS;
+
        return rp->status;
 }
 
@@ -1068,28 +1056,6 @@ static u8 hci_cc_write_page_scan_type(struct hci_dev *hdev, void *data,
        return rp->status;
 }
 
-static u8 hci_cc_read_data_block_size(struct hci_dev *hdev, void *data,
-                                     struct sk_buff *skb)
-{
-       struct hci_rp_read_data_block_size *rp = data;
-
-       bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
-
-       if (rp->status)
-               return rp->status;
-
-       hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
-       hdev->block_len = __le16_to_cpu(rp->block_len);
-       hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
-
-       hdev->block_cnt = hdev->num_blocks;
-
-       BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
-              hdev->block_cnt, hdev->block_len);
-
-       return rp->status;
-}
-
 static u8 hci_cc_read_clock(struct hci_dev *hdev, void *data,
                            struct sk_buff *skb)
 {
@@ -1124,30 +1090,6 @@ unlock:
        return rp->status;
 }
 
-static u8 hci_cc_read_local_amp_info(struct hci_dev *hdev, void *data,
-                                    struct sk_buff *skb)
-{
-       struct hci_rp_read_local_amp_info *rp = data;
-
-       bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
-
-       if (rp->status)
-               return rp->status;
-
-       hdev->amp_status = rp->amp_status;
-       hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
-       hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
-       hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
-       hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
-       hdev->amp_type = rp->amp_type;
-       hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
-       hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
-       hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
-       hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
-
-       return rp->status;
-}
-
 static u8 hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, void *data,
                                       struct sk_buff *skb)
 {
@@ -1263,6 +1205,9 @@ static u8 hci_cc_le_read_buffer_size(struct hci_dev *hdev, void *data,
 
        BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
 
+       if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
+               return HCI_ERROR_INVALID_PARAMETERS;
+
        return rp->status;
 }
 
@@ -1779,8 +1724,7 @@ static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable)
                hci_dev_set_flag(hdev, HCI_LE_SCAN);
                if (hdev->le_scan_type == LE_SCAN_ACTIVE)
                        clear_pending_adv_report(hdev);
-               if (hci_dev_test_flag(hdev, HCI_MESH))
-                       hci_discovery_set_state(hdev, DISCOVERY_FINDING);
+               hci_discovery_set_state(hdev, DISCOVERY_FINDING);
                break;
 
        case LE_SCAN_DISABLE:
@@ -2342,8 +2286,8 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
                if (!conn) {
                        conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
                                                  HCI_ROLE_MASTER);
-                       if (!conn)
-                               bt_dev_err(hdev, "no memory for new connection");
+                       if (IS_ERR(conn))
+                               bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
                }
        }
 
@@ -3154,8 +3098,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
                                                      BDADDR_BREDR)) {
                        conn = hci_conn_add_unset(hdev, ev->link_type,
                                                  &ev->bdaddr, HCI_ROLE_SLAVE);
-                       if (!conn) {
-                               bt_dev_err(hdev, "no memory for new conn");
+                       if (IS_ERR(conn)) {
+                               bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
                                goto unlock;
                        }
                } else {
@@ -3343,8 +3287,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
        if (!conn) {
                conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
                                          HCI_ROLE_SLAVE);
-               if (!conn) {
-                       bt_dev_err(hdev, "no memory for new connection");
+               if (IS_ERR(conn)) {
+                       bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
                        goto unlock;
                }
        }
@@ -3821,6 +3765,9 @@ static u8 hci_cc_le_read_buffer_size_v2(struct hci_dev *hdev, void *data,
        BT_DBG("%s acl mtu %d:%d iso mtu %d:%d", hdev->name, hdev->acl_mtu,
               hdev->acl_pkts, hdev->iso_mtu, hdev->iso_pkts);
 
+       if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
+               return HCI_ERROR_INVALID_PARAMETERS;
+
        return rp->status;
 }
 
@@ -4112,12 +4059,6 @@ static const struct hci_cc {
        HCI_CC(HCI_OP_READ_PAGE_SCAN_TYPE, hci_cc_read_page_scan_type,
               sizeof(struct hci_rp_read_page_scan_type)),
        HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_TYPE, hci_cc_write_page_scan_type),
-       HCI_CC(HCI_OP_READ_DATA_BLOCK_SIZE, hci_cc_read_data_block_size,
-              sizeof(struct hci_rp_read_data_block_size)),
-       HCI_CC(HCI_OP_READ_FLOW_CONTROL_MODE, hci_cc_read_flow_control_mode,
-              sizeof(struct hci_rp_read_flow_control_mode)),
-       HCI_CC(HCI_OP_READ_LOCAL_AMP_INFO, hci_cc_read_local_amp_info,
-              sizeof(struct hci_rp_read_local_amp_info)),
        HCI_CC(HCI_OP_READ_CLOCK, hci_cc_read_clock,
               sizeof(struct hci_rp_read_clock)),
        HCI_CC(HCI_OP_READ_ENC_KEY_SIZE, hci_cc_read_enc_key_size,
@@ -4308,7 +4249,7 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
        hci_dev_lock(hdev);
 
        /* Remove connection if command failed */
-       for (i = 0; cp->num_cis; cp->num_cis--, i++) {
+       for (i = 0; i < cp->num_cis; i++) {
                struct hci_conn *conn;
                u16 handle;
 
@@ -4324,6 +4265,7 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
                        hci_conn_del(conn);
                }
        }
+       cp->num_cis = 0;
 
        if (pending)
                hci_le_create_cis_pending(hdev);
@@ -4452,11 +4394,6 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
                             flex_array_size(ev, handles, ev->num)))
                return;
 
-       if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
-               bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
-               return;
-       }
-
        bt_dev_dbg(hdev, "num %d", ev->num);
 
        for (i = 0; i < ev->num; i++) {
@@ -4524,78 +4461,6 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
        queue_work(hdev->workqueue, &hdev->tx_work);
 }
 
-static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
-                                                __u16 handle)
-{
-       struct hci_chan *chan;
-
-       switch (hdev->dev_type) {
-       case HCI_PRIMARY:
-               return hci_conn_hash_lookup_handle(hdev, handle);
-       case HCI_AMP:
-               chan = hci_chan_lookup_handle(hdev, handle);
-               if (chan)
-                       return chan->conn;
-               break;
-       default:
-               bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type);
-               break;
-       }
-
-       return NULL;
-}
-
-static void hci_num_comp_blocks_evt(struct hci_dev *hdev, void *data,
-                                   struct sk_buff *skb)
-{
-       struct hci_ev_num_comp_blocks *ev = data;
-       int i;
-
-       if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS,
-                            flex_array_size(ev, handles, ev->num_hndl)))
-               return;
-
-       if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
-               bt_dev_err(hdev, "wrong event for mode %d",
-                          hdev->flow_ctl_mode);
-               return;
-       }
-
-       bt_dev_dbg(hdev, "num_blocks %d num_hndl %d", ev->num_blocks,
-                  ev->num_hndl);
-
-       for (i = 0; i < ev->num_hndl; i++) {
-               struct hci_comp_blocks_info *info = &ev->handles[i];
-               struct hci_conn *conn = NULL;
-               __u16  handle, block_count;
-
-               handle = __le16_to_cpu(info->handle);
-               block_count = __le16_to_cpu(info->blocks);
-
-               conn = __hci_conn_lookup_handle(hdev, handle);
-               if (!conn)
-                       continue;
-
-               conn->sent -= block_count;
-
-               switch (conn->type) {
-               case ACL_LINK:
-               case AMP_LINK:
-                       hdev->block_cnt += block_count;
-                       if (hdev->block_cnt > hdev->num_blocks)
-                               hdev->block_cnt = hdev->num_blocks;
-                       break;
-
-               default:
-                       bt_dev_err(hdev, "unknown type %d conn %p",
-                                  conn->type, conn);
-                       break;
-               }
-       }
-
-       queue_work(hdev->workqueue, &hdev->tx_work);
-}
-
 static void hci_mode_change_evt(struct hci_dev *hdev, void *data,
                                struct sk_buff *skb)
 {
@@ -5768,8 +5633,8 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
                        goto unlock;
 
                conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
-               if (!conn) {
-                       bt_dev_err(hdev, "no memory for new connection");
+               if (IS_ERR(conn)) {
+                       bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
                        goto unlock;
                }
 
@@ -6493,14 +6358,16 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
        if (!(flags & HCI_PROTO_DEFER))
                goto unlock;
 
-       if (ev->status) {
-               /* Add connection to indicate the failed PA sync event */
-               pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
-                                            HCI_ROLE_SLAVE);
+       /* Add connection to indicate PA sync event */
+       pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
+                                    HCI_ROLE_SLAVE);
 
-               if (!pa_sync)
-                       goto unlock;
+       if (IS_ERR(pa_sync))
+               goto unlock;
 
+       pa_sync->sync_handle = le16_to_cpu(ev->handle);
+
+       if (ev->status) {
                set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
 
                /* Notify iso layer */
@@ -6517,6 +6384,7 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data,
        struct hci_ev_le_per_adv_report *ev = data;
        int mask = hdev->link_mode;
        __u8 flags = 0;
+       struct hci_conn *pa_sync;
 
        bt_dev_dbg(hdev, "sync_handle 0x%4.4x", le16_to_cpu(ev->sync_handle));
 
@@ -6524,8 +6392,28 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data,
 
        mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
        if (!(mask & HCI_LM_ACCEPT))
-               hci_le_pa_term_sync(hdev, ev->sync_handle);
+               goto unlock;
+
+       if (!(flags & HCI_PROTO_DEFER))
+               goto unlock;
+
+       pa_sync = hci_conn_hash_lookup_pa_sync_handle
+                       (hdev,
+                       le16_to_cpu(ev->sync_handle));
+
+       if (!pa_sync)
+               goto unlock;
+
+       if (ev->data_status == LE_PA_DATA_COMPLETE &&
+           !test_and_set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags)) {
+               /* Notify iso layer */
+               hci_connect_cfm(pa_sync, 0);
+
+               /* Notify MGMT layer */
+               mgmt_device_connected(hdev, pa_sync, NULL, 0);
+       }
 
+unlock:
        hci_dev_unlock(hdev);
 }
 
@@ -6898,7 +6786,7 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data,
        if (!cis) {
                cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE,
                                   cis_handle);
-               if (!cis) {
+               if (IS_ERR(cis)) {
                        hci_le_reject_cis(hdev, ev->cis_handle);
                        goto unlock;
                }
@@ -7007,7 +6895,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
                if (!bis) {
                        bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
                                           HCI_ROLE_SLAVE, handle);
-                       if (!bis)
+                       if (IS_ERR(bis))
                                continue;
                }
 
@@ -7060,10 +6948,8 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
        hci_dev_lock(hdev);
 
        mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
-       if (!(mask & HCI_LM_ACCEPT)) {
-               hci_le_pa_term_sync(hdev, ev->sync_handle);
+       if (!(mask & HCI_LM_ACCEPT))
                goto unlock;
-       }
 
        if (!(flags & HCI_PROTO_DEFER))
                goto unlock;
@@ -7072,24 +6958,11 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
                        (hdev,
                        le16_to_cpu(ev->sync_handle));
 
-       if (pa_sync)
-               goto unlock;
-
-       /* Add connection to indicate the PA sync event */
-       pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
-                                    HCI_ROLE_SLAVE);
-
        if (!pa_sync)
                goto unlock;
 
-       pa_sync->sync_handle = le16_to_cpu(ev->sync_handle);
-       set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags);
-
        /* Notify iso layer */
-       hci_connect_cfm(pa_sync, 0x00);
-
-       /* Notify MGMT layer */
-       mgmt_device_connected(hdev, pa_sync, NULL, 0);
+       hci_connect_cfm(pa_sync, 0);
 
 unlock:
        hci_dev_unlock(hdev);
@@ -7503,9 +7376,6 @@ static const struct hci_ev {
        /* [0x3e = HCI_EV_LE_META] */
        HCI_EV_REQ_VL(HCI_EV_LE_META, hci_le_meta_evt,
                      sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
-       /* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
-       HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
-              sizeof(struct hci_ev_num_comp_blocks)),
        /* [0xff = HCI_EV_VENDOR] */
        HCI_EV_VL(HCI_EV_VENDOR, msft_vendor_evt, 0, HCI_MAX_EVENT_SIZE),
 };