summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-05-29 10:26:18 +0800
committerChromeBot <chrome-bot@google.com>2013-06-03 14:32:16 -0700
commite52aba6ecac45d2c27acc78316e835620840408a (patch)
tree7648425ebe293671a43ced7d824b72e6779b7e3f
parentd6d3b7cbc5621519d54d231aba13aa4ab50651aa (diff)
downloadchrome-ec-e52aba6ecac45d2c27acc78316e835620840408a.tar.gz
Make ectool LED command more generic
This adds the option to specify which LED to control as well as the ability to query the supported LED color on the board. BUG=chrome-os-partner:19745 TEST=On Spring: - ectool led 0 query -> See the max value for R, G, Y is 0x80. - ectool led 1 query -> See error message. - ectool led 0 yellow -> See LED turns yellow. - ectool led 0 green=0x40 red=0x40 -> See green and red lit up. - ectool led 0 auto -> See LED turns off (without charger.) BRANCH=spring Change-Id: Ibdde2f7450122f59383dad1030a0a2a985386f73 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/56877
-rw-r--r--common/lp5562_battery_led.c32
-rw-r--r--include/ec_commands.h43
-rw-r--r--util/ectool.c100
3 files changed, 128 insertions, 47 deletions
diff --git a/common/lp5562_battery_led.c b/common/lp5562_battery_led.c
index 02bf85b5da..3aebeb0b76 100644
--- a/common/lp5562_battery_led.c
+++ b/common/lp5562_battery_led.c
@@ -63,28 +63,46 @@ static int set_led_color(enum led_state_t state)
/*****************************************************************************/
/* Host commands */
-static int led_command_set(struct host_cmd_handler_args *args)
+static int led_command_control(struct host_cmd_handler_args *args)
{
- const struct ec_params_led_set *p = args->params;
+ const struct ec_params_led_control *p = args->params;
+ struct ec_response_led_control *r = args->response;
+ int i;
+ uint8_t clipped[EC_LED_COLOR_COUNT];
+
+ /* Only support battery LED control */
+ if (p->led_id != EC_LED_ID_BATTERY_LED)
+ return EC_RES_INVALID_PARAM;
if (p->flags & EC_LED_FLAGS_AUTO) {
if (!extpower_is_present())
lp5562_poweroff();
last_state = LED_STATE_OFF;
led_auto_control = 1;
- } else {
+ } else if (!(p->flags & EC_LED_FLAGS_QUERY)) {
+ for (i = 0; i < EC_LED_COLOR_COUNT; ++i)
+ clipped[i] = MIN(p->brightness[i], 0x80);
led_auto_control = 0;
if (!extpower_is_present())
lp5562_poweron();
- if (lp5562_set_color((p->r << 16) + (p->g << 8) + p->b))
+ if (lp5562_set_color((clipped[EC_LED_COLOR_RED] << 16) +
+ (clipped[EC_LED_COLOR_GREEN] << 8) +
+ clipped[EC_LED_COLOR_YELLOW]))
return EC_RES_ERROR;
}
+ r->brightness_range[EC_LED_COLOR_RED] = 0x80;
+ r->brightness_range[EC_LED_COLOR_GREEN] = 0x80;
+ r->brightness_range[EC_LED_COLOR_BLUE] = 0x0;
+ r->brightness_range[EC_LED_COLOR_YELLOW] = 0x80;
+ r->brightness_range[EC_LED_COLOR_WHITE] = 0x0;
+ args->response_size = sizeof(struct ec_response_led_control);
+
return EC_RES_SUCCESS;
}
-DECLARE_HOST_COMMAND(EC_CMD_LED_SET,
- led_command_set,
- EC_VER_MASK(0));
+DECLARE_HOST_COMMAND(EC_CMD_LED_CONTROL,
+ led_command_control,
+ EC_VER_MASK(1));
/*****************************************************************************/
/* Hooks */
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 93258df241..3390e3ab85 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -726,15 +726,44 @@ enum lightbar_command {
/*****************************************************************************/
/* LED control commands */
-#define EC_CMD_LED_SET 0x29
+#define EC_CMD_LED_CONTROL 0x29
-#define EC_LED_FLAGS_AUTO (1 << 1)
+enum ec_led_id {
+ EC_LED_ID_BATTERY_LED = 0,
+ EC_LED_ID_POWER_BUTTON_LED,
+ EC_LED_ID_ADAPTER_LED,
+};
-struct ec_params_led_set {
- uint8_t r;
- uint8_t g;
- uint8_t b; /* Used as yellow if there is no blue LED */
- uint8_t flags;
+/* LED control flags */
+#define EC_LED_FLAGS_QUERY (1 << 0) /* Query LED capability only */
+#define EC_LED_FLAGS_AUTO (1 << 1) /* Switch LED back to automatic control */
+
+enum ec_led_colors {
+ EC_LED_COLOR_RED = 0,
+ EC_LED_COLOR_GREEN,
+ EC_LED_COLOR_BLUE,
+ EC_LED_COLOR_YELLOW,
+ EC_LED_COLOR_WHITE,
+
+ EC_LED_COLOR_COUNT
+};
+
+struct ec_params_led_control {
+ uint8_t led_id; /* Which LED to control */
+ uint8_t flags; /* Control flags */
+
+ uint8_t brightness[EC_LED_COLOR_COUNT];
+} __packed;
+
+struct ec_response_led_control {
+ /*
+ * Available brightness value range.
+ *
+ * Range 0 means color channel not present.
+ * Range 1 means on/off control.
+ * Other values means the LED is control by PWM.
+ */
+ uint8_t brightness_range[EC_LED_COLOR_COUNT];
} __packed;
/*****************************************************************************/
diff --git a/util/ectool.c b/util/ectool.c
index b7db98f548..5deb582742 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -161,6 +161,10 @@ const char help_str[] =
/* Note: depends on enum system_image_copy_t */
static const char * const image_names[] = {"unknown", "RO", "RW"};
+/* Note: depends on enum ec_led_colors */
+static const char * const led_color_names[EC_LED_COLOR_COUNT] = {
+ "red", "green", "blue", "yellow", "white"};
+
/* Write a buffer to the file. Return non-zero if error. */
static int write_file(const char *filename, const char *buf, int size)
{
@@ -1405,51 +1409,81 @@ static int cmd_lightbar(int argc, char **argv)
}
+static int find_led_color_by_name(const char *color)
+{
+ int i;
+
+ for (i = 0; i < EC_LED_COLOR_COUNT; ++i)
+ if (!strcasecmp(color, led_color_names[i]))
+ return i;
+ return -1;
+}
+
int cmd_led(int argc, char *argv[])
{
- struct ec_params_led_set p;
- char *e;
- int rv;
+ struct ec_params_led_control p;
+ struct ec_response_led_control r;
+ char *e, *ptr;
+ int rv, i, j;
- if (argc == 1) {
+ memset(p.brightness, 0, sizeof(p.brightness));
+ p.flags = 0;
+
+ if (argc < 3) {
fprintf(stderr,
- "Usage: %s <auto | red | green | blue | "
- "<R> <G> <B>>\n", argv[0]);
+ "Usage: %s <ID> <query | auto | "
+ "<color>=<brightness>...>\n", argv[0]);
+ return -1;
+ }
+
+ p.led_id = strtol(argv[1], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad LED ID.\n");
return -1;
}
- p.r = p.g = p.b = p.flags = 0;
+ if (!strcasecmp(argv[2], "query")) {
+ p.flags = EC_LED_FLAGS_QUERY;
+ rv = ec_command(EC_CMD_LED_CONTROL, 1, &p, sizeof(p),
+ &r, sizeof(r));
+ printf("Brightness range for LED %d:\n", p.led_id);
+ if (rv < 0) {
+ fprintf(stderr, "Error. Not existing LED?\n");
+ return rv;
+ }
+ for (i = 0; i < 5; ++i)
+ printf("\t%s\t: 0x%x\n",
+ led_color_names[i],
+ r.brightness_range[i]);
+ return 0;
+ }
- if (!strcasecmp(argv[1], "auto")) {
+ if (!strcasecmp(argv[2], "auto")) {
p.flags = EC_LED_FLAGS_AUTO;
- } else if (!strcasecmp(argv[1], "red")) {
- p.r = 0xff;
- } else if (!strcasecmp(argv[1], "green")) {
- p.g = 0xff;
- } else if (!strcasecmp(argv[1], "blue")) {
- p.b = 0xff;
- } else if (argc != 4) {
- fprintf(stderr, "Incorrect number of arguments\n");
- return -1;
+ } else if ((i = find_led_color_by_name(argv[2])) != -1) {
+ p.brightness[i] = 0xff;
} else {
- p.r = strtol(argv[1], &e, 0);
- if (e && *e) {
- fprintf(stderr, "Bad R value.\n");
- return -1;
- }
- p.g = strtol(argv[2], &e, 0);
- if (e && *e) {
- fprintf(stderr, "Bad G value.\n");
- return -1;
- }
- p.b = strtol(argv[3], &e, 0);
- if (e && *e) {
- fprintf(stderr, "Bad B value.\n");
- return -1;
+ for (i = 2; i < argc; ++i) {
+ ptr = strtok(argv[i], "=");
+ j = find_led_color_by_name(ptr);
+ if (j == -1) {
+ fprintf(stderr, "Bad color name: %s\n", ptr);
+ return -1;
+ }
+ ptr = strtok(NULL, "=");
+ if (ptr == NULL) {
+ fprintf(stderr, "Missing brightness value\n");
+ return -1;
+ }
+ p.brightness[j] = strtol(ptr, &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad brightness: %s\n", ptr);
+ return -1;
+ }
}
- p.flags = 0;
}
- rv = ec_command(EC_CMD_LED_SET, 0, &p, sizeof(p), NULL, 0);
+
+ rv = ec_command(EC_CMD_LED_CONTROL, 1, &p, sizeof(p), &r, sizeof(r));
return (rv < 0 ? rv : 0);
}