diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2009-06-08 08:41:38 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-06-08 08:50:01 -0400 |
commit | 611b30f74b5d8ca036a9923b3bf6e0ee10a21a53 (patch) | |
tree | 75da131d873d19c2ee40dd6b05bf094d5afed2c1 | |
parent | 092b85853b161a5ca285c429faf1cf2ff4318a01 (diff) |
Bluetooth: Add native RFKILL soft-switch support for all devices
With the re-write of the RFKILL subsystem it is now possible to easily
integrate RFKILL soft-switch support into the Bluetooth subsystem. All
Bluetooth devices will now get automatically RFKILL support.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | include/net/bluetooth/hci_core.h | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 41 |
2 files changed, 42 insertions, 1 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 73aead222b32..c4ca4228b083 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -137,6 +137,8 @@ struct hci_dev { | |||
137 | struct device *parent; | 137 | struct device *parent; |
138 | struct device dev; | 138 | struct device dev; |
139 | 139 | ||
140 | struct rfkill *rfkill; | ||
141 | |||
140 | struct module *owner; | 142 | struct module *owner; |
141 | 143 | ||
142 | int (*open)(struct hci_dev *hdev); | 144 | int (*open)(struct hci_dev *hdev); |
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); |