mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-07 16:11:43 +00:00
In most cases we can't actually know whether a battery is present until we've been able to talk to it. This adds that NOT_SURE case. BUG=none BRANCH=ToT TEST=none Nothing uses this case yet, and the only time that battery_is_present() is called is when we have hardware to detect the battery (which always returns YES or NO). This is just preparation for charge_state_v2, which will need the NOT_SURE case for trickle charging. Change-Id: Ic5793de080529d50c98860450a021a1abae168db Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/191782 Reviewed-by: Randall Spangler <rspangler@chromium.org>
240 lines
5.3 KiB
C
240 lines
5.3 KiB
C
/* 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.
|
|
*/
|
|
enum battery_present battery_is_present(void)
|
|
{
|
|
/* The GPIO is low when the battery is present */
|
|
return gpio_get_level(CONFIG_BATTERY_PRESENT_GPIO) ? BP_NO : BP_YES;
|
|
}
|
|
#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,
|
|
"<repeat_count> <sleep_ms>",
|
|
"Print battery info",
|
|
NULL);
|