#include <linux/skbuff.h>
#include <linux/interrupt.h>
#include <linux/notifier.h>
+#include <linux/rfkill.h>
#include <net/sock.h>
#include <asm/system.h>
hci_req_lock(hdev);
+ if (hdev->rfkill &&
+ (hdev->rfkill->state == RFKILL_STATE_HARD_BLOCKED ||
+ hdev->rfkill->state == RFKILL_STATE_SOFT_BLOCKED)) {
+ ret = -EBUSY;
+ goto done;
+ }
+
if (test_bit(HCI_UP, &hdev->flags)) {
ret = -EALREADY;
goto done;
/* ---- Interface to HCI drivers ---- */
+static int hci_rfkill_set_block(void *data, enum rfkill_state state)
+{
+ struct hci_dev *hdev = data;
+ bool blocked = !(state == RFKILL_STATE_UNBLOCKED);
+
+ BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
+
+ if (!blocked)
+ return 0;
+
+ hci_dev_do_close(hdev);
+
+ return 0;
+}
+
/* Alloc HCI device */
struct hci_dev *hci_alloc_dev(void)
{
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;
hci_register_sysfs(hdev);
+ hdev->rfkill = rfkill_allocate(&hdev->dev, RFKILL_TYPE_BLUETOOTH);
+ if (hdev->rfkill) {
+ hdev->rfkill->name = hdev->name;
+ hdev->rfkill->toggle_radio = hci_rfkill_set_block;
+ hdev->rfkill->data = hdev;
+ if (rfkill_register(hdev->rfkill) < 0) {
+ rfkill_free(hdev->rfkill);
+ hdev->rfkill = NULL;
+ }
+ }
+
hci_notify(hdev, HCI_DEV_REG);
return id;
hci_notify(hdev, HCI_DEV_UNREG);
+ if (hdev->rfkill) {
+ rfkill_unregister(hdev->rfkill);
+ }
+
hci_unregister_sysfs(hdev);
__hci_dev_put(hdev);