summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-11-12 22:38:34 -0700
committerCommit Bot <commit-bot@chromium.org>2020-11-20 18:43:53 +0000
commitc98936e40a87add7fe5a543e3851958b204149e1 (patch)
treef9b93cefc31f3e251dcdfc8c5c0957c808e25326
parent6d1599b4a05de382b20f13e4677b534672678747 (diff)
downloadchrome-ec-c98936e40a87add7fe5a543e3851958b204149e1.tar.gz
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>
-rw-r--r--common/usbc/usb_pd_host.c5
-rw-r--r--common/usbc/usb_pe_drp_sm.c53
-rw-r--r--include/usb_pd.h14
-rw-r--r--test/usb_pe.h1
-rw-r--r--test/usb_pe_drp_old.c9
5 files changed, 67 insertions, 15 deletions
diff --git a/common/usbc/usb_pd_host.c b/common/usbc/usb_pd_host.c
index 7fa49874dc..c72e16afe9 100644
--- a/common/usbc/usb_pd_host.c
+++ b/common/usbc/usb_pd_host.c
@@ -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;
}
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index c893f225db..86563efc59 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -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
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 640cbba7ed..6a8e084ff3 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -2759,6 +2759,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.
*
diff --git a/test/usb_pe.h b/test/usb_pe.h
index fb5ac10f88..8c1177f1f3 100644
--- a/test/usb_pe.h
+++ b/test/usb_pe.h
@@ -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 */
diff --git a/test/usb_pe_drp_old.c b/test/usb_pe_drp_old.c
index c9815b4726..c6e55f47ca 100644
--- a/test/usb_pe_drp_old.c
+++ b/test/usb_pe_drp_old.c
@@ -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);