Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 611b30f7 authored by Marcel Holtmann's avatar Marcel Holtmann
Browse files

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: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 092b8585
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+40 −1
Original line number Diff line number Diff line
@@ -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);