diff options
author | Heiner Kallweit <hkallweit1@gmail.com> | 2016-01-08 13:28:58 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2016-02-23 14:29:35 -0500 |
commit | 6d5d2ee63cee7025badda3b74ae2ef7ab097acfa (patch) | |
tree | 84d89e34753cdd8e2a00dabb73eb6c6e3d1896d6 /net/bluetooth | |
parent | a30a9ea6e21b495372aff549f3dfd63198bd1f45 (diff) |
Bluetooth: add LED trigger for indicating HCI is powered up
Add support for LED triggers to the Bluetooth subsystem and add kernel
config symbol BT_LEDS for it.
For now one trigger for indicating "HCI is powered up" is supported.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/Kconfig | 9 | ||||
-rw-r--r-- | net/bluetooth/Makefile | 1 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 8 | ||||
-rw-r--r-- | net/bluetooth/leds.c | 80 | ||||
-rw-r--r-- | net/bluetooth/leds.h | 18 |
5 files changed, 116 insertions, 0 deletions
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 95d1a66ba03a..06c31b9a68b0 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -69,6 +69,15 @@ config BT_6LOWPAN | |||
69 | help | 69 | help |
70 | IPv6 compression over Bluetooth Low Energy. | 70 | IPv6 compression over Bluetooth Low Energy. |
71 | 71 | ||
72 | config BT_LEDS | ||
73 | bool "Enable LED triggers" | ||
74 | depends on BT | ||
75 | depends on LEDS_CLASS | ||
76 | select LEDS_TRIGGERS | ||
77 | help | ||
78 | This option selects a few LED triggers for different | ||
79 | Bluetooth events. | ||
80 | |||
72 | config BT_SELFTEST | 81 | config BT_SELFTEST |
73 | bool "Bluetooth self testing support" | 82 | bool "Bluetooth self testing support" |
74 | depends on BT && DEBUG_KERNEL | 83 | depends on BT && DEBUG_KERNEL |
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index 2b15ae8c1def..b3ff12eb9b6d 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile | |||
@@ -17,6 +17,7 @@ bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ | |||
17 | 17 | ||
18 | bluetooth-$(CONFIG_BT_BREDR) += sco.o | 18 | bluetooth-$(CONFIG_BT_BREDR) += sco.o |
19 | bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o | 19 | bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o |
20 | bluetooth-$(CONFIG_BT_LEDS) += leds.o | ||
20 | bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o | 21 | bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o |
21 | bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o | 22 | bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o |
22 | 23 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 883c821a9e78..88f1ef3589d8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "hci_request.h" | 40 | #include "hci_request.h" |
41 | #include "hci_debugfs.h" | 41 | #include "hci_debugfs.h" |
42 | #include "smp.h" | 42 | #include "smp.h" |
43 | #include "leds.h" | ||
43 | 44 | ||
44 | static void hci_rx_work(struct work_struct *work); | 45 | static void hci_rx_work(struct work_struct *work); |
45 | static void hci_cmd_work(struct work_struct *work); | 46 | static void hci_cmd_work(struct work_struct *work); |
@@ -1395,6 +1396,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
1395 | hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); | 1396 | hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); |
1396 | set_bit(HCI_UP, &hdev->flags); | 1397 | set_bit(HCI_UP, &hdev->flags); |
1397 | hci_sock_dev_event(hdev, HCI_DEV_UP); | 1398 | hci_sock_dev_event(hdev, HCI_DEV_UP); |
1399 | hci_leds_update_powered(hdev, true); | ||
1398 | if (!hci_dev_test_flag(hdev, HCI_SETUP) && | 1400 | if (!hci_dev_test_flag(hdev, HCI_SETUP) && |
1399 | !hci_dev_test_flag(hdev, HCI_CONFIG) && | 1401 | !hci_dev_test_flag(hdev, HCI_CONFIG) && |
1400 | !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && | 1402 | !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && |
@@ -1532,6 +1534,8 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1532 | return 0; | 1534 | return 0; |
1533 | } | 1535 | } |
1534 | 1536 | ||
1537 | hci_leds_update_powered(hdev, false); | ||
1538 | |||
1535 | /* Flush RX and TX works */ | 1539 | /* Flush RX and TX works */ |
1536 | flush_work(&hdev->tx_work); | 1540 | flush_work(&hdev->tx_work); |
1537 | flush_work(&hdev->rx_work); | 1541 | flush_work(&hdev->rx_work); |
@@ -3067,6 +3071,8 @@ int hci_register_dev(struct hci_dev *hdev) | |||
3067 | if (error < 0) | 3071 | if (error < 0) |
3068 | goto err_wqueue; | 3072 | goto err_wqueue; |
3069 | 3073 | ||
3074 | hci_leds_init(hdev); | ||
3075 | |||
3070 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, | 3076 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, |
3071 | RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, | 3077 | RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, |
3072 | hdev); | 3078 | hdev); |
@@ -3128,6 +3134,8 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
3128 | 3134 | ||
3129 | id = hdev->id; | 3135 | id = hdev->id; |
3130 | 3136 | ||
3137 | hci_leds_exit(hdev); | ||
3138 | |||
3131 | write_lock(&hci_dev_list_lock); | 3139 | write_lock(&hci_dev_list_lock); |
3132 | list_del(&hdev->list); | 3140 | list_del(&hdev->list); |
3133 | write_unlock(&hci_dev_list_lock); | 3141 | write_unlock(&hci_dev_list_lock); |
diff --git a/net/bluetooth/leds.c b/net/bluetooth/leds.c new file mode 100644 index 000000000000..ded7c88eaccc --- /dev/null +++ b/net/bluetooth/leds.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright 2015, Heiner Kallweit <hkallweit1@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <net/bluetooth/bluetooth.h> | ||
10 | #include <net/bluetooth/hci_core.h> | ||
11 | |||
12 | #include "leds.h" | ||
13 | |||
14 | struct hci_basic_led_trigger { | ||
15 | struct led_trigger led_trigger; | ||
16 | struct hci_dev *hdev; | ||
17 | }; | ||
18 | |||
19 | #define to_hci_basic_led_trigger(arg) container_of(arg, \ | ||
20 | struct hci_basic_led_trigger, led_trigger) | ||
21 | |||
22 | void hci_leds_update_powered(struct hci_dev *hdev, bool enabled) | ||
23 | { | ||
24 | if (hdev->power_led) | ||
25 | led_trigger_event(hdev->power_led, | ||
26 | enabled ? LED_FULL : LED_OFF); | ||
27 | } | ||
28 | |||
29 | static void power_activate(struct led_classdev *led_cdev) | ||
30 | { | ||
31 | struct hci_basic_led_trigger *htrig; | ||
32 | bool powered; | ||
33 | |||
34 | htrig = to_hci_basic_led_trigger(led_cdev->trigger); | ||
35 | powered = test_bit(HCI_UP, &htrig->hdev->flags); | ||
36 | |||
37 | led_trigger_event(led_cdev->trigger, powered ? LED_FULL : LED_OFF); | ||
38 | } | ||
39 | |||
40 | static struct led_trigger *led_allocate_basic(struct hci_dev *hdev, | ||
41 | void (*activate)(struct led_classdev *led_cdev), | ||
42 | const char *name) | ||
43 | { | ||
44 | struct hci_basic_led_trigger *htrig; | ||
45 | |||
46 | htrig = devm_kzalloc(&hdev->dev, sizeof(*htrig), GFP_KERNEL); | ||
47 | if (!htrig) | ||
48 | return NULL; | ||
49 | |||
50 | htrig->hdev = hdev; | ||
51 | htrig->led_trigger.activate = activate; | ||
52 | htrig->led_trigger.name = devm_kasprintf(&hdev->dev, GFP_KERNEL, | ||
53 | "%s-%s", hdev->name, | ||
54 | name); | ||
55 | if (!htrig->led_trigger.name) | ||
56 | goto err_alloc; | ||
57 | |||
58 | if (led_trigger_register(&htrig->led_trigger)) | ||
59 | goto err_register; | ||
60 | |||
61 | return &htrig->led_trigger; | ||
62 | |||
63 | err_register: | ||
64 | devm_kfree(&hdev->dev, (void *)htrig->led_trigger.name); | ||
65 | err_alloc: | ||
66 | devm_kfree(&hdev->dev, htrig); | ||
67 | return NULL; | ||
68 | } | ||
69 | |||
70 | void hci_leds_init(struct hci_dev *hdev) | ||
71 | { | ||
72 | /* initialize power_led */ | ||
73 | hdev->power_led = led_allocate_basic(hdev, power_activate, "power"); | ||
74 | } | ||
75 | |||
76 | void hci_leds_exit(struct hci_dev *hdev) | ||
77 | { | ||
78 | if (hdev->power_led) | ||
79 | led_trigger_unregister(hdev->power_led); | ||
80 | } | ||
diff --git a/net/bluetooth/leds.h b/net/bluetooth/leds.h new file mode 100644 index 000000000000..068261a4e12c --- /dev/null +++ b/net/bluetooth/leds.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * Copyright 2015, Heiner Kallweit <hkallweit1@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #if IS_ENABLED(CONFIG_BT_LEDS) | ||
10 | void hci_leds_update_powered(struct hci_dev *hdev, bool enabled); | ||
11 | void hci_leds_init(struct hci_dev *hdev); | ||
12 | void hci_leds_exit(struct hci_dev *hdev); | ||
13 | #else | ||
14 | static inline void hci_leds_update_powered(struct hci_dev *hdev, | ||
15 | bool enabled) {} | ||
16 | static inline void hci_leds_init(struct hci_dev *hdev) {} | ||
17 | static inline void hci_leds_exit(struct hci_dev *hdev) {} | ||
18 | #endif | ||