Files
OpenCellular/common/battery.c
Bill Richardson f47b6e84e5 Make battery_is_present() tristate: YES, NO, NOT_SURE
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>
2014-03-27 18:45:06 +00:00

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);