diff options
Diffstat (limited to 'net/bluetooth/hci_core.c')
-rw-r--r-- | net/bluetooth/hci_core.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index cd061510b6bd..406ad07cdea1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -39,6 +39,7 @@ #include <linux/skbuff.h> #include <linux/interrupt.h> #include <linux/notifier.h> +#include <linux/rfkill.h> #include <net/sock.h> #include <asm/system.h> @@ -476,6 +477,11 @@ int hci_dev_open(__u16 dev) hci_req_lock(hdev); + if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) { + ret = -ERFKILL; + goto done; + } + if (test_bit(HCI_UP, &hdev->flags)) { ret = -EALREADY; goto done; @@ -813,6 +819,24 @@ int hci_get_dev_info(void __user *arg) /* ---- Interface to HCI drivers ---- */ +static int hci_rfkill_set_block(void *data, bool blocked) +{ + struct hci_dev *hdev = data; + + BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked); + + if (!blocked) + return 0; + + hci_dev_do_close(hdev); + + return 0; +} + +static const struct rfkill_ops hci_rfkill_ops = { + .set_block = hci_rfkill_set_block, +}; + /* Alloc HCI device */ struct hci_dev *hci_alloc_dev(void) { @@ -844,7 +868,8 @@ int hci_register_dev(struct hci_dev *hdev) struct list_head *head = &hci_dev_list, *p; int i, id = 0; - BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); + BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, + hdev->type, hdev->owner); if (!hdev->open || !hdev->close || !hdev->destruct) return -EINVAL; @@ -900,6 +925,15 @@ int hci_register_dev(struct hci_dev *hdev) hci_register_sysfs(hdev); + hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, + RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev); + if (hdev->rfkill) { + if (rfkill_register(hdev->rfkill) < 0) { + rfkill_destroy(hdev->rfkill); + hdev->rfkill = NULL; + } + } + hci_notify(hdev, HCI_DEV_REG); return id; @@ -924,6 +958,11 @@ int hci_unregister_dev(struct hci_dev *hdev) hci_notify(hdev, HCI_DEV_UNREG); + if (hdev->rfkill) { + rfkill_unregister(hdev->rfkill); + rfkill_destroy(hdev->rfkill); + } + hci_unregister_sysfs(hdev); __hci_dev_put(hdev); |