diff options
Diffstat (limited to 'net')
-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 @@ | |||
39 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
40 | #include <linux/interrupt.h> | 40 | #include <linux/interrupt.h> |
41 | #include <linux/notifier.h> | 41 | #include <linux/notifier.h> |
42 | #include <linux/rfkill.h> | ||
42 | #include <net/sock.h> | 43 | #include <net/sock.h> |
43 | 44 | ||
44 | #include <asm/system.h> | 45 | #include <asm/system.h> |
@@ -476,6 +477,11 @@ int hci_dev_open(__u16 dev) | |||
476 | 477 | ||
477 | hci_req_lock(hdev); | 478 | hci_req_lock(hdev); |
478 | 479 | ||
480 | if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) { | ||
481 | ret = -ERFKILL; | ||
482 | goto done; | ||
483 | } | ||
484 | |||
479 | if (test_bit(HCI_UP, &hdev->flags)) { | 485 | if (test_bit(HCI_UP, &hdev->flags)) { |
480 | ret = -EALREADY; | 486 | ret = -EALREADY; |
481 | goto done; | 487 | goto done; |
@@ -813,6 +819,24 @@ int hci_get_dev_info(void __user *arg) | |||
813 | 819 | ||
814 | /* ---- Interface to HCI drivers ---- */ | 820 | /* ---- Interface to HCI drivers ---- */ |
815 | 821 | ||
822 | static int hci_rfkill_set_block(void *data, bool blocked) | ||
823 | { | ||
824 | struct hci_dev *hdev = data; | ||
825 | |||
826 | BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked); | ||
827 | |||
828 | if (!blocked) | ||
829 | return 0; | ||
830 | |||
831 | hci_dev_do_close(hdev); | ||
832 | |||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static const struct rfkill_ops hci_rfkill_ops = { | ||
837 | .set_block = hci_rfkill_set_block, | ||
838 | }; | ||
839 | |||
816 | /* Alloc HCI device */ | 840 | /* Alloc HCI device */ |
817 | struct hci_dev *hci_alloc_dev(void) | 841 | struct hci_dev *hci_alloc_dev(void) |
818 | { | 842 | { |
@@ -844,7 +868,8 @@ int hci_register_dev(struct hci_dev *hdev) | |||
844 | struct list_head *head = &hci_dev_list, *p; | 868 | struct list_head *head = &hci_dev_list, *p; |
845 | int i, id = 0; | 869 | int i, id = 0; |
846 | 870 | ||
847 | BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); | 871 | BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, |
872 | hdev->type, hdev->owner); | ||
848 | 873 | ||
849 | if (!hdev->open || !hdev->close || !hdev->destruct) | 874 | if (!hdev->open || !hdev->close || !hdev->destruct) |
850 | return -EINVAL; | 875 | return -EINVAL; |
@@ -900,6 +925,15 @@ int hci_register_dev(struct hci_dev *hdev) | |||
900 | 925 | ||
901 | hci_register_sysfs(hdev); | 926 | hci_register_sysfs(hdev); |
902 | 927 | ||
928 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, | ||
929 | RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev); | ||
930 | if (hdev->rfkill) { | ||
931 | if (rfkill_register(hdev->rfkill) < 0) { | ||
932 | rfkill_destroy(hdev->rfkill); | ||
933 | hdev->rfkill = NULL; | ||
934 | } | ||
935 | } | ||
936 | |||
903 | hci_notify(hdev, HCI_DEV_REG); | 937 | hci_notify(hdev, HCI_DEV_REG); |
904 | 938 | ||
905 | return id; | 939 | return id; |
@@ -924,6 +958,11 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
924 | 958 | ||
925 | hci_notify(hdev, HCI_DEV_UNREG); | 959 | hci_notify(hdev, HCI_DEV_UNREG); |
926 | 960 | ||
961 | if (hdev->rfkill) { | ||
962 | rfkill_unregister(hdev->rfkill); | ||
963 | rfkill_destroy(hdev->rfkill); | ||
964 | } | ||
965 | |||
927 | hci_unregister_sysfs(hdev); | 966 | hci_unregister_sysfs(hdev); |
928 | 967 | ||
929 | __hci_dev_put(hdev); | 968 | __hci_dev_put(hdev); |