diff --git a/extendedcommands.c b/extendedcommands.c index 30b2f3e..3ec3436 100644 --- a/extendedcommands.c +++ b/extendedcommands.c @@ -19,6 +19,7 @@ #include #include +#include #include "bootloader.h" #include "common.h" @@ -1158,22 +1159,95 @@ int volume_main(int argc, char **argv) { return 0; } +static int write_file(char* path, void* data, int data_size) +{ + int fd; + fd = open(path, O_WRONLY); + if (fd >= 0) { + int written = write(fd, data, data_size); + close(fd); + return written; + } + return -1; +} + +static int read_file(char* path, void* data, int data_size) +{ + int fd; + fd = open(path, O_RDONLY); + if(fd >= 0){ + int readed = read(fd, data, data_size); + close(fd); + return readed; + } + return -1; +} + +static void* battery_thread(void *cookie) +{ + char status[40]; + int state=-1; + int dischargeCount=0; + + while(1){ + memset(status, 0, sizeof(status)); + read_file("/sys/class/power_supply/battery/status", status, sizeof(status)-1); + if(strstr(status, "Full")!=NULL && state!=1){ + state=1; + write_file("/sys/class/leds/amber/brightness", "0\n", sizeof("0\n")-1); + write_file("/sys/class/leds/green/brightness", "1\n", sizeof("1\n")-1); + }else if(strstr(status, "Charging")!=NULL && state!=2){ + state=2; + write_file("/sys/class/leds/amber/brightness", "1\n", sizeof("1\n")-1); + write_file("/sys/class/leds/green/brightness", "0\n", sizeof("0\n")-1); + }else if(strstr(status, "Discharging")!=NULL){ + state=3; + if(dischargeCount==0){ //blink every 2 seconds + read_file("/sys/class/leds/amber/brightness", status, sizeof(status)-1); + if(status[0]=='0') write_file("/sys/class/leds/amber/brightness", "1\n", sizeof("1\n")-1); + else write_file("/sys/class/leds/amber/brightness", "0\n", sizeof("0\n")-1); + } + read_file("/sys/class/power_supply/battery/over_vchg", status, sizeof(status)-1); + dischargeCount=(dischargeCount+1)%4; + }else if(strstr(status,"Not charging")!=NULL && state!=4){ + state=4; + write_file("/sys/class/leds/amber/brightness", "0\n", sizeof("0\n")-1); + write_file("/sys/class/leds/green/brightness", "0\n", sizeof("0\n")-1); + sync(); + reboot(RB_POWER_OFF); + for(;;); + } + usleep(500000); //wait half a second + } + return NULL; +} + void handle_chargemode() { - const char* filename = "/proc/cmdline"; - struct stat file_info; - if (0 != stat(filename, &file_info)) - return; - int file_len = file_info.st_size; - char* file_data = (char*)malloc(file_len + 1); - FILE *file = fopen(filename, "rb"); - if (file == NULL) - return; - fread(file_data, file_len, 1, file); - // supposedly not necessary, but let's be safe. - file_data[file_len] = '\0'; - fclose(file); - - if (strstr(file_data, "androidboot.mode=offmode_charging") != NULL) - reboot(RB_POWER_OFF); + // old code to read /proc/cmdline was broken because file size is always 0 so file_data was always empty string + char cmdline[1024]; + memset(cmdline, 0, sizeof(cmdline)); + if(read_file("/proc/cmdline", cmdline, sizeof(cmdline)-1) < 0) return; + + if (strstr(cmdline, "androidboot.mode=offmode_charging") != NULL) + { + write_file("/sys/class/leds/lcd-backlight/brightness", "0\n", sizeof("0\n")-1); + write_file("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "powersave\n", sizeof("powersave\n")-1); + write_file("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "245000\n", sizeof("245000\n")-1); + write_file("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", "245000\n", sizeof("245000\n")-1); + + pthread_t t; + pthread_create(&t, NULL, battery_thread, NULL); + + // let recovery kernel charge the battery, reboot on any key press so Android will start as user would expect + ev_init(); + struct input_event ev; + do { + ev_get(&ev, 0); + if(ev.type==EV_KEY) write_file("/sys/class/leds/lcd-backlight/brightness", "0\n", sizeof("0\n")-1); + } while (!(ev.type==EV_KEY && ev.code==KEY_END)); + + reboot(RB_AUTOBOOT); + for(;;); + } }