mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
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 <shurst@google.com> Tested-by: Sam Hurst <shurst@google.com> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
401
test/usb_pd.c
401
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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user