Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2015, Heiner Kallweit <hkallweit1@gmail.com>
0004  */
0005 
0006 #include <net/bluetooth/bluetooth.h>
0007 #include <net/bluetooth/hci_core.h>
0008 
0009 #include "leds.h"
0010 
0011 DEFINE_LED_TRIGGER(bt_power_led_trigger);
0012 
0013 struct hci_basic_led_trigger {
0014     struct led_trigger  led_trigger;
0015     struct hci_dev      *hdev;
0016 };
0017 
0018 #define to_hci_basic_led_trigger(arg) container_of(arg, \
0019             struct hci_basic_led_trigger, led_trigger)
0020 
0021 void hci_leds_update_powered(struct hci_dev *hdev, bool enabled)
0022 {
0023     if (hdev->power_led)
0024         led_trigger_event(hdev->power_led,
0025                   enabled ? LED_FULL : LED_OFF);
0026 
0027     if (!enabled) {
0028         struct hci_dev *d;
0029 
0030         read_lock(&hci_dev_list_lock);
0031 
0032         list_for_each_entry(d, &hci_dev_list, list) {
0033             if (test_bit(HCI_UP, &d->flags))
0034                 enabled = true;
0035         }
0036 
0037         read_unlock(&hci_dev_list_lock);
0038     }
0039 
0040     led_trigger_event(bt_power_led_trigger, enabled ? LED_FULL : LED_OFF);
0041 }
0042 
0043 static int power_activate(struct led_classdev *led_cdev)
0044 {
0045     struct hci_basic_led_trigger *htrig;
0046     bool powered;
0047 
0048     htrig = to_hci_basic_led_trigger(led_cdev->trigger);
0049     powered = test_bit(HCI_UP, &htrig->hdev->flags);
0050 
0051     led_trigger_event(led_cdev->trigger, powered ? LED_FULL : LED_OFF);
0052 
0053     return 0;
0054 }
0055 
0056 static struct led_trigger *led_allocate_basic(struct hci_dev *hdev,
0057             int (*activate)(struct led_classdev *led_cdev),
0058             const char *name)
0059 {
0060     struct hci_basic_led_trigger *htrig;
0061 
0062     htrig = devm_kzalloc(&hdev->dev, sizeof(*htrig), GFP_KERNEL);
0063     if (!htrig)
0064         return NULL;
0065 
0066     htrig->hdev = hdev;
0067     htrig->led_trigger.activate = activate;
0068     htrig->led_trigger.name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
0069                          "%s-%s", hdev->name,
0070                          name);
0071     if (!htrig->led_trigger.name)
0072         goto err_alloc;
0073 
0074     if (devm_led_trigger_register(&hdev->dev, &htrig->led_trigger))
0075         goto err_register;
0076 
0077     return &htrig->led_trigger;
0078 
0079 err_register:
0080     devm_kfree(&hdev->dev, (void *)htrig->led_trigger.name);
0081 err_alloc:
0082     devm_kfree(&hdev->dev, htrig);
0083     return NULL;
0084 }
0085 
0086 void hci_leds_init(struct hci_dev *hdev)
0087 {
0088     /* initialize power_led */
0089     hdev->power_led = led_allocate_basic(hdev, power_activate, "power");
0090 }
0091 
0092 void bt_leds_init(void)
0093 {
0094     led_trigger_register_simple("bluetooth-power", &bt_power_led_trigger);
0095 }
0096 
0097 void bt_leds_cleanup(void)
0098 {
0099     led_trigger_unregister_simple(bt_power_led_trigger);
0100 }