Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fa95189 authored by Fenglin Wu's avatar Fenglin Wu Committed by Steve Kondik
Browse files

healthd: charger: Add tricolor led to indicate battery capacity

Add led to indicate battery capacity when doing off mode charging. The
led behavior is design as below:
   i. 	Shows red led if capacity is lower than 15%.
   ii.	Shows yellow (red + green) led if capacity is
	lower than 90% but higher than 15%.
   iii. Shows green led if capacity is higher than 90%.

Change-Id: If637defec8a04e859b00a6492ec1f95d6bff2200
parent b5c316ed
Loading
Loading
Loading
Loading
+87 −0
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@ char *locale;
#define LAST_KMSG_PATH          "/proc/last_kmsg"
#define LAST_KMSG_PSTORE_PATH   "/sys/fs/pstore/console-ramoops"
#define LAST_KMSG_MAX_SZ        (32 * 1024)
#define RED_LED_PATH            "/sys/class/leds/red/brightness"
#define GREEN_LED_PATH          "/sys/class/leds/green/brightness"
#define BLUE_LED_PATH           "/sys/class/leds/blue/brightness"

#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
#define LOGI(x...) do { KLOG_INFO("charger", x); } while (0)
@@ -169,12 +172,87 @@ static struct animation battery_animation = {
    .capacity = 0,
};

enum {
    RED_LED = 0x01 << 0,
    GREEN_LED = 0x01 << 1,
    BLUE_LED = 0x01 << 2,
};

struct led_ctl {
    int color;
    const char *path;
};

struct led_ctl leds[3] =
    {{RED_LED, RED_LED_PATH},
    {GREEN_LED, GREEN_LED_PATH},
    {BLUE_LED, BLUE_LED_PATH}};

struct soc_led_color_mapping {
    int soc;
    int color;
};

struct soc_led_color_mapping soc_leds[3] = {
    {15, RED_LED},
    {90, RED_LED | GREEN_LED},
    {100, GREEN_LED},
};

static struct charger charger_state;

static int char_width;
static int char_height;
static bool minui_inited;

static int set_tricolor_led(int on, int color)
{
    int fd, i;
    char buffer[10];

    for (i = 0; i < (int)ARRAY_SIZE(leds); i++) {
        if ((color & leds[i].color) && (access(leds[i].path, R_OK | W_OK) == 0)) {
            fd = open(leds[i].path, O_RDWR);
            if (fd < 0) {
                LOGE("Could not open red led node\n");
                goto cleanup;
            }
            if (on)
                snprintf(buffer, sizeof(int), "%d\n", 255);
            else
                snprintf(buffer, sizeof(int), "%d\n", 0);

            if (write(fd, buffer, strlen(buffer)) < 0)
                LOGE("Could not write to led node\n");
cleanup:
            if (fd >= 0)
                close(fd);
        }
    }

    return 0;
}

static int set_battery_soc_leds(int soc)
{
    int i, color;
    static int old_color = 0;

    for (i = 0; i < (int)ARRAY_SIZE(soc_leds); i++) {
        if (soc < soc_leds[i].soc)
            break;
    }
    color = soc_leds[i].color;
    if (old_color != color) {
        set_tricolor_led(0, old_color);
        set_tricolor_led(1, color);
        old_color = color;
        LOGV("soc = %d, set led color 0x%x\n", soc, soc_leds[i].color);
    }

    return 0;
}

/* current time in milliseconds */
static int64_t curr_time_ms(void)
{
@@ -561,9 +639,18 @@ static void handle_input_state(struct charger *charger, int64_t now)

static void handle_power_supply_state(struct charger *charger, int64_t now)
{
    static int old_soc = 0;
    int soc;

    if (!charger->have_battery_state)
        return;

    soc = get_battery_capacity();
    if (old_soc != soc) {
        old_soc = soc;
        set_battery_soc_leds(soc);
    }

    if (!charger->charger_connected) {
        request_suspend(false);
        if (charger->next_pwr_check == -1) {