summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/link/board.c7
-rw-r--r--board/link/board.h5
-rw-r--r--chip/lm4/power_button.c2
-rw-r--r--common/firmware_image.lds.S2
-rw-r--r--common/fmap.c25
-rw-r--r--common/lightbar.c63
-rw-r--r--common/system_common.c68
-rw-r--r--common/util.c21
-rw-r--r--common/x86_power.c6
-rw-r--r--include/lightbar.h1
-rw-r--r--include/lpc_commands.h24
-rw-r--r--include/util.h1
-rw-r--r--util/ectool.c44
-rw-r--r--util/lbplay.c32
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(&params);
+ 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, &param);
+ 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, &param);
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)
&param, 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,
+ &param,
+ lb_command_paramcount[param.in.cmd].insize,
+ &param,
+ 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();