Enabling charging/notification LED

Search This thread

Johnsondr80

Inactive Recognized Developer
Dec 13, 2010
3,468
5,142
Tuscaloosa
That's not what I asked for.
But so you will better understand, my mother fell and broke her hip on July 3rd and has been in the hospital ever since that day. She has been doing better just before doing worse again. We had to move her to a higher quality hospital, where she began to do better and then again got worse. I have been by her bed side the entire time, living in ICU with her watching her fight for her life. Much of the time she was on a ventilator and during the couple of times she was well enough to be removed from it her throat was so sore her voice could nearly be heard, and was only able to say a few words.
And as horrible as it was to see her like this, I stayed with her.
Then on July 21 her body had all the stress it could take. She passed at 11:50 pm with out a struggle.

Being a recognized developer of XDA I am fully aware of factory images and how to access/modify/add/remove anything I want. And believe it or not I know where to get them and identify the correct one I need.
How ever as a recognized dev of XDA I expected that the response to my request would be greeted with a reply of respect, where someone might just provide me what I was asking for.

It is your example @doitright that your response has illustrated the perfect reason why so many devs leave the forms, and rarely return. Your smartellic reply is an insult to those who regularly spend hours on end solving and creating software for your simple enjoyment, free of charge. But you offer nothing in return but a middle finger.

Most just ignore the request. Don't care. But you just have to make a show. Pretend to be helpful but in reality your a jerk.

Thanks for nothing.

I pray you never need help with anything on here. Because I fear you may be treated how you have treated me.

Peace

Sent from my Nexus 6 using Tapatalk
 

AlxMAX

Senior Member
Sep 30, 2007
543
133
Bucharest
@Johnsondr80: I am very sorry for your loss and I would like to express my deepest condolences. However, you shouldn't let your grief invade you. doitright could not know about your problems and he/she meant implicitly he/she did not have the file and suggested the source you can use to extract your file instead. Personally, I don't see any lack of respect. If you know the file is not in the system image or you can't extract it whatsoever, just tell us about it and one of us might help you with the file. There's no reason to use words like "jerk".
 

doitright

Senior Member
Oct 31, 2014
1,512
861
So back into this thread after some very long time away (at least from the technical end of things).

So here is what I know now (and have been playing with for a few hours now)...

1) Regular old GPIO LEDs *can* be controlled via PWM. See below;
Code:
&spmi_bus {
	qcom,[email protected] {
		qcom,[email protected] {
			compatible = "qcom,leds-qpnp";
			reg = <0xc600 0x100>;
			status = "okay";
			qcom,led_gpio_7 {
				label = "rgb";
				linux,name = "red";
				qcom,mode = "pwm";
				qcom,pwm-channel = <2>;
				qcom,start-idx = <1>;
				qcom,idx-len = <10>;
				qcom,duty-pcts = [00 19 32 4B 64
						 64 4B 32 19 00];
				qcom,lut-flags = <3>;
				qcom,pause-lo = <0>;
				qcom,pause-hi = <0>;
				qcom,ramp-step-ms = <255>;
				qcom,max-current = <12>;
				qcom,default-state = "on";
				qcom,turn-off-delay-ms = <500>;
				qcom,id = <5>;
				linux,default-trigger = "none";
				qcom,pwm-us = <1000>;
				qcom,use-blink;			};
		};

		qcom,[email protected] {
			compatible = "qcom,leds-qpnp";
			reg = <0xc700 0x100>;
			status = "okay";
			qcom,led_gpio_8 {
				label = "rgb";
				linux,name = "green";
				qcom,mode = "pwm";
				qcom,pwm-channel = <3>;
				qcom,start-idx = <1>;
				qcom,idx-len = <10>;
				qcom,duty-pcts = [00 19 32 4B 64
						 64 4B 32 19 00];
				qcom,lut-flags = <3>;
				qcom,pause-lo = <0>;
				qcom,pause-hi = <0>;
				qcom,ramp-step-ms = <255>;
				qcom,max-current = <12>;
				qcom,default-state = "on";
				qcom,turn-off-delay-ms = <500>;
				qcom,id = <5>;
				linux,default-trigger = "none";
				qcom,pwm-us = <1000>;
				qcom,use-blink;			};
		};

		qcom,[email protected] {
			compatible = "qcom,leds-qpnp";
			reg = <0xc800 0x100>;
			status = "okay";
			qcom,led_gpio_9 {
				label = "rgb";
				linux,name = "blue";
				qcom,mode = "pwm";
				qcom,pwm-channel = <4>;
				qcom,start-idx = <1>;
				qcom,idx-len = <10>;
				qcom,duty-pcts = [00 19 32 4B 64
						 64 4B 32 19 00];
				qcom,lut-flags = <3>;
				qcom,pause-lo = <0>;
				qcom,pause-hi = <0>;
				qcom,ramp-step-ms = <255>;
				qcom,max-current = <12>;
				qcom,default-state = "on";
				qcom,turn-off-delay-ms = <500>;
				qcom,id = <5>;
				linux,default-trigger = "none";
				qcom,pwm-us = <1000>;
				qcom,use-blink;
			};
		};
	};
};
Yes, this makes them *brightness controllable* with brightness values from 0-255.

2) qcom BLINKING is performed by LPG mode.

3) It switches between PWM and LPG mode by writing "1" into "blink".

4) I'm not sure what I'm missing, but when I do this with the above code, it just turns the light off. No blinking. :(

5) The PWM channels are HARD WIRED to the different GPIOs.

6) I believe that the LPGs are also hardwired to specific GPIOs.
[email protected] (gpio7) --> LPG3
[email protected] (gpio8) --> LPG4
[email protected] (gpio9) --> LPG5

Still working on it.
 
Last edited:
  • Like
Reactions: Johnsondr80

doitright

Senior Member
Oct 31, 2014
1,512
861
2) qcom BLINKING is performed by LPG mode.

3) It switches between PWM and LPG mode by writing "1" into "blink".

4) I'm not sure what I'm missing, but when I do this with the above code, it just turns the light off. No blinking. :(

5) The PWM channels are HARD WIRED to the different GPIOs.

6) I believe that the LPGs are also hardwired to specific GPIOs.
[email protected] (gpio7) --> LPG3
[email protected] (gpio8) --> LPG4
[email protected] (gpio9) --> LPG5

Still working on it.
I tried out the timer trigger (which uses kernel timers to decide when to turn the LED on and off), and what I have found is that it works fine when the CPU is kept online, but doesn't seem to have the ability to wake the CPU up to do the switch. That means that once the thing starts sleeping, the blinking doesn't really work -- just when the CPU comes alive.

As a stopgap method of getting a blinker, I'm going to look into modifying the timer trigger code to include an alarm. That should yield a *fairly low* added power consumption vs going entirely into hardware blinking. Once that is in place, I'll see about trying to figure out the LPG functionality. This is really difficult without the PMIC documentation, basically just guessing based on the implementation of other devices, and there really aren't many devices around with this PMIC. There's a couple of samsucks, which are completely useless due to their coding methods (basically obfuscated), a couple of motorolas, which are the same as nexus 6 (i.e., not implemented), an LG which has a very *strange* implementation, and the Razer Forge (pearlyn), which has its LED on a different GPIO. One good thing about the pearlyn is that I happen to own one, and it is unlocked, so I could use it to trace what is actually going on.


This is the lights.c implementation I'm using, based on https://github.com/cyanogenmod/android_device_moto_shamu/liblight/lights.c :
Code:
/*
 * Copyright (C) 2008 The Android Open Source Project
 * Copyright (C) 2014 The  Linux Foundation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


// #define LOG_NDEBUG 0

#include <cutils/log.h>

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>

#include <sys/ioctl.h>
#include <sys/types.h>

#include <hardware/lights.h>

/******************************************************************************/

static pthread_once_t g_init = PTHREAD_ONCE_INIT;
static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;

static struct light_state_t g_notification;
static struct light_state_t g_battery;
static int rgb_brightness_ratio = 32;

char const*const RED_LED_FILE
        = "/sys/class/leds/red/brightness";
char const*const GREEN_LED_FILE
        = "/sys/class/leds/green/brightness";
char const*const BLUE_LED_FILE
        = "/sys/class/leds/blue/brightness";
char const*const LCD_FILE
        = "/sys/class/leds/lcd-backlight/brightness";
char const*const RED_ON_MS_FILE
        = "/sys/class/leds/red/delay_on";
char const*const GREEN_ON_MS_FILE
        = "/sys/class/leds/green/delay_on";
char const*const BLUE_ON_MS_FILE
        = "/sys/class/leds/blue/delay_on";
char const*const RED_OFF_MS_FILE
        = "/sys/class/leds/red/delay_off";
char const*const GREEN_OFF_MS_FILE
        = "/sys/class/leds/green/delay_off";
char const*const BLUE_OFF_MS_FILE
        = "/sys/class/leds/blue/delay_off";
char const*const RED_TRIGGER_FILE
        = "/sys/class/leds/red/trigger";
char const*const GREEN_TRIGGER_FILE
        = "/sys/class/leds/green/trigger";
char const*const BLUE_TRIGGER_FILE
        = "/sys/class/leds/blue/trigger";

/**
 * device methods
 */

void init_globals(void)
{
    // init the mutex
    pthread_mutex_init(&g_lock, NULL);

    memset(&g_battery, 0, sizeof(g_battery));
    memset(&g_notification, 0, sizeof(g_notification));
}

static int
write_int(char const* path, int value)
{
    int fd;
    static int already_warned = 0;

    fd = open(path, O_RDWR);
    if (fd >= 0) {
        char buffer[20];
        int bytes = sprintf(buffer, "%d\n", value);
        ssize_t amt = write(fd, buffer, (size_t)bytes);
        close(fd);
        return amt == -1 ? -errno : 0;
    } else {
        if (already_warned == 0) {
            ALOGE("write_int failed to open %s\n", path);
            already_warned = 1;
        }
        return -errno;
    }
}

static int
is_lit(struct light_state_t const* state)
{
    return state->color & 0x00ffffff;
}

static int
rgb_to_brightness(struct light_state_t const* state)
{
    int color = state->color & 0x00ffffff;
    return ((77*((color>>16)&0x00ff))
            + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
}

static int
set_light_backlight(struct light_device_t* dev,
        struct light_state_t const* state)
{
    int err = 0;
    int brightness = rgb_to_brightness(state);
    if(!dev) {
        return -1;
    }
    pthread_mutex_lock(&g_lock);
    err = write_int(LCD_FILE, brightness);
    pthread_mutex_unlock(&g_lock);
    return err;
}

/**
 * There is a sperate gpio per led. Each with a maximum brightness of 20.
 * The normal rgb values are computed on a scale up to 255 so we divide them
 * by 12.75 so that varied brightness per led is spread out evenly per color.
 * The led is only optimal on absolute red, green or blue, and produces artifacts
 * of two different colors appearing at once when more than one is active, but
 * this is very limiting so ultimately we allow the end user full control.
ABOVE DESCRIPTION IS TYPICAL CYANOGENMOD NONSENSE. They have the LED
configured in DIGITAL mode without PWM, which means it is either ON or OFF.
Varying the brightness of a digital LED is completely meaningless.
... this implementation has been altered from the CM BOGUS to match up with
a kernel that ties PWM to the digital LED GPIO pins, yielding a brightness range
of [0,255]
 **/
static int
set_speaker_light_locked(struct light_device_t* dev,
        struct light_state_t const* state)
{
    unsigned int colorRGB = state->color;
    int red = 0;
    int green = 0;
    int blue = 0;

    red = ((colorRGB >> 16) & 0xFF) * rgb_brightness_ratio / 255;
    green = ((colorRGB >> 8) & 0xFF) * rgb_brightness_ratio / 255;
    blue = (colorRGB & 0xFF) * rgb_brightness_ratio / 255;
    if (red < 10) red = 0;
    if (blue < 10) blue = 0;
    if (green < 10) green = 0;

    write_int(RED_LED_FILE, red);
    write_int(GREEN_LED_FILE, green);
    write_int(BLUE_LED_FILE, blue);

#if 0
    ALOGD("set_speaker_light_locked colorRGB=%08X, red=%d, green=%d, blue=%d\n",
            colorRGB, red, green, blue);
#endif

    return 0;
}

static void
handle_speaker_battery_locked(struct light_device_t* dev)
{
    if (is_lit(&g_notification)) {
        set_speaker_light_locked(dev, &g_notification);
    } else {
        set_speaker_light_locked(dev, &g_battery);
    }
}

static int
set_light_notifications(struct light_device_t* dev,
        struct light_state_t const* state)
{
    pthread_mutex_lock(&g_lock);
    g_notification = *state;
    handle_speaker_battery_locked(dev);
    pthread_mutex_unlock(&g_lock);
    return 0;
}

static int
set_light_battery(struct light_device_t* dev,
        struct light_state_t const* state)
{
    pthread_mutex_lock(&g_lock);
    g_battery = *state;
    handle_speaker_battery_locked(dev);
    pthread_mutex_unlock(&g_lock);
    return 0;
}

/** Close the lights device */
static int
close_lights(struct light_device_t *dev)
{
    if (dev) {
        free(dev);
    }
    return 0;
}


/******************************************************************************/

/**
 * module methods
 */

/** Open a new instance of a lights device using name */
static int open_lights(const struct hw_module_t* module, char const* name,
        struct hw_device_t** device)
{
    int (*set_light)(struct light_device_t* dev,
            struct light_state_t const* state);

    if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
        set_light = set_light_backlight;
    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
        set_light = set_light_notifications;
    else if (0 == strcmp(LIGHT_ID_BATTERY, name))
        set_light = set_light_battery;
    else
        return -EINVAL;

    pthread_once(&g_init, init_globals);

    struct light_device_t *dev = malloc(sizeof(struct light_device_t));
    memset(dev, 0, sizeof(*dev));

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (struct hw_module_t*)module;
    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
    dev->set_light = set_light;

    *device = (struct hw_device_t*)dev;
    return 0;
}

static struct hw_module_methods_t lights_module_methods = {
    .open =  open_lights,
};

/*
 * The lights Module
 */
struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .version_major = 1,
    .version_minor = 0,
    .id = LIGHTS_HARDWARE_MODULE_ID,
    .name = "shamu lights module",
    .author = "Google, Inc.",
    .methods = &lights_module_methods,
};
This implementation does away with their 0-20 intensity adjustment (which doesn't make any sense at all, since any kernel implementation that exposes the 0-20 range has the gpio configured in BINARY -- on or off) in favor of a brightness ratio shift of 32/255 so that it outputs a sensible brightness level instead of DEATH RAY mode.
 
Last edited:
  • Like
Reactions: nazfalas

doitright

Senior Member
Oct 31, 2014
1,512
861
So very interesting thing I'm finding out about this... it turns out that a new day is a new perspective.

So what I've learned today... is that the PWM and LPG are, in fact, the same device. The distinction is all in the *mode of operation*.
Blinking LED and all the fancy patterns like fading in and out, are the LPG *mode*.
And since I have the brightness controls working, means that the PWM/LPG are activated. I'm just having trouble getting it to work correctly in LPG mode.

qcom,use-blink is just a mode switcher.
 
Last edited:
  • Like
Reactions: nazfalas

MrBrady

Senior Member
Oct 26, 2010
3,336
903
Does anybody know of a way to have the LED enabled for notifications but disabled for charging? It's annoying to have the phone plugged in next to the bedside with a bright green LED lighting up the room.
 

doitright

Senior Member
Oct 31, 2014
1,512
861
Does anybody know of a way to have the LED enabled for notifications but disabled for charging? It's annoying to have the phone plugged in next to the bedside with a bright green LED lighting up the room.

In lights.c function open_lights, comment out the 'else if' that checks for name=="LIGHT_ID_BATTERY", then compile your lights.shamu.

Better option though is to apply my adjustments to the kernel to enable pwm and just turn down the brightness. The charging led is very nice to have, as long as it is subtle and isn't a death ray.

---------- Post added at 02:15 AM ---------- Previous post was at 02:11 AM ----------

I think that the driver may be fubared.

I wonder if the blinker code was maybe not compiled into the pmic firmware? It is labeled as "special function 1", which suggests that it could be programmed differently. I've also seen references that suggest that it may be possible to program some really strange functionality into that hardware block.
 
  • Like
Reactions: MrBrady

MrBrady

Senior Member
Oct 26, 2010
3,336
903
In lights.c function open_lights, comment out the 'else if' that checks for name=="LIGHT_ID_BATTERY", then compile your lights.shamu.

Better option though is to apply my adjustments to the kernel to enable pwm and just turn down the brightness. The charging led is very nice to have, as long as it is subtle and isn't a death ray.

---------- Post added at 02:15 AM ---------- Previous post was at 02:11 AM ----------



I wonder if the blinker code was maybe not compiled into the pmic firmware? It is labeled as "special function 1", which suggests that it could be programmed differently. I've also seen references that suggest that it may be possible to program some really strange functionality into that hardware block.

Thanks for the info. My ideal situation is to have the LED "display black" (aka off) when fully charged. Some custom ROMs let you set this feature. I'm thinking about going back to stock for stability, but the LED is the one big conflict for me.
 

doitright

Senior Member
Oct 31, 2014
1,512
861
Thanks for the info. My ideal situation is to have the LED "display black" (aka off) when fully charged. Some custom ROMs let you set this feature. I'm thinking about going back to stock for stability, but the LED is the one big conflict for me.

From the sysimage, the *only* change you need is to lights.shamu.so (lights.c source).
Kernel change is also quite minimal to improve light functionality.
You could actually modify the battery lights function and if it is sending pure green, modify it to off.

personally, I quite *HATE* it when the light goes off when charged. The light being solid on lets you know that its actually still plugged in.
 
  • Like
Reactions: MrBrady

saa1618

Member
Aug 7, 2016
30
15
Bengaluru
Hi Devs,

Nice thread you have here, the LED is definitely an elephant in the room when I use the Nexus 6 rarely or let it charge overnight bedside. I have rooted it and flashed the Elite kernel. I'm running the Official Google Nougat 7.0 now. The charging LED works but not notifications. Can you suggest what lines of code to edit and on what files so the Notification LED works with any application?

Thank you and happy new year!

Love,
Syed
 

Yank555

Senior Member
Sep 18, 2009
8,717
19,947
Sony Xperia Pro-I
Hi Devs,

Nice thread you have here, the LED is definitely an elephant in the room when I use the Nexus 6 rarely or let it charge overnight bedside. I have rooted it and flashed the Elite kernel. I'm running the Official Google Nougat 7.0 now. The charging LED works but not notifications. Can you suggest what lines of code to edit and on what files so the Notification LED works with any application?

Thank you and happy new year!

Love,
Syed

That will need more than a change in a file. While charging led can be controlled by the kernel directly (easy), app notifications require changes in the device tree, you'll only find this in custom ROMs, or maybe using apps like lightflow (not 100% sure about the name amd not sure it'll work at all, or if so, reliably and it will likely require root)...

And even then, led's on shamu are crippled, no blinking, no real dimming.

JP.
 
  • Like
Reactions: saa1618

MartinN6

Senior Member
Jul 6, 2015
662
388
Kassel
Google Pixel 6 Pro
Led charging color

Is there any chance to edit the lights.shamu.so file to change the colors of the enabled charging leds?
Is the lights.shamu.so file responsible for the colors?
 

Top Liked Posts

  • There are no posts matching your filters.
  • 19
    The nexus 6 has two LED (enumerated as 4 devices - one charging, one red, one blue, one green) devices. This thread is to discuss getting them working with android properly.

    Issues:

    The LED devices, as implemented by moto (or google) don't contain sysfs support for flashing (blinking.) They are seem to support kernel triggers (limited) and brightness controls.

    However, at least as seen by the triggers for the charging LED, there is some back-end support for flashing the LED. (I'm not sure, as I can't find the source for the "blink while charging" trigger.)

    The triggers for the 3 color LED's are all steady on (or reactionary) triggers.


    The shared lib commonly called liblights.so (called lights.shamu.so on the nexus 6) seems to be crippled and only allows controlling the LCD backlight. BATTERY, NOTIFICATION and ATTENTION led's aren't supported. Moto/google doesn't supply the source for lights.shamu.so (which was originally compiled under a different name... lights.apq8084.so)

    However, liblights.so is trivial to re-write (once you realize that the google pre-load of android uses sysv hashes and not gnu hashes), and I've already done so to support as much as the sysfs kernel support exposes by default. (charging led attached to BATTERY, red/blue/green LED's attached to ATTENTION/NOTIFICATION.)

    (I'll attach source later when I'm home. I can't keep personal android related source at work due to potential conflicts of interest.)


    The remaining issue, as mentioned, is that nothing is exposed in sysfs to allow the LED's to flash.

    Edit: I'll be asking a moderator to move some of my posts in another section to this thread (for completeness.)
    18
    [R&D][DEV] Fix Standard Kernel Features

    I'm going to assume not enough people know a about the devs only thread, that or we have an extremely low number of devs that code themselves. Anywho, as we all know, the nexus 6 should be able to manage LEDS itself at the kernel level and indeed the qpnp-led drivers are in the kernel source. As far as actually adding the support and led features to the kernel, this is done by editing the dts files in the arch/arm/boot/dts and arch/arm/boot/dts/qcom and by editing them to support the gpio led drivers does indeed enable leds and led management auto managed by the kernel I'll link to the edits I made on git at the end.

    Unfortunately getting full support isn't so cut and dry, for example charging red led will turn on if I turn on my display while charging (instead of off) but the green indicator for full charge works fine. Before someone replies linking me to the light app devs thread or liquids ROM which both control LEDs at the sysfs level, realize that, but I want to enable auto managed leds from the kernel itself the way it's supposed to be.


    were not really going to echo commands into sysfs to control this are we? With all the talent we have here I'm sure we can solve this.

    here's the git I'm working from https://github.com/Surge1223/android_kernel_moto_shamu/commits/master

    if anyone has any ideas on dts edits that could help that would be awesome.

    I'm using the purified_shamu_defconfig and currently I have red charging led only when charging when screen on, green led kicks in when charge is complete though.

    ramdisk is stock, I have not messed with writing sysfs values via editing ramdisk because it should not be needed. We should fix the basic issue instead of using work arounds.

    I half way expect no other devs to reply here either, so is the nature of the beast, but hey maybe (hopefully?) I'm wrong and we can set an example of how open source and community efforts can effect a device.

    I'm going to ask moderators to strictly limit posts to development only.


    This is a nexus dev forum, let's start acting like it and fix this issue together.
    17
    By the way... if someone decides they want to take some of this information and publish an app that basically does nothing but write to sysfs files, that's fine. However, please make it a free app.

    Why? Because this community is about development and sharing ideas freely. Profiteering from those ideas (especially when they are as trivial as obvious sysfs writes) is despicable, and really goes against what I feel xda-developers is about.
    14
    ah man I'm trying to remember what I did to probe for support for hardware accelerated blinking. I made some tweaks to arch/arm/boot/dts/apq8084-shamu/apq8084-shamu.dtsi to enable various different modes, but each time I tried to enable a mode other than QPNP_ID_LED_GPIO (default), the phone doesn't boot.
    I'm starting to think about reversing things: The charging LED has hardware blinking support, but the RGB doesn't... so I could just make the RGB cluster be the "charging LED" (with soft blinking) and the brighter green LED be the notification LED....

    Extra "battery drain" used while software blinking wouldn't actually mean anything as the unit is being charged (and doesn't go into deep sleep while charging anyway.)

    Of course, we'd then be forced to only GREEN notification lights. On the other hand, a single color LED notification with 0 excess battery drain is better than none at all. (My last phone was an HTC M8, and that only had orange and green.)

    In fact, doing that, I could have some fun with the RGB LED while charging by changing the LED color based on the charge percentage. (I just need to figure out how to get the current battery percentage into liblights.so.)

    Best of all, it's Friday, so I'll have some time to work on it over the weekend.

    Sounds like fun.


    notes:

    liblights can access the current charge level (1-100) from sysfs /sys/class/power_supply/battery/capacity, and the charge status (Full/Charging) from /sys/class/power_supply/battery/status

    edit for more notes:

    For the 3 sysfs nodes representing the RGB LED, the "brightness" setting doesn't seem to have any impact. A brightness of "1" looks the same to me as a brightness of "20" (which is the max.) I'll have to retest that in a dark room.
    10
    As an additional note, a repacked kernel init.rc script (or some other mechanism that runs a command line at startup) can write into /sys/class/leds/charging/trigger to enable the charging LED. This doesn't require any special kernel support or shared libs... It appears to work fine "out of the box" with the standard kernel. The following are listed as supported triggers:

    • none
    • usb-online
    • max170xx_battery-online
    • wireless-online
    • rfkill0
    • mmc0
    • backlight
    • default-on
    • battery-charging-or-full
    • battery-charging
    • battery-full
    • battery-charging-blink-full-solid
    • dc-online
    • rfkill1
    • rfkill2

    Of these, I've only played with a couple battery related (they seem to work after a short delay), and mmc0 (which is like a disk activity light.) (Please don't ask me what each one of these does. It's more fun to try them out yourself.)

    How to play? Here's an example:
    Code:
    adb shell
    su
    echo battery-charging-blink-full-solid > /sys/class/leds/charging/trigger
    (The above example, as far as I can tell, does the obvious: the green LED blinks while it's charging and goes solid when the battery is charged.)