diff options
-rw-r--r-- | board/link/board.c | 7 | ||||
-rw-r--r-- | board/link/board.h | 5 | ||||
-rw-r--r-- | chip/lm4/power_button.c | 2 | ||||
-rw-r--r-- | common/firmware_image.lds.S | 2 | ||||
-rw-r--r-- | common/fmap.c | 25 | ||||
-rw-r--r-- | common/lightbar.c | 63 | ||||
-rw-r--r-- | common/system_common.c | 68 | ||||
-rw-r--r-- | common/util.c | 21 | ||||
-rw-r--r-- | common/x86_power.c | 6 | ||||
-rw-r--r-- | include/lightbar.h | 1 | ||||
-rw-r--r-- | include/lpc_commands.h | 24 | ||||
-rw-r--r-- | include/util.h | 1 | ||||
-rw-r--r-- | util/ectool.c | 44 | ||||
-rw-r--r-- | util/lbplay.c | 32 |
14 files changed, 205 insertions, 96 deletions
diff --git a/board/link/board.c b/board/link/board.c index 1235bf15f5..7b8e1d2c27 100644 --- a/board/link/board.c +++ b/board/link/board.c @@ -81,6 +81,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"ENABLE_TOUCHPAD", LM4_GPIO_C, (1<<6), GPIO_OUT_LOW, NULL}, {"ENABLE_VCORE", LM4_GPIO_F, (1<<7), GPIO_OUT_LOW, NULL}, {"ENABLE_VS", LM4_GPIO_G, (1<<6), GPIO_OUT_LOW, NULL}, + {"ENABLE_WLAN", LM4_GPIO_Q, (1<<5), GPIO_OUT_LOW, NULL}, {"ENTERING_RW", LM4_GPIO_J, (1<<5), GPIO_OUT_LOW, NULL}, {"LIGHTBAR_RESETn", LM4_GPIO_B, (1<<1), GPIO_OUT_LOW, NULL}, {"PCH_A20GATE", LM4_GPIO_Q, (1<<6), GPIO_OUT_LOW, NULL}, @@ -92,8 +93,14 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"PCH_PWROK", LM4_GPIO_F, (1<<5), GPIO_OUT_LOW, NULL}, {"PCH_RCINn", LM4_GPIO_Q, (1<<7), GPIO_OUT_LOW, NULL}, {"PCH_RSMRSTn", LM4_GPIO_F, (1<<1), GPIO_OUT_LOW, NULL}, + /* RTCRST# (and SRTCRST# below) are unasserted by default so we don't + * clear the RTC wells in the PCH when the EC resets. */ + {"PCH_RTCRSTn", LM4_GPIO_F, (1<<6), GPIO_OUT_HIGH, NULL}, {"PCH_SMIn", LM4_GPIO_F, (1<<4), GPIO_OUT_HIGH, NULL}, + {"PCH_SRTCRSTn", LM4_GPIO_C, (1<<7), GPIO_OUT_HIGH, NULL}, {"PCH_SUSACKn", LM4_GPIO_F, (1<<3), GPIO_OUT_HIGH, NULL}, + {"RADIO_DISABLE_WLAN", LM4_GPIO_D, (1<<0), GPIO_OUT_LOW, NULL}, + {"RADIO_DISABLE_BT", LM4_GPIO_D, (1<<1), GPIO_OUT_LOW, NULL}, {"TOUCHSCREEN_RESETn", LM4_GPIO_B, (1<<0), GPIO_OUT_LOW, NULL}, {"USB1_CTL1", LM4_GPIO_E, (1<<2), GPIO_OUT_LOW, NULL}, {"USB1_CTL2", LM4_GPIO_E, (1<<3), GPIO_OUT_LOW, NULL}, diff --git a/board/link/board.h b/board/link/board.h index e041903bd0..b4f822b9ac 100644 --- a/board/link/board.h +++ b/board/link/board.h @@ -149,6 +149,7 @@ enum gpio_signal { GPIO_ENABLE_TOUCHPAD, /* Enable touchpad power */ GPIO_ENABLE_VCORE, /* Enable +CPU_CORE and +VGFX_CORE */ GPIO_ENABLE_VS, /* Enable VS power supplies */ + GPIO_ENABLE_WLAN, /* Enable WLAN module power (+3VS_WLAN) */ GPIO_ENTERING_RW, /* Indicate when EC is entering RW code */ GPIO_LIGHTBAR_RESETn, /* Reset lightbar controllers (Proto1+) */ GPIO_PCH_A20GATE, /* A20GATE signal to PCH */ @@ -161,8 +162,12 @@ enum gpio_signal { GPIO_PCH_PWROK, /* PWROK / APWROK signals to PCH */ GPIO_PCH_RCINn, /* RCIN# signal to PCH */ GPIO_PCH_RSMRSTn, /* Reset PCH resume power plane logic */ + GPIO_PCH_RTCRSTn, /* Reset PCH RTC well */ GPIO_PCH_SMIn, /* System management interrupt to PCH */ + GPIO_PCH_SRTCRSTn, /* Reset PCH ME RTC well */ GPIO_PCH_SUSACKn, /* Acknowledge PCH SUSWARN# signal */ + GPIO_RADIO_DISABLE_WLAN, /* Disable WLAN radio */ + GPIO_RADIO_DISABLE_BT, /* Disable bluetooth radio */ GPIO_TOUCHSCREEN_RESETn, /* Reset touch screen (Proto1+) */ GPIO_USB1_CTL1, /* USB charger port 1 CTL1 output */ GPIO_USB1_CTL2, /* USB charger port 1 CTL2 output */ diff --git a/chip/lm4/power_button.c b/chip/lm4/power_button.c index f6597d30d5..b2841c77b1 100644 --- a/chip/lm4/power_button.c +++ b/chip/lm4/power_button.c @@ -93,6 +93,8 @@ static void update_other_switches(void) *memmap_switches &= ~EC_LPC_SWITCH_DEDICATED_RECOVERY; /* Was this a reboot requesting recovery? */ + /* TODO: should use a different flag, not the dedicated recovery + * switch flag! */ if (system_get_recovery_required()) *memmap_switches |= EC_LPC_SWITCH_DEDICATED_RECOVERY; diff --git a/common/firmware_image.lds.S b/common/firmware_image.lds.S index 3b2ef7f561..bfaaaee7f4 100644 --- a/common/firmware_image.lds.S +++ b/common/firmware_image.lds.S @@ -20,11 +20,13 @@ SECTIONS . = ALIGN(CONFIG_FLASH_BANK_SIZE); .image.A : AT(CONFIG_FW_A_OFF) { *(.image.A) + BYTE(0xEA) /* Mark end explicitly */ } > FLASH =0xff #ifndef CONFIG_NO_RW_B . = ALIGN(CONFIG_FLASH_BANK_SIZE); .image.B : AT(CONFIG_FW_B_OFF) { *(.image.B) + BYTE(0xEB) /* Mark end explicitly */ } > FLASH =0xff #endif /* NOTE: EC implementation reserves one bank for itself */ diff --git a/common/fmap.c b/common/fmap.c index 438a45d1c1..3f7baceb93 100644 --- a/common/fmap.c +++ b/common/fmap.c @@ -37,7 +37,7 @@ typedef struct _FmapAreaHeader { } __attribute__((packed)) FmapAreaHeader; -#define NUM_EC_FMAP_AREAS 14 +#define NUM_EC_FMAP_AREAS 17 const struct _ec_fmap { FmapHeader header; FmapAreaHeader area[NUM_EC_FMAP_AREAS]; @@ -96,6 +96,29 @@ const struct _ec_fmap { .area_size = 0, /* Always zero */ .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, }, + { + /* The range for write protect, for lagecy firmware + * updater. Should be identical to 'WP_RO'. */ + .area_name = "EC_RO", + .area_offset = CONFIG_FW_RO_OFF, + .area_size = CONFIG_FW_IMAGE_SIZE, + .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, + }, + { + /* The range for autoupdate to update A/B at once. */ + .area_name = "EC_RW", + .area_offset = CONFIG_FW_A_OFF, + .area_size = CONFIG_FW_IMAGE_SIZE * 2, + .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, + }, + { + /* The range for write protect, for factory finalize + * test case. Should be identical to 'EC_RO'. */ + .area_name = "WP_RO", + .area_offset = CONFIG_FW_RO_OFF, + .area_size = CONFIG_FW_IMAGE_SIZE, + .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO, + }, /* Firmware A */ { diff --git a/common/lightbar.c b/common/lightbar.c index d81b75c298..3c90e834c5 100644 --- a/common/lightbar.c +++ b/common/lightbar.c @@ -590,10 +590,11 @@ static struct lightbar_cmd_t lightbar_cmds[] = { }; #undef LBMSG +static enum lightbar_sequence current_state, previous_state; + void lightbar_task(void) { uint32_t msg; - enum lightbar_sequence state, previous_state; /* Keep the controllers out of reset. The reset pullup uses more power * than leaving them in standby. */ @@ -605,36 +606,36 @@ void lightbar_task(void) /* FIXME: What to do first? For now, nothing, followed by more nothing. */ - state = LIGHTBAR_STOP; + current_state = LIGHTBAR_STOP; previous_state = LIGHTBAR_S5; while (1) { - msg = lightbar_cmds[state].sequence(); + msg = lightbar_cmds[current_state].sequence(); CPRINTF("[%s(%d)]\n", __func__, msg); msg = TASK_EVENT_CUSTOM(msg); if (msg && msg < LIGHTBAR_NUM_SEQUENCES) { - previous_state = state; - state = TASK_EVENT_CUSTOM(msg); + previous_state = current_state; + current_state = TASK_EVENT_CUSTOM(msg); } else { - switch (state) { + switch (current_state) { case LIGHTBAR_S5S3: - state = LIGHTBAR_S3; + current_state = LIGHTBAR_S3; break; case LIGHTBAR_S3S0: - state = LIGHTBAR_S0; + current_state = LIGHTBAR_S0; break; case LIGHTBAR_S0S3: - state = LIGHTBAR_S3; + current_state = LIGHTBAR_S3; break; case LIGHTBAR_S3S5: - state = LIGHTBAR_S5; + current_state = LIGHTBAR_S5; break; case LIGHTBAR_TEST: case LIGHTBAR_STOP: case LIGHTBAR_RUN: case LIGHTBAR_ERROR: case LIGHTBAR_KONAMI: - state = previous_state; + current_state = previous_state; default: break; } @@ -663,20 +664,19 @@ static const uint8_t dump_reglist[] = { 0x18, 0x19, 0x1a }; -static void do_cmd_dump(uint8_t *outptr) +static void do_cmd_dump(struct lpc_params_lightbar_cmd *ptr) { - int i, n; + int i; uint8_t reg; - BUILD_ASSERT(3 * ARRAY_SIZE(dump_reglist) == - sizeof(((struct lpc_params_lightbar_cmd *)0)->out.dump)); + BUILD_ASSERT(ARRAY_SIZE(dump_reglist) == + ARRAY_SIZE(ptr->out.dump.vals)); - n = ARRAY_SIZE(dump_reglist); - for (i = 0; i < n; i++) { + for (i = 0; i < ARRAY_SIZE(dump_reglist); i++) { reg = dump_reglist[i]; - *outptr++ = reg; - *outptr++ = controller_read(0, reg); - *outptr++ = controller_read(1, reg); + ptr->out.dump.vals[i].reg = reg; + ptr->out.dump.vals[i].ic0 = controller_read(0, reg); + ptr->out.dump.vals[i].ic1 = controller_read(1, reg); } } @@ -704,7 +704,7 @@ static enum lpc_status lpc_cmd_lightbar(uint8_t *data) switch (ptr->in.cmd) { case LIGHTBAR_CMD_DUMP: - do_cmd_dump(ptr->out.dump); + do_cmd_dump(ptr); break; case LIGHTBAR_CMD_OFF: lightbar_off(); @@ -732,7 +732,11 @@ static enum lpc_status lpc_cmd_lightbar(uint8_t *data) ptr->in.rgb.green, ptr->in.rgb.blue); break; + case LIGHTBAR_CMD_GET_SEQ: + ptr->out.get_seq.num = current_state; + break; default: + CPRINTF("[invalid lightbar cmd 0x%x]\n", ptr->in.cmd); return EC_LPC_RESULT_INVALID_PARAM; } @@ -778,19 +782,24 @@ static void show_msg_names(void) ccprintf("sequence names:"); for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) ccprintf(" %s", lightbar_cmds[i].string); - ccprintf("\n"); + ccprintf("\nCurrent = 0x%x %s\n", current_state, + lightbar_cmds[current_state].string); } static int command_lightbar(int argc, char **argv) { - int i, j; - uint8_t num, buf[128]; + int i; + uint8_t num; + struct lpc_params_lightbar_cmd params; if (1 == argc) { /* no args = dump 'em all */ - do_cmd_dump(buf); - for (i = j = 0; i < ARRAY_SIZE(dump_reglist); i++, j += 3) + do_cmd_dump(¶ms); + for (i = 0; i < ARRAY_SIZE(dump_reglist); i++) ccprintf(" %02x %02x %02x\n", - buf[j], buf[j+1], buf[j+2]); + params.out.dump.vals[i].reg, + params.out.dump.vals[i].ic0, + params.out.dump.vals[i].ic1); + return EC_SUCCESS; } diff --git a/common/system_common.c b/common/system_common.c index 793bdaf263..d429780aaa 100644 --- a/common/system_common.c +++ b/common/system_common.c @@ -31,14 +31,15 @@ struct jump_tag { * images. */ #define JUMP_DATA_MAGIC 0x706d754a /* "Jump" */ #define JUMP_DATA_VERSION 3 +#define JUMP_DATA_SIZE_V2 16 /* Size of version 2 jump data struct */ struct jump_data { /* Add new fields to the _start_ of the struct, since we copy it to the * _end_ of RAM between images. This way, the magic number will always * be the last word in RAM regardless of how many fields are added. */ /* Fields from version 3 */ - uint8_t recovery_required; /* signal recovery mode to BIOS */ - int header_size; /* Header size to correctly point to jump tags. */ + uint8_t recovery_required; /* Signal recovery mode to BIOS */ + int struct_size; /* Size of struct jump_data */ /* Fields from version 2 */ int jump_tag_total; /* Total size of all jump tags */ @@ -56,13 +57,14 @@ static struct jump_data * const jdata = (struct jump_data *)(CONFIG_RAM_BASE + CONFIG_RAM_SIZE - sizeof(struct jump_data)); +static const char * const image_names[] = {"unknown", "RO", "A", "B"}; static enum system_reset_cause_t reset_cause = SYSTEM_RESET_UNKNOWN; static int jumped_to_image; int system_usable_ram_end(void) { - /* Leave space at the end of RAM for jump data. + /* Leave space at the end of RAM for jump data and tags. * * Note that jump_tag_total is 0 on a reboot, so we have the maximum * amount of RAM available on a reboot; we only lose space for stored @@ -196,9 +198,8 @@ int system_unsafe_to_overwrite(uint32_t offset, uint32_t size) { const char *system_get_image_copy_string(void) { - static const char * const copy_descs[] = {"unknown", "RO", "A", "B"}; int copy = system_get_image_copy(); - return copy < ARRAY_SIZE(copy_descs) ? copy_descs[copy] : "?"; + return copy < ARRAY_SIZE(image_names) ? image_names[copy] : "?"; } @@ -222,7 +223,7 @@ static void jump_to_image(uint32_t init_addr, jdata->version = JUMP_DATA_VERSION; jdata->reset_cause = reset_cause; jdata->jump_tag_total = 0; /* Reset tags */ - jdata->header_size = sizeof(struct jump_data); + jdata->struct_size = sizeof(struct jump_data); /* Call other hooks; these may add tags */ hook_notify(HOOK_SYSJUMP, 0); @@ -250,13 +251,6 @@ static uint32_t get_base(enum system_image_copy_t copy) } -static const char * const image_names[] = { - "Unknown", - "RO", - "A", - "B" -}; - int system_run_image_copy(enum system_image_copy_t copy, int recovery_required) { @@ -330,37 +324,28 @@ int system_common_pre_init(void) if (jdata->magic == JUMP_DATA_MAGIC && jdata->version >= 1 && reset_cause == SYSTEM_RESET_SOFT_WARM) { - int jtag_total; /* #byte of jump tags */ - int delta; /* delta of header size */ - uint8_t *jtag; /* point to _real_ start of jump tags */ + int delta; /* Change in jump data struct size between the + * previous image and this one. */ /* Yes, we jumped to this image */ jumped_to_image = 1; /* Overwrite the reset cause with the real one */ reset_cause = jdata->reset_cause; - /* Header version 3 introduces the header_size field. - * Thus we can estimate the real offset of jump tags - * between different header versions. - */ - if (jdata->version == 1) { - jtag_total = 0; - delta = sizeof(struct jump_data) - 12; - } else if (jdata->version == 2) { - jtag_total = jdata->jump_tag_total; - delta = sizeof(struct jump_data) - 16; - } else { - jtag_total = jdata->jump_tag_total; - delta = sizeof(struct jump_data) - jdata->header_size; - } - jtag = ((uint8_t*)jdata) + delta - jtag_total; - /* TODO: re-write with memmove(). */ - if (delta > 0) { - memcpy(jtag - delta, jtag, jtag_total); - } else { - int i; - for (i = jtag_total - 1; i >= 0; i--) - jtag[i - delta] = jtag[i]; + /* If the jump data structure isn't the same size as the + * current one, shift the jump tags to immediately before the + * current jump data structure, to make room for initalizing + * the new fields below. */ + if (jdata->version == 1) + delta = 0; /* No tags in v1, so no need for move */ + else if (jdata->version == 2) + delta = sizeof(struct jump_data) - JUMP_DATA_SIZE_V2; + else + delta = sizeof(struct jump_data) - jdata->struct_size; + + if (delta && jdata->jump_tag_total) { + uint8_t *d = (uint8_t *)system_usable_ram_end(); + memmove(d, d + delta, jdata->jump_tag_total); } /* Initialize fields added after version 1 */ @@ -368,10 +353,11 @@ int system_common_pre_init(void) jdata->jump_tag_total = 0; /* Initialize fields added after version 2 */ - if (jdata->version < 3) { + if (jdata->version < 3) jdata->recovery_required = 0; - jdata->header_size = 16; - } + + /* Struct size is now the current struct size */ + jdata->struct_size = sizeof(struct jump_data); /* Clear the jump struct's magic number. This prevents * accidentally detecting a jump when there wasn't one, and diff --git a/common/util.c b/common/util.c index fe30ffa518..47e9ba1226 100644 --- a/common/util.c +++ b/common/util.c @@ -144,6 +144,27 @@ void *memset(void *dest, int c, int len) } +void *memmove(void *dest, const void *src, int len) +{ + if ((uint32_t)dest <= (uint32_t)src || + (uint32_t)dest >= (uint32_t)src + len) { + /* Start of destination doesn't overlap source, so just use + * memcpy(). */ + return memcpy(dest, src, len); + } else { + /* Copy from end, so we don't overwrite the source */ + char *d = (char *)dest + len; + const char *s = (const char *)src + len; + /* TODO: optimized version using LDM/STM would be much faster */ + while (len > 0) { + *(--d) = *(--s); + len--; + } + return dest; + } +} + + char *strzcpy(char *dest, const char *src, int len) { char *d = dest; diff --git a/common/x86_power.c b/common/x86_power.c index 24979cc2b8..4c8183cfe3 100644 --- a/common/x86_power.c +++ b/common/x86_power.c @@ -358,6 +358,9 @@ void x86_power_task(void) /* Turn on power rails */ gpio_set_level(GPIO_ENABLE_VS, 1); + /* Enable WLAN */ + gpio_set_level(GPIO_ENABLE_WLAN, 1); + /* Enable fan, now that +5VS is turned on */ /* TODO: On proto1+, fan is on +5VALW, so we can leave * it on all the time. */ @@ -401,6 +404,9 @@ void x86_power_task(void) * it on all the time. */ pwm_enable_fan(0); + /* Disable WLAN */ + gpio_set_level(GPIO_ENABLE_WLAN, 0); + /* Turn off power rails */ gpio_set_level(GPIO_ENABLE_VS, 0); diff --git a/include/lightbar.h b/include/lightbar.h index 0cc19e2b9b..395166191d 100644 --- a/include/lightbar.h +++ b/include/lightbar.h @@ -35,6 +35,7 @@ enum lightbar_command { LIGHTBAR_CMD_SEQ, LIGHTBAR_CMD_REG, LIGHTBAR_CMD_RGB, + LIGHTBAR_CMD_GET_SEQ, LIGHTBAR_NUM_CMDS }; diff --git a/include/lpc_commands.h b/include/lpc_commands.h index 354c059b1f..c7f2530df1 100644 --- a/include/lpc_commands.h +++ b/include/lpc_commands.h @@ -349,7 +349,6 @@ struct lpc_params_pwm_set_keyboard_backlight { * 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 { @@ -357,7 +356,7 @@ struct lpc_params_lightbar_cmd { uint8_t cmd; struct { uint8_t cmd; - } dump, off, on, init; + } dump, off, on, init, get_seq; struct num { uint8_t cmd; uint8_t num; @@ -373,14 +372,19 @@ struct lpc_params_lightbar_cmd { } 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]; + struct dump { + struct { + uint8_t reg; + uint8_t ic0; + uint8_t ic1; + } vals[23]; + } dump; + struct get_seq { + uint8_t num; + } get_seq; + struct { + /* no return params */ + } off, on, init, brightness, seq, reg, rgb; } out; }; } __attribute__ ((packed)); diff --git a/include/util.h b/include/util.h index 5b9dd364db..6f8fe1c581 100644 --- a/include/util.h +++ b/include/util.h @@ -56,6 +56,7 @@ int isspace(int c); int isalpha(int c); void *memcpy(void *dest, const void *src, int len); void *memset(void *dest, int c, int len); +void *memmove(void *dest, const void *src, int len); int strcasecmp(const char *s1, const char *s2); int strlen(const char *s); int strtoi(const char *nptr, char **endptr, int base); diff --git a/util/ectool.c b/util/ectool.c index d90db5dee5..c395a525af 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -11,10 +11,12 @@ #include <sys/io.h> #include <unistd.h> +#include "battery.h" #include "lightbar.h" #include "lpc_commands.h" -#include "battery.h" +/* Handy tricks */ +#define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2*!(cond)])) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* Don't use a macro where an inline will do... */ static inline int MIN(int a, int b) { return a < b ? a : b; } @@ -846,14 +848,14 @@ static const char const *lightbar_cmds[] = { }; #undef LBMSG -/* This needs to match the values used in common/lightbar.c. I'd like to +/* This needs to match the values defined in lightbar.h. 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] = { +} lb_command_paramcount[] = { { 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), @@ -870,6 +872,8 @@ static const struct { 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) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.get_seq), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.get_seq) }, }; static int lb_help(const char *cmd) @@ -898,15 +902,6 @@ static uint8_t lb_find_msg_by_name(const char *str) 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) { @@ -918,6 +913,21 @@ static int lb_do_cmd(enum lightbar_command cmd, return r; } +static void lb_show_msg_names(void) +{ + int i, current_state; + struct lpc_params_lightbar_cmd param; + + (void)lb_do_cmd(LIGHTBAR_CMD_GET_SEQ, ¶m); + current_state = param.out.get_seq.num; + + printf("sequence names:"); + for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) + printf(" %s", lightbar_cmds[i]); + printf("\nCurrent = 0x%x %s\n", current_state, + lightbar_cmds[current_state]); +} + static int cmd_lightbar(int argc, char **argv) { int i, r; @@ -927,11 +937,11 @@ static int cmd_lightbar(int argc, char **argv) r = lb_do_cmd(LIGHTBAR_CMD_DUMP, ¶m); if (r) return r; - for (i = 0; i < sizeof(param.out.dump); i += 3) { + for (i = 0; i < ARRAY_SIZE(param.out.dump.vals); i++) { printf(" %02x %02x %02x\n", - param.out.dump[i], - param.out.dump[i+1], - param.out.dump[i+2]); + param.out.dump.vals[i].reg, + param.out.dump.vals[i].ic0, + param.out.dump.vals[i].ic1); } return 0; } @@ -1465,6 +1475,8 @@ int main(int argc, char *argv[]) { const struct command *cmd; + BUILD_ASSERT(ARRAY_SIZE(lb_command_paramcount) == LIGHTBAR_NUM_CMDS); + if (argc < 2 || !strcasecmp(argv[1], "-?") || !strcasecmp(argv[1], "help")) { print_help(argv[0]); diff --git a/util/lbplay.c b/util/lbplay.c index 33d8bb731e..56934ebea2 100644 --- a/util/lbplay.c +++ b/util/lbplay.c @@ -13,6 +13,9 @@ #include "lightbar.h" #include "lpc_commands.h" +/* Handy tricks */ +#define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2*!(cond)])) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* Waits for the EC to be unbusy. Returns 0 if unbusy, non-zero if * timeout. */ @@ -80,7 +83,7 @@ static int ec_command(int command, const void *indata, int insize, static const struct { uint8_t insize; uint8_t outsize; -} lb_command_paramcount[LIGHTBAR_NUM_CMDS] = { +} lb_command_paramcount[] = { { 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), @@ -97,6 +100,8 @@ static const struct { 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) }, + { sizeof(((struct lpc_params_lightbar_cmd *)0)->in.get_seq), + sizeof(((struct lpc_params_lightbar_cmd *)0)->out.get_seq) }, }; @@ -169,11 +174,33 @@ void lightbar_rgb(int led, int red, int green, int blue) ¶m, lb_command_paramcount[param.in.cmd].outsize); } +void wait_for_ec_to_stop(void) +{ + int r; + struct lpc_params_lightbar_cmd param; + int count = 0; + + do { + usleep(100000); + param.in.cmd = LIGHTBAR_CMD_GET_SEQ; + r = ec_command(EC_LPC_COMMAND_LIGHTBAR_CMD, + ¶m, + lb_command_paramcount[param.in.cmd].insize, + ¶m, + lb_command_paramcount[param.in.cmd].outsize); + if (count++ > 10) { + fprintf(stderr, "EC isn't responding\n"); + exit(1); + } + } while (r != 0 && param.out.get_seq.num != LIGHTBAR_STOP); +} int main(int argc, char **argv) { int i; + BUILD_ASSERT(ARRAY_SIZE(lb_command_paramcount) == LIGHTBAR_NUM_CMDS); + /* Request I/O privilege */ if (iopl(3) < 0) { perror("Error getting I/O privilege"); @@ -184,6 +211,9 @@ int main(int argc, char **argv) /* Tell the EC to let us drive. */ lightbar_sequence(LIGHTBAR_STOP); + /* Wait until it's listening */ + wait_for_ec_to_stop(); + /* Initialize it */ lightbar_off(); lightbar_init_vals(); |