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 4440156b8a91363da69675e7e4cb7947c371871654Iliyan Malchev#ifdef CHARGER_ENABLE_SUSPEND 459255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee#include <suspend/autosuspend.h> 4640156b8a91363da69675e7e4cb7947c371871654Iliyan Malchev#endif 479255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee 48f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include "minui/minui.h" 49f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 50f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifndef max 51f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define max(a,b) ((a) > (b) ? (a) : (b)) 52f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 53f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 54f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifndef min 55f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define min(a,b) ((a) < (b) ? (a) : (b)) 56f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 57f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 580052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 590052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 60f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define MSEC_PER_SEC (1000LL) 61f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define NSEC_PER_MSEC (1000000LL) 62f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 630052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin#define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC) 6492312a515b0b877deed5dfdbf9d7613e8d66fee5Dima Zavin#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC) 65f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC) 66f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 671a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin#define BATTERY_FULL_THRESH 95 681a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 69823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin#define LAST_KMSG_PATH "/proc/last_kmsg" 70823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin#define LAST_KMSG_MAX_SZ (32 * 1024) 71823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 72f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0) 73f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGI(x...) do { KLOG_INFO("charger", x); } while (0) 74f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0) 75f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 76f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct key_state { 77f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool pending; 78f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool down; 79f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timestamp; 80f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 81f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 82f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct power_supply { 83f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode list; 84f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char name[256]; 85f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char type[32]; 86f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool online; 87f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool valid; 880052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin char cap_path[PATH_MAX]; 890052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 900052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 910052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstruct frame { 920052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin const char *name; 930052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int disp_time; 940052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int min_capacity; 959ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin bool level_only; 960052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 970052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_surface surface; 980052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 990052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1000052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstruct animation { 1010052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin bool run; 1020052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1030052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct frame *frames; 1040052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int cur_frame; 1050052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int num_frames; 1060052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1070052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int cur_cycle; 1080052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int num_cycles; 1090052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1100052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* current capacity being animated */ 1110052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int capacity; 112f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 113f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 114f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct charger { 115f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_screen_transition; 116f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_key_check; 117f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_pwr_check; 118f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 119f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state keys[KEY_MAX + 1]; 120f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int uevent_fd; 121f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 122f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode supplies; 123f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int num_supplies; 124f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int num_supplies_online; 125f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 1260052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct animation *batt_anim; 1270052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_surface surf_unknown; 1280052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 129f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *battery; 130f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 131f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 132f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct uevent { 133f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *action; 134f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *path; 135f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *subsystem; 136f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_name; 137f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_type; 138f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_online; 139f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 140f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 1410052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic struct frame batt_anim_frames[] = { 1420052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1430052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_0", 1440052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1450052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 0, 1460052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1470052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1480052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_1", 1490052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1500052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 20, 1510052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1520052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1530052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_2", 1540052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1550052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 40, 1560052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1570052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1580052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_3", 1590052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1600052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 60, 1610052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1620052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin { 1630052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .name = "charger/battery_4", 1640052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .disp_time = 750, 1650052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .min_capacity = 80, 1669ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin .level_only = true, 1670052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin }, 1681a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin { 1691a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin .name = "charger/battery_5", 1701a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin .disp_time = 750, 1711a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin .min_capacity = BATTERY_FULL_THRESH, 1721a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin }, 1730052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 1740052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1750052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic struct animation battery_animation = { 1760052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .frames = batt_anim_frames, 1770052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .num_frames = ARRAY_SIZE(batt_anim_frames), 1780052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .num_cycles = 3, 1790052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 1800052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 1810052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic struct charger charger_state = { 1820052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin .batt_anim = &battery_animation, 1830052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin}; 1840052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 185f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int char_width; 186f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int char_height; 187f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 188f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin/* current time in milliseconds */ 189f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int64_t curr_time_ms(void) 190f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 191f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct timespec tm; 192f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin clock_gettime(CLOCK_MONOTONIC, &tm); 193f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return tm.tv_sec * MSEC_PER_SEC + (tm.tv_nsec / NSEC_PER_MSEC); 194f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 195f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 196f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void clear_screen(void) 197f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 198f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_color(0, 0, 0, 255); 199f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_fill(0, 0, gr_fb_width(), gr_fb_height()); 200f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 201f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 202823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin#define MAX_KLOG_WRITE_BUF_SZ 256 203823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 204823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavinstatic void dump_last_kmsg(void) 205823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin{ 206823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin char *buf; 207823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin char *ptr; 208823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin unsigned sz = 0; 209823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin int len; 210823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 211823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("\n"); 212823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("*************** LAST KMSG ***************\n"); 213823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("\n"); 214823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin buf = load_file(LAST_KMSG_PATH, &sz); 215823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin if (!buf || !sz) { 216823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("last_kmsg not found. Cold reset?\n"); 217823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin goto out; 218823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin } 219823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 220823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin len = min(sz, LAST_KMSG_MAX_SZ); 221823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin ptr = buf + (sz - len); 222823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 223823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin while (len > 0) { 224823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ); 225823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin char yoink; 226823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin char *nl; 227823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 228823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin nl = memrchr(ptr, '\n', cnt - 1); 229823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin if (nl) 230823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin cnt = nl - ptr + 1; 231823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 232823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin yoink = ptr[cnt]; 233823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin ptr[cnt] = '\0'; 234d11e1a0278c602c761ac37d843926e1eba5a63f1Dima Zavin klog_write(6, "<6>%s", ptr); 235823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin ptr[cnt] = yoink; 236823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 237823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin len -= cnt; 238823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin ptr += cnt; 239823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin } 240823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 241823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin free(buf); 242823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 243823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavinout: 244823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("\n"); 245823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("************* END LAST KMSG *************\n"); 246823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("\n"); 247823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin} 248823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 249f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int read_file(const char *path, char *buf, size_t sz) 250f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 251f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int fd; 252f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin size_t cnt; 253f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 254f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = open(path, O_RDONLY, 0); 255f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) 256f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 257f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 258f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin cnt = read(fd, buf, sz - 1); 259f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (cnt <= 0) 260f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 261f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin buf[cnt] = '\0'; 262f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (buf[cnt - 1] == '\n') { 263f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin cnt--; 264f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin buf[cnt] = '\0'; 265f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 266f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 267f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 268f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return cnt; 269f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 270f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinerr: 271f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) 272f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 273f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 274f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 275f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 276f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int read_file_int(const char *path, int *val) 277f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 278f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char buf[32]; 279f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 280f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int tmp; 281f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char *end; 282f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 283f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = read_file(path, buf, sizeof(buf)); 284f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) 285f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 286f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 287f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin tmp = strtol(buf, &end, 0); 288f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (end == buf || 289f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ((end < buf+sizeof(buf)) && (*end != '\n' && *end != '\0'))) 290f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 291f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 292f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin *val = tmp; 293f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 294f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 295f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinerr: 296f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 297f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 298f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 2991a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavinstatic int get_battery_capacity(struct charger *charger) 3001a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin{ 3011a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin int ret; 3021a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin int batt_cap = -1; 3031a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 3041a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin if (!charger->battery) 3051a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin return -1; 3061a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 3071a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin ret = read_file_int(charger->battery->cap_path, &batt_cap); 3081a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin if (ret < 0 || batt_cap > 100) { 3091a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin batt_cap = -1; 3101a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin } 3111a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 3121a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin return batt_cap; 3131a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin} 3141a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin 315f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic struct power_supply *find_supply(struct charger *charger, 316f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *name) 317f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 318f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode *node; 319f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply; 320f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 321f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_for_each(node, &charger->supplies) { 322f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = node_to_item(node, struct power_supply, list); 323f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(name, supply->name, sizeof(supply->name))) 324f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return supply; 325f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 326f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return NULL; 327f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 328f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 329f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic struct power_supply *add_supply(struct charger *charger, 330f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *name, const char *type, 3310052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin const char *path, bool online) 332f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 333f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply; 334f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 335f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = calloc(1, sizeof(struct power_supply)); 336f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) 337f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return NULL; 338f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 339f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(supply->name, name, sizeof(supply->name)); 340f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(supply->type, type, sizeof(supply->type)); 3410052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin snprintf(supply->cap_path, sizeof(supply->cap_path), 3420052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin "/sys/%s/capacity", path); 343f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply->online = online; 344f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_add_tail(&charger->supplies, &supply->list); 345f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies++; 346f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("... added %s %s %d\n", supply->name, supply->type, online); 347f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return supply; 348f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 349f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 350f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void remove_supply(struct charger *charger, struct power_supply *supply) 351f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 352f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) 353f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 354f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_remove(&supply->list); 355f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies--; 356f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin free(supply); 357f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 358f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 3599255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee#ifdef CHARGER_ENABLE_SUSPEND 3609255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.leestatic int request_suspend(bool enable) 3619255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee{ 3629255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee if (enable) 3639255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee return autosuspend_enable(); 3649255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee else 3659255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee return autosuspend_disable(); 3669255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee} 3679255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee#else 3689255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.leestatic int request_suspend(bool enable) 3699255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee{ 3709255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee return 0; 3719255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee} 3729255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee#endif 3739255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee 374f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void parse_uevent(const char *msg, struct uevent *uevent) 375f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 376f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action = ""; 377f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->path = ""; 378f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->subsystem = ""; 379f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name = ""; 380f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_online = ""; 381f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type = ""; 382f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 383f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* currently ignoring SEQNUM */ 384f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (*msg) { 385f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifdef DEBUG_UEVENTS 386f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("uevent str: %s\n", msg); 387f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 388f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(msg, "ACTION=", 7)) { 389f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 7; 390f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action = msg; 391f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "DEVPATH=", 8)) { 392f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 8; 393f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->path = msg; 394f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "SUBSYSTEM=", 10)) { 395f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 10; 396f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->subsystem = msg; 397f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_NAME=", 18)) { 398f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 18; 399f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name = msg; 400f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_ONLINE=", 20)) { 401f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 20; 402f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_online = msg; 403f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_TYPE=", 18)) { 404f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 18; 405f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type = msg; 406f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 407f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 408f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* advance to after the next \0 */ 409f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (*msg++) 410f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ; 411f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 412f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 413f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("event { '%s', '%s', '%s', '%s', '%s', '%s' }\n", 414f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action, uevent->path, uevent->subsystem, 415f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, uevent->ps_type, uevent->ps_online); 416f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 417f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 418f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_ps_uevent(struct charger *charger, struct uevent *uevent) 419f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 420f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int online; 421f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char ps_type[32]; 422f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply = NULL; 423f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int i; 424f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool was_online = false; 425f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool battery = false; 426f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 427f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (uevent->ps_type[0] == '\0') { 428f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char *path; 429f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 430f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 431f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (uevent->path[0] == '\0') 432f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 433f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = asprintf(&path, "/sys/%s/type", uevent->path); 434f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret <= 0) 435f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 436f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = read_file(path, ps_type, sizeof(ps_type)); 437f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin free(path); 438f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) 439f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 440f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 441f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(ps_type, uevent->ps_type, sizeof(ps_type)); 442f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 443f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 444f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(ps_type, "Battery", 7)) 445f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin battery = true; 446f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 447f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin online = atoi(uevent->ps_online); 448f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = find_supply(charger, uevent->ps_name); 449f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (supply) { 450f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin was_online = supply->online; 451f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply->online = online; 452f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 453f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 454f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strcmp(uevent->action, "add")) { 455f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 4560052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin supply = add_supply(charger, uevent->ps_name, ps_type, uevent->path, 4570052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin online); 458f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 459f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("cannot add supply '%s' (%s %d)\n", uevent->ps_name, 460f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type, online); 461f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 462f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 463f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* only pick up the first battery for now */ 464f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (battery && !charger->battery) 465f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->battery = supply; 466f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 467f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("supply '%s' already exists..\n", uevent->ps_name); 468f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 469f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strcmp(uevent->action, "remove")) { 470f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (supply) { 471f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->battery == supply) 472f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->battery = NULL; 473f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin remove_supply(charger, supply); 474f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = NULL; 475f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 476f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strcmp(uevent->action, "change")) { 477f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 478f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("power supply '%s' not found ('%s' %d)\n", 479f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, ps_type, online); 480f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 481f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 482f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 483f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 484f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 485f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 486f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* allow battery to be managed in the supply list but make it not 487f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * contribute to online power supplies. */ 488f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!battery) { 489f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (was_online && !online) 490f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies_online--; 491f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else if (supply && !was_online && online) 492f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies_online++; 493f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 494f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 495f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("power supply %s (%s) %s (action=%s num_online=%d num_supplies=%d)\n", 496f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, ps_type, battery ? "" : online ? "online" : "offline", 497f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action, charger->num_supplies_online, charger->num_supplies); 498f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 499f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 500f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_uevent(struct charger *charger, struct uevent *uevent) 501f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 502f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strcmp(uevent->subsystem, "power_supply")) 503f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_ps_uevent(charger, uevent); 504f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 505f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 506f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define UEVENT_MSG_LEN 1024 507f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int handle_uevent_fd(struct charger *charger, int fd) 508f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 509f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char msg[UEVENT_MSG_LEN+2]; 510f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int n; 511f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 512f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) 513f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 514f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 515f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (true) { 516f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct uevent uevent; 517f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 518f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin n = uevent_kernel_multicast_recv(fd, msg, UEVENT_MSG_LEN); 519f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (n <= 0) 520f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin break; 521f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ 522f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 523f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 524f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg[n] = '\0'; 525f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg[n+1] = '\0'; 526f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 527f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin parse_uevent(msg, &uevent); 528f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_uevent(charger, &uevent); 529f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 530f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 531f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 532f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 533f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 534f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int uevent_callback(int fd, short revents, void *data) 535f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 536f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = data; 537f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 538f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!(revents & POLLIN)) 539f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 540f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return handle_uevent_fd(charger, fd); 541f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 542f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 543f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin/* force the kernel to regenerate the change events for the existing 544f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * devices, if valid */ 545f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void do_coldboot(struct charger *charger, DIR *d, const char *event, 546f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool follow_links, int max_depth) 547f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 548f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct dirent *de; 549f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int dfd, fd; 550f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 551f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin dfd = dirfd(d); 552f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 553f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = openat(dfd, "uevent", O_WRONLY); 554f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) { 555f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin write(fd, event, strlen(event)); 556f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 557f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_uevent_fd(charger, charger->uevent_fd); 558f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 559f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 560f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while ((de = readdir(d)) && max_depth > 0) { 561f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin DIR *d2; 562f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 563f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("looking at '%s'\n", de->d_name); 564f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 565f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if ((de->d_type != DT_DIR && !(de->d_type == DT_LNK && follow_links)) || 566f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin de->d_name[0] == '.') { 567f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("skipping '%s' type %d (depth=%d follow=%d)\n", 568f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin de->d_name, de->d_type, max_depth, follow_links); 569f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 570f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 571f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("can descend into '%s'\n", de->d_name); 572f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 573f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); 574f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) { 575f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("cannot openat %d '%s' (%d: %s)\n", dfd, de->d_name, 576f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin errno, strerror(errno)); 577f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 578f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 579f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 580f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin d2 = fdopendir(fd); 581f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (d2 == 0) 582f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 583f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else { 584f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("opened '%s'\n", de->d_name); 585f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin do_coldboot(charger, d2, event, follow_links, max_depth - 1); 586f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin closedir(d2); 587f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 588f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 589f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 590f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 591f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void coldboot(struct charger *charger, const char *path, 592f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *event) 593f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 594f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char str[256]; 595f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 596f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("doing coldboot '%s' in '%s'\n", event, path); 597f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin DIR *d = opendir(path); 598f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (d) { 599f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin snprintf(str, sizeof(str), "%s\n", event); 600f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin do_coldboot(charger, d, str, true, 1); 601f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin closedir(d); 602f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 603f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 604f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 605f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int draw_text(const char *str, int x, int y) 606f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 607f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int str_len_px = gr_measure(str); 608f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 609f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (x < 0) 610f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin x = (gr_fb_width() - str_len_px) / 2; 611f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (y < 0) 612f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y = (gr_fb_height() - char_height) / 2; 61312c45fb9beba80c95c1a0db3ff5cd0efb21e82f3Doug Zongker gr_text(x, y, str, 0); 614f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 615f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return y + char_height; 616f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 617f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 618f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void android_green(void) 619f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 620f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_color(0xa4, 0xc6, 0x39, 255); 621f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 622f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6230052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin/* returns the last y-offset of where the surface ends */ 6240052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic int draw_surface_centered(struct charger *charger, gr_surface surface) 625f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 6260052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int w; 6270052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int h; 628f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int x; 6290052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int y; 630f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6310052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin w = gr_get_width(surface); 6320052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin h = gr_get_height(surface); 6330052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin x = (gr_fb_width() - w) / 2 ; 6340052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin y = (gr_fb_height() - h) / 2 ; 635f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6360052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y); 6370052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_blit(surface, 0, 0, w, h, x, y); 6380052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin return y + h; 6390052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 640f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6410052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void draw_unknown(struct charger *charger) 6420052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6430052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int y; 6440052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (charger->surf_unknown) { 6450052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_surface_centered(charger, charger->surf_unknown); 646f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 647f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_green(); 648f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y = draw_text("Charging!", -1, -1); 6490052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_text("?\?/100", -1, y + 25); 650f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 6510052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 652f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6530052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void draw_battery(struct charger *charger) 6540052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6550052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct animation *batt_anim = charger->batt_anim; 6560052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct frame *frame = &batt_anim->frames[batt_anim->cur_frame]; 6570052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6580052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->num_frames != 0) { 6590052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_surface_centered(charger, frame->surface); 6600052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("drawing frame #%d name=%s min_cap=%d time=%d\n", 6610052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_frame, frame->name, frame->min_capacity, 6620052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin frame->disp_time); 663f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 6640052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 665f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6660052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void redraw_screen(struct charger *charger) 6670052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6680052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct animation *batt_anim = charger->batt_anim; 669f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6700052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin clear_screen(); 671f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6720052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* try to display *something* */ 6730052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->capacity < 0 || batt_anim->num_frames == 0) 6740052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_unknown(charger); 6750052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin else 6760052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin draw_battery(charger); 677f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_flip(); 678f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 679f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 6800052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void kick_animation(struct animation *anim) 6810052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6820052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin anim->run = true; 6830052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 6840052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6850052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void reset_animation(struct animation *anim) 6860052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin{ 6870052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin anim->cur_cycle = 0; 6880052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin anim->cur_frame = 0; 6890052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin anim->run = false; 6900052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin} 6910052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6920052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavinstatic void update_screen_state(struct charger *charger, int64_t now) 693f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 6940052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct animation *batt_anim = charger->batt_anim; 6950052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int cur_frame; 6960052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int disp_time; 6970052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 6980052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (!batt_anim->run || now < charger->next_screen_transition) 699f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 700f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7010052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* animation is over, blank screen and leave */ 7020052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->cur_cycle == batt_anim->num_cycles) { 7030052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin reset_animation(batt_anim); 704f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition = -1; 7050052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_fb_blank(true); 7060052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("[%lld] animation done\n", now); 707fd8e6504e355d2c73a2aaad260475f72af0495bfDevin Kim if (charger->num_supplies_online > 0) 708fd8e6504e355d2c73a2aaad260475f72af0495bfDevin Kim request_suspend(true); 7090052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin return; 7100052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7110052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7120052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time; 7130052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7140052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* animation starting, set up the animation */ 7150052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->cur_frame == 0) { 7160052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int batt_cap; 7170052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int ret; 7180052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7190052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("[%lld] animation starting\n", now); 7201a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin batt_cap = get_battery_capacity(charger); 7211a5ca61b28b3269b625b7a7162b4f50734f7fea9Dima Zavin if (batt_cap >= 0 && batt_anim->num_frames != 0) { 7220052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int i; 7230052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7240052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* find first frame given current capacity */ 7250052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin for (i = 1; i < batt_anim->num_frames; i++) { 7260052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_cap < batt_anim->frames[i].min_capacity) 7270052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin break; 7280052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7290052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_frame = i - 1; 7300052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7310052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* show the first frame for twice as long */ 7320052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2; 7330052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7340052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7350052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->capacity = batt_cap; 7360052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7370052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7380052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* unblank the screen on first cycle */ 7390052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->cur_cycle == 0) 7400052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin gr_fb_blank(false); 7410052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7420052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* draw the new frame (@ cur_frame) */ 7430052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin redraw_screen(charger); 7440052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7450052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* if we don't have anim frames, we only have one image, so just bump 7460052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin * the cycle counter and exit 7470052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin */ 7480052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (batt_anim->num_frames == 0 || batt_anim->capacity < 0) { 7490052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGV("[%lld] animation missing or unknown battery status\n", now); 7500052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME; 7510052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_cycle++; 7520052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin return; 7530052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 7540052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7550052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* schedule next screen transition */ 7560052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->next_screen_transition = now + disp_time; 7570052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 7580052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* advance frame cntr to the next valid frame 7590052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin * if necessary, advance cycle cntr, and reset frame cntr 7600052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin */ 7610052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_frame++; 7629ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin 7639ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin /* if the frame is used for level-only, that is only show it when it's 7649ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin * the current level, skip it during the animation. 7659ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin */ 7669ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin while (batt_anim->cur_frame < batt_anim->num_frames && 7679ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin batt_anim->frames[batt_anim->cur_frame].level_only) 7689ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin batt_anim->cur_frame++; 7699ec3f3e2e4ccb18ed85fa47015b0fa71985710c4Dima Zavin if (batt_anim->cur_frame >= batt_anim->num_frames) { 7700052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_cycle++; 7710052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin batt_anim->cur_frame = 0; 772f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7730052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* don't reset the cycle counter, since we use that as a signal 7740052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin * in a test above to check if animation is over 7750052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin */ 7760052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 777f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 778f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7792471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavinstatic int set_key_callback(int code, int value, void *data) 780f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 7812471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin struct charger *charger = data; 7822471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin int64_t now = curr_time_ms(); 7832471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin int down = !!value; 784f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7852471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin if (code > KEY_MAX) 7862471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin return -1; 787f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 7882d978c01ee71002b3c5999126c009ec07a773c30Dima Zavin /* ignore events that don't modify our state */ 7892d978c01ee71002b3c5999126c009ec07a773c30Dima Zavin if (charger->keys[code].down == down) 790471157a393d052aece013d1f8b7701aaadca3b6cDima Zavin return 0; 7912d978c01ee71002b3c5999126c009ec07a773c30Dima Zavin 792f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* only record the down even timestamp, as the amount 793f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * of time the key spent not being pressed is not useful */ 794f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (down) 7952471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin charger->keys[code].timestamp = now; 7962471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin charger->keys[code].down = down; 7972471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin charger->keys[code].pending = true; 798f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (down) { 7992471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin LOGV("[%lld] key[%d] down\n", now, code); 800f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 8012471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin int64_t duration = now - charger->keys[code].timestamp; 802f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t secs = duration / 1000; 803f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t msecs = duration - secs * 1000; 804f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] key[%d] up (was down for %lld.%lldsec)\n", now, 8052471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin code, secs, msecs); 806f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 8072471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin 8082471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin return 0; 8092471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin} 8102471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin 8112471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavinstatic void update_input_state(struct charger *charger, 8122471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin struct input_event *ev) 8132471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin{ 8142471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin if (ev->type != EV_KEY) 8152471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin return; 8162471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin set_key_callback(ev->code, ev->value, charger); 817f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 818f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 819f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void set_next_key_check(struct charger *charger, 820f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state *key, 821f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timeout) 822f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 823f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t then = key->timestamp + timeout; 824f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 825f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check == -1 || then < charger->next_key_check) 826f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = then; 827f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 828f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 829f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_key(struct charger *charger, int code, int64_t now) 830f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 831f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state *key = &charger->keys[code]; 832f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_key_check; 833f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 834f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (code == KEY_POWER) { 835f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (key->down) { 836f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME; 837f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (now >= reboot_timeout) { 838f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] rebooting\n", now); 839f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_reboot(ANDROID_RB_RESTART, 0, 0); 840f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 841f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* if the key is pressed but timeout hasn't expired, 842f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * make sure we wake up at the right-ish time to check 843f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin */ 844f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin set_next_key_check(charger, key, POWER_ON_KEY_TIME); 845f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 846f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 847f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* if the power key got released, force screen state cycle */ 8489255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee if (key->pending) { 8499255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee request_suspend(false); 8500052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin kick_animation(charger->batt_anim); 8519255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee } 852f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 853f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 854f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 855f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin key->pending = false; 856f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 857f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 858f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void handle_input_state(struct charger *charger, int64_t now) 859f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 860f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_key(charger, KEY_POWER, now); 861f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 862f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check != -1 && now > charger->next_key_check) 863f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = -1; 864f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 865f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 866f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void handle_power_supply_state(struct charger *charger, int64_t now) 867f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 868f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->num_supplies_online == 0) { 8699255713bcf929e7cdd2817481f0dd08f838285c3choongryeol.lee request_suspend(false); 870f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check == -1) { 871f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME; 872f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] device unplugged: shutting down in %lld (@ %lld)\n", 873f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin now, UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check); 874f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (now >= charger->next_pwr_check) { 875f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] shutting down\n", now); 876f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_reboot(ANDROID_RB_POWEROFF, 0, 0); 877f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 878f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* otherwise we already have a shutdown timer scheduled */ 879f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 880f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 881f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* online supply present, reset shutdown timer if set */ 882f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check != -1) { 883f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] device plugged in: shutdown cancelled\n", now); 8840052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin kick_animation(charger->batt_anim); 885f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 886f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = -1; 887f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 888f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 889f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 890f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void wait_next_event(struct charger *charger, int64_t now) 891f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 892f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_event = INT64_MAX; 893f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timeout; 894f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct input_event ev; 895f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 896f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 897f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] next screen: %lld next key: %lld next pwr: %lld\n", now, 898f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition, charger->next_key_check, 899f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check); 900f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 901f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_screen_transition != -1) 902f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_screen_transition; 903f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check != -1 && charger->next_key_check < next_event) 904f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_key_check; 905f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check != -1 && charger->next_pwr_check < next_event) 906f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_pwr_check; 907f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 908f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (next_event != -1 && next_event != INT64_MAX) 909f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin timeout = max(0, next_event - now); 910f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else 911f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin timeout = -1; 912f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] blocking (%lld)\n", now, timeout); 913f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = ev_wait((int)timeout); 914f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!ret) 915f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_dispatch(); 916f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 917f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 918f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int input_callback(int fd, short revents, void *data) 919f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 920f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = data; 921f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct input_event ev; 922f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 923f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 924f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = ev_get_input(fd, revents, &ev); 925f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret) 926f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 9272471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin update_input_state(charger, &ev); 928f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 929f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 930f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 931f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void event_loop(struct charger *charger) 932f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 933f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 934f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 935f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (true) { 936f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t now = curr_time_ms(); 937f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 938f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] event_loop()\n", now); 939f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_input_state(charger, now); 940f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_power_supply_state(charger, now); 941f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 9420052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* do screen update last in case any of the above want to start 9430052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin * screen transitions (animations, etc) 9440052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin */ 9450052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin update_screen_state(charger, now); 9460052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 947f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin wait_next_event(charger, now); 948f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 949f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 950f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 951f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinint main(int argc, char **argv) 952f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 953f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 954f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = &charger_state; 955f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t now = curr_time_ms() - 1; 956f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int fd; 9570052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin int i; 958f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 959f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_init(&charger->supplies); 960f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 961f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin klog_init(); 962f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin klog_set_level(CHARGER_KLOG_LEVEL); 963f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 964823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin dump_last_kmsg(); 965823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 966823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin LOGI("--------------- STARTING CHARGER MODE ---------------\n"); 967823ebc4d824ea70e5ec7d376adf2fbce50eb9cb2Dima Zavin 968f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_init(); 969f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_font_size(&char_width, &char_height); 970f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 971f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_init(input_callback, charger); 972f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 973f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = uevent_open_socket(64*1024, true); 974f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) { 975f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fcntl(fd, F_SETFL, O_NONBLOCK); 976f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_add_fd(fd, uevent_callback, charger); 977f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 978f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->uevent_fd = fd; 979f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin coldboot(charger, "/sys/class/power_supply", "add"); 980f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 9810052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin ret = res_create_surface("charger/battery_fail", &charger->surf_unknown); 982f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) { 983f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("Cannot load image\n"); 9840052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->surf_unknown = NULL; 9850052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 9860052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 9870052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin for (i = 0; i < charger->batt_anim->num_frames; i++) { 9880052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin struct frame *frame = &charger->batt_anim->frames[i]; 9890052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin 9900052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin ret = res_create_surface(frame->name, &frame->surface); 9910052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin if (ret < 0) { 9920052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin LOGE("Cannot load image %s\n", frame->name); 9930052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin /* TODO: free the already allocated surfaces... */ 9940052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->batt_anim->num_frames = 0; 9950052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin charger->batt_anim->num_cycles = 1; 9960052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin break; 9970052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin } 998f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 999f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 10002471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin ev_sync_key_state(set_key_callback, charger); 10012471a6a3956c591b3979b9b73a0d68f3b214da57Dima Zavin 1002209c7b0fad9604d1dde1b74d9f9d577b923469fdDima Zavin#ifndef CHARGER_DISABLE_INIT_BLANK 1003f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_fb_blank(true); 1004209c7b0fad9604d1dde1b74d9f9d577b923469fdDima Zavin#endif 1005f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 1006f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition = now - 1; 1007f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = -1; 1008f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = -1; 10090052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin reset_animation(charger->batt_anim); 10100052abdafd7179fc4a7458f09d2f95c74dda0021Dima Zavin kick_animation(charger->batt_anim); 1011f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 1012f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin event_loop(charger); 1013f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 1014f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 1015f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 1016