samus: Add host command to query USB type-C accessory attached.

PD accessories that are RW update-able will broadcast their rw_hash
SHA1 digest upon connection to the PD MCU which will store it.

For update purposes, the host needs that accessories device id and
rw_hash to determine its proper firmware update payload.

This CL creates a host command that requests the type-C accessory info
attached to a particular port.  It also implements an ectool command
to expose the host command.

BRANCH=none
BUG=chrome-os-partner:31361
TEST=manual,
  # connect zinger to port 1 on samus
  ectool --dev=1 --interface=lpc infopddev 1
  Port:0 Device:1 Hash:  0x7f4d7a13 0xf07b65b9 0x41181e10 0xb99b3d5f 0x9dee1206

  ectool --dev=1 --interface=lpc infopddev 0
  Port:0 has no valid device

Also do the same on port 0 with similar results.

Change-Id: Id63c7edad77a43d43c14d8cd6bd96e08d0d9b501
Signed-off-by: Todd Broch <tbroch@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/216814
Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
Todd Broch
2014-09-05 15:03:02 -07:00
committed by chrome-internal-fetch
parent 5bb0fd6b05
commit 7698c323ea
6 changed files with 115 additions and 24 deletions

View File

@@ -139,6 +139,7 @@ int pd_board_checks(void)
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
{
int cmd = PD_VDO_CMD(payload[0]);
uint8_t dev_id = 0;
ccprintf("VDM/%d [%d] %08x\n", cnt, cmd, payload[0]);
/* make sure we have some payload */
@@ -152,16 +153,17 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
ccprintf("version: %s\n", (char *)(payload+1));
break;
case VDO_CMD_READ_INFO:
/* copy hash */
if (cnt >= 6)
pd_dev_store_rw_hash(port, payload + 1);
/* if last word is present, it contains lots of info */
if (cnt == 7)
ccprintf("Dev:%d SW:%d RW:%d\n",
VDO_INFO_HW_DEV_ID(payload[6]),
if (cnt == 7) {
dev_id = VDO_INFO_HW_DEV_ID(payload[6]);
ccprintf("Dev:%d SW:%d RW:%d\n", dev_id,
VDO_INFO_SW_DBG_VER(payload[6]),
VDO_INFO_IS_RW(payload[6]));
}
/* copy hash */
if (cnt >= 6)
pd_dev_store_rw_hash(port, dev_id, payload + 1);
break;
}

View File

@@ -154,6 +154,7 @@ int pd_board_checks(void)
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
{
int cmd = PD_VDO_CMD(payload[0]);
uint8_t dev_id = 0;
ccprintf("VDM/%d [%d] %08x\n", cnt, cmd, payload[0]);
/* make sure we have some payload */
@@ -167,16 +168,17 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
ccprintf("version: %s\n", (char *)(payload+1));
break;
case VDO_CMD_READ_INFO:
/* copy hash */
if (cnt >= 6)
pd_dev_store_rw_hash(port, payload + 1);
/* if last word is present, it contains lots of info */
if (cnt == 7)
ccprintf("Dev:%d SW:%d RW:%d\n",
VDO_INFO_HW_DEV_ID(payload[6]),
if (cnt == 7) {
dev_id = VDO_INFO_HW_DEV_ID(payload[6]);
ccprintf("Dev:%d SW:%d RW:%d\n", dev_id,
VDO_INFO_SW_DBG_VER(payload[6]),
VDO_INFO_IS_RW(payload[6]));
}
/* copy hash */
if (cnt >= 6)
pd_dev_store_rw_hash(port, dev_id, payload + 1);
break;
case VDO_CMD_CURRENT:
ccprintf("Current: %dmA\n", payload[1]);

View File

@@ -253,7 +253,8 @@ static struct pd_protocol {
uint32_t vdo_data[VDO_MAX_SIZE];
uint8_t vdo_count;
/* Attached ChromeOS device RW hash */
/* Attached ChromeOS device id & RW hash */
uint8_t dev_id;
uint32_t dev_rw_hash[SHA1_DIGEST_SIZE/4];
} pd[PD_PORT_COUNT];
@@ -290,9 +291,11 @@ static inline void set_state(int port, enum pd_states next_state)
pd[port].task_state = next_state;
#ifdef CONFIG_USBC_SS_MUX
if (next_state == PD_STATE_SRC_DISCONNECTED)
if (next_state == PD_STATE_SRC_DISCONNECTED) {
pd[port].dev_id = 0;
board_set_usb_mux(port, TYPEC_MUX_NONE,
pd[port].polarity);
}
#endif
/* Log state transition, except for toggling between sink and source */
@@ -1083,9 +1086,21 @@ static void pd_vdm_send_state_machine(int port)
}
}
void pd_dev_store_rw_hash(int port, uint32_t *rw_hash)
static inline void pd_dev_dump_info(uint8_t dev_id, uint32_t *hash)
{
int j;
ccprintf("Device:%d Hash:", dev_id);
for (j = 0; j < SHA1_DIGEST_SIZE/4; j++)
ccprintf(" 0x%08x", hash[j]);
ccprintf("\n");
}
void pd_dev_store_rw_hash(int port, uint8_t dev_id, uint32_t *rw_hash)
{
pd[port].dev_id = dev_id;
memcpy(pd[port].dev_rw_hash, rw_hash, SHA1_DIGEST_SIZE);
if (debug_level >= 1)
pd_dev_dump_info(dev_id, rw_hash);
}
#ifdef CONFIG_USB_PD_DUAL_ROLE
@@ -1700,14 +1715,11 @@ static int command_pd(int argc, char **argv)
ccprintf("Ports %s\n", enable ? "enabled" : "disabled");
return EC_SUCCESS;
} else if (!strncasecmp(argv[1], "rwhashtable", 3)) {
int i, j;
int i;
struct ec_params_usb_pd_rw_hash_entry *p;
for (i = 0; i < RW_HASH_ENTRIES; i++) {
p = &rw_hash_table[i];
ccprintf("Device:%d Hash:", p->dev_id);
for (j = 0; j < SHA1_DIGEST_SIZE/4; j++)
ccprintf(" 0x%08x", p->dev_rw_hash.w[j]);
ccprintf("\n");
pd_dev_dump_info(p->dev_id, p->dev_rw_hash.w);
}
return EC_SUCCESS;
}
@@ -2028,4 +2040,31 @@ DECLARE_HOST_COMMAND(EC_CMD_USB_PD_RW_HASH_ENTRY,
hc_remote_rw_hash_entry,
EC_VER_MASK(0));
static int hc_remote_pd_dev_info(struct host_cmd_handler_args *args)
{
const uint8_t *port = args->params;
struct ec_params_usb_pd_rw_hash_entry *r = args->response;
if (*port >= PD_PORT_COUNT) {
ccprintf("PD DEV_INFO - Port:%d >= %d (max ports)\n",
*port, PD_PORT_COUNT);
return EC_RES_INVALID_PARAM;
}
r->dev_id = pd[*port].dev_id;
ccprintf("PD DEV_INFO - requested Port:%d has Device:%d\n",
*port, r->dev_id);
if (r->dev_id) {
memcpy(r->dev_rw_hash.b, pd[*port].dev_rw_hash,
SHA1_DIGEST_SIZE);
}
args->response_size = sizeof(*r);
return EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_USB_PD_DEV_INFO,
hc_remote_pd_dev_info,
EC_VER_MASK(0));
#endif /* CONFIG_COMMON_RUNTIME */

View File

@@ -2637,6 +2637,13 @@ struct ec_params_usb_pd_rw_hash_entry {
uint32_t w[DIV_ROUND_UP(SHA1_DIGEST_SIZE, sizeof(uint32_t))];
} dev_rw_hash;
} __packed;
/* Read USB-PD Accessory info */
#define EC_CMD_USB_PD_DEV_INFO 0x112
struct ec_params_usb_pd_info_request {
uint8_t port;
} __packed;
/*****************************************************************************/
/*
* Passthru commands

View File

@@ -307,12 +307,13 @@ int pd_board_checks(void);
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
/**
* Store RW hash of device
* Store Device ID & RW hash of device
*
* @param port USB-C port number
* @param dev_id device identifier
* @param rw_hash pointer to sha1 rw_hash
*/
void pd_dev_store_rw_hash(int port, uint32_t *rw_hash);
void pd_dev_store_rw_hash(int port, uint8_t dev_id, uint32_t *rw_hash);
/**
* Send Vendor Defined Message

View File

@@ -118,6 +118,8 @@ const char help_str[] =
" Write I2C bus\n"
" i2cxfer <port> <slave_addr> <read_count> [write bytes...]\n"
" Perform I2C transfer on EC's I2C bus\n"
" infopddev <port>\n"
" Get info about USB type-C accessory attached to port\n"
" keyscan <beat_us> <filename>\n"
" Test low-level key scanning\n"
" led <name> <query | auto | off | <color> | <color>=<value>...>\n"
@@ -812,6 +814,43 @@ int cmd_rw_hash_pd(int argc, char *argv[])
}
int cmd_pd_device_info(int argc, char *argv[])
{
int i, rv;
char *e;
struct ec_params_usb_pd_info_request *p =
(struct ec_params_usb_pd_info_request *)ec_outbuf;
struct ec_params_usb_pd_rw_hash_entry *r =
(struct ec_params_usb_pd_rw_hash_entry *)ec_inbuf;
if (argc < 2) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
return -1;
}
p->port = strtol(argv[1], &e, 0);
if (e && *e) {
fprintf(stderr, "Bad port\n");
return -1;
}
rv = ec_command(EC_CMD_USB_PD_DEV_INFO, 0, p, sizeof(*p),
ec_inbuf, ec_max_insize);
if (rv < 0)
return rv;
if (!r->dev_id)
printf("Port:%d has no valid device\n", p->port);
else {
printf("Port:%d Device:%d Hash: ", p->port, r->dev_id);
for (i = 0; i < 5; i++)
printf(" 0x%08x", r->dev_rw_hash.w[i]);
printf("\n");
}
return rv;
}
/* PD image size is 16k minus 32 bits for the RW hash */
#define PD_RW_IMAGE_SIZE (16 * 1024 - 32)
static struct sha1_ctx ctx;
@@ -4742,6 +4781,7 @@ const struct command commands[] = {
{"i2cread", cmd_i2c_read},
{"i2cwrite", cmd_i2c_write},
{"i2cxfer", cmd_i2c_xfer},
{"infopddev", cmd_pd_device_info},
{"led", cmd_led},
{"lightbar", cmd_lightbar},
{"keyconfig", cmd_keyconfig},