forked from Minki/linux
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>
This commit is contained in:
parent
092b85853b
commit
611b30f74b
@ -137,6 +137,8 @@ struct hci_dev {
|
||||
struct device *parent;
|
||||
struct device dev;
|
||||
|
||||
struct rfkill *rfkill;
|
||||
|
||||
struct module *owner;
|
||||
|
||||
int (*open)(struct hci_dev *hdev);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user