diff options
-rw-r--r-- | common/lightbar.c | 188 | ||||
-rw-r--r-- | include/lightbar.h | 21 | ||||
-rw-r--r-- | include/lightbar_msg_list.h | 26 | ||||
-rw-r--r-- | include/lpc_commands.h | 48 | ||||
-rw-r--r-- | util/ectool.c | 167 |
5 files changed, 342 insertions, 108 deletions
diff --git a/common/lightbar.c b/common/lightbar.c index 3aff41130c..dc07ba3952 100644 --- a/common/lightbar.c +++ b/common/lightbar.c @@ -93,12 +93,6 @@ static void set_from_array(const struct initdata_s *data, int count) } } -static void lightbar_init_vals(void) -{ - CPRINTF("[%s()]\n", __func__); - set_from_array(init_vals, ARRAY_SIZE(init_vals)); -} - /* Controller register lookup tables. */ static const uint8_t led_to_ctrl[] = { 0, 0, 1, 1 }; static const uint8_t led_to_isc[] = { 0x15, 0x18, 0x15, 0x18 }; @@ -122,6 +116,13 @@ static inline uint8_t scale(int val, int max) return scale_abs((val * brightness)/255, max); } +static void lightbar_init_vals(void) +{ + CPRINTF("[%s()]\n", __func__); + set_from_array(init_vals, ARRAY_SIZE(init_vals)); + memset(current, 0, sizeof(current)); +} + /* Helper function. */ static void setrgb(int led, int red, int green, int blue) @@ -582,7 +583,7 @@ struct lightbar_cmd_t { uint32_t (*sequence)(void); }; -#define LBMSG(state) { #state, sequence_##state }, +#define LBMSG(state) { #state, sequence_##state } #include "lightbar_msg_list.h" static struct lightbar_cmd_t lightbar_cmds[] = { LIGHTBAR_MSG_LIST @@ -652,24 +653,93 @@ void lightbar_sequence(enum lightbar_sequence num) /****************************************************************************/ -/* Host commands via LPC bus */ +/* Generic command-handling (should work the same for both console & LPC) */ /****************************************************************************/ -/* FIXME(wfrichar): provide the same functions as the EC console */ +static const uint8_t dump_reglist[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a +}; -static enum lpc_status lpc_cmd_reset(uint8_t *data) +static void do_cmd_dump(uint8_t *outptr) { - lightbar_init_vals(); - return EC_LPC_RESULT_SUCCESS; + int i, n; + uint8_t reg; + + BUILD_ASSERT(3 * ARRAY_SIZE(dump_reglist) == + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.dump)); + + n = ARRAY_SIZE(dump_reglist); + for (i = 0; i < n; i++) { + reg = dump_reglist[i]; + *outptr++ = reg; + *outptr++ = controller_read(0, reg); + *outptr++ = controller_read(1, reg); + } +} + +static void do_cmd_rgb(uint8_t led, + uint8_t red, uint8_t green, uint8_t blue) +{ + int i; + + if (led >= NUM_LEDS) + for (i = 0; i < NUM_LEDS; i++) + lightbar_setrgb(i, red, green, blue); + else + lightbar_setrgb(led, red, green, blue); } -DECLARE_HOST_COMMAND(EC_LPC_COMMAND_LIGHTBAR_RESET, lpc_cmd_reset); -static enum lpc_status lpc_cmd_test(uint8_t *data) + +/****************************************************************************/ +/* Host commands via LPC bus */ +/****************************************************************************/ + +static enum lpc_status lpc_cmd_lightbar(uint8_t *data) { - lightbar_sequence(LIGHTBAR_TEST); + struct lpc_params_lightbar_cmd *ptr = + (struct lpc_params_lightbar_cmd *)data; + + switch (ptr->in.cmd) { + case LIGHTBAR_CMD_DUMP: + do_cmd_dump(ptr->out.dump); + break; + case LIGHTBAR_CMD_OFF: + lightbar_off(); + break; + case LIGHTBAR_CMD_ON: + lightbar_on(); + break; + case LIGHTBAR_CMD_INIT: + lightbar_init_vals(); + break; + case LIGHTBAR_CMD_BRIGHTNESS: + lightbar_brightness(ptr->in.brightness.num); + break; + case LIGHTBAR_CMD_SEQ: + lightbar_sequence(ptr->in.seq.num); + break; + case LIGHTBAR_CMD_REG: + controller_write(ptr->in.reg.ctrl, + ptr->in.reg.reg, + ptr->in.reg.value); + break; + case LIGHTBAR_CMD_RGB: + do_cmd_rgb(ptr->in.rgb.led, + ptr->in.rgb.red, + ptr->in.rgb.green, + ptr->in.rgb.blue); + break; + default: + return EC_LPC_RESULT_INVALID_PARAM; + } + return EC_LPC_RESULT_SUCCESS; } -DECLARE_HOST_COMMAND(EC_LPC_COMMAND_LIGHTBAR_TEST, lpc_cmd_test); + +DECLARE_HOST_COMMAND(EC_LPC_COMMAND_LIGHTBAR_CMD, lpc_cmd_lightbar); /****************************************************************************/ @@ -678,46 +748,34 @@ DECLARE_HOST_COMMAND(EC_LPC_COMMAND_LIGHTBAR_TEST, lpc_cmd_test); static int help(const char *cmd) { - ccprintf("Usage: %s\n", cmd); - ccprintf(" %s off\n", cmd); - ccprintf(" %s init\n", cmd); - ccprintf(" %s on\n", cmd); - ccprintf(" %s msg NUM\n", cmd); - ccprintf(" %s brightness NUM\n", cmd); - ccprintf(" %s CTRL REG VAL\n", cmd); - ccprintf(" %s LED RED GREEN BLUE\n", cmd); - return EC_ERROR_UNKNOWN; -} - -static void dump_regs(void) -{ - int reg, d1, d2, i; - int reglist[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a }; - for (i = 0; i < ARRAY_SIZE(reglist); i++) { - reg = reglist[i]; - d1 = controller_read(0, reg); - d2 = controller_read(1, reg); - ccprintf(" %02x %02x %02x\n", reg, d1, d2); - } + ccprintf("Usage:\n"); + ccprintf(" %s - dump all regs\n", cmd); + ccprintf(" %s off - enter standby\n", cmd); + ccprintf(" %s on - leave standby\n", cmd); + ccprintf(" %s init - load default vals\n", cmd); + ccprintf(" %s brightness NUM - set intensity (0-ff)\n", cmd); + ccprintf(" %s seq [NUM|SEQUENCE] - run given pattern" + " (no arg for list)\n", cmd); + ccprintf(" %s CTRL REG VAL - set LED controller regs\n", cmd); + ccprintf(" %s LED RED GREEN BLUE - set color manually" + " (LED=4 for all)\n", cmd); + return EC_SUCCESS; } -static int find_msg_by_name(const char *str) +static uint8_t find_msg_by_name(const char *str) { - int i; + uint8_t i; for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) if (!strcasecmp(str, lightbar_cmds[i].string)) return i; - return LIGHTBAR_ERROR; + return LIGHTBAR_NUM_SEQUENCES; } static void show_msg_names(void) { int i; - ccprintf("message names: "); + ccprintf("sequence names:"); for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) ccprintf(" %s", lightbar_cmds[i].string); ccprintf("\n"); @@ -725,10 +783,14 @@ static void show_msg_names(void) static int command_lightbar(int argc, char **argv) { - int i; + int i, j; + uint8_t num, buf[128]; if (1 == argc) { /* no args = dump 'em all */ - dump_regs(); + do_cmd_dump(buf); + for (i = j = 0; i < ARRAY_SIZE(dump_reglist); i++, j += 3) + ccprintf(" %02x %02x %02x\n", + buf[j], buf[j+1], buf[j+2]); return EC_SUCCESS; } @@ -749,45 +811,45 @@ static int command_lightbar(int argc, char **argv) if (argc == 3 && !strcasecmp(argv[1], "brightness")) { char *e; - int num = strtoi(argv[2], &e, 16); + num = 0xff & strtoi(argv[2], &e, 16); lightbar_brightness(num); return EC_SUCCESS; } - if (argc >= 2 && !strcasecmp(argv[1], "msg")) { + if (argc >= 2 && !strcasecmp(argv[1], "seq")) { char *e; - int num; + uint8_t num; if (argc == 2) { show_msg_names(); - return EC_SUCCESS; + return 0; } - num = strtoi(argv[2], &e, 16); + num = 0xff & strtoi(argv[2], &e, 16); if (e && *e) num = find_msg_by_name(argv[2]); + if (num >= LIGHTBAR_NUM_SEQUENCES) + return EC_ERROR_INVAL; lightbar_sequence(num); return EC_SUCCESS; } if (argc == 4) { char *e; - int ctrl = strtoi(argv[1], &e, 16); - int reg = strtoi(argv[2], &e, 16); - int val = strtoi(argv[3], &e, 16); + uint8_t ctrl, reg, val; + ctrl = 0xff & strtoi(argv[1], &e, 16); + reg = 0xff & strtoi(argv[2], &e, 16); + val = 0xff & strtoi(argv[3], &e, 16); controller_write(ctrl, reg, val); return EC_SUCCESS; } if (argc == 5) { char *e; - int led = strtoi(argv[1], &e, 16); - int red = strtoi(argv[2], &e, 16); - int green = strtoi(argv[3], &e, 16); - int blue = strtoi(argv[4], &e, 16); - if (led >= NUM_LEDS) - for (i = 0; i < NUM_LEDS; i++) - lightbar_setrgb(i, red, green, blue); - else - lightbar_setrgb(led, red, green, blue); + uint8_t led, r, g, b; + led = strtoi(argv[1], &e, 16); + r = strtoi(argv[2], &e, 16); + g = strtoi(argv[3], &e, 16); + b = strtoi(argv[4], &e, 16); + do_cmd_rgb(led, r, g, b); return EC_SUCCESS; } diff --git a/include/lightbar.h b/include/lightbar.h index a18f236f3f..0cc19e2b9b 100644 --- a/include/lightbar.h +++ b/include/lightbar.h @@ -7,8 +7,11 @@ #ifndef __CROS_EC_LIGHTBAR_H #define __CROS_EC_LIGHTBAR_H +/****************************************************************************/ +/* Internal stuff */ + /* Define the types of sequences */ -#define LBMSG(state) LIGHTBAR_##state, +#define LBMSG(state) LIGHTBAR_##state #include "lightbar_msg_list.h" enum lightbar_sequence { LIGHTBAR_MSG_LIST @@ -19,4 +22,20 @@ enum lightbar_sequence { /* Request a preset sequence from the lightbar task. */ void lightbar_sequence(enum lightbar_sequence s); +/****************************************************************************/ +/* External stuff */ + +/* These are the commands available to the EC console or via LPC. */ +enum lightbar_command { + LIGHTBAR_CMD_DUMP, + LIGHTBAR_CMD_OFF, + LIGHTBAR_CMD_ON, + LIGHTBAR_CMD_INIT, + LIGHTBAR_CMD_BRIGHTNESS, + LIGHTBAR_CMD_SEQ, + LIGHTBAR_CMD_REG, + LIGHTBAR_CMD_RGB, + LIGHTBAR_NUM_CMDS +}; + #endif /* __CROS_EC_LIGHTBAR_H */ diff --git a/include/lightbar_msg_list.h b/include/lightbar_msg_list.h index d6a33ed20f..f1c73a7f83 100644 --- a/include/lightbar_msg_list.h +++ b/include/lightbar_msg_list.h @@ -7,16 +7,16 @@ * types. */ #define LIGHTBAR_MSG_LIST \ - LBMSG(ERROR) \ - LBMSG(S5) \ - LBMSG(S3) \ - LBMSG(S0) \ - LBMSG(S5S3) \ - LBMSG(S3S0) \ - LBMSG(S0S3) \ - LBMSG(S3S5) \ - LBMSG(STOP) \ - LBMSG(RUN) \ - LBMSG(PULSE) \ - LBMSG(TEST) \ - LBMSG(KONAMI) + LBMSG(ERROR), \ + LBMSG(S5), \ + LBMSG(S3), \ + LBMSG(S0), \ + LBMSG(S5S3), \ + LBMSG(S3S0), \ + LBMSG(S0S3), \ + LBMSG(S3S5), \ + LBMSG(STOP), \ + LBMSG(RUN), \ + LBMSG(PULSE), \ + LBMSG(TEST), \ + LBMSG(KONAMI), diff --git a/include/lpc_commands.h b/include/lpc_commands.h index d9890b7b25..a3386c7280 100644 --- a/include/lpc_commands.h +++ b/include/lpc_commands.h @@ -345,18 +345,46 @@ struct lpc_params_pwm_set_keyboard_backlight { } __attribute__ ((packed)); /*****************************************************************************/ -/* Lightbar commands */ - -#define EC_LPC_COMMAND_LIGHTBAR_RESET 0x28 -/* No params needed */ - -#define EC_LPC_COMMAND_LIGHTBAR_TEST 0x29 -struct lpc_params_lightbar_test { - uint8_t tbd; +/* Lightbar commands. This looks worse than it is. Since we only use one LPC + * command to say "talk to the lightbar", we put the "and tell it to do X" + * part into a subcommand. We'll make separate structs for subcommands with + * different input args, so that we know how much to expect. */ + +#define EC_LPC_COMMAND_LIGHTBAR_CMD 0x28 +struct lpc_params_lightbar_cmd { + union { + union { + uint8_t cmd; + struct { + uint8_t cmd; + } dump, off, on, init; + struct num { + uint8_t cmd; + uint8_t num; + } brightness, seq; + + struct reg { + uint8_t cmd; + uint8_t ctrl, reg, value; + } reg; + struct rgb { + uint8_t cmd; + uint8_t led, red, green, blue; + } rgb; + } in; + union { + uint8_t dump[69]; + uint8_t off[0]; + uint8_t on[0]; + uint8_t init[0]; + uint8_t brightness[0]; + uint8_t seq[0]; + uint8_t reg[0]; + uint8_t rgb[0]; + } out; + }; } __attribute__ ((packed)); - - /*****************************************************************************/ /* USB charging control commands */ diff --git a/util/ectool.c b/util/ectool.c index 944265fe8e..8b3b000fa5 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -3,12 +3,14 @@ * found in the LICENSE file. */ +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/io.h> #include <unistd.h> +#include "lightbar.h" #include "lpc_commands.h" #include "battery.h" @@ -816,32 +818,155 @@ int cmd_pwm_set_keyboard_backlight(int argc, char *argv[]) return 0; } -int cmd_lightbar(int argc, char *argv[]) + +#define LBMSG(state) #state +#include "lightbar_msg_list.h" +static const char const *lightbar_cmds[] = { + LIGHTBAR_MSG_LIST +}; +#undef LBMSG + +/* This needs to match the values used in common/lightbar.c. I'd like to + * define this in one and only one place, but I can't think of a good way to do + * that without adding bunch of complexity. This will do for now. + */ +static const struct { + uint8_t insize; + uint8_t outsize; +} lb_command_paramcount[LIGHTBAR_NUM_CMDS] = { + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.dump), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.dump) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.off), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.off) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.on), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.on) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.init), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.init) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.brightness), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.brightness) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.seq), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.seq) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.reg), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.reg) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.rgb), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.rgb) }, +}; + +static int lb_help(const char *cmd) { - struct lpc_params_lightbar_test p; - char *e; + printf("Usage:\n"); + printf(" %s - dump all regs\n", cmd); + printf(" %s off - enter standby\n", cmd); + printf(" %s on - leave standby\n", cmd); + printf(" %s init - load default vals\n", cmd); + printf(" %s brightness NUM - set intensity (0-ff)\n", cmd); + printf(" %s seq [NUM|SEQUENCE] - run given pattern" + " (no arg for list)\n", cmd); + printf(" %s CTRL REG VAL - set LED controller regs\n", cmd); + printf(" %s LED RED GREEN BLUE - set color manually" + " (LED=4 for all)\n", cmd); + return 0; +} - p.tbd = 0; - - if (argc > 1) { - if (!strcmp("reset", argv[1])) { - return ec_command(EC_LPC_COMMAND_LIGHTBAR_RESET, - NULL, 0, NULL, 0); - } else if (!strcmp("test", argv[1])) { - if (argc > 2) { - p.tbd = strtol(argv[2], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad arg\n"); - return -1; - } - } - return ec_command(EC_LPC_COMMAND_LIGHTBAR_TEST, - &p, sizeof(p), NULL, 0); +static uint8_t lb_find_msg_by_name(const char *str) +{ + uint8_t i; + for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) + if (!strcasecmp(str, lightbar_cmds[i])) + return i; + + return LIGHTBAR_NUM_SEQUENCES; +} + +static void lb_show_msg_names(void) +{ + int i; + printf("sequence names:"); + for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) + printf(" %s", lightbar_cmds[i]); + printf("\n"); +} + +static int lb_do_cmd(enum lightbar_command cmd, + struct lpc_params_lightbar_cmd *ptr) +{ + int r; + ptr->in.cmd = cmd; + r = ec_command(EC_LPC_COMMAND_LIGHTBAR_CMD, + ptr, lb_command_paramcount[cmd].insize, + ptr, lb_command_paramcount[cmd].outsize); + return r; +} + +static int cmd_lightbar(int argc, char **argv) +{ + int i, r; + struct lpc_params_lightbar_cmd param; + + if (1 == argc) { /* no args = dump 'em all */ + r = lb_do_cmd(LIGHTBAR_CMD_DUMP, ¶m); + if (r) + return r; + for (i = 0; i < sizeof(param.out.dump); i += 3) { + printf(" %02x %02x %02x\n", + param.out.dump[i], + param.out.dump[i+1], + param.out.dump[i+2]); + } + return 0; + } + + if (argc == 2 && !strcasecmp(argv[1], "init")) + return lb_do_cmd(LIGHTBAR_CMD_INIT, ¶m); + + if (argc == 2 && !strcasecmp(argv[1], "off")) + return lb_do_cmd(LIGHTBAR_CMD_OFF, ¶m); + + if (argc == 2 && !strcasecmp(argv[1], "on")) + return lb_do_cmd(LIGHTBAR_CMD_ON, ¶m); + + if (argc == 3 && !strcasecmp(argv[1], "brightness")) { + char *e; + param.in.brightness.num = 0xff & strtoul(argv[2], &e, 16); + return lb_do_cmd(LIGHTBAR_CMD_BRIGHTNESS, ¶m); + } + + if (argc >= 2 && !strcasecmp(argv[1], "seq")) { + char *e; + uint8_t num; + if (argc == 2) { + lb_show_msg_names(); + return 0; + } + num = 0xff & strtoul(argv[2], &e, 16); + if (e && *e) + num = lb_find_msg_by_name(argv[2]); + if (num >= LIGHTBAR_NUM_SEQUENCES) { + fprintf(stderr, "Invalid arg\n"); + return -1; } + param.in.seq.num = num; + return lb_do_cmd(LIGHTBAR_CMD_SEQ, ¶m); + } + + if (argc == 4) { + char *e; + param.in.reg.ctrl = 0xff & strtoul(argv[1], &e, 16); + param.in.reg.reg = 0xff & strtoul(argv[2], &e, 16); + param.in.reg.value = 0xff & strtoul(argv[3], &e, 16); + return lb_do_cmd(LIGHTBAR_CMD_REG, ¶m); + } + + if (argc == 5) { + char *e; + param.in.rgb.led = strtoul(argv[1], &e, 16); + param.in.rgb.red = strtoul(argv[2], &e, 16); + param.in.rgb.green = strtoul(argv[3], &e, 16); + param.in.rgb.blue = strtoul(argv[4], &e, 16); + return lb_do_cmd(LIGHTBAR_CMD_RGB, ¶m); } - printf("Usage: %s reset | test [NUM]\n", argv[0]); - return -1; + return lb_help(argv[0]); } int cmd_usb_charge_set_mode(int argc, char *argv[]) |