charger.c revision b77d3d724945f38b39f3116e3aead4edcbd08a36
1f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin/* 2f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * Copyright (C) 2011 The Android Open Source Project 3f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * 4f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * Licensed under the Apache License, Version 2.0 (the "License"); 5f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * you may not use this file except in compliance with the License. 6f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * You may obtain a copy of the License at 7f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * 8f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * http://www.apache.org/licenses/LICENSE-2.0 9f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * 10f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * Unless required by applicable law or agreed to in writing, software 11f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * distributed under the License is distributed on an "AS IS" BASIS, 12f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * See the License for the specific language governing permissions and 14f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * limitations under the License. 15f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin */ 16f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 17f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin//#define DEBUG_UEVENTS 18f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define CHARGER_KLOG_LEVEL 6 19f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 20f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <dirent.h> 21f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <errno.h> 22f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <fcntl.h> 23f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <linux/input.h> 24f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <stdbool.h> 25f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <stdio.h> 26f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <stdlib.h> 27f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <string.h> 28f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/poll.h> 29f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/stat.h> 30f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/types.h> 31f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/un.h> 32f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <time.h> 33f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <unistd.h> 34f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 35b77d3d724945f38b39f3116e3aead4edcbd08a36Elliott Hughes#include <sys/socket.h> 36b77d3d724945f38b39f3116e3aead4edcbd08a36Elliott Hughes#include <linux/netlink.h> 37b77d3d724945f38b39f3116e3aead4edcbd08a36Elliott Hughes 38f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <cutils/android_reboot.h> 39f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <cutils/klog.h> 40f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <cutils/list.h> 41823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin#include <cutils/misc.h> 42f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <cutils/uevent.h> 43f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 44f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include "minui/minui.h" 45f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 46f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifndef max 47f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define max(a,b) ((a) > (b) ? (a) : (b)) 48f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 49f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 50f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifndef min 51f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define min(a,b) ((a) < (b) ? (a) : (b)) 52f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 53f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 540052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 550052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 56f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define MSEC_PER_SEC (1000LL) 57f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define NSEC_PER_MSEC (1000000LL) 58f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 590052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin#define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC) 6092312a515b0b877deed5dfdbf9d7613e8d66fee5Dima Zavin#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC) 61f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC) 62f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 631a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin#define BATTERY_FULL_THRESH 95 641a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 65823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin#define LAST_KMSG_PATH "/proc/last_kmsg" 66823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin#define LAST_KMSG_MAX_SZ (32 * 1024) 67823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 68f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0) 69f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGI(x...) do { KLOG_INFO("charger", x); } while (0) 70f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0) 71f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 72f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct key_state { 73f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool pending; 74f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool down; 75f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timestamp; 76f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 77f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 78f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct power_supply { 79f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode list; 80f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char name[256]; 81f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char type[32]; 82f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool online; 83f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool valid; 840052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin char cap_path[PATH_MAX]; 850052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 860052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 870052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstruct frame { 880052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin const char *name; 890052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int disp_time; 900052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int min_capacity; 919ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin bool level_only; 920052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 930052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_surface surface; 940052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 950052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 960052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstruct animation { 970052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin bool run; 980052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 990052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct frame *frames; 1000052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int cur_frame; 1010052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int num_frames; 1020052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1030052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int cur_cycle; 1040052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int num_cycles; 1050052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1060052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* current capacity being animated */ 1070052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int capacity; 108f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 109f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 110f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct charger { 111f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_screen_transition; 112f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_key_check; 113f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_pwr_check; 114f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 115f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state keys[KEY_MAX + 1]; 116f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int uevent_fd; 117f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 118f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode supplies; 119f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int num_supplies; 120f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int num_supplies_online; 121f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 1220052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct animation *batt_anim; 1230052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_surface surf_unknown; 1240052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 125f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *battery; 126f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 127f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 128f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct uevent { 129f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *action; 130f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *path; 131f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *subsystem; 132f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_name; 133f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_type; 134f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_online; 135f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 136f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 1370052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic struct frame batt_anim_frames[] = { 1380052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1390052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_0", 1400052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1410052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 0, 1420052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1430052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1440052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_1", 1450052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1460052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 20, 1470052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1480052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1490052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_2", 1500052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1510052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 40, 1520052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1530052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1540052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_3", 1550052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1560052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 60, 1570052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1580052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1590052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_4", 1600052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1610052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 80, 1629ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin .level_only = true, 1630052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1641a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin { 1651a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin .name = "charger/battery_5", 1661a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin .disp_time = 750, 1671a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin .min_capacity = BATTERY_FULL_THRESH, 1681a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin }, 1690052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 1700052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1710052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic struct animation battery_animation = { 1720052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .frames = batt_anim_frames, 1730052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .num_frames = ARRAY_SIZE(batt_anim_frames), 1740052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .num_cycles = 3, 1750052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 1760052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1770052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic struct charger charger_state = { 1780052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .batt_anim = &battery_animation, 1790052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 1800052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 181f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int char_width; 182f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int char_height; 183f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 184f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin/* current time in milliseconds */ 185f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int64_t curr_time_ms(void) 186f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 187f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct timespec tm; 188f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin clock_gettime(CLOCK_MONOTONIC, &tm); 189f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return tm.tv_sec * MSEC_PER_SEC + (tm.tv_nsec / NSEC_PER_MSEC); 190f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 191f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 192f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void clear_screen(void) 193f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 194f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_color(0, 0, 0, 255); 195f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_fill(0, 0, gr_fb_width(), gr_fb_height()); 196f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 197f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 198823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin#define MAX_KLOG_WRITE_BUF_SZ 256 199823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 200823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavinstatic void dump_last_kmsg(void) 201823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin{ 202823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin char *buf; 203823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin char *ptr; 204823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin unsigned sz = 0; 205823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin int len; 206823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 207823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("\n"); 208823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("*************** LAST KMSG ***************\n"); 209823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("\n"); 210823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin buf = load_file(LAST_KMSG_PATH, &sz); 211823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin if (!buf || !sz) { 212823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("last_kmsg not found. Cold reset?\n"); 213823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin goto out; 214823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin } 215823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 216823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin len = min(sz, LAST_KMSG_MAX_SZ); 217823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin ptr = buf + (sz - len); 218823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 219823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin while (len > 0) { 220823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ); 221823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin char yoink; 222823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin char *nl; 223823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 224823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin nl = memrchr(ptr, '\n', cnt - 1); 225823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin if (nl) 226823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin cnt = nl - ptr + 1; 227823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 228823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin yoink = ptr[cnt]; 229823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin ptr[cnt] = '\0'; 230d11e1a0278c602c761ac37d843926e1eba5a63f1Dima Zavin klog_write(6, "<6>%s", ptr); 231823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin ptr[cnt] = yoink; 232823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 233823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin len -= cnt; 234823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin ptr += cnt; 235823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin } 236823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 237823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin free(buf); 238823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 239823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavinout: 240823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("\n"); 241823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("************* END LAST KMSG *************\n"); 242823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("\n"); 243823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin} 244823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 245f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int read_file(const char *path, char *buf, size_t sz) 246f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 247f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int fd; 248f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin size_t cnt; 249f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 250f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = open(path, O_RDONLY, 0); 251f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) 252f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 253f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 254f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin cnt = read(fd, buf, sz - 1); 255f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (cnt <= 0) 256f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 257f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin buf[cnt] = '\0'; 258f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (buf[cnt - 1] == '\n') { 259f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin cnt--; 260f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin buf[cnt] = '\0'; 261f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 262f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 263f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 264f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return cnt; 265f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 266f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinerr: 267f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) 268f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 269f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 270f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 271f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 272f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int read_file_int(const char *path, int *val) 273f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 274f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char buf[32]; 275f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 276f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int tmp; 277f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char *end; 278f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 279f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = read_file(path, buf, sizeof(buf)); 280f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) 281f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 282f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 283f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin tmp = strtol(buf, &end, 0); 284f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (end == buf || 285f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ((end < buf+sizeof(buf)) && (*end != '\n' && *end != '\0'))) 286f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 287f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 288f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin *val = tmp; 289f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 290f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 291f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinerr: 292f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 293f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 294f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 2951a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavinstatic int get_battery_capacity(struct charger *charger) 2961a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin{ 2971a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin int ret; 2981a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin int batt_cap = -1; 2991a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 3001a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin if (!charger->battery) 3011a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin return -1; 3021a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 3031a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin ret = read_file_int(charger->battery->cap_path, &batt_cap); 3041a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin if (ret < 0 || batt_cap > 100) { 3051a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin batt_cap = -1; 3061a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin } 3071a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 3081a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin return batt_cap; 3091a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin} 3101a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 311f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic struct power_supply *find_supply(struct charger *charger, 312f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *name) 313f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 314f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode *node; 315f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply; 316f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 317f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_for_each(node, &charger->supplies) { 318f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = node_to_item(node, struct power_supply, list); 319f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(name, supply->name, sizeof(supply->name))) 320f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return supply; 321f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 322f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return NULL; 323f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 324f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 325f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic struct power_supply *add_supply(struct charger *charger, 326f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *name, const char *type, 3270052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin const char *path, bool online) 328f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 329f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply; 330f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 331f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = calloc(1, sizeof(struct power_supply)); 332f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) 333f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return NULL; 334f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 335f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(supply->name, name, sizeof(supply->name)); 336f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(supply->type, type, sizeof(supply->type)); 3370052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin snprintf(supply->cap_path, sizeof(supply->cap_path), 3380052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin "/sys/%s/capacity", path); 339f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply->online = online; 340f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_add_tail(&charger->supplies, &supply->list); 341f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies++; 342f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("... added %s %s %d\n", supply->name, supply->type, online); 343f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return supply; 344f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 345f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 346f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void remove_supply(struct charger *charger, struct power_supply *supply) 347f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 348f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) 349f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 350f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_remove(&supply->list); 351f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies--; 352f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin free(supply); 353f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 354f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 355f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void parse_uevent(const char *msg, struct uevent *uevent) 356f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 357f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action = ""; 358f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->path = ""; 359f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->subsystem = ""; 360f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name = ""; 361f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_online = ""; 362f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type = ""; 363f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 364f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* currently ignoring SEQNUM */ 365f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (*msg) { 366f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifdef DEBUG_UEVENTS 367f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("uevent str: %s\n", msg); 368f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 369f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(msg, "ACTION=", 7)) { 370f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 7; 371f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action = msg; 372f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "DEVPATH=", 8)) { 373f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 8; 374f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->path = msg; 375f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "SUBSYSTEM=", 10)) { 376f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 10; 377f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->subsystem = msg; 378f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_NAME=", 18)) { 379f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 18; 380f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name = msg; 381f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_ONLINE=", 20)) { 382f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 20; 383f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_online = msg; 384f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_TYPE=", 18)) { 385f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 18; 386f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type = msg; 387f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 388f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 389f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* advance to after the next \0 */ 390f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (*msg++) 391f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ; 392f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 393f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 394f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("event { '%s', '%s', '%s', '%s', '%s', '%s' }\n", 395f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action, uevent->path, uevent->subsystem, 396f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, uevent->ps_type, uevent->ps_online); 397f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 398f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 399f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_ps_uevent(struct charger *charger, struct uevent *uevent) 400f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 401f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int online; 402f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char ps_type[32]; 403f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply = NULL; 404f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int i; 405f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool was_online = false; 406f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool battery = false; 407f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 408f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (uevent->ps_type[0] == '\0') { 409f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char *path; 410f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 411f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 412f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (uevent->path[0] == '\0') 413f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 414f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = asprintf(&path, "/sys/%s/type", uevent->path); 415f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret <= 0) 416f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 417f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = read_file(path, ps_type, sizeof(ps_type)); 418f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin free(path); 419f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) 420f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 421f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 422f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(ps_type, uevent->ps_type, sizeof(ps_type)); 423f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 424f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 425f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(ps_type, "Battery", 7)) 426f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin battery = true; 427f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 428f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin online = atoi(uevent->ps_online); 429f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = find_supply(charger, uevent->ps_name); 430f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (supply) { 431f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin was_online = supply->online; 432f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply->online = online; 433f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 434f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 435f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strcmp(uevent->action, "add")) { 436f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 4370052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin supply = add_supply(charger, uevent->ps_name, ps_type, uevent->path, 4380052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin online); 439f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 440f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("cannot add supply '%s' (%s %d)\n", uevent->ps_name, 441f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type, online); 442f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 443f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 444f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* only pick up the first battery for now */ 445f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (battery && !charger->battery) 446f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->battery = supply; 447f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 448f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("supply '%s' already exists..\n", uevent->ps_name); 449f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 450f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strcmp(uevent->action, "remove")) { 451f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (supply) { 452f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->battery == supply) 453f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->battery = NULL; 454f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin remove_supply(charger, supply); 455f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = NULL; 456f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 457f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strcmp(uevent->action, "change")) { 458f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 459f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("power supply '%s' not found ('%s' %d)\n", 460f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, ps_type, online); 461f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 462f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 463f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 464f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 465f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 466f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 467f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* allow battery to be managed in the supply list but make it not 468f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * contribute to online power supplies. */ 469f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!battery) { 470f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (was_online && !online) 471f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies_online--; 472f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else if (supply && !was_online && online) 473f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies_online++; 474f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 475f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 476f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("power supply %s (%s) %s (action=%s num_online=%d num_supplies=%d)\n", 477f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, ps_type, battery ? "" : online ? "online" : "offline", 478f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action, charger->num_supplies_online, charger->num_supplies); 479f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 480f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 481f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_uevent(struct charger *charger, struct uevent *uevent) 482f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 483f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strcmp(uevent->subsystem, "power_supply")) 484f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_ps_uevent(charger, uevent); 485f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 486f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 487f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define UEVENT_MSG_LEN 1024 488f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int handle_uevent_fd(struct charger *charger, int fd) 489f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 490f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char msg[UEVENT_MSG_LEN+2]; 491f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int n; 492f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 493f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) 494f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 495f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 496f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (true) { 497f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct uevent uevent; 498f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 499f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin n = uevent_kernel_multicast_recv(fd, msg, UEVENT_MSG_LEN); 500f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (n <= 0) 501f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin break; 502f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ 503f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 504f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 505f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg[n] = '\0'; 506f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg[n+1] = '\0'; 507f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 508f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin parse_uevent(msg, &uevent); 509f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_uevent(charger, &uevent); 510f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 511f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 512f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 513f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 514f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 515f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int uevent_callback(int fd, short revents, void *data) 516f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 517f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = data; 518f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 519f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!(revents & POLLIN)) 520f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 521f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return handle_uevent_fd(charger, fd); 522f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 523f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 524f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin/* force the kernel to regenerate the change events for the existing 525f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * devices, if valid */ 526f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void do_coldboot(struct charger *charger, DIR *d, const char *event, 527f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool follow_links, int max_depth) 528f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 529f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct dirent *de; 530f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int dfd, fd; 531f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 532f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin dfd = dirfd(d); 533f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 534f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = openat(dfd, "uevent", O_WRONLY); 535f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) { 536f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin write(fd, event, strlen(event)); 537f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 538f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_uevent_fd(charger, charger->uevent_fd); 539f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 540f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 541f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while ((de = readdir(d)) && max_depth > 0) { 542f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin DIR *d2; 543f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 544f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("looking at '%s'\n", de->d_name); 545f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 546f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if ((de->d_type != DT_DIR && !(de->d_type == DT_LNK && follow_links)) || 547f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin de->d_name[0] == '.') { 548f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("skipping '%s' type %d (depth=%d follow=%d)\n", 549f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin de->d_name, de->d_type, max_depth, follow_links); 550f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 551f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 552f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("can descend into '%s'\n", de->d_name); 553f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 554f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); 555f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) { 556f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("cannot openat %d '%s' (%d: %s)\n", dfd, de->d_name, 557f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin errno, strerror(errno)); 558f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 559f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 560f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 561f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin d2 = fdopendir(fd); 562f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (d2 == 0) 563f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 564f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else { 565f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("opened '%s'\n", de->d_name); 566f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin do_coldboot(charger, d2, event, follow_links, max_depth - 1); 567f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin closedir(d2); 568f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 569f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 570f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 571f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 572f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void coldboot(struct charger *charger, const char *path, 573f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *event) 574f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 575f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char str[256]; 576f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 577f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("doing coldboot '%s' in '%s'\n", event, path); 578f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin DIR *d = opendir(path); 579f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (d) { 580f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin snprintf(str, sizeof(str), "%s\n", event); 581f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin do_coldboot(charger, d, str, true, 1); 582f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin closedir(d); 583f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 584f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 585f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 586f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int draw_text(const char *str, int x, int y) 587f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 588f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int str_len_px = gr_measure(str); 589f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 590f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (x < 0) 591f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin x = (gr_fb_width() - str_len_px) / 2; 592f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (y < 0) 593f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y = (gr_fb_height() - char_height) / 2; 594f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_text(x, y, str); 595f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 596f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return y + char_height; 597f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 598f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 599f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void android_green(void) 600f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 601f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_color(0xa4, 0xc6, 0x39, 255); 602f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 603f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6040052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin/* returns the last y-offset of where the surface ends */ 6050052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic int draw_surface_centered(struct charger *charger, gr_surface surface) 606f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 6070052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int w; 6080052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int h; 609f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int x; 6100052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int y; 611f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6120052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin w = gr_get_width(surface); 6130052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin h = gr_get_height(surface); 6140052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin x = (gr_fb_width() - w) / 2 ; 6150052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin y = (gr_fb_height() - h) / 2 ; 616f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6170052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y); 6180052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_blit(surface, 0, 0, w, h, x, y); 6190052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin return y + h; 6200052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 621f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6220052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void draw_unknown(struct charger *charger) 6230052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6240052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int y; 6250052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (charger->surf_unknown) { 6260052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_surface_centered(charger, charger->surf_unknown); 627f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 628f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_green(); 629f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y = draw_text("Charging!", -1, -1); 6300052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_text("?\?/100", -1, y + 25); 631f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 6320052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 633f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6340052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void draw_battery(struct charger *charger) 6350052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6360052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct animation *batt_anim = charger->batt_anim; 6370052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct frame *frame = &batt_anim->frames[batt_anim->cur_frame]; 6380052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6390052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->num_frames != 0) { 6400052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_surface_centered(charger, frame->surface); 6410052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("drawing frame #%d name=%s min_cap=%d time=%d\n", 6420052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_frame, frame->name, frame->min_capacity, 6430052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin frame->disp_time); 644f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 6450052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 646f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6470052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void redraw_screen(struct charger *charger) 6480052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6490052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct animation *batt_anim = charger->batt_anim; 650f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6510052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin clear_screen(); 652f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6530052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* try to display *something* */ 6540052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->capacity < 0 || batt_anim->num_frames == 0) 6550052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_unknown(charger); 6560052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin else 6570052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_battery(charger); 658f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_flip(); 659f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 660f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6610052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void kick_animation(struct animation *anim) 6620052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6630052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin anim->run = true; 6640052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 6650052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6660052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void reset_animation(struct animation *anim) 6670052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6680052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin anim->cur_cycle = 0; 6690052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin anim->cur_frame = 0; 6700052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin anim->run = false; 6710052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 6720052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6730052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void update_screen_state(struct charger *charger, int64_t now) 674f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 6750052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct animation *batt_anim = charger->batt_anim; 6760052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int cur_frame; 6770052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int disp_time; 6780052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6790052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (!batt_anim->run || now < charger->next_screen_transition) 680f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 681f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6820052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* animation is over, blank screen and leave */ 6830052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->cur_cycle == batt_anim->num_cycles) { 6840052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin reset_animation(batt_anim); 685f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition = -1; 6860052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_fb_blank(true); 6870052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("[%lld] animation done\n", now); 6880052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin return; 6890052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 6900052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6910052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time; 6920052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6930052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* animation starting, set up the animation */ 6940052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->cur_frame == 0) { 6950052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int batt_cap; 6960052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int ret; 6970052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6980052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("[%lld] animation starting\n", now); 6991a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin batt_cap = get_battery_capacity(charger); 7001a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin if (batt_cap >= 0 && batt_anim->num_frames != 0) { 7010052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int i; 7020052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7030052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* find first frame given current capacity */ 7040052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin for (i = 1; i < batt_anim->num_frames; i++) { 7050052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_cap < batt_anim->frames[i].min_capacity) 7060052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin break; 7070052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7080052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_frame = i - 1; 7090052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7100052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* show the first frame for twice as long */ 7110052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2; 7120052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7130052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7140052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->capacity = batt_cap; 7150052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7160052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7170052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* unblank the screen on first cycle */ 7180052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->cur_cycle == 0) 7190052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_fb_blank(false); 7200052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7210052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* draw the new frame (@ cur_frame) */ 7220052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin redraw_screen(charger); 7230052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7240052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* if we don't have anim frames, we only have one image, so just bump 7250052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin * the cycle counter and exit 7260052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin */ 7270052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->num_frames == 0 || batt_anim->capacity < 0) { 7280052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("[%lld] animation missing or unknown battery status\n", now); 7290052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME; 7300052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_cycle++; 7310052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin return; 7320052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7330052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7340052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* schedule next screen transition */ 7350052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->next_screen_transition = now + disp_time; 7360052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7370052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* advance frame cntr to the next valid frame 7380052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin * if necessary, advance cycle cntr, and reset frame cntr 7390052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin */ 7400052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_frame++; 7419ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin 7429ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin /* if the frame is used for level-only, that is only show it when it's 7439ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin * the current level, skip it during the animation. 7449ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin */ 7459ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin while (batt_anim->cur_frame < batt_anim->num_frames && 7469ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin batt_anim->frames[batt_anim->cur_frame].level_only) 7479ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin batt_anim->cur_frame++; 7489ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin if (batt_anim->cur_frame >= batt_anim->num_frames) { 7490052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_cycle++; 7500052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_frame = 0; 751f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7520052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* don't reset the cycle counter, since we use that as a signal 7530052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin * in a test above to check if animation is over 7540052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin */ 7550052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 756f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 757f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7582471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavinstatic int set_key_callback(int code, int value, void *data) 759f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 7602471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin struct charger *charger = data; 7612471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin int64_t now = curr_time_ms(); 7622471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin int down = !!value; 763f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7642471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin if (code > KEY_MAX) 7652471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin return -1; 766f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7672d978c01ee71002b3c5999126c009ec07a773c30Dima Zavin /* ignore events that don't modify our state */ 7682d978c01ee71002b3c5999126c009ec07a773c30Dima Zavin if (charger->keys[code].down == down) 769471157a393d052aece013d1f8b7701aaadca3b6cDima Zavin return 0; 7702d978c01ee71002b3c5999126c009ec07a773c30Dima Zavin 771f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* only record the down even timestamp, as the amount 772f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * of time the key spent not being pressed is not useful */ 773f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (down) 7742471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin charger->keys[code].timestamp = now; 7752471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin charger->keys[code].down = down; 7762471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin charger->keys[code].pending = true; 777f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (down) { 7782471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin LOGV("[%lld] key[%d] down\n", now, code); 779f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 7802471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin int64_t duration = now - charger->keys[code].timestamp; 781f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t secs = duration / 1000; 782f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t msecs = duration - secs * 1000; 783f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] key[%d] up (was down for %lld.%lldsec)\n", now, 7842471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin code, secs, msecs); 785f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 7862471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin 7872471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin return 0; 7882471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin} 7892471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin 7902471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavinstatic void update_input_state(struct charger *charger, 7912471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin struct input_event *ev) 7922471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin{ 7932471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin if (ev->type != EV_KEY) 7942471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin return; 7952471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin set_key_callback(ev->code, ev->value, charger); 796f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 797f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 798f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void set_next_key_check(struct charger *charger, 799f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state *key, 800f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timeout) 801f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 802f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t then = key->timestamp + timeout; 803f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 804f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check == -1 || then < charger->next_key_check) 805f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = then; 806f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 807f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 808f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_key(struct charger *charger, int code, int64_t now) 809f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 810f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state *key = &charger->keys[code]; 811f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_key_check; 812f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 813f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (code == KEY_POWER) { 814f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (key->down) { 815f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME; 816f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (now >= reboot_timeout) { 817f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] rebooting\n", now); 818f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_reboot(ANDROID_RB_RESTART, 0, 0); 819f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 820f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* if the key is pressed but timeout hasn't expired, 821f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * make sure we wake up at the right-ish time to check 822f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin */ 823f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin set_next_key_check(charger, key, POWER_ON_KEY_TIME); 824f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 825f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 826f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* if the power key got released, force screen state cycle */ 827f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (key->pending) 8280052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin kick_animation(charger->batt_anim); 829f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 830f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 831f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 832f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin key->pending = false; 833f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 834f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 835f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void handle_input_state(struct charger *charger, int64_t now) 836f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 837f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_key(charger, KEY_POWER, now); 838f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 839f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check != -1 && now > charger->next_key_check) 840f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = -1; 841f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 842f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 843f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void handle_power_supply_state(struct charger *charger, int64_t now) 844f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 845f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->num_supplies_online == 0) { 846f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check == -1) { 847f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME; 848f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] device unplugged: shutting down in %lld (@ %lld)\n", 849f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin now, UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check); 850f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (now >= charger->next_pwr_check) { 851f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] shutting down\n", now); 852f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_reboot(ANDROID_RB_POWEROFF, 0, 0); 853f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 854f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* otherwise we already have a shutdown timer scheduled */ 855f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 856f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 857f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* online supply present, reset shutdown timer if set */ 858f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check != -1) { 859f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] device plugged in: shutdown cancelled\n", now); 8600052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin kick_animation(charger->batt_anim); 861f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 862f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = -1; 863f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 864f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 865f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 866f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void wait_next_event(struct charger *charger, int64_t now) 867f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 868f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_event = INT64_MAX; 869f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timeout; 870f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct input_event ev; 871f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 872f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 873f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] next screen: %lld next key: %lld next pwr: %lld\n", now, 874f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition, charger->next_key_check, 875f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check); 876f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 877f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_screen_transition != -1) 878f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_screen_transition; 879f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check != -1 && charger->next_key_check < next_event) 880f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_key_check; 881f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check != -1 && charger->next_pwr_check < next_event) 882f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_pwr_check; 883f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 884f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (next_event != -1 && next_event != INT64_MAX) 885f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin timeout = max(0, next_event - now); 886f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else 887f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin timeout = -1; 888f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] blocking (%lld)\n", now, timeout); 889f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = ev_wait((int)timeout); 890f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!ret) 891f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_dispatch(); 892f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 893f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 894f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int input_callback(int fd, short revents, void *data) 895f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 896f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = data; 897f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct input_event ev; 898f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 899f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 900f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = ev_get_input(fd, revents, &ev); 901f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret) 902f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 9032471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin update_input_state(charger, &ev); 904f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 905f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 906f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 907f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void event_loop(struct charger *charger) 908f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 909f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 910f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 911f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (true) { 912f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t now = curr_time_ms(); 913f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 914f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] event_loop()\n", now); 915f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_input_state(charger, now); 916f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_power_supply_state(charger, now); 917f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 9180052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* do screen update last in case any of the above want to start 9190052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin * screen transitions (animations, etc) 9200052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin */ 9210052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin update_screen_state(charger, now); 9220052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 923f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin wait_next_event(charger, now); 924f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 925f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 926f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 927f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinint main(int argc, char **argv) 928f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 929f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 930f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = &charger_state; 931f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t now = curr_time_ms() - 1; 932f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int fd; 9330052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int i; 934f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 935f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_init(&charger->supplies); 936f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 937f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin klog_init(); 938f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin klog_set_level(CHARGER_KLOG_LEVEL); 939f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 940823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin dump_last_kmsg(); 941823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 942823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("--------------- STARTING CHARGER MODE ---------------\n"); 943823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 944f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_init(); 945f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_font_size(&char_width, &char_height); 946f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 947f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_init(input_callback, charger); 948f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 949f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = uevent_open_socket(64*1024, true); 950f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) { 951f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fcntl(fd, F_SETFL, O_NONBLOCK); 952f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_add_fd(fd, uevent_callback, charger); 953f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 954f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->uevent_fd = fd; 955f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin coldboot(charger, "/sys/class/power_supply", "add"); 956f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 9570052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin ret = res_create_surface("charger/battery_fail", &charger->surf_unknown); 958f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) { 959f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("Cannot load image\n"); 9600052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->surf_unknown = NULL; 9610052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 9620052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 9630052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin for (i = 0; i < charger->batt_anim->num_frames; i++) { 9640052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct frame *frame = &charger->batt_anim->frames[i]; 9650052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 9660052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin ret = res_create_surface(frame->name, &frame->surface); 9670052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (ret < 0) { 9680052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGE("Cannot load image %s\n", frame->name); 9690052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* TODO: free the already allocated surfaces... */ 9700052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->batt_anim->num_frames = 0; 9710052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->batt_anim->num_cycles = 1; 9720052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin break; 9730052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 974f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 975f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 9762471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin ev_sync_key_state(set_key_callback, charger); 9772471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin 978f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_fb_blank(true); 979f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 980f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition = now - 1; 981f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = -1; 982f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = -1; 9830052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin reset_animation(charger->batt_anim); 9840052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin kick_animation(charger->batt_anim); 985f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 986f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin event_loop(charger); 987f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 988f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 989f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 990