/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Common battery command. */ #include "battery.h" #include "common.h" #include "console.h" #include "gpio.h" #include "timer.h" #include "util.h" #include "watchdog.h" #ifdef CONFIG_BATTERY_PRESENT_GPIO #ifdef CONFIG_BATTERY_PRESENT_CUSTOM #error "Don't define both CONFIG_BATTERY_PRESENT_CUSTOM and" \ "CONFIG_BATTERY_PRESENT_GPIO" #endif /** * Physical detection of battery. */ int battery_is_present(void) { return (gpio_get_level(CONFIG_BATTERY_PRESENT_GPIO) == 0); } #endif static const char *get_error_text(int rv) { if (rv == EC_ERROR_UNIMPLEMENTED) return "(unsupported)"; else return "(error)"; } static void print_item_name(const char *name) { ccprintf(" %-11s", name); } static int check_print_error(int rv) { if (rv != EC_SUCCESS) ccprintf("%s\n", get_error_text(rv)); return rv == EC_SUCCESS; } static void print_battery_status(void) { static const char * const st[] = {"EMPTY", "FULL", "DCHG", "INIT",}; static const char * const al[] = {"RT", "RC", "--", "TD", "OT", "--", "TC", "OC"}; int value, i; print_item_name("Status:"); if (check_print_error(battery_status(&value))) { ccprintf("0x%04x", value); /* bits 0-3 are only valid when the previous transaction * failed, so ignore them */ /* bits 4-7 are status */ for (i = 0; i < 4; i++) if (value & (1 << (i+4))) ccprintf(" %s", st[i]); /* bits 15-8 are alarms */ for (i = 0; i < 8; i++) if (value & (1 << (i+8))) ccprintf(" %s", al[i]); ccprintf("\n"); } } static void print_battery_strings(void) { char text[32]; print_item_name("Manuf:"); if (check_print_error(battery_manufacturer_name(text, sizeof(text)))) ccprintf("%s\n", text); print_item_name("Device:"); if (check_print_error(battery_device_name(text, sizeof(text)))) ccprintf("%s\n", text); print_item_name("Chem:"); if (check_print_error(battery_device_chemistry(text, sizeof(text)))) ccprintf("%s\n", text); } static void print_battery_params(void) { struct batt_params batt; battery_get_params(&batt); print_item_name("Param flags:"); ccprintf("%08x\n", batt.flags); print_item_name("Temp:"); ccprintf("0x%04x = %.1d K (%.1d C)\n", batt.temperature, batt.temperature, batt.temperature - 2731); print_item_name("V:"); ccprintf("0x%04x = %d mV\n", batt.voltage, batt.voltage); print_item_name("V-desired:"); ccprintf("0x%04x = %d mV\n", batt.desired_voltage, batt.desired_voltage); print_item_name("I:"); ccprintf("0x%04x = %d mA", batt.current & 0xffff, batt.current); if (batt.current > 0) ccputs("(CHG)"); else if (batt.current < 0) ccputs("(DISCHG)"); ccputs("\n"); print_item_name("I-desired:"); ccprintf("0x%04x = %d mA\n", batt.desired_current, batt.desired_current); print_item_name("Charging:"); ccprintf("%sAllowed\n", batt.flags & BATT_FLAG_WANT_CHARGE ? "" : "Not "); print_item_name("Charge:"); ccprintf("%d %%\n", batt.state_of_charge); } static void print_battery_info(void) { int value; int hour, minute; print_item_name("Serial:"); if (check_print_error(battery_serial_number(&value))) ccprintf("0x%04x\n", value); print_item_name("V-design:"); if (check_print_error(battery_design_voltage(&value))) ccprintf("0x%04x = %d mV\n", value, value); print_item_name("Mode:"); if (check_print_error(battery_get_mode(&value))) ccprintf("0x%04x\n", value); print_item_name("Abs charge:"); if (check_print_error(battery_state_of_charge_abs(&value))) ccprintf("%d %%\n", value); print_item_name("Remaining:"); if (check_print_error(battery_remaining_capacity(&value))) ccprintf("%d mAh\n", value); print_item_name("Cap-full:"); if (check_print_error(battery_full_charge_capacity(&value))) ccprintf("%d mAh\n", value); print_item_name(" Design:"); if (check_print_error(battery_design_capacity(&value))) ccprintf("%d mAh\n", value); print_item_name("Time-full:"); if (check_print_error(battery_time_to_full(&value))) { if (value == 65535) { hour = 0; minute = 0; } else { hour = value / 60; minute = value % 60; } ccprintf("%dh:%d\n", hour, minute); } print_item_name(" Empty:"); if (check_print_error(battery_time_to_empty(&value))) { if (value == 65535) { hour = 0; minute = 0; } else { hour = value / 60; minute = value % 60; } ccprintf("%dh:%d\n", hour, minute); } } static int command_battery(int argc, char **argv) { int repeat = 1; int loop; int sleep_ms = 0; char *e; if (argc > 1) { repeat = strtoi(argv[1], &e, 0); if (*e) { ccputs("Invalid repeat count\n"); return EC_ERROR_INVAL; } } if (argc > 2) { sleep_ms = strtoi(argv[2], &e, 0); if (*e) { ccputs("Invalid sleep ms\n"); return EC_ERROR_INVAL; } } for (loop = 0; loop < repeat; loop++) { print_battery_status(); print_battery_params(); print_battery_strings(); print_battery_info(); /* * Running with a high repeat count will take so long the * watchdog timer fires. So reset the watchdog timer each * iteration. */ watchdog_reload(); if (sleep_ms) msleep(sleep_ms); } return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(battery, command_battery, " ", "Print battery info", NULL);