|
@@ -984,6 +984,11 @@ int hci_inquiry(void __user *arg)
|
|
|
if (!hdev)
|
|
|
return -ENODEV;
|
|
|
|
|
|
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
|
|
|
+ err = -EBUSY;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
hci_dev_lock(hdev);
|
|
|
if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
|
|
|
inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) {
|
|
@@ -1177,7 +1182,8 @@ int hci_dev_open(__u16 dev)
|
|
|
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
|
|
|
set_bit(HCI_RAW, &hdev->flags);
|
|
|
|
|
|
- if (!test_bit(HCI_RAW, &hdev->flags))
|
|
|
+ if (!test_bit(HCI_RAW, &hdev->flags) &&
|
|
|
+ !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
|
|
|
ret = __hci_init(hdev);
|
|
|
}
|
|
|
|
|
@@ -1188,6 +1194,7 @@ int hci_dev_open(__u16 dev)
|
|
|
set_bit(HCI_UP, &hdev->flags);
|
|
|
hci_notify(hdev, HCI_DEV_UP);
|
|
|
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
|
|
|
+ !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) &&
|
|
|
mgmt_valid_hdev(hdev)) {
|
|
|
hci_dev_lock(hdev);
|
|
|
mgmt_powered(hdev, 1);
|
|
@@ -1324,11 +1331,17 @@ int hci_dev_close(__u16 dev)
|
|
|
if (!hdev)
|
|
|
return -ENODEV;
|
|
|
|
|
|
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
|
|
|
+ err = -EBUSY;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
|
|
cancel_delayed_work(&hdev->power_off);
|
|
|
|
|
|
err = hci_dev_do_close(hdev);
|
|
|
|
|
|
+done:
|
|
|
hci_dev_put(hdev);
|
|
|
return err;
|
|
|
}
|
|
@@ -1349,6 +1362,11 @@ int hci_dev_reset(__u16 dev)
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
/* Drop queues */
|
|
|
skb_queue_purge(&hdev->rx_q);
|
|
|
skb_queue_purge(&hdev->cmd_q);
|
|
@@ -1382,10 +1400,15 @@ int hci_dev_reset_stat(__u16 dev)
|
|
|
if (!hdev)
|
|
|
return -ENODEV;
|
|
|
|
|
|
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
|
|
|
|
|
|
+done:
|
|
|
hci_dev_put(hdev);
|
|
|
-
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -1402,6 +1425,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
|
|
|
if (!hdev)
|
|
|
return -ENODEV;
|
|
|
|
|
|
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
|
|
|
+ err = -EBUSY;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
switch (cmd) {
|
|
|
case HCISETAUTH:
|
|
|
err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
|
|
@@ -1460,6 +1488,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+done:
|
|
|
hci_dev_put(hdev);
|
|
|
return err;
|
|
|
}
|
|
@@ -1568,6 +1597,9 @@ static int hci_rfkill_set_block(void *data, bool blocked)
|
|
|
|
|
|
BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
|
|
|
|
|
|
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
if (!blocked)
|
|
|
return 0;
|
|
|
|
|
@@ -3459,7 +3491,8 @@ static void hci_rx_work(struct work_struct *work)
|
|
|
hci_send_to_sock(hdev, skb);
|
|
|
}
|
|
|
|
|
|
- if (test_bit(HCI_RAW, &hdev->flags)) {
|
|
|
+ if (test_bit(HCI_RAW, &hdev->flags) ||
|
|
|
+ test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
|
|
|
kfree_skb(skb);
|
|
|
continue;
|
|
|
}
|