TCPMv2: Store and report sink caps

Copy sink caps for later reference, and report them up to the AP in the
TYPEC_STATUS host command return.  This also moves the location of the
DPM set for sink caps, to be symmetrical between source and sink inits.

Set the old unit tests to clear all DPM requests.  New PE tests will
correctly handle our startup sequence, but the old tests may have
erratic behavior based on how many states run before the connection is
forced over to READY.

BRANCH=None
BUG=b:160009733,b:168862110
TEST=on drawcia, verify sink capabilities match those from PD traces
with several docks and dongles

Signed-off-by: Diana Z <dzigterman@chromium.org>
Change-Id: Iadc6ef4c7364d7c709878a75fd5e707a965f77f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2540390
Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
This commit is contained in:
Diana Z 2020-11-12 22:38:34 -07:00 committed by Commit Bot
parent 6d1599b4a0
commit c98936e40a
5 changed files with 67 additions and 15 deletions

View File

@ -165,8 +165,9 @@ static enum ec_status hc_typec_status(struct host_cmd_handler_args *args)
memcpy(r->source_cap_pdos, pd_get_src_caps(p->port),
r->source_cap_count * sizeof(uint32_t));
/* TODO(b/160009733): Populate sink cap PDOs */
r->sink_cap_count = 0;
r->sink_cap_count = pd_get_snk_cap_cnt(p->port);
memcpy(r->sink_cap_pdos, pd_get_snk_caps(p->port),
r->sink_cap_count * sizeof(uint32_t));
return EC_RES_SUCCESS;
}

View File

@ -749,6 +749,10 @@ static struct policy_engine {
uint32_t src_caps[PDO_MAX_OBJECTS];
int src_cap_cnt;
/* Last received sink cap */
uint32_t snk_caps[PDO_MAX_OBJECTS];
int snk_cap_cnt;
/* Attached ChromeOS device id, RW hash, and current RO / RW image */
uint16_t dev_id;
uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4];
@ -1028,6 +1032,23 @@ uint32_t pd_get_events(int port)
return pe[port].events;
}
void pe_set_snk_caps(int port, int cnt, uint32_t *snk_caps)
{
pe[port].snk_cap_cnt = cnt;
memcpy(pe[port].snk_caps, snk_caps, sizeof(uint32_t) * cnt);
}
const uint32_t * const pd_get_snk_caps(int port)
{
return pe[port].snk_caps;
}
uint8_t pd_get_snk_cap_cnt(int port)
{
return pe[port].snk_cap_cnt;
}
/*
* Determine if this port may communicate with the cable plug.
*
@ -1249,9 +1270,10 @@ static void pe_handle_detach(void)
pe_invalidate_explicit_contract(port);
/*
* Saved SRC_Capabilities are no longer valid on disconnect
* Saved Source and Sink Capabilities are no longer valid on disconnect
*/
pd_set_src_caps(port, 0, NULL);
pe_set_snk_caps(port, 0, NULL);
}
DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, pe_handle_detach, HOOK_PRIO_DEFAULT);
@ -2681,6 +2703,12 @@ static void pe_snk_startup_entry(int port)
*/
PE_SET_FLAG(port, PE_FLAGS_DR_SWAP_TO_DFP);
PE_SET_FLAG(port, PE_FLAGS_VCONN_SWAP_TO_ON);
/*
* Set up to get Device Policy Manager to
* request Sink Capabilities
*/
pd_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS);
}
}
@ -2873,11 +2901,6 @@ static void pe_snk_select_capability_run(int port)
set_state_pe(port, PE_SNK_TRANSITION_SINK);
/*
* Setup to get Device Policy Manager to
* request Sink Capabilities for possible FRS
*/
pd_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS);
return;
}
/*
@ -6121,8 +6144,12 @@ static void pe_dr_get_sink_cap_run(int port)
if (ext == 0 && sop == TCPC_TX_SOP) {
if ((cnt > 0) && (type == PD_DATA_SINK_CAP)) {
uint32_t payload =
*(uint32_t *)rx_emsg[port].buf;
uint32_t *payload =
(uint32_t *)rx_emsg[port].buf;
uint8_t cap_cnt = rx_emsg[port].len /
sizeof(uint32_t);
pe_set_snk_caps(port, cap_cnt, payload);
/*
* Check message to see if we can handle
@ -6136,8 +6163,8 @@ static void pe_dr_get_sink_cap_run(int port)
*/
if (IS_ENABLED(CONFIG_USB_PD_REV30) &&
(rev > PD_REV20) &&
(payload & PDO_FIXED_DUAL_ROLE)) {
switch (payload &
(payload[0] & PDO_FIXED_DUAL_ROLE)) {
switch (payload[0] &
PDO_FIXED_FRS_CURR_MASK) {
case PDO_FIXED_FRS_CURR_NOT_SUPPORTED:
break;
@ -6300,7 +6327,6 @@ uint8_t pd_get_src_cap_cnt(int port)
return pe[port].src_cap_cnt;
}
/* Track access to the PD discovery structures during HC execution */
uint32_t task_access[CONFIG_USB_PD_PORT_MAX_COUNT][DISCOVERY_TYPE_COUNT];
@ -6711,6 +6737,7 @@ static const struct usb_state pe_states[] = {
};
#ifdef TEST_BUILD
/* TODO(b/173791979): Unit tests shouldn't need to access internal states */
const struct test_sm_data test_pe_sm_data[] = {
{
.base = pe_states,
@ -6742,4 +6769,8 @@ void pe_set_all_flags(int port, int flags)
{
pe[port].flags = flags;
}
void pe_clr_dpm_requests(int port)
{
pe[port].dpm_request = 0;
}
#endif

View File

@ -2758,6 +2758,20 @@ uint8_t pd_get_src_cap_cnt(int port);
*/
void pd_set_src_caps(int port, int cnt, uint32_t *src_caps);
/**
* Returns the sink caps list
*
* @param port USB-C port number
*/
const uint32_t * const pd_get_snk_caps(int port);
/**
* Returns the number of sink caps
*
* @param port USB-C port number
*/
uint8_t pd_get_snk_cap_cnt(int port);
/**
* Return true if partner port is capable of communication over USB data
* lines.

View File

@ -152,5 +152,6 @@ void pe_clr_flag(int port, int flag);
int pe_chk_flag(int port, int flag);
int pe_get_all_flags(int port);
void pe_set_all_flags(int port, int flags);
void pe_clr_dpm_requests(int port);
#endif /* __CROS_TEST_USB_PE_H */

View File

@ -79,6 +79,8 @@ test_static void setup_source(void)
task_wait_event(10 * MSEC);
pe_set_flag(PORT0, PE_FLAGS_VDM_SETUP_DONE);
pe_set_flag(PORT0, PE_FLAGS_EXPLICIT_CONTRACT);
/* As long as we're hacking our way to ready, clear any DPM requests */
pe_clr_dpm_requests(PORT0);
set_state_pe(PORT0, PE_SRC_READY);
task_wait_event(10 * MSEC);
/* At this point, the PE should be running in PE_SRC_Ready. */
@ -93,6 +95,8 @@ test_static void setup_sink(void)
task_wait_event(10 * MSEC);
pe_set_flag(PORT0, PE_FLAGS_VDM_SETUP_DONE);
pe_set_flag(PORT0, PE_FLAGS_EXPLICIT_CONTRACT);
/* As long as we're hacking our way to ready, clear any DPM requests */
pe_clr_dpm_requests(PORT0);
set_state_pe(PORT0, PE_SNK_READY);
task_wait_event(10 * MSEC);
/* At this point, the PE should be running in PE_SNK_Ready. */
@ -104,8 +108,8 @@ test_static void setup_sink(void)
static int test_pe_frs(void)
{
/*
* TODO: This test should validate PE boundary API differences -- not
* internal state changes.
* TODO(b/173791979): This test should validate PE boundary API
* differences -- not internal state changes.
*/
task_wait_event(10 * MSEC);
@ -119,6 +123,7 @@ static int test_pe_frs(void)
tc_prs_src_snk_assert_rd(PORT0);
pe_set_flag(PORT0, PE_FLAGS_VDM_SETUP_DONE);
pe_set_flag(PORT0, PE_FLAGS_EXPLICIT_CONTRACT);
pe_clr_dpm_requests(PORT0);
set_state_pe(PORT0, PE_SNK_READY);
task_wait_event(10 * MSEC);
TEST_ASSERT(get_state_pe(PORT0) == PE_SNK_READY);