summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/spring/board.c67
-rw-r--r--include/ec_commands.h43
-rw-r--r--util/ectool.c100
3 files changed, 144 insertions, 66 deletions
diff --git a/board/spring/board.c b/board/spring/board.c
index db65e77986..117338d469 100644
--- a/board/spring/board.c
+++ b/board/spring/board.c
@@ -342,32 +342,6 @@ static int set_led_color(enum led_state_t state)
}
/*****************************************************************************/
-/* Host commands */
-
-static int led_command_set(struct host_cmd_handler_args *args)
-{
- const struct ec_params_led_set *p = args->params;
-
- if (p->flags & EC_LED_FLAGS_AUTO) {
- if (!board_get_ac())
- lp5562_poweroff();
- last_state = LED_STATE_OFF;
- led_auto_control = 1;
- } else {
- led_auto_control = 0;
- if (!board_get_ac())
- lp5562_poweron();
- if (lp5562_set_color((p->r << 16) + (p->g << 8) + p->b))
- return EC_RES_ERROR;
- }
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_LED_SET,
- led_command_set,
- EC_VER_MASK(0));
-
-/*****************************************************************************/
/* Hooks */
static void board_battery_led_update(void)
@@ -458,3 +432,44 @@ static int power_command_info(struct host_cmd_handler_args *args)
return EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_POWER_INFO, power_command_info, EC_VER_MASK(0));
+
+static int led_command_control(struct host_cmd_handler_args *args)
+{
+ 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 (!board_get_ac())
+ lp5562_poweroff();
+ last_state = LED_STATE_OFF;
+ led_auto_control = 1;
+ } 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 (!board_get_ac())
+ lp5562_poweron();
+ 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_CONTROL,
+ led_command_control,
+ EC_VER_MASK(1));
diff --git a/include/ec_commands.h b/include/ec_commands.h
index b16871462e..b35b15050a 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -729,15 +729,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 c5ebf30c6f..597dd72eaf 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.r = p.g = p.b = p.flags = 0;
+ p.led_id = strtol(argv[1], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad LED ID.\n");
+ return -1;
+ }
- if (!strcasecmp(argv[1], "auto")) {
+ 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[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);
}