charger.c revision f48b23688c1303212c65e470af9f9f3892e98f8e
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 <linux/netlink.h> 25f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <stdbool.h> 26f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <stdio.h> 27f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <stdlib.h> 28f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <string.h> 29f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/poll.h> 30f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/socket.h> 31f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/stat.h> 32f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/types.h> 33f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <sys/un.h> 34f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <time.h> 35f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <unistd.h> 36f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 37f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <cutils/android_reboot.h> 38f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <cutils/klog.h> 39f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <cutils/list.h> 40f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include <cutils/uevent.h> 41f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 42f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#include "minui/minui.h" 43f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 44f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifndef max 45f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define max(a,b) ((a) > (b) ? (a) : (b)) 46f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 47f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 48f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifndef min 49f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define min(a,b) ((a) < (b) ? (a) : (b)) 50f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 51f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 52f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define MSEC_PER_SEC (1000LL) 53f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define NSEC_PER_MSEC (1000000LL) 54f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 55f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define SCREEN_ON_TIME (5 * MSEC_PER_SEC) 56f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define POWER_ON_KEY_TIME (5 * MSEC_PER_SEC) 57f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC) 58f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 59f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0) 60f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGI(x...) do { KLOG_INFO("charger", x); } while (0) 61f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0) 62f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 63f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct key_state { 64f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool pending; 65f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool down; 66f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timestamp; 67f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 68f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 69f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct power_supply { 70f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode list; 71f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char name[256]; 72f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char type[32]; 73f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool online; 74f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool valid; 75f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 76f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 77f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct charger { 78f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_screen_transition; 79f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_key_check; 80f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_pwr_check; 81f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool screen_on; 82f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 83f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state keys[KEY_MAX + 1]; 84f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_surface surf_charging; 85f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int uevent_fd; 86f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 87f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode supplies; 88f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int num_supplies; 89f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int num_supplies_online; 90f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 91f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *battery; 92f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 93f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 94f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct uevent { 95f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *action; 96f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *path; 97f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *subsystem; 98f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_name; 99f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_type; 100f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *ps_online; 101f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 102f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 103f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int char_width; 104f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int char_height; 105f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 106f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstruct charger charger_state; 107f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 108f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin/* current time in milliseconds */ 109f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int64_t curr_time_ms(void) 110f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 111f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct timespec tm; 112f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin clock_gettime(CLOCK_MONOTONIC, &tm); 113f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return tm.tv_sec * MSEC_PER_SEC + (tm.tv_nsec / NSEC_PER_MSEC); 114f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 115f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 116f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void clear_screen(void) 117f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 118f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_color(0, 0, 0, 255); 119f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_fill(0, 0, gr_fb_width(), gr_fb_height()); 120f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin}; 121f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 122f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int read_file(const char *path, char *buf, size_t sz) 123f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 124f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int fd; 125f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin size_t cnt; 126f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 127f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = open(path, O_RDONLY, 0); 128f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) 129f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 130f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 131f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin cnt = read(fd, buf, sz - 1); 132f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (cnt <= 0) 133f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 134f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin buf[cnt] = '\0'; 135f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (buf[cnt - 1] == '\n') { 136f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin cnt--; 137f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin buf[cnt] = '\0'; 138f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 139f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 140f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 141f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return cnt; 142f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 143f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinerr: 144f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) 145f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 146f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 147f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 148f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 149f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int read_file_int(const char *path, int *val) 150f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 151f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char buf[32]; 152f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 153f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int tmp; 154f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char *end; 155f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 156f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = read_file(path, buf, sizeof(buf)); 157f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) 158f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 159f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 160f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin tmp = strtol(buf, &end, 0); 161f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (end == buf || 162f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ((end < buf+sizeof(buf)) && (*end != '\n' && *end != '\0'))) 163f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto err; 164f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 165f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin *val = tmp; 166f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 167f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 168f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinerr: 169f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 170f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 171f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 172f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic struct power_supply *find_supply(struct charger *charger, 173f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *name) 174f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 175f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct listnode *node; 176f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply; 177f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 178f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_for_each(node, &charger->supplies) { 179f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = node_to_item(node, struct power_supply, list); 180f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(name, supply->name, sizeof(supply->name))) 181f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return supply; 182f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 183f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return NULL; 184f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 185f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 186f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic struct power_supply *add_supply(struct charger *charger, 187f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *name, const char *type, 188f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool online) 189f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 190f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply; 191f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 192f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = calloc(1, sizeof(struct power_supply)); 193f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) 194f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return NULL; 195f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 196f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(supply->name, name, sizeof(supply->name)); 197f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(supply->type, type, sizeof(supply->type)); 198f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply->online = online; 199f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_add_tail(&charger->supplies, &supply->list); 200f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies++; 201f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("... added %s %s %d\n", supply->name, supply->type, online); 202f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return supply; 203f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 204f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 205f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void remove_supply(struct charger *charger, struct power_supply *supply) 206f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 207f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) 208f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 209f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_remove(&supply->list); 210f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies--; 211f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin free(supply); 212f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 213f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 214f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void parse_uevent(const char *msg, struct uevent *uevent) 215f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 216f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action = ""; 217f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->path = ""; 218f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->subsystem = ""; 219f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name = ""; 220f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_online = ""; 221f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type = ""; 222f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 223f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* currently ignoring SEQNUM */ 224f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (*msg) { 225f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#ifdef DEBUG_UEVENTS 226f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("uevent str: %s\n", msg); 227f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#endif 228f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(msg, "ACTION=", 7)) { 229f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 7; 230f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action = msg; 231f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "DEVPATH=", 8)) { 232f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 8; 233f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->path = msg; 234f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "SUBSYSTEM=", 10)) { 235f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 10; 236f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->subsystem = msg; 237f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_NAME=", 18)) { 238f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 18; 239f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name = msg; 240f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_ONLINE=", 20)) { 241f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 20; 242f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_online = msg; 243f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strncmp(msg, "POWER_SUPPLY_TYPE=", 18)) { 244f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg += 18; 245f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type = msg; 246f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 247f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 248f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* advance to after the next \0 */ 249f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (*msg++) 250f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ; 251f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 252f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 253f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("event { '%s', '%s', '%s', '%s', '%s', '%s' }\n", 254f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action, uevent->path, uevent->subsystem, 255f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, uevent->ps_type, uevent->ps_online); 256f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 257f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 258f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_ps_uevent(struct charger *charger, struct uevent *uevent) 259f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 260f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int online; 261f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char ps_type[32]; 262f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct power_supply *supply = NULL; 263f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int i; 264f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool was_online = false; 265f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool battery = false; 266f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 267f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (uevent->ps_type[0] == '\0') { 268f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char *path; 269f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 270f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 271f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (uevent->path[0] == '\0') 272f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 273f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = asprintf(&path, "/sys/%s/type", uevent->path); 274f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret <= 0) 275f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 276f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = read_file(path, ps_type, sizeof(ps_type)); 277f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin free(path); 278f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) 279f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 280f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 281f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin strlcpy(ps_type, uevent->ps_type, sizeof(ps_type)); 282f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 283f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 284f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strncmp(ps_type, "Battery", 7)) 285f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin battery = true; 286f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 287f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin online = atoi(uevent->ps_online); 288f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = find_supply(charger, uevent->ps_name); 289f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (supply) { 290f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin was_online = supply->online; 291f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply->online = online; 292f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 293f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 294f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strcmp(uevent->action, "add")) { 295f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 296f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = add_supply(charger, uevent->ps_name, ps_type, online); 297f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 298f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("cannot add supply '%s' (%s %d)\n", uevent->ps_name, 299f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_type, online); 300f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 301f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 302f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* only pick up the first battery for now */ 303f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (battery && !charger->battery) 304f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->battery = supply; 305f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 306f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("supply '%s' already exists..\n", uevent->ps_name); 307f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 308f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strcmp(uevent->action, "remove")) { 309f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (supply) { 310f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->battery == supply) 311f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->battery = NULL; 312f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin remove_supply(charger, supply); 313f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin supply = NULL; 314f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 315f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (!strcmp(uevent->action, "change")) { 316f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!supply) { 317f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("power supply '%s' not found ('%s' %d)\n", 318f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, ps_type, online); 319f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 320f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 321f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 322f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 323f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 324f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 325f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* allow battery to be managed in the supply list but make it not 326f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * contribute to online power supplies. */ 327f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!battery) { 328f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (was_online && !online) 329f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies_online--; 330f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else if (supply && !was_online && online) 331f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->num_supplies_online++; 332f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 333f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 334f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("power supply %s (%s) %s (action=%s num_online=%d num_supplies=%d)\n", 335f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->ps_name, ps_type, battery ? "" : online ? "online" : "offline", 336f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin uevent->action, charger->num_supplies_online, charger->num_supplies); 337f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 338f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 339f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_uevent(struct charger *charger, struct uevent *uevent) 340f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 341f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!strcmp(uevent->subsystem, "power_supply")) 342f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_ps_uevent(charger, uevent); 343f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 344f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 345f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin#define UEVENT_MSG_LEN 1024 346f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int handle_uevent_fd(struct charger *charger, int fd) 347f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 348f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char msg[UEVENT_MSG_LEN+2]; 349f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int n; 350f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 351f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) 352f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 353f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 354f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (true) { 355f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct uevent uevent; 356f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 357f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin n = uevent_kernel_multicast_recv(fd, msg, UEVENT_MSG_LEN); 358f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (n <= 0) 359f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin break; 360f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ 361f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 362f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 363f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg[n] = '\0'; 364f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin msg[n+1] = '\0'; 365f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 366f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin parse_uevent(msg, &uevent); 367f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_uevent(charger, &uevent); 368f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 369f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 370f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 371f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 372f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 373f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int uevent_callback(int fd, short revents, void *data) 374f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 375f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = data; 376f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 377f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!(revents & POLLIN)) 378f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 379f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return handle_uevent_fd(charger, fd); 380f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 381f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 382f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin/* force the kernel to regenerate the change events for the existing 383f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * devices, if valid */ 384f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void do_coldboot(struct charger *charger, DIR *d, const char *event, 385f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool follow_links, int max_depth) 386f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 387f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct dirent *de; 388f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int dfd, fd; 389f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 390f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin dfd = dirfd(d); 391f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 392f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = openat(dfd, "uevent", O_WRONLY); 393f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) { 394f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin write(fd, event, strlen(event)); 395f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 396f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_uevent_fd(charger, charger->uevent_fd); 397f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 398f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 399f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while ((de = readdir(d)) && max_depth > 0) { 400f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin DIR *d2; 401f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 402f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("looking at '%s'\n", de->d_name); 403f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 404f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if ((de->d_type != DT_DIR && !(de->d_type == DT_LNK && follow_links)) || 405f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin de->d_name[0] == '.') { 406f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("skipping '%s' type %d (depth=%d follow=%d)\n", 407f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin de->d_name, de->d_type, max_depth, follow_links); 408f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 409f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 410f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("can descend into '%s'\n", de->d_name); 411f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 412f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); 413f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd < 0) { 414f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("cannot openat %d '%s' (%d: %s)\n", dfd, de->d_name, 415f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin errno, strerror(errno)); 416f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin continue; 417f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 418f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 419f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin d2 = fdopendir(fd); 420f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (d2 == 0) 421f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin close(fd); 422f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else { 423f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("opened '%s'\n", de->d_name); 424f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin do_coldboot(charger, d2, event, follow_links, max_depth - 1); 425f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin closedir(d2); 426f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 427f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 428f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 429f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 430f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void coldboot(struct charger *charger, const char *path, 431f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin const char *event) 432f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 433f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char str[256]; 434f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 435f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("doing coldboot '%s' in '%s'\n", event, path); 436f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin DIR *d = opendir(path); 437f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (d) { 438f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin snprintf(str, sizeof(str), "%s\n", event); 439f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin do_coldboot(charger, d, str, true, 1); 440f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin closedir(d); 441f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 442f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 443f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 444f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int draw_text(const char *str, int x, int y) 445f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 446f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int str_len_px = gr_measure(str); 447f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 448f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (x < 0) 449f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin x = (gr_fb_width() - str_len_px) / 2; 450f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (y < 0) 451f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y = (gr_fb_height() - char_height) / 2; 452f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_text(x, y, str); 453f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 454f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return y + char_height; 455f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 456f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 457f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void android_green(void) 458f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 459f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_color(0xa4, 0xc6, 0x39, 255); 460f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 461f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 462f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void redraw_screen(struct charger *charger) 463f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 464f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int surf_height; 465f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int surf_width; 466f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int x; 467f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int y = 0; 468f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int batt_cap; 469f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 470f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char cap_string[128]; 471f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin char cap_path[256]; 472f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 473f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin clear_screen(); 474f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 475f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->surf_charging) { 476f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin surf_width = gr_get_width(charger->surf_charging); 477f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin surf_height = gr_get_height(charger->surf_charging); 478f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin x = (gr_fb_width() - surf_width) / 2 ; 479f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y = (gr_fb_height() - surf_height) / 2 ; 480f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 481f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_blit(charger->surf_charging, 0, 0, 482f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin surf_width, surf_height, 483f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin x, y); 484f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y += surf_height; 485f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 486f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_green(); 487f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y = draw_text("Charging!", -1, -1); 488f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 489f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 490f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin cap_string[0] = '\0'; 491f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->battery) { 492f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = snprintf(cap_path, sizeof(cap_path), 493f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin "/sys/class/power_supply/%s/capacity", 494f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->battery->name); 495f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret <= 0) 496f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin goto done; 497f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = read_file_int(cap_path, &batt_cap); 498f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret >= 0) 499f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin snprintf(cap_string, sizeof(cap_string), "%d/100", batt_cap); 500f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 501f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 502f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (cap_string[0] == '\0') 503f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin snprintf(cap_string, sizeof(cap_string), "?\?/100"); 504f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 505f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin y += 25; 506f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_green(); 507f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin draw_text(cap_string, -1, y); 508f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 509f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavindone: 510f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_flip(); 511f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 512f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 513f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void update_screen_state(struct charger *charger, int64_t now, 514f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin bool force) 515f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 516f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!force && ((now < charger->next_screen_transition) || 517f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin (charger->next_screen_transition == -1))) 518f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 519f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 520f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!charger->screen_on) 521f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition = now + SCREEN_ON_TIME; 522f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else 523f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition = -1; 524f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->screen_on = !charger->screen_on; 525f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 526f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_fb_blank(!charger->screen_on); 527f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->screen_on) 528f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin redraw_screen(charger); 529f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] screen %s\n", now, charger->screen_on ? "on" : "off"); 530f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 531f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 532f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void update_input_state(struct charger *charger, 533f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct input_event *ev, 534f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t now) 535f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 536f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int down = !!ev->value; 537f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 538f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ev->type != EV_KEY || ev->code > KEY_MAX) 539f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return; 540f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 541f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* only record the down even timestamp, as the amount 542f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * of time the key spent not being pressed is not useful */ 543f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (down) 544f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->keys[ev->code].timestamp = now; 545f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->keys[ev->code].down = down; 546f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->keys[ev->code].pending = true; 547f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (down) { 548f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] key[%d] down\n", now, ev->code); 549f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 550f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t duration = now - charger->keys[ev->code].timestamp; 551f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t secs = duration / 1000; 552f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t msecs = duration - secs * 1000; 553f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] key[%d] up (was down for %lld.%lldsec)\n", now, 554f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev->code, secs, msecs); 555f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 556f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 557f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 558f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void set_next_key_check(struct charger *charger, 559f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state *key, 560f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timeout) 561f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 562f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t then = key->timestamp + timeout; 563f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 564f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check == -1 || then < charger->next_key_check) 565f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = then; 566f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 567f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 568f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void process_key(struct charger *charger, int code, int64_t now) 569f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 570f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct key_state *key = &charger->keys[code]; 571f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_key_check; 572f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 573f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (code == KEY_POWER) { 574f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (key->down) { 575f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME; 576f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (now >= reboot_timeout) { 577f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] rebooting\n", now); 578f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_reboot(ANDROID_RB_RESTART, 0, 0); 579f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 580f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* if the key is pressed but timeout hasn't expired, 581f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * make sure we wake up at the right-ish time to check 582f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin */ 583f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin set_next_key_check(charger, key, POWER_ON_KEY_TIME); 584f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 585f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 586f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* if the power key got released, force screen state cycle */ 587f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (key->pending) 588f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin update_screen_state(charger, now, true); 589f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 590f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 591f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 592f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin key->pending = false; 593f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 594f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 595f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void handle_input_state(struct charger *charger, int64_t now) 596f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 597f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin process_key(charger, KEY_POWER, now); 598f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 599f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check != -1 && now > charger->next_key_check) 600f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = -1; 601f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 602f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 603f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void handle_power_supply_state(struct charger *charger, int64_t now) 604f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 605f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->num_supplies_online == 0) { 606f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check == -1) { 607f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME; 608f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] device unplugged: shutting down in %lld (@ %lld)\n", 609f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin now, UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check); 610f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else if (now >= charger->next_pwr_check) { 611f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] shutting down\n", now); 612f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin android_reboot(ANDROID_RB_POWEROFF, 0, 0); 613f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 614f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* otherwise we already have a shutdown timer scheduled */ 615f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 616f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } else { 617f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* online supply present, reset shutdown timer if set */ 618f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check != -1) { 619f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGI("[%lld] device plugged in: shutdown cancelled\n", now); 620f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin update_screen_state(charger, now, true); 621f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 622f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = -1; 623f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 624f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 625f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 626f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void wait_next_event(struct charger *charger, int64_t now) 627f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 628f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t next_event = INT64_MAX; 629f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t timeout; 630f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct input_event ev; 631f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 632f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 633f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] next screen: %lld next key: %lld next pwr: %lld\n", now, 634f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition, charger->next_key_check, 635f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check); 636f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 637f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin /* TODO: right now it's just screen on/off and keys, but later I'm sure 638f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin * there will be animations */ 639f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_screen_transition != -1) 640f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_screen_transition; 641f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_key_check != -1 && charger->next_key_check < next_event) 642f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_key_check; 643f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (charger->next_pwr_check != -1 && charger->next_pwr_check < next_event) 644f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin next_event = charger->next_pwr_check; 645f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 646f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (next_event != -1 && next_event != INT64_MAX) 647f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin timeout = max(0, next_event - now); 648f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin else 649f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin timeout = -1; 650f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] blocking (%lld)\n", now, timeout); 651f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = ev_wait((int)timeout); 652f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (!ret) 653f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_dispatch(); 654f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 655f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 656f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic int input_callback(int fd, short revents, void *data) 657f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 658f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = data; 659f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct input_event ev; 660f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 661f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 662f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = ev_get_input(fd, revents, &ev); 663f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret) 664f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return -1; 665f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin update_input_state(charger, &ev, curr_time_ms()); 666f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 667f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 668f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 669f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinstatic void event_loop(struct charger *charger) 670f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 671f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 672f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 673f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin while (true) { 674f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t now = curr_time_ms(); 675f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 676f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGV("[%lld] event_loop()\n", now); 677f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_input_state(charger, now); 678f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin update_screen_state(charger, now, false); 679f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin handle_power_supply_state(charger, now); 680f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 681f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin wait_next_event(charger, now); 682f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 683f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 684f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 685f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavinint main(int argc, char **argv) 686f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin{ 687f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int ret; 688f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin struct charger *charger = &charger_state; 689f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int64_t now = curr_time_ms() - 1; 690f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin int fd; 691f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 692f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin list_init(&charger->supplies); 693f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 694f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin klog_init(); 695f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin klog_set_level(CHARGER_KLOG_LEVEL); 696f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 697f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_init(); 698f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_font_size(&char_width, &char_height); 699f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 700f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_init(input_callback, charger); 701f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 702f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fd = uevent_open_socket(64*1024, true); 703f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (fd >= 0) { 704f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin fcntl(fd, F_SETFL, O_NONBLOCK); 705f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ev_add_fd(fd, uevent_callback, charger); 706f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 707f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->uevent_fd = fd; 708f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin coldboot(charger, "/sys/class/power_supply", "add"); 709f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 710f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin ret = res_create_surface("charging", &charger->surf_charging); 711f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin if (ret < 0) { 712f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin LOGE("Cannot load image\n"); 713f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->surf_charging = NULL; 714f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin } 715f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 716f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin gr_fb_blank(true); 717f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 718f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_screen_transition = now - 1; 719f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_key_check = -1; 720f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->next_pwr_check = -1; 721f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin charger->screen_on = false; 722f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 723f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin event_loop(charger); 724f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin 725f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin return 0; 726f48b23688c1303212c65e470af9f9f3892e98f8eDima Zavin} 727