Bluetooth: hci_sync: Convert MGMT_OP_READ_LOCAL_OOB_DATA
authorBrian Gix <brian.gix@intel.com>
Wed, 27 Oct 2021 23:58:52 +0000 (16:58 -0700)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 29 Oct 2021 14:51:59 +0000 (16:51 +0200)
New functions:
  hci_read_local_oob_data_sync

This function requires all of the data from the cmd cmplt event
to be passed up to the caller via the skb.

mgmt-tester paths:
Read Local OOB Data - Not powered
Read Local OOB Data - Legacy pairing
Read Local OOB Data - Success SSP
Read Local OOB Data - Success SC

Signed-off-by: Brian Gix <brian.gix@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci_sync.h
net/bluetooth/hci_sync.c
net/bluetooth/mgmt.c
net/bluetooth/mgmt_util.h

index d969693..a381621 100644 (file)
@@ -78,6 +78,8 @@ int hci_update_scan_sync(struct hci_dev *hdev);
 int hci_write_le_host_supported_sync(struct hci_dev *hdev, u8 le, u8 simul);
 int hci_remove_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance,
                                     struct sock *sk);
+struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev, bool ext,
+                                            struct sock *sk);
 
 int hci_dev_open_sync(struct hci_dev *hdev);
 int hci_dev_close_sync(struct hci_dev *hdev);
index 877f5b9..a0a5c27 100644 (file)
@@ -1703,6 +1703,15 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
        return err;
 }
 
+struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
+                                            bool extended, struct sock *sk)
+{
+       u16 opcode = extended ? HCI_OP_READ_LOCAL_OOB_EXT_DATA :
+                                       HCI_OP_READ_LOCAL_OOB_DATA;
+
+       return __hci_cmd_sync_sk(hdev, opcode, 0, NULL, 0, HCI_CMD_TIMEOUT, sk);
+}
+
 /* Device must not be scanning when updating the accept list.
  *
  * Update is done using the following sequence:
index 82369db..6bd75ec 100644 (file)
@@ -4793,28 +4793,33 @@ unlock:
                               status);
 }
 
-static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
-                                        u16 opcode, struct sk_buff *skb)
+static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int err)
 {
        struct mgmt_rp_read_local_oob_data mgmt_rp;
        size_t rp_size = sizeof(mgmt_rp);
-       struct mgmt_pending_cmd *cmd;
+       struct mgmt_pending_cmd *cmd = data;
+       struct sk_buff *skb = cmd->skb;
+       u8 status = mgmt_status(err);
 
-       bt_dev_dbg(hdev, "status %u", status);
+       if (!status) {
+               if (!skb)
+                       status = MGMT_STATUS_FAILED;
+               else if (IS_ERR(skb))
+                       status = mgmt_status(PTR_ERR(skb));
+               else
+                       status = mgmt_status(skb->data[0]);
+       }
 
-       cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
-       if (!cmd)
-               return;
+       bt_dev_dbg(hdev, "status %d", status);
 
-       if (status || !skb) {
-               mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
-                               status ? mgmt_status(status) : MGMT_STATUS_FAILED);
+       if (status) {
+               mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, status);
                goto remove;
        }
 
        memset(&mgmt_rp, 0, sizeof(mgmt_rp));
 
-       if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
+       if (!bredr_sc_enabled(hdev)) {
                struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
 
                if (skb->len < sizeof(*rp)) {
@@ -4849,14 +4854,31 @@ static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
                          MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
 
 remove:
-       mgmt_pending_remove(cmd);
+       if (skb && !IS_ERR(skb))
+               kfree_skb(skb);
+
+       mgmt_pending_free(cmd);
+}
+
+static int read_local_oob_data_sync(struct hci_dev *hdev, void *data)
+{
+       struct mgmt_pending_cmd *cmd = data;
+
+       if (bredr_sc_enabled(hdev))
+               cmd->skb = hci_read_local_oob_data_sync(hdev, true, cmd->sk);
+       else
+               cmd->skb = hci_read_local_oob_data_sync(hdev, false, cmd->sk);
+
+       if (IS_ERR(cmd->skb))
+               return PTR_ERR(cmd->skb);
+       else
+               return 0;
 }
 
 static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
                               void *data, u16 data_len)
 {
        struct mgmt_pending_cmd *cmd;
-       struct hci_request req;
        int err;
 
        bt_dev_dbg(hdev, "sock %p", sk);
@@ -4881,22 +4903,20 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
                goto unlock;
        }
 
-       cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
-       if (!cmd) {
+       cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
+       if (!cmd)
                err = -ENOMEM;
-               goto unlock;
-       }
-
-       hci_req_init(&req, hdev);
-
-       if (bredr_sc_enabled(hdev))
-               hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
        else
-               hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
+               err = hci_cmd_sync_queue(hdev, read_local_oob_data_sync, cmd,
+                                        read_local_oob_data_complete);
 
-       err = hci_req_run_skb(&req, read_local_oob_data_complete);
-       if (err < 0)
-               mgmt_pending_remove(cmd);
+       if (err < 0) {
+               err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
+                                     MGMT_STATUS_FAILED);
+
+               if (cmd)
+                       mgmt_pending_free(cmd);
+       }
 
 unlock:
        hci_dev_unlock(hdev);
index 9dc24ba..63b965e 100644 (file)
@@ -27,6 +27,7 @@ struct mgmt_pending_cmd {
        void *param;
        size_t param_len;
        struct sock *sk;
+       struct sk_buff *skb;
        void *user_data;
        int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
 };