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(¶m_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),
- ¶m_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);
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);