Bluetooth: Fix issue where start_le_discovery_complete() was not called 46/317446/1
authorWootak Jung <wootak.jung@samsung.com>
Mon, 25 Nov 2024 01:14:16 +0000 (10:14 +0900)
committerJaehoon Chung <jh80.chung@samsung.com>
Thu, 2 Jan 2025 06:09:06 +0000 (15:09 +0900)
Change-Id: I850cf1a1b66088fcd006ebd51515e72ffac6b284
Signed-off-by: Wootak Jung <wootak.jung@samsung.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
include/net/bluetooth/hci_sync.h
net/bluetooth/hci_core.c
net/bluetooth/hci_sync.c
net/bluetooth/mgmt.c

index e2582c242544982c73b0a442759a3e48267c5390..d5b4e5f20f8785dbe5e1954fd643eb81a608a571 100644 (file)
@@ -138,3 +138,8 @@ int hci_le_terminate_big_sync(struct hci_dev *hdev, u8 handle, u8 reason);
 int hci_le_big_terminate_sync(struct hci_dev *hdev, u8 handle);
 
 int hci_le_pa_terminate_sync(struct hci_dev *hdev, u16 handle);
+
+#ifdef TIZEN_BT
+int hci_start_le_discovery_sync(struct hci_dev *hdev);
+int hci_stop_le_discovery_sync(struct hci_dev *hdev);
+#endif
index 906091567395f212dde2466daae0d547d1a6ef52..e5b8fe60adb2b800d4aa3ae3448d736818def2b1 100644 (file)
@@ -192,17 +192,20 @@ bool hci_le_discovery_active(struct hci_dev *hdev)
 
 void hci_le_discovery_set_state(struct hci_dev *hdev, int state)
 {
-       BT_DBG("%s state %u -> %u", hdev->name,
-                       hdev->le_discovery.state, state);
+       int old_state = hdev->le_discovery.state;
 
-       if (hdev->le_discovery.state == state)
+       bt_dev_dbg(hdev, "%s le state %u -> %u", hdev->name, old_state, state);
+
+       if (old_state == state)
                return;
 
+       hdev->le_discovery.state = state;
+
        switch (state) {
        case DISCOVERY_STOPPED:
                hci_update_passive_scan(hdev);
 
-               if (hdev->le_discovery.state != DISCOVERY_STARTING)
+               if (old_state != DISCOVERY_STARTING)
                        mgmt_le_discovering(hdev, 0);
                break;
        case DISCOVERY_STARTING:
@@ -215,8 +218,6 @@ void hci_le_discovery_set_state(struct hci_dev *hdev, int state)
        case DISCOVERY_STOPPING:
                break;
        }
-
-       hdev->le_discovery.state = state;
 }
 
 static void hci_tx_timeout_error_evt(struct hci_dev *hdev)
index 6c08be70441156f3c3f342e3e7a6d832b957fa6d..367d9f547497d1745f58d28ea7893c958b2ae8b2 100644 (file)
@@ -6569,3 +6569,29 @@ int hci_update_adv_data(struct hci_dev *hdev, u8 instance)
        return hci_cmd_sync_queue(hdev, _update_adv_data_sync,
                                  UINT_PTR(instance), NULL);
 }
+
+#ifdef TIZEN_BT
+int hci_start_le_discovery_sync(struct hci_dev *hdev)
+{
+       u8 own_addr_type;
+       int err;
+
+       /* All active scans will be done with either a resolvable private
+        * address (when privacy feature has been enabled) or non-resolvable
+        * private address.
+        */
+       err = hci_update_random_address_sync(hdev, true, scan_use_rpa(hdev),
+                                            &own_addr_type);
+       if (err)
+               return err;
+
+       return hci_start_scan_sync(hdev, hdev->le_scan_type,
+                                  hdev->le_scan_interval, hdev->le_scan_window,
+                                  own_addr_type, 0, LE_SCAN_FILTER_DUP_DISABLE);
+}
+
+int hci_stop_le_discovery_sync(struct hci_dev *hdev)
+{
+       return hci_scan_disable_sync(hdev);
+}
+#endif
index a31efc031dd822355f5395396df09164e42d4100..7c01ff947fd7178f0977d422ed2f55d29ae76b0a 100644 (file)
@@ -8237,192 +8237,121 @@ void mgmt_rssi_alert_evt(struct hci_dev *hdev, u16 conn_handle,
                        NULL);
 }
 
-static int mgmt_start_le_discovery_failed(struct hci_dev *hdev, u8 status)
+static void start_le_discovery_complete(struct hci_dev *hdev, void *data,
+                                       int err)
 {
-       struct mgmt_pending_cmd *cmd;
-       u8 type;
-       int err;
-
-       hci_le_discovery_set_state(hdev, DISCOVERY_STOPPED);
+       struct mgmt_pending_cmd *cmd = data;
 
-       cmd = pending_find(MGMT_OP_START_LE_DISCOVERY, hdev);
-       if (!cmd)
-               return -ENOENT;
+       if (cmd != pending_find(MGMT_OP_START_LE_DISCOVERY, hdev))
+               return;
 
-       type = hdev->le_discovery.type;
+       bt_dev_dbg(hdev, "err %d", err);
 
-       err = mgmt_cmd_complete(cmd->sk, hdev->id, cmd->opcode,
-                               mgmt_status(status), &type, sizeof(type));
+       mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
+                         cmd->param, 1);
        mgmt_pending_remove(cmd);
 
-       return err;
+       hci_le_discovery_set_state(hdev, err ? DISCOVERY_STOPPED:
+                                  DISCOVERY_FINDING);
 }
 
-static void start_le_discovery_complete(struct hci_dev *hdev, u8 status,
-               u16 opcode)
+static int start_le_discovery_sync(struct hci_dev *hdev, void *data)
 {
-       unsigned long timeout = 0;
-
-       BT_DBG("status %d", status);
-
-       if (status) {
-               hci_dev_lock(hdev);
-               mgmt_start_le_discovery_failed(hdev, status);
-               hci_dev_unlock(hdev);
-               return;
-       }
-
-       hci_dev_lock(hdev);
-       hci_le_discovery_set_state(hdev, DISCOVERY_FINDING);
-       hci_dev_unlock(hdev);
-
-       if (hdev->le_discovery.type != DISCOV_TYPE_LE)
-               BT_ERR("Invalid discovery type %d", hdev->le_discovery.type);
-
-       if (!timeout)
-               return;
-
-       queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
+       return hci_start_le_discovery_sync(hdev);
 }
 
-static int start_le_discovery(struct sock *sk, struct hci_dev *hdev,
-               void *data, u16 len)
+static int start_le_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
+                             u16 len)
 {
        struct mgmt_cp_start_le_discovery *cp = data;
        struct mgmt_pending_cmd *cmd;
-       struct hci_cp_le_set_scan_param param_cp;
-       struct hci_cp_le_set_scan_enable enable_cp;
-       struct hci_request req;
-       u8 status, own_addr_type;
+       u8 status;
        int err;
 
-       BT_DBG("%s", hdev->name);
+       bt_dev_dbg(hdev, "sock %p", sk);
+
+       hci_dev_lock(hdev);
 
        if (!hdev_is_powered(hdev)) {
-               err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
-                               MGMT_STATUS_NOT_POWERED);
+               err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
+                                       MGMT_STATUS_NOT_POWERED, &cp->type,
+                                       sizeof(cp->type));
                goto unlock;
        }
 
        if (hdev->le_discovery.state != DISCOVERY_STOPPED) {
-               err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
-                               MGMT_STATUS_BUSY);
+               err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
+                                       MGMT_STATUS_BUSY, &cp->type,
+                                       sizeof(cp->type));
                goto unlock;
        }
 
        if (cp->type != DISCOV_TYPE_LE) {
-               err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
-                               MGMT_STATUS_INVALID_PARAMS);
+               err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
+                                       MGMT_STATUS_INVALID_PARAMS, &cp->type,
+                                       sizeof(cp->type));
                goto unlock;
        }
 
-       cmd = mgmt_pending_add(sk, MGMT_OP_START_LE_DISCOVERY, hdev, NULL, 0);
-       if (!cmd) {
-               err = -ENOMEM;
+       status = mgmt_le_support(hdev);
+       if (status) {
+               err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
+                                       status, &cp->type, sizeof(cp->type));
                goto unlock;
        }
 
        hdev->le_discovery.type = cp->type;
 
-       hci_req_init(&req, hdev);
-
-       status = mgmt_le_support(hdev);
-       if (status) {
-               err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
-                               status);
-               mgmt_pending_remove(cmd);
+       cmd = mgmt_pending_add(sk, MGMT_OP_START_LE_DISCOVERY, hdev, data, len);
+       if (!cmd) {
+               err = -ENOMEM;
                goto unlock;
        }
 
-       /* If controller is scanning, it means the background scanning
-        * is running. Thus, we should temporarily stop it in order to
-        * set the discovery scanning parameters.
-        */
-       if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
-               hci_req_add_le_scan_disable(&req, false);
-
-       memset(&param_cp, 0, sizeof(param_cp));
-
-       /* All active scans will be done with either a resolvable
-        * private address (when privacy feature has been enabled)
-        * or unresolvable private address.
-        */
-       err = hci_update_random_address_sync(hdev, true, hci_dev_test_flag(hdev, HCI_PRIVACY), &own_addr_type);
+       err = hci_cmd_sync_queue(hdev, start_le_discovery_sync, cmd,
+                                start_le_discovery_complete);
        if (err < 0) {
-               err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_START_LE_DISCOVERY,
-                               MGMT_STATUS_FAILED);
                mgmt_pending_remove(cmd);
                goto unlock;
        }
 
-       param_cp.type = hdev->le_scan_type;
-       param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
-       param_cp.window = cpu_to_le16(hdev->le_scan_window);
-       param_cp.own_address_type = own_addr_type;
-       hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
-                   &param_cp);
-
-       memset(&enable_cp, 0, sizeof(enable_cp));
-       enable_cp.enable = LE_SCAN_ENABLE;
-       enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
-
-       hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
-                   &enable_cp);
-
-       err = hci_req_run(&req, start_le_discovery_complete);
-       if (err < 0)
-               mgmt_pending_remove(cmd);
-       else
-               hci_le_discovery_set_state(hdev, DISCOVERY_STARTING);
+       hci_le_discovery_set_state(hdev, DISCOVERY_STARTING);
 
 unlock:
+       hci_dev_unlock(hdev);
        return err;
 }
 
-static int mgmt_stop_le_discovery_failed(struct hci_dev *hdev, u8 status)
+static void stop_le_discovery_complete(struct hci_dev *hdev, void *data, int err)
 {
-       struct mgmt_pending_cmd *cmd;
-       int err;
+       struct mgmt_pending_cmd *cmd = data;
 
-       cmd = pending_find(MGMT_OP_STOP_LE_DISCOVERY, hdev);
-       if (!cmd)
-               return -ENOENT;
+       if (cmd != pending_find(MGMT_OP_STOP_LE_DISCOVERY, hdev))
+               return;
+
+       bt_dev_dbg(hdev, "err %d", err);
 
-       err = mgmt_cmd_complete(cmd->sk, hdev->id, cmd->opcode,
-                               mgmt_status(status), &hdev->le_discovery.type,
-                               sizeof(hdev->le_discovery.type));
+       mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
+                         cmd->param, 1);
        mgmt_pending_remove(cmd);
 
-       return err;
+       if (!err)
+               hci_le_discovery_set_state(hdev, DISCOVERY_STOPPED);
 }
 
-static void stop_le_discovery_complete(struct hci_dev *hdev, u8 status,
-               u16 opcode)
+static int stop_le_discovery_sync(struct hci_dev *hdev, void *data)
 {
-       BT_DBG("status %d", status);
-
-       hci_dev_lock(hdev);
-
-       if (status) {
-               mgmt_stop_le_discovery_failed(hdev, status);
-               goto unlock;
-       }
-
-       hci_le_discovery_set_state(hdev, DISCOVERY_STOPPED);
-
-unlock:
-       hci_dev_unlock(hdev);
+       return hci_stop_le_discovery_sync(hdev);
 }
 
-static int stop_le_discovery(struct sock *sk, struct hci_dev *hdev,
-               void *data, u16 len)
+static int stop_le_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
+                            u16 len)
 {
        struct mgmt_cp_stop_le_discovery *mgmt_cp = data;
        struct mgmt_pending_cmd *cmd;
-       struct hci_request req;
        int err;
 
-       BT_DBG("%s", hdev->name);
+       bt_dev_dbg(hdev, "sock %p", sk);
 
        hci_dev_lock(hdev);
 
@@ -8440,33 +8369,30 @@ static int stop_le_discovery(struct sock *sk, struct hci_dev *hdev,
                goto unlock;
        }
 
-       cmd = mgmt_pending_add(sk, MGMT_OP_STOP_LE_DISCOVERY, hdev, NULL, 0);
-       if (!cmd) {
-               err = -ENOMEM;
-               goto unlock;
-       }
-
-       hci_req_init(&req, hdev);
-
-       if (hdev->le_discovery.state  != DISCOVERY_FINDING) {
-               BT_DBG("unknown le discovery state %u",
-                                       hdev->le_discovery.state);
+       if (hdev->le_discovery.state != DISCOVERY_FINDING) {
+               bt_dev_dbg(hdev, "unknown le discovery state %u",
+                          hdev->le_discovery.state);
 
-               mgmt_pending_remove(cmd);
                err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_LE_DISCOVERY,
                                        MGMT_STATUS_FAILED, &mgmt_cp->type,
                                        sizeof(mgmt_cp->type));
                goto unlock;
        }
 
-       cancel_delayed_work(&hdev->le_scan_disable);
-       hci_req_add_le_scan_disable(&req, false);
+       cmd = mgmt_pending_add(sk, MGMT_OP_STOP_LE_DISCOVERY, hdev, data, len);
+       if (!cmd) {
+               err = -ENOMEM;
+               goto unlock;
+       }
 
-       err = hci_req_run(&req, stop_le_discovery_complete);
-       if (err < 0)
+       err = hci_cmd_sync_queue(hdev, stop_le_discovery_sync, cmd,
+                                stop_le_discovery_complete);
+       if (err < 0) {
                mgmt_pending_remove(cmd);
-       else
-               hci_le_discovery_set_state(hdev, DISCOVERY_STOPPING);
+               goto unlock;
+       }
+
+       hci_le_discovery_set_state(hdev, DISCOVERY_STOPPING);
 
 unlock:
        hci_dev_unlock(hdev);