linux/net/bluetooth/leds.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright 2015, Heiner Kallweit <hkallweit1@gmail.com>
   4 */
   5
   6#include <net/bluetooth/bluetooth.h>
   7#include <net/bluetooth/hci_core.h>
   8
   9#include "leds.h"
  10
  11DEFINE_LED_TRIGGER(bt_power_led_trigger);
  12
  13struct hci_basic_led_trigger {
  14        struct led_trigger      led_trigger;
  15        struct hci_dev          *hdev;
  16};
  17
  18#define to_hci_basic_led_trigger(arg) container_of(arg, \
  19                        struct hci_basic_led_trigger, led_trigger)
  20
  21void hci_leds_update_powered(struct hci_dev *hdev, bool enabled)
  22{
  23        if (hdev->power_led)
  24                led_trigger_event(hdev->power_led,
  25                                  enabled ? LED_FULL : LED_OFF);
  26
  27        if (!enabled) {
  28                struct hci_dev *d;
  29
  30                read_lock(&hci_dev_list_lock);
  31
  32                list_for_each_entry(d, &hci_dev_list, list) {
  33                        if (test_bit(HCI_UP, &d->flags))
  34                                enabled = true;
  35                }
  36
  37                read_unlock(&hci_dev_list_lock);
  38        }
  39
  40        led_trigger_event(bt_power_led_trigger, enabled ? LED_FULL : LED_OFF);
  41}
  42
  43static int power_activate(struct led_classdev *led_cdev)
  44{
  45        struct hci_basic_led_trigger *htrig;
  46        bool powered;
  47
  48        htrig = to_hci_basic_led_trigger(led_cdev->trigger);
  49        powered = test_bit(HCI_UP, &htrig->hdev->flags);
  50
  51        led_trigger_event(led_cdev->trigger, powered ? LED_FULL : LED_OFF);
  52
  53        return 0;
  54}
  55
  56static struct led_trigger *led_allocate_basic(struct hci_dev *hdev,
  57                        int (*activate)(struct led_classdev *led_cdev),
  58                        const char *name)
  59{
  60        struct hci_basic_led_trigger *htrig;
  61
  62        htrig = devm_kzalloc(&hdev->dev, sizeof(*htrig), GFP_KERNEL);
  63        if (!htrig)
  64                return NULL;
  65
  66        htrig->hdev = hdev;
  67        htrig->led_trigger.activate = activate;
  68        htrig->led_trigger.name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
  69                                                 "%s-%s", hdev->name,
  70                                                 name);
  71        if (!htrig->led_trigger.name)
  72                goto err_alloc;
  73
  74        if (devm_led_trigger_register(&hdev->dev, &htrig->led_trigger))
  75                goto err_register;
  76
  77        return &htrig->led_trigger;
  78
  79err_register:
  80        devm_kfree(&hdev->dev, (void *)htrig->led_trigger.name);
  81err_alloc:
  82        devm_kfree(&hdev->dev, htrig);
  83        return NULL;
  84}
  85
  86void hci_leds_init(struct hci_dev *hdev)
  87{
  88        /* initialize power_led */
  89        hdev->power_led = led_allocate_basic(hdev, power_activate, "power");
  90}
  91
  92void bt_leds_init(void)
  93{
  94        led_trigger_register_simple("bluetooth-power", &bt_power_led_trigger);
  95}
  96
  97void bt_leds_cleanup(void)
  98{
  99        led_trigger_unregister_simple(bt_power_led_trigger);
 100}
 101