From 22858a07a5076cb0c97d22c32071d2ff540934f6 Mon Sep 17 00:00:00 2001 From: Sam Hurst Date: Tue, 29 Nov 2016 13:58:51 -0800 Subject: [PATCH] usb pd: Resend request after receiving a WAIT in response to a request When a WAIT is received in response to a request, wait SinkRequestTime before resending the request. BUG=chrome-os-partner:34984 TEST=make -j buildall BRANCH=none Change-Id: I5c8429c4a7b9cf06609996f924b8d9d535ab6b5f Reviewed-on: https://chromium-review.googlesource.com/414533 Commit-Ready: Sam Hurst Tested-by: Sam Hurst Reviewed-by: Vincent Palatin --- board/host/usb_pd_policy.c | 1 + chip/host/usb_pd_phy.c | 33 ++- common/usb_pd_protocol.c | 50 ++++- include/usb_pd.h | 1 + test/usb_pd.c | 401 +++++++++++++++++++++++++++++++++---- 5 files changed, 445 insertions(+), 41 deletions(-) diff --git a/board/host/usb_pd_policy.c b/board/host/usb_pd_policy.c index cbfab71993..cffa22530d 100644 --- a/board/host/usb_pd_policy.c +++ b/board/host/usb_pd_policy.c @@ -15,6 +15,7 @@ const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 900, PDO_FIXED_FLAGS), + PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); diff --git a/chip/host/usb_pd_phy.c b/chip/host/usb_pd_phy.c index 1a8e74b97e..96d7f06ea8 100644 --- a/chip/host/usb_pd_phy.c +++ b/chip/host/usb_pd_phy.c @@ -42,9 +42,30 @@ static const uint16_t enc4b5b[] = { 0x17, 0x1A, 0x1B, 0x1C, 0x1D}; /* Test utilities */ +static void pd_test_reset_phy(int port) +{ + int i; + int enc_len = PD_BIT_LEN / 5; + + for (i = 0; i < PD_BIT_LEN; i++) + pd_phy[port].bits[i] = 0; + + for (i = 0; i < enc_len; i++) + pd_phy[port].out_msg[i] = 0; + + pd_phy[port].total = 0; + pd_phy[port].has_preamble = 0; + pd_phy[port].rx_started = 0; + pd_phy[port].rx_monitoring = 0; + pd_phy[port].preamble_written = 0; + pd_phy[port].has_msg = 0; + pd_phy[port].last_edge_written = 0; + pd_phy[port].verified_idx = 0; +} void pd_test_rx_set_preamble(int port, int has_preamble) { + pd_phy[port].total = 0; pd_phy[port].has_preamble = has_preamble; } @@ -105,7 +126,8 @@ void pd_simulate_rx(int port) { if (!pd_phy[port].rx_monitoring) return; - pd_rx_start(port); + + pd_phy[port].rx_started = 1; pd_rx_disable_monitoring(port); pd_rx_event(port); } @@ -241,6 +263,7 @@ int pd_start_tx(int port, int polarity, int bit_len) pd_phy[port].has_msg = 0; pd_phy[port].preamble_written = 0; pd_phy[port].verified_idx = 0; + pd_phy[port].total = 0; /* * Hand over to test runner. The test runner must wake us after @@ -254,19 +277,23 @@ int pd_start_tx(int port, int polarity, int bit_len) void pd_tx_done(int port, int polarity) { - /* Nothing to do */ + pd_test_reset_phy(port); } void pd_rx_start(int port) { ASSERT(pd_phy[port].hw_init_done); + + task_wake(TASK_ID_TEST_RUNNER); + task_wait_event(-1); + pd_phy[port].rx_started = 1; } void pd_rx_complete(int port) { ASSERT(pd_phy[port].hw_init_done); - pd_phy[port].rx_started = 0; + pd_test_reset_phy(port); } int pd_rx_started(int port) diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index d0773724e2..4370835fe1 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -958,9 +958,53 @@ static void handle_ctrl_request(int port, uint16_t head, set_state(port, PD_STATE_SRC_READY); else if (pd[port].task_state == PD_STATE_SNK_SWAP_INIT) set_state(port, PD_STATE_SNK_READY); - else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) - /* no explicit contract */ - set_state(port, PD_STATE_SNK_READY); + else if (pd[port].task_state == PD_STATE_SNK_REQUESTED) { + /* + * Explicit Contract in place + * + * On reception of a WAIT message, transition to + * PD_STATE_SNK_READY after PD_T_SINK_REQUEST ms to + * send another reqest. + * + * On reception of a REJECT messag, transition to + * PD_STATE_SNK_READY but don't resend the request. + * + * NO Explicit Contract in place + * + * On reception of a WAIT or REJECT message, + * transition to PD_STATE_SNK_DISCOVERY + */ + if (pd[port].flags & PD_FLAGS_EXPLICIT_CONTRACT) { + /* We have an explicit contract */ + if (type == PD_CTRL_WAIT) { + /* + * Trigger a new power request when + * we enter PD_STATE_SNK_READY + */ + pd[port].new_power_request = 1; + + /* + * After the request is triggered, + * make sure the request is sent. + */ + pd[port].prev_request_mv = 0; + + /* + * Transition to PD_STATE_SNK_READY + * after PD_T_SINK_REQUEST ms. + */ + set_state_timeout(port, get_time().val + + PD_T_SINK_REQUEST, + PD_STATE_SNK_READY); + } else { + /* The request was rejected */ + set_state(port, PD_STATE_SNK_READY); + } + } else { + /* No explicit contract */ + set_state(port, PD_STATE_SNK_DISCOVERY); + } + } #endif break; case PD_CTRL_ACCEPT: diff --git a/include/usb_pd.h b/include/usb_pd.h index b2cba7542b..10b148af68 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -160,6 +160,7 @@ enum pd_rx_errors { #define PD_T_VCONN_SOURCE_ON (100*MSEC) /* 100ms */ #define PD_T_TRY_SRC (125*MSEC) /* Max time for Try.SRC state */ #define PD_T_TRY_WAIT (600*MSEC) /* Max time for TryWait.SNK state */ +#define PD_T_SINK_REQUEST (100*MSEC) /* Wait 100ms before next request */ /* number of edges and time window to detect CC line is not idle */ #define PD_RX_TRANSITION_COUNT 3 diff --git a/test/usb_pd.c b/test/usb_pd.c index ea68c66599..233714e3ad 100644 --- a/test/usb_pd.c +++ b/test/usb_pd.c @@ -14,6 +14,9 @@ #include "usb_pd_test_util.h" #include "util.h" +#define PORT0 0 +#define PORT1 1 + struct pd_port_t { int host_mode; int has_vbus; @@ -113,12 +116,42 @@ static void simulate_rx_msg(int port, uint16_t header, int cnt, pd_simulate_rx(port); } -static void simulate_source_cap(int port) +static void simulate_wait(int port) { + uint16_t header = PD_HEADER(PD_CTRL_WAIT, PD_ROLE_SOURCE, + PD_ROLE_DFP, pd_port[port].msg_rx_id, + 0); + + simulate_rx_msg(port, header, 0, NULL); +} + +static void simulate_accept(int port) +{ + uint16_t header = PD_HEADER(PD_CTRL_ACCEPT, PD_ROLE_SOURCE, + PD_ROLE_DFP, pd_port[port].msg_rx_id, + 0); + + simulate_rx_msg(port, header, 0, NULL); +} + +static void simulate_reject(int port) +{ + uint16_t header = PD_HEADER(PD_CTRL_REJECT, PD_ROLE_SOURCE, + PD_ROLE_DFP, pd_port[port].msg_rx_id, + 0); + + simulate_rx_msg(port, header, 0, NULL); +} + +static void simulate_source_cap(int port, uint32_t cnt) +{ + uint32_t src_pdo_cnt = (cnt == 0) ? 1 : pd_src_pdo_cnt; + uint16_t header = PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE, PD_ROLE_DFP, pd_port[port].msg_rx_id, - pd_src_pdo_cnt); - simulate_rx_msg(port, header, pd_src_pdo_cnt, pd_src_pdo); + src_pdo_cnt); + + simulate_rx_msg(port, header, src_pdo_cnt, pd_src_pdo); } static void simulate_goodcrc(int port, int role, int id) @@ -129,11 +162,11 @@ static void simulate_goodcrc(int port, int role, int id) static int verify_goodcrc(int port, int role, int id) { - return pd_test_tx_msg_verify_sop(0) && - pd_test_tx_msg_verify_short(0, PD_HEADER(PD_CTRL_GOOD_CRC, + return pd_test_tx_msg_verify_sop(port) && + pd_test_tx_msg_verify_short(port, PD_HEADER(PD_CTRL_GOOD_CRC, role, role, id, 0)) && - pd_test_tx_msg_verify_crc(0) && - pd_test_tx_msg_verify_eop(0); + pd_test_tx_msg_verify_crc(port) && + pd_test_tx_msg_verify_eop(port); } static void plug_in_source(int port, int polarity) @@ -152,74 +185,369 @@ static void plug_in_sink(int port, int polarity) static void unplug(int port) { + pd_port[port].msg_tx_id = 0; + pd_port[port].msg_rx_id = 0; pd_port[port].has_vbus = 0; pd_port[port].partner_role = -1; task_wake(PD_PORT_TO_TASK_ID(port)); usleep(30 * MSEC); } +static int test_request_with_wait_and_contract(void) +{ + uint32_t expected_rdo = RDO_FIXED(2, 3000, 3000, 0); + uint8_t port = PORT0; + + plug_in_source(port, 0); + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(2 * PD_T_CC_DEBOUNCE + 100 * MSEC); + TEST_ASSERT(pd_port[port].polarity == 0); + + /* We're in SNK_DISCOVERY now. Let's send the source cap. */ + simulate_source_cap(port, 1); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(port, PD_ROLE_SINK, + pd_port[port].msg_rx_id)); + + /* Wait for the power request */ + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */ + inc_rx_id(port); + + /* Process the request */ + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, + PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP, + pd_port[port].msg_tx_id, 1))); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo)); + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + + /* Request was good. Send GoodCRC */ + simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id); + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + inc_tx_id(port); + + /* We're in SNK_REQUESTED. Send accept */ + simulate_accept(port); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + inc_rx_id(port); + + /* + * We're in SNK_TRANSITION. + * And we have an explicit power contract. + */ + simulate_source_cap(port, 1); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(port, PD_ROLE_SINK, + pd_port[port].msg_rx_id)); + + /* Wait for the power request */ + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */ + inc_rx_id(port); + + /* Process the request */ + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, + PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP, + pd_port[port].msg_tx_id, 1))); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo)); + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + + /* Request was good. Send GoodCRC */ + simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id); + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + inc_tx_id(port); + + /* We're in SNK_REQUESTED. Send wait */ + simulate_wait(port); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + /* PD_T_SINK_REQUEST. Request is sent again after 100 ms */ + task_wait_event(100 * MSEC); + inc_rx_id(port); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + + /* We had an explicit contract. So request should have been resent. */ + /* Process the request */ + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, + PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP, + pd_port[port].msg_tx_id, 1))); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo)); + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + + /* Request was good. Send GoodCRC */ + simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id); + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + inc_tx_id(port); + + /* We're in SNK_REQUESTED. Send accept */ + simulate_accept(port); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + /* We're done */ + unplug(port); + + return EC_SUCCESS; +} + +static int test_request_with_wait(void) +{ + uint32_t expected_rdo = RDO_FIXED(1, 900, 900, RDO_CAP_MISMATCH); + uint8_t port = PORT0; + + plug_in_source(port, 0); + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(2 * PD_T_CC_DEBOUNCE + 100 * MSEC); + TEST_ASSERT(pd_port[port].polarity == 0); + + /* We're in SNK_DISCOVERY now. Let's send the source cap. */ + simulate_source_cap(port, 0); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(port, + PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + /* Wait for the power request */ + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */ + inc_rx_id(port); + + /* Process the request */ + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, + PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP, + pd_port[port].msg_tx_id, 1))); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo)); + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + + /* Request is good. Send GoodCRC */ + simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id); + task_wake(PD_PORT_TO_TASK_ID(0)); + task_wait_event(30 * MSEC); + inc_tx_id(port); + + /* We're in SNK_REQUESTED. Send wait */ + simulate_wait(port); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + inc_rx_id(port); + + /* We didn't have an explicit contract. So we're in SNK_DISCOVERY. */ + /* Resend Source Cap. */ + simulate_source_cap(port, 0); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(port, + PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + /* Wait for the power request */ + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */ + inc_rx_id(port); + + /* Process the request */ + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, + PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP, + pd_port[port].msg_tx_id, 1))); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo)); + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + + /* Request was good. Send GoodCRC */ + simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id); + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + inc_tx_id(port); + + /* We're done */ + unplug(port); + return EC_SUCCESS; +} + +static int test_request_with_reject(void) +{ + uint32_t expected_rdo = RDO_FIXED(1, 900, 900, RDO_CAP_MISMATCH); + uint8_t port = PORT0; + + plug_in_source(port, 0); + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(2 * PD_T_CC_DEBOUNCE + 100 * MSEC); + TEST_ASSERT(pd_port[port].polarity == 0); + + /* We're in SNK_DISCOVERY now. Let's send the source cap. */ + simulate_source_cap(port, 0); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(port, + PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + /* Wait for the power request */ + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */ + inc_rx_id(port); + + /* Process the request */ + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, + PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP, + pd_port[port].msg_tx_id, 1))); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo)); + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + + /* Request is good. Send GoodCRC */ + simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id); + task_wake(PD_PORT_TO_TASK_ID(0)); + task_wait_event(30 * MSEC); + inc_tx_id(port); + + /* We're in SNK_REQUESTED. Send reject */ + simulate_reject(port); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + inc_rx_id(port); + + /* We're in SNK_READY. Send source cap. again. */ + simulate_source_cap(port, 0); + task_wait_event(30 * MSEC); + TEST_ASSERT(verify_goodcrc(port, + PD_ROLE_SINK, pd_port[port].msg_rx_id)); + + /* Wait for the power request */ + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */ + inc_rx_id(port); + + /* Process the request */ + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, + PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP, + pd_port[port].msg_tx_id, 1))); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo)); + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); + + /* We're done */ + unplug(port); + return EC_SUCCESS; +} + static int test_request(void) { uint32_t expected_rdo = RDO_FIXED(1, 900, 900, RDO_CAP_MISMATCH); + uint8_t port = PORT0; - plug_in_source(0, 0); - task_wake(PD_PORT_TO_TASK_ID(0)); + plug_in_source(port, 0); + task_wake(PD_PORT_TO_TASK_ID(port)); task_wait_event(2 * PD_T_CC_DEBOUNCE + 100 * MSEC); - TEST_ASSERT(pd_port[0].polarity == 0); + TEST_ASSERT(pd_port[port].polarity == 0); /* We're in SNK_DISCOVERY now. Let's send the source cap. */ - simulate_source_cap(0); + simulate_source_cap(port, 0); task_wait_event(30 * MSEC); - TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[0].msg_rx_id)); + TEST_ASSERT(verify_goodcrc(port, + PD_ROLE_SINK, pd_port[port].msg_rx_id)); /* Wait for the power request */ - task_wake(PD_PORT_TO_TASK_ID(0)); + task_wake(PD_PORT_TO_TASK_ID(port)); task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */ - inc_rx_id(0); + inc_rx_id(port); /* Process the request */ - TEST_ASSERT(pd_test_tx_msg_verify_sop(0)); - TEST_ASSERT(pd_test_tx_msg_verify_short(0, + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP, - pd_port[0].msg_tx_id, 1))); - TEST_ASSERT(pd_test_tx_msg_verify_word(0, expected_rdo)); - TEST_ASSERT(pd_test_tx_msg_verify_crc(0)); - TEST_ASSERT(pd_test_tx_msg_verify_eop(0)); - inc_tx_id(0); + pd_port[port].msg_tx_id, 1))); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo)); + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); + + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + + /* Request was good. Send GoodCRC */ + simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id); + task_wake(PD_PORT_TO_TASK_ID(port)); + task_wait_event(30 * MSEC); + inc_tx_id(port); /* We're done */ - unplug(0); + unplug(port); + return EC_SUCCESS; } + static int test_sink(void) { int i; + uint8_t port = PORT1; - plug_in_sink(1, 1); - task_wake(PD_PORT_TO_TASK_ID(1)); + plug_in_sink(port, 1); + task_wake(PD_PORT_TO_TASK_ID(port)); task_wait_event(250 * MSEC); /* tTypeCSinkWaitCap: 210~250 ms */ - TEST_ASSERT(pd_port[1].polarity == 1); + TEST_ASSERT(pd_port[port].polarity == 1); /* The source cap should be sent */ - TEST_ASSERT(pd_test_tx_msg_verify_sop(1)); - TEST_ASSERT(pd_test_tx_msg_verify_short(1, + TEST_ASSERT(pd_test_tx_msg_verify_sop(port)); + TEST_ASSERT(pd_test_tx_msg_verify_short(port, PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE, - PD_ROLE_DFP, pd_port[1].msg_tx_id, + PD_ROLE_DFP, pd_port[port].msg_tx_id, pd_src_pdo_cnt))); for (i = 0; i < pd_src_pdo_cnt; ++i) - TEST_ASSERT(pd_test_tx_msg_verify_word(1, pd_src_pdo[i])); - TEST_ASSERT(pd_test_tx_msg_verify_crc(1)); - TEST_ASSERT(pd_test_tx_msg_verify_eop(1)); + TEST_ASSERT(pd_test_tx_msg_verify_word(port, pd_src_pdo[i])); + + TEST_ASSERT(pd_test_tx_msg_verify_crc(port)); + TEST_ASSERT(pd_test_tx_msg_verify_eop(port)); /* Looks good. Ack the source cap. */ - simulate_goodcrc(1, PD_ROLE_SINK, pd_port[1].msg_tx_id); - task_wake(PD_PORT_TO_TASK_ID(1)); + simulate_goodcrc(port, PD_ROLE_SINK, pd_port[port].msg_tx_id); + task_wake(PD_PORT_TO_TASK_ID(port)); usleep(30 * MSEC); - inc_tx_id(1); + inc_tx_id(port); /* We're done */ - unplug(1); + unplug(port); return EC_SUCCESS; } @@ -231,6 +559,9 @@ void run_test(void) RUN_TEST(test_request); RUN_TEST(test_sink); + RUN_TEST(test_request_with_wait); + RUN_TEST(test_request_with_wait_and_contract); + RUN_TEST(test_request_with_reject); test_print_result(); }