summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2015-07-07 16:39:42 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-07-09 12:30:38 +0000
commit0eb88ff59bd9a07ba23fa25e8e1b966782b6de73 (patch)
treeacda8862d565eafbe509b4854618bc4329b16f5b
parent08593b8fe02244a976e2653d25cd433bc50ff396 (diff)
downloadchrome-ec-0eb88ff59bd9a07ba23fa25e8e1b966782b6de73.tar.gz
Cr50: Enable host commands over SPI bus
This enables the feature that lets the Cr50 receive host commands via the SPI (slave) interface. BUG=chrome-os-partner:40969 BRANCH=none TEST=make buildall CQ-DEPEND=CL:283998 This CL also adds a test example in the extra/ftdi_hostcmd/ directory. To use it, you need the Cr50 attached to the build host via an FTDI USB-to-SPI adapter. cd extra/ftdi_hostcmd make ./test_cmds Change-Id: Ia719b1c898afc45b3105a9cd573a8492178d9be2 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/284001
-rw-r--r--board/cr50/board.h7
-rw-r--r--board/cr50/ec.tasklist1
-rw-r--r--extra/ftdi_hostcmd/.gitignore1
-rw-r--r--extra/ftdi_hostcmd/Makefile37
-rw-r--r--extra/ftdi_hostcmd/README6
-rw-r--r--extra/ftdi_hostcmd/test_cmds.c573
6 files changed, 624 insertions, 1 deletions
diff --git a/board/cr50/board.h b/board/cr50/board.h
index 42fcaa74a8..e93ff03ff1 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -26,8 +26,13 @@
/* Enable SPI Slave (SPS) module */
#define CONFIG_SPI
+#define CONFIG_HOSTCMD_SPI
+
+/* We don't need to send events to the AP */
+#undef CONFIG_HOSTCMD_EVENTS
+
+#endif /* not A1 */
-#endif
/*
* Allow dangerous commands all the time, since we don't have a write protect
* switch.
diff --git a/board/cr50/ec.tasklist b/board/cr50/ec.tasklist
index 961b7750bd..98404b339a 100644
--- a/board/cr50/ec.tasklist
+++ b/board/cr50/ec.tasklist
@@ -19,4 +19,5 @@
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(BLOB, blob_task, NULL, TASK_STACK_SIZE) \
+ TASK_NOTEST(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE)
diff --git a/extra/ftdi_hostcmd/.gitignore b/extra/ftdi_hostcmd/.gitignore
new file mode 100644
index 0000000000..9831af29be
--- /dev/null
+++ b/extra/ftdi_hostcmd/.gitignore
@@ -0,0 +1 @@
+test_cmds
diff --git a/extra/ftdi_hostcmd/Makefile b/extra/ftdi_hostcmd/Makefile
new file mode 100644
index 0000000000..d46b4b1c72
--- /dev/null
+++ b/extra/ftdi_hostcmd/Makefile
@@ -0,0 +1,37 @@
+# Copyright 2015 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Use your own libmpsse if you want, but we're going to use the files
+# that are part of the Chromium OS trunks_client program.
+PLATFORM2 = ../../../../platform2
+MPSSE_DIR = $(PLATFORM2)/trunks/ftdi
+
+PROG = test_cmds
+SRCS = test_cmds.c $(MPSSE_DIR)/mpsse.c $(MPSSE_DIR)/support.c
+
+CFLAGS = \
+ -std=gnu99 \
+ -g3 \
+ -O3 \
+ -Wall \
+ -Werror \
+ -Wpointer-arith \
+ -Wcast-align \
+ -Wcast-qual \
+ -Wundef \
+ -Wsign-compare \
+ -Wredundant-decls \
+ -Wmissing-declarations
+
+CFLAGS += -I../../include -I${MPSSE_DIR} -I${PLATFORM2}
+
+CFLAGS += $(shell pkg-config --cflags libusb-1.0 libftdi1)
+LIBS += $(shell pkg-config --libs libusb-1.0 libftdi1)
+
+$(PROG): $(SRCS) Makefile
+ gcc $(CFLAGS) $(SRCS) $(LDFLAGS) $(LIBS) -o $@
+
+.PHONY: clean
+clean:
+ rm -rf $(PROG)
diff --git a/extra/ftdi_hostcmd/README b/extra/ftdi_hostcmd/README
new file mode 100644
index 0000000000..4de2f45fb3
--- /dev/null
+++ b/extra/ftdi_hostcmd/README
@@ -0,0 +1,6 @@
+
+Ubuntu Trusty uses an ancient version of libftdi.
+
+You'll probably want to grab the latest libftdi1-1.2.tar.bz2 from
+http://www.intra2net.com/en/developer/libftdi/ and install it into /usr
+instead.
diff --git a/extra/ftdi_hostcmd/test_cmds.c b/extra/ftdi_hostcmd/test_cmds.c
new file mode 100644
index 0000000000..d042b93fd2
--- /dev/null
+++ b/extra/ftdi_hostcmd/test_cmds.c
@@ -0,0 +1,573 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mpsse.h"
+
+#include "ec_commands.h"
+
+/* Communication handle */
+static struct mpsse_context *mpsse;
+
+
+/* enum ec_status meaning */
+static const char *ec_strerr(enum ec_status r)
+{
+ static const char * const strs[] = {
+ "SUCCESS",
+ "INVALID_COMMAND",
+ "ERROR",
+ "INVALID_PARAM",
+ "ACCESS_DENIED",
+ "INVALID_RESPONSE",
+ "INVALID_VERSION",
+ "INVALID_CHECKSUM",
+ "IN_PROGRESS",
+ "UNAVAILABLE",
+ "TIMEOUT",
+ "OVERFLOW",
+ "INVALID_HEADER",
+ "REQUEST_TRUNCATED",
+ "RESPONSE_TOO_BIG",
+ "BUS_ERROR",
+ "BUSY",
+ };
+ if (r >= EC_RES_SUCCESS && r <= EC_RES_BUSY)
+ return strs[r];
+
+ return "<undefined result>";
+};
+
+
+/****************************************************************************
+ * TODO: Add an option to enable this stuff to help with debugging
+ */
+
+#define LINELEN 16
+
+#if 0
+static void showline(uint8_t *buf, int len)
+{
+ int i;
+ printf(" ");
+ for (i = 0; i < len; i++)
+ printf(" %02x", buf[i]);
+ for (i = len; i < LINELEN; i++)
+ printf(" ");
+ printf(" ");
+ for (i = 0; i < len; i++)
+ printf("%c",
+ (buf[i] >= ' ' && buf[i] <= '~') ? buf[i] : '.');
+ printf("\n");
+}
+#endif
+
+static void show(const char *fmt, uint8_t *buf, int len)
+{
+#if 0
+ int i, m, n;
+ printf(fmt, len);
+
+ m = len / LINELEN;
+ n = len % LINELEN;
+
+ for (i = 0; i < m; i++)
+ showline(buf + i * LINELEN, LINELEN);
+ if (n)
+ showline(buf + m * LINELEN, n);
+#endif
+}
+
+/****************************************************************************
+ * Send command & receive result
+ */
+
+/*
+ * With proto v3, the kernel driver asks the EC for the max param size
+ * (EC_CMD_GET_PROTOCOL_INFO) at probe time, because it can vary depending on
+ * the bus and/or the supported commands.
+ *
+ * FIXME: For now we'll just hard-code a size.
+ */
+static uint8_t txbuf[128];
+
+/*
+ * Load the output buffer with a proto v3 request (header, then data, with
+ * checksum correct in header).
+ */
+static size_t prepare_request(int cmd, int version,
+ const uint8_t *data, size_t data_len)
+{
+ struct ec_host_request *request;
+ size_t i, total_len;
+ uint8_t csum = 0;
+
+ total_len = sizeof(*request) + data_len;
+ if (total_len > sizeof(txbuf)) {
+ printf("Request too large (%zd > %zd)\n",
+ total_len, sizeof(txbuf));
+ return -1;
+ }
+
+ /* Header first */
+ request = (struct ec_host_request *)txbuf;
+ request->struct_version = EC_HOST_REQUEST_VERSION;
+ request->checksum = 0;
+ request->command = cmd;
+ request->command_version = version;
+ request->reserved = 0;
+ request->data_len = data_len;
+
+ /* Then data */
+ memcpy(txbuf + sizeof(*request), data, data_len);
+
+ /* Update checksum */
+ for (i = 0; i < total_len; i++)
+ csum += txbuf[i];
+ request->checksum = -csum;
+
+ return total_len;
+}
+
+/*
+ * Sends prepared proto v3 command using the SPI protocol
+ *
+ * Returns zero if command was sent, nonzero otherwise.
+ */
+static int send_request(uint8_t *txbuf, size_t len)
+{
+ uint8_t *tptr;
+ size_t i;
+ int ret = 0;
+
+ show("Transfer(%d) =>\n", txbuf, len);
+ tptr = Transfer(mpsse, txbuf, len);
+
+ if (!tptr) {
+ fprintf(stderr, "Transfer failed: %s\n",
+ ErrorString(mpsse));
+ return -1;
+ }
+
+ show("Transfer(%d) <=\n", tptr, len);
+
+ /* Make sure the EC was listening */
+ for (i = 0; i < len; i++) {
+ switch (tptr[i]) {
+ case EC_SPI_PAST_END:
+ case EC_SPI_RX_BAD_DATA:
+ case EC_SPI_NOT_READY:
+ ret = tptr[i];
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+ if (ret)
+ break;
+ }
+ free(tptr);
+ return ret;
+}
+
+
+/* Timeout flag, so we don't wait forever */
+static int timedout;
+static void alarm_handler(int sig)
+{
+ timedout = 1;
+}
+
+/*
+ * Read proto v3 response from SPI bus
+ *
+ * The response header and data are copied into the provided locations.
+ *
+ * Return value:
+ * 0 = response received (check hdr for EC result and body size)
+ * -1 = problems
+ */
+static int get_response(struct ec_host_response *hdr,
+ uint8_t *bodydest, size_t bodylen)
+{
+ uint8_t *hptr = 0, *bptr = 0;
+ uint8_t sum = 0;
+ int ret = -1;
+ size_t i;
+
+ /* Give up eventually */
+ timedout = 0;
+ if (SIG_ERR == signal(SIGALRM, alarm_handler)) {
+ perror("Problem with signal handler");
+ goto out;
+ }
+ alarm(3);
+
+ /* Read a byte at a time until we see the start of the frame.
+ * This is slow, but still faster than the EC. */
+ while (1) {
+ uint8_t *ptr = Read(mpsse, 1);
+ if (!ptr) {
+ fprintf(stderr, "Read failed: %s\n",
+ ErrorString(mpsse));
+ alarm(0);
+ goto out;
+ }
+ if (*ptr == EC_SPI_FRAME_START) {
+ free(ptr);
+ break;
+ }
+ free(ptr);
+
+ if (timedout) {
+ fprintf(stderr, "timed out\n");
+ goto out;
+ }
+ }
+ alarm(0);
+
+ /* Now read the response header */
+ hptr = Read(mpsse, sizeof(*hdr));
+ if (!hptr) {
+ fprintf(stderr, "Read failed: %s\n",
+ ErrorString(mpsse));
+ goto out;
+ }
+ show("Header(%d):\n", hptr, sizeof(*hdr));
+ memcpy(hdr, hptr, sizeof(*hdr));
+
+ /* Check the header */
+ if (hdr->struct_version != EC_HOST_RESPONSE_VERSION) {
+ printf("response version %d (should be %d)\n",
+ hdr->struct_version,
+ EC_HOST_RESPONSE_VERSION);
+ goto out;
+ }
+
+ if (hdr->data_len > bodylen) {
+ printf("response data_len %d is > %zd\n",
+ hdr->data_len,
+ bodylen);
+ goto out;
+ }
+
+ /* Read the data */
+ if (hdr->data_len) {
+ bptr = Read(mpsse, hdr->data_len);
+ if (!bptr) {
+ fprintf(stderr, "Read failed: %s\n",
+ ErrorString(mpsse));
+ goto out;
+ }
+ show("Body(%d):\n", bptr, hdr->data_len);
+ memcpy(bodydest, bptr, hdr->data_len);
+ }
+
+ /* Verify the checksum */
+ for (i = 0; i < sizeof(hdr); i++)
+ sum += hptr[i];
+ for (i = 0; i < hdr->data_len; i++)
+ sum += bptr[i];
+ if (sum)
+
+ printf("Checksum invalid\n");
+ else
+ ret = 0;
+
+out:
+ if (hptr)
+ free(hptr);
+ if (bptr)
+ free(bptr);
+ return ret;
+}
+
+
+/*
+ * Send command, wait for result. Return zero if communication succeeded; check
+ * response to see if the EC liked the command.
+ */
+static int send_cmd(int cmd, int version,
+ void *outbuf,
+ size_t outsize,
+ struct ec_host_response *resp,
+ void *inbuf,
+ size_t insize)
+{
+
+ size_t len;
+ int ret = -1;
+
+ /* Load up the txbuf with the stuff to send */
+ len = prepare_request(cmd, version, outbuf, outsize);
+ if (len < 0)
+ return -1;
+
+ if (MPSSE_OK != Start(mpsse)) {
+ fprintf(stderr, "Start failed: %s\n",
+ ErrorString(mpsse));
+ return -1;
+ }
+
+ if (0 == send_request(txbuf, len) &&
+ 0 == get_response(resp, inbuf, insize))
+ ret = 0;
+
+ if (MPSSE_OK != Stop(mpsse)) {
+ fprintf(stderr, "Stop failed: %s\n",
+ ErrorString(mpsse));
+ return -1;
+ }
+
+ return ret;
+}
+
+
+/****************************************************************************
+ * Probe for basic protocol info
+ */
+
+/**
+ * Try to talk to the attached(?) device.
+ *
+ * @return zero on success
+ */
+static int probe_v3(void)
+{
+ struct ec_host_response resp;
+ struct ec_response_get_protocol_info info;
+ int i, ret;
+
+ memset(&resp, 0, sizeof(resp));
+ memset(&info, 0, sizeof(info));
+
+ ret = send_cmd(EC_CMD_GET_PROTOCOL_INFO, 0,
+ 0, 0,
+ &resp,
+ &info, sizeof(info));
+
+ if (ret) {
+ printf("EC_CMD_GET_PROTOCOL_INFO failed\n");
+ return -1;
+ }
+
+ if (EC_RES_SUCCESS != resp.result) {
+ printf("EC result is %d: %s\n",
+ resp.result, ec_strerr(resp.result));
+ return -1;
+ }
+
+ printf("EC_CMD_GET_PROTOCOL_INFO Success!\n");
+ printf(" protocol_versions: ");
+ for (i = 0; i < 32; i++)
+ if (info.protocol_versions & (1 << i))
+ printf(" %d", i);
+ printf("\n");
+ printf(" max_request_packet_size: %d\n",
+ info.max_request_packet_size);
+ printf(" max_response_packet_size: %d\n",
+ info.max_response_packet_size);
+ printf(" flags: 0x%x\n",
+ info.flags);
+
+ return 0;
+}
+
+/****************************************************************************
+ * Pretty-print the host commands that the device admits to having
+ */
+
+struct lookup {
+ uint16_t cmd;
+ const char * const desc;
+};
+
+static struct lookup cmd_table[] = {
+ {0x00, "EC_CMD_PROTO_VERSION"},
+ {0x01, "EC_CMD_HELLO"},
+ {0x02, "EC_CMD_GET_VERSION"},
+ {0x03, "EC_CMD_READ_TEST"},
+ {0x04, "EC_CMD_GET_BUILD_INFO"},
+ {0x05, "EC_CMD_GET_CHIP_INFO"},
+ {0x06, "EC_CMD_GET_BOARD_VERSION"},
+ {0x07, "EC_CMD_READ_MEMMAP"},
+ {0x08, "EC_CMD_GET_CMD_VERSIONS"},
+ {0x09, "EC_CMD_GET_COMMS_STATUS"},
+ {0x0a, "EC_CMD_TEST_PROTOCOL"},
+ {0x0b, "EC_CMD_GET_PROTOCOL_INFO"},
+ {0x0c, "EC_CMD_GSV_PAUSE_IN_S5"},
+ {0x0d, "EC_CMD_GET_FEATURES"},
+ {0x10, "EC_CMD_FLASH_INFO"},
+ {0x11, "EC_CMD_FLASH_READ"},
+ {0x12, "EC_CMD_FLASH_WRITE"},
+ {0x13, "EC_CMD_FLASH_ERASE"},
+ {0x15, "EC_CMD_FLASH_PROTECT"},
+ {0x16, "EC_CMD_FLASH_REGION_INFO"},
+ {0x17, "EC_CMD_VBNV_CONTEXT"},
+ {0x20, "EC_CMD_PWM_GET_FAN_TARGET_RPM"},
+ {0x21, "EC_CMD_PWM_SET_FAN_TARGET_RPM"},
+ {0x22, "EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT"},
+ {0x23, "EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT"},
+ {0x24, "EC_CMD_PWM_SET_FAN_DUTY"},
+ {0x28, "EC_CMD_LIGHTBAR_CMD"},
+ {0x29, "EC_CMD_LED_CONTROL"},
+ {0x2a, "EC_CMD_VBOOT_HASH"},
+ {0x2b, "EC_CMD_MOTION_SENSE_CMD"},
+ {0x2c, "EC_CMD_FORCE_LID_OPEN"},
+ {0x30, "EC_CMD_USB_CHARGE_SET_MODE"},
+ {0x40, "EC_CMD_PSTORE_INFO"},
+ {0x41, "EC_CMD_PSTORE_READ"},
+ {0x42, "EC_CMD_PSTORE_WRITE"},
+ {0x44, "EC_CMD_RTC_GET_VALUE"},
+ {0x45, "EC_CMD_RTC_GET_ALARM"},
+ {0x46, "EC_CMD_RTC_SET_VALUE"},
+ {0x47, "EC_CMD_RTC_SET_ALARM"},
+ {0x48, "EC_CMD_PORT80_LAST_BOOT"},
+ {0x48, "EC_CMD_PORT80_READ"},
+ {0x50, "EC_CMD_THERMAL_SET_THRESHOLD"},
+ {0x51, "EC_CMD_THERMAL_GET_THRESHOLD"},
+ {0x52, "EC_CMD_THERMAL_AUTO_FAN_CTRL"},
+ {0x53, "EC_CMD_TMP006_GET_CALIBRATION"},
+ {0x54, "EC_CMD_TMP006_SET_CALIBRATION"},
+ {0x55, "EC_CMD_TMP006_GET_RAW"},
+ {0x60, "EC_CMD_MKBP_STATE"},
+ {0x61, "EC_CMD_MKBP_INFO"},
+ {0x62, "EC_CMD_MKBP_SIMULATE_KEY"},
+ {0x64, "EC_CMD_MKBP_SET_CONFIG"},
+ {0x65, "EC_CMD_MKBP_GET_CONFIG"},
+ {0x66, "EC_CMD_KEYSCAN_SEQ_CTRL"},
+ {0x67, "EC_CMD_GET_NEXT_EVENT"},
+ {0x70, "EC_CMD_TEMP_SENSOR_GET_INFO"},
+ {0x87, "EC_CMD_HOST_EVENT_GET_B"},
+ {0x88, "EC_CMD_HOST_EVENT_GET_SMI_MASK"},
+ {0x89, "EC_CMD_HOST_EVENT_GET_SCI_MASK"},
+ {0x8d, "EC_CMD_HOST_EVENT_GET_WAKE_MASK"},
+ {0x8a, "EC_CMD_HOST_EVENT_SET_SMI_MASK"},
+ {0x8b, "EC_CMD_HOST_EVENT_SET_SCI_MASK"},
+ {0x8c, "EC_CMD_HOST_EVENT_CLEAR"},
+ {0x8e, "EC_CMD_HOST_EVENT_SET_WAKE_MASK"},
+ {0x8f, "EC_CMD_HOST_EVENT_CLEAR_B"},
+ {0x90, "EC_CMD_SWITCH_ENABLE_BKLIGHT"},
+ {0x91, "EC_CMD_SWITCH_ENABLE_WIRELESS"},
+ {0x92, "EC_CMD_GPIO_SET"},
+ {0x93, "EC_CMD_GPIO_GET"},
+ {0x94, "EC_CMD_I2C_READ"},
+ {0x95, "EC_CMD_I2C_WRITE"},
+ {0x96, "EC_CMD_CHARGE_CONTROL"},
+ {0x97, "EC_CMD_CONSOLE_SNAPSHOT"},
+ {0x98, "EC_CMD_CONSOLE_READ"},
+ {0x99, "EC_CMD_BATTERY_CUT_OFF"},
+ {0x9a, "EC_CMD_USB_MUX"},
+ {0x9b, "EC_CMD_LDO_SET"},
+ {0x9c, "EC_CMD_LDO_GET"},
+ {0x9d, "EC_CMD_POWER_INFO"},
+ {0x9e, "EC_CMD_I2C_PASSTHRU"},
+ {0x9f, "EC_CMD_HANG_DETECT"},
+ {0xa0, "EC_CMD_CHARGE_STATE"},
+ {0xa1, "EC_CMD_CHARGE_CURRENT_LIMIT"},
+ {0xa2, "EC_CMD_EXT_POWER_CURRENT_LIMIT"},
+ {0xb0, "EC_CMD_SB_READ_WORD"},
+ {0xb1, "EC_CMD_SB_WRITE_WORD"},
+ {0xb2, "EC_CMD_SB_READ_BLOCK"},
+ {0xb3, "EC_CMD_SB_WRITE_BLOCK"},
+ {0xb4, "EC_CMD_BATTERY_VENDOR_PARAM"},
+ {0xb5, "EC_CMD_SB_FW_UPDATE"},
+ {0xb6, "EC_CMD_ENTERING_MODE"},
+ {0xd2, "EC_CMD_REBOOT_EC"},
+ {0xd3, "EC_CMD_GET_PANIC_INFO"},
+ {0xd1, "EC_CMD_REBOOT"},
+ {0xdb, "EC_CMD_RESEND_RESPONSE"},
+ {0xdc, "EC_CMD_VERSION0"},
+ {0x100, "EC_CMD_PD_EXCHANGE_STATUS"},
+ {0x104, "EC_CMD_PD_HOST_EVENT_STATUS"},
+ {0x101, "EC_CMD_USB_PD_CONTROL"},
+ {0x102, "EC_CMD_USB_PD_PORTS"},
+ {0x103, "EC_CMD_USB_PD_POWER_INFO"},
+ {0x110, "EC_CMD_USB_PD_FW_UPDATE"},
+ {0x111, "EC_CMD_USB_PD_RW_HASH_ENTRY"},
+ {0x112, "EC_CMD_USB_PD_DEV_INFO"},
+ {0x113, "EC_CMD_USB_PD_DISCOVERY"},
+ {0x114, "EC_CMD_PD_CHARGE_PORT_OVERRIDE"},
+ {0x115, "EC_CMD_PD_GET_LOG_ENTRY"},
+ {0x116, "EC_CMD_USB_PD_GET_AMODE"},
+ {0x117, "EC_CMD_USB_PD_SET_AMODE"},
+ {0x118, "EC_CMD_PD_WRITE_LOG_ENTRY"},
+ {0x200, "EC_CMD_BLOB"},
+};
+
+#define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0]))
+
+static void show_command(uint16_t c)
+{
+ unsigned int i;
+ const char *desc = "<unknown>";
+
+ for (i = 0; i < ARRAY_SIZE(cmd_table); i++)
+ if (cmd_table[i].cmd == c) {
+ desc = cmd_table[i].desc;
+ break;
+ }
+
+ printf(" %02x %s\n", c, desc);
+}
+
+static void scan_commands(void)
+{
+ struct ec_params_get_cmd_versions_v1 q_vers;
+ struct ec_response_get_cmd_versions r_vers;
+ struct ec_host_response ec_resp;
+ uint16_t i;
+
+ memset(&ec_resp, 0, sizeof(ec_resp));
+
+ printf("Supported host commands:\n");
+ for (i = 0; i < 0x201; i++) {
+ q_vers.cmd = i;
+ if (0 != send_cmd(EC_CMD_GET_CMD_VERSIONS, 1,
+ &q_vers, sizeof(q_vers),
+ &ec_resp,
+ &r_vers, sizeof(r_vers))) {
+ printf("query failed on cmd %d - aborting\n", i);
+ return;
+ }
+
+ if (ec_resp.result == EC_RES_SUCCESS)
+ show_command(i);
+ else if (ec_resp.result != EC_RES_INVALID_PARAM)
+ printf("lookup of cmd 0x%02x returned %d %s\n", i,
+ ec_resp.result,
+ ec_strerr(ec_resp.result));
+ }
+}
+
+/****************************************************************************/
+
+int main(int argc, char *argv[])
+{
+ int retval = 1;
+
+ /* Find something to talk to */
+ mpsse = MPSSE(SPI0, 2000000, 0);
+ if (!mpsse) {
+ printf("Can't find a device to open\n");
+ return 1;
+ }
+
+ if (0 != probe_v3())
+ goto out;
+
+ scan_commands();
+
+ retval = 0;
+out:
+ Close(mpsse);
+ mpsse = 0;
+ return retval;
+}