linux/drivers/power/supply/power_supply_leds.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  LEDs triggers for power supply class
   4 *
   5 *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
   6 *  Copyright © 2004  Szabolcs Gyurko
   7 *  Copyright © 2003  Ian Molton <spyro@f2s.com>
   8 *
   9 *  Modified: 2004, Oct     Szabolcs Gyurko
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/device.h>
  14#include <linux/power_supply.h>
  15#include <linux/slab.h>
  16
  17#include "power_supply.h"
  18
  19/* Battery specific LEDs triggers. */
  20
  21static void power_supply_update_bat_leds(struct power_supply *psy)
  22{
  23        union power_supply_propval status;
  24        unsigned long delay_on = 0;
  25        unsigned long delay_off = 0;
  26
  27        if (power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
  28                return;
  29
  30        dev_dbg(&psy->dev, "%s %d\n", __func__, status.intval);
  31
  32        switch (status.intval) {
  33        case POWER_SUPPLY_STATUS_FULL:
  34                led_trigger_event(psy->charging_full_trig, LED_FULL);
  35                led_trigger_event(psy->charging_trig, LED_OFF);
  36                led_trigger_event(psy->full_trig, LED_FULL);
  37                led_trigger_event(psy->charging_blink_full_solid_trig,
  38                        LED_FULL);
  39                break;
  40        case POWER_SUPPLY_STATUS_CHARGING:
  41                led_trigger_event(psy->charging_full_trig, LED_FULL);
  42                led_trigger_event(psy->charging_trig, LED_FULL);
  43                led_trigger_event(psy->full_trig, LED_OFF);
  44                led_trigger_blink(psy->charging_blink_full_solid_trig,
  45                        &delay_on, &delay_off);
  46                break;
  47        default:
  48                led_trigger_event(psy->charging_full_trig, LED_OFF);
  49                led_trigger_event(psy->charging_trig, LED_OFF);
  50                led_trigger_event(psy->full_trig, LED_OFF);
  51                led_trigger_event(psy->charging_blink_full_solid_trig,
  52                        LED_OFF);
  53                break;
  54        }
  55}
  56
  57static int power_supply_create_bat_triggers(struct power_supply *psy)
  58{
  59        psy->charging_full_trig_name = kasprintf(GFP_KERNEL,
  60                                        "%s-charging-or-full", psy->desc->name);
  61        if (!psy->charging_full_trig_name)
  62                goto charging_full_failed;
  63
  64        psy->charging_trig_name = kasprintf(GFP_KERNEL,
  65                                        "%s-charging", psy->desc->name);
  66        if (!psy->charging_trig_name)
  67                goto charging_failed;
  68
  69        psy->full_trig_name = kasprintf(GFP_KERNEL, "%s-full", psy->desc->name);
  70        if (!psy->full_trig_name)
  71                goto full_failed;
  72
  73        psy->charging_blink_full_solid_trig_name = kasprintf(GFP_KERNEL,
  74                "%s-charging-blink-full-solid", psy->desc->name);
  75        if (!psy->charging_blink_full_solid_trig_name)
  76                goto charging_blink_full_solid_failed;
  77
  78        led_trigger_register_simple(psy->charging_full_trig_name,
  79                                    &psy->charging_full_trig);
  80        led_trigger_register_simple(psy->charging_trig_name,
  81                                    &psy->charging_trig);
  82        led_trigger_register_simple(psy->full_trig_name,
  83                                    &psy->full_trig);
  84        led_trigger_register_simple(psy->charging_blink_full_solid_trig_name,
  85                                    &psy->charging_blink_full_solid_trig);
  86
  87        return 0;
  88
  89charging_blink_full_solid_failed:
  90        kfree(psy->full_trig_name);
  91full_failed:
  92        kfree(psy->charging_trig_name);
  93charging_failed:
  94        kfree(psy->charging_full_trig_name);
  95charging_full_failed:
  96        return -ENOMEM;
  97}
  98
  99static void power_supply_remove_bat_triggers(struct power_supply *psy)
 100{
 101        led_trigger_unregister_simple(psy->charging_full_trig);
 102        led_trigger_unregister_simple(psy->charging_trig);
 103        led_trigger_unregister_simple(psy->full_trig);
 104        led_trigger_unregister_simple(psy->charging_blink_full_solid_trig);
 105        kfree(psy->charging_blink_full_solid_trig_name);
 106        kfree(psy->full_trig_name);
 107        kfree(psy->charging_trig_name);
 108        kfree(psy->charging_full_trig_name);
 109}
 110
 111/* Generated power specific LEDs triggers. */
 112
 113static void power_supply_update_gen_leds(struct power_supply *psy)
 114{
 115        union power_supply_propval online;
 116
 117        if (power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
 118                return;
 119
 120        dev_dbg(&psy->dev, "%s %d\n", __func__, online.intval);
 121
 122        if (online.intval)
 123                led_trigger_event(psy->online_trig, LED_FULL);
 124        else
 125                led_trigger_event(psy->online_trig, LED_OFF);
 126}
 127
 128static int power_supply_create_gen_triggers(struct power_supply *psy)
 129{
 130        psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online",
 131                                          psy->desc->name);
 132        if (!psy->online_trig_name)
 133                return -ENOMEM;
 134
 135        led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
 136
 137        return 0;
 138}
 139
 140static void power_supply_remove_gen_triggers(struct power_supply *psy)
 141{
 142        led_trigger_unregister_simple(psy->online_trig);
 143        kfree(psy->online_trig_name);
 144}
 145
 146/* Choice what triggers to create&update. */
 147
 148void power_supply_update_leds(struct power_supply *psy)
 149{
 150        if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
 151                power_supply_update_bat_leds(psy);
 152        else
 153                power_supply_update_gen_leds(psy);
 154}
 155
 156int power_supply_create_triggers(struct power_supply *psy)
 157{
 158        if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
 159                return power_supply_create_bat_triggers(psy);
 160        return power_supply_create_gen_triggers(psy);
 161}
 162
 163void power_supply_remove_triggers(struct power_supply *psy)
 164{
 165        if (psy->desc->type == POWER_SUPPLY_TYPE_BATTERY)
 166                power_supply_remove_bat_triggers(psy);
 167        else
 168                power_supply_remove_gen_triggers(psy);
 169}
 170