diff options
-rw-r--r-- | common/mock/tcpci_i2c_mock.c | 23 | ||||
-rw-r--r-- | include/mock/tcpci_i2c_mock.h | 6 | ||||
-rw-r--r-- | test/build.mk | 1 | ||||
-rw-r--r-- | test/usb_tcpmv2_compliance.c | 1 | ||||
-rw-r--r-- | test/usb_tcpmv2_compliance.h | 1 | ||||
-rw-r--r-- | test/usb_tcpmv2_td_pd_src_e2.c | 157 |
6 files changed, 189 insertions, 0 deletions
diff --git a/common/mock/tcpci_i2c_mock.c b/common/mock/tcpci_i2c_mock.c index 8dcc84e034..ce07241577 100644 --- a/common/mock/tcpci_i2c_mock.c +++ b/common/mock/tcpci_i2c_mock.c @@ -70,6 +70,7 @@ static struct tcpci_reg tcpci_regs[] = { static uint8_t tx_buffer[BUFFER_SIZE]; static int tx_pos = -1; +static int tx_msg_cnt; static int tx_retry_cnt = -1; static uint8_t rx_buffer[BUFFER_SIZE]; static int rx_pos = -1; @@ -231,6 +232,26 @@ int verify_tcpci_tx_retry_count(enum tcpm_transmit_type tx_type, VERIFY_TIMEOUT); } +int verify_tcpci_tx_with_data(enum tcpm_transmit_type tx_type, + enum pd_data_msg_type data_msg, + uint8_t *data, + int data_bytes, + int *msg_len) +{ + int rv; + + rv = verify_transmit(tx_type, -1, + 0, data_msg, + VERIFY_TIMEOUT); + if (!rv) { + TEST_NE(data, NULL, "%p"); + TEST_GE(data_bytes, tx_msg_cnt, "%d"); + memcpy(data, tx_buffer, tx_msg_cnt); + if (msg_len) + *msg_len = tx_msg_cnt; + } + return rv; +} void mock_tcpci_receive(enum pd_msg_type sop, uint16_t header, uint32_t *payload) { @@ -431,6 +452,7 @@ int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, } memcpy(tx_buffer + tx_pos, out, out_size); tx_pos += out_size; + tx_msg_cnt = tx_pos; if (tx_pos > 0 && tx_pos == tx_buffer[0] + 1) { print_header("TX", UINT16_FROM_BYTE_ARRAY_LE( tx_buffer, 1)); @@ -450,6 +472,7 @@ int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags, return EC_ERROR_UNKNOWN; } tx_pos = 0; + tx_msg_cnt = 0; if (out_size != 1) { ccprints("ERROR: TCPC_REG_TX_BUFFER out_size != 1"); return EC_ERROR_UNKNOWN; diff --git a/include/mock/tcpci_i2c_mock.h b/include/mock/tcpci_i2c_mock.h index 7b068280d4..2c7faabd37 100644 --- a/include/mock/tcpci_i2c_mock.h +++ b/include/mock/tcpci_i2c_mock.h @@ -30,6 +30,12 @@ int verify_tcpci_tx_timeout(enum tcpm_transmit_type tx_type, enum pd_data_msg_type data_msg, int timeout); +int verify_tcpci_tx_with_data(enum tcpm_transmit_type tx_type, + enum pd_data_msg_type data_msg, + uint8_t *data, + int data_bytes, + int *msg_len); + void mock_tcpci_receive(enum pd_msg_type sop, uint16_t header, uint32_t *payload); diff --git a/test/build.mk b/test/build.mk index d0f813adb2..526eca8f22 100644 --- a/test/build.mk +++ b/test/build.mk @@ -221,6 +221,7 @@ usb_tcpmv2_compliance-y=usb_tcpmv2_compliance.o usb_tcpmv2_compliance_common.o \ usb_tcpmv2_td_pd_ll_e4.o \ usb_tcpmv2_td_pd_ll_e5.o \ usb_tcpmv2_td_pd_src_e1.o \ + usb_tcpmv2_td_pd_src_e2.o \ usb_tcpmv2_td_pd_src3_e26.o \ usb_tcpmv2_td_pd_snk3_e12.o \ usb_tcpmv2_td_pd_other.o diff --git a/test/usb_tcpmv2_compliance.c b/test/usb_tcpmv2_compliance.c index f2e8924638..aab01cf534 100644 --- a/test/usb_tcpmv2_compliance.c +++ b/test/usb_tcpmv2_compliance.c @@ -34,6 +34,7 @@ void run_test(int argc, char **argv) RUN_TEST(test_td_pd_ll_e5_dfp); RUN_TEST(test_td_pd_ll_e5_ufp); RUN_TEST(test_td_pd_src_e1); + RUN_TEST(test_td_pd_src_e2); RUN_TEST(test_td_pd_src3_e26); RUN_TEST(test_td_pd_snk3_e12); diff --git a/test/usb_tcpmv2_compliance.h b/test/usb_tcpmv2_compliance.h index 4b57ebb11d..654ca0c421 100644 --- a/test/usb_tcpmv2_compliance.h +++ b/test/usb_tcpmv2_compliance.h @@ -80,6 +80,7 @@ int test_td_pd_ll_e5_dfp(void); int test_td_pd_ll_e5_ufp(void); int test_td_pd_src_e1(void); +int test_td_pd_src_e2(void); int test_td_pd_src3_e26(void); diff --git a/test/usb_tcpmv2_td_pd_src_e2.c b/test/usb_tcpmv2_td_pd_src_e2.c new file mode 100644 index 0000000000..7943c0fa86 --- /dev/null +++ b/test/usb_tcpmv2_td_pd_src_e2.c @@ -0,0 +1,157 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "mock/tcpci_i2c_mock.h" +#include "task.h" +#include "tcpci.h" +#include "test_util.h" +#include "timer.h" +#include "usb_tcpmv2_compliance.h" +#include "usb_tc_sm.h" + +#define BUFFER_SIZE 100 +#define HEADER_BYTE_CNT 2 +#define PDO_BYTE_CNT 4 + +enum pd_revision { + REVISION_1 = 0, + REVISION_2 = 1, + REVISION_3 = 2, + REVISION_RESERVED = 3 +}; + +/***************************************************************************** + * TD.PD.SRC.E2 Source Capabilities Fields Checks + * + * Description: + * As Consumer (UFP), the Tester waits for a Source Capabilities message + * from the Provider (DFP,UUT) and verifies correct field values. + */ +int test_td_pd_src_e2(void) +{ + int i; + int msg_len; + uint8_t data[BUFFER_SIZE]; + uint16_t header; + uint16_t revision; + uint16_t pd_cnt; + uint32_t pdo; + uint32_t type; + uint32_t last_fixed_voltage = 0; + uint32_t last_battery_voltage = 0; + uint32_t last_variable_voltage = 0; + + partner_set_pd_rev(PD_REV20); + + TEST_EQ(tcpci_startup(), EC_SUCCESS, "%d"); + + /* + * a) Run PROC.PD.E1 Bring-up according to the UUT role. + * + * NOTE: Calling PROC.PD.E1 with INITIAL_ATTACH will stop just before + * the PD_DATA_SOURCE_CAP is verified. We need to stop the process + * there to gather the actual message data. + */ + TEST_EQ(proc_pd_e1(PD_ROLE_DFP, INITIAL_ATTACH), EC_SUCCESS, "%d"); + + /* + * b) Upon receipt of the Source Capabilities message from the + * Provider, if the Specification Revision field is 10b + * (Rev 3.0), the test passes and stops here, + */ + TEST_EQ(verify_tcpci_tx_with_data(TCPC_TX_SOP, + PD_DATA_SOURCE_CAP, + data, + sizeof(data), + &msg_len), + EC_SUCCESS, "%d"); + TEST_GE(msg_len, HEADER_BYTE_CNT, "%d"); + + header = UINT16_FROM_BYTE_ARRAY_LE(data, 1); + revision = PD_HEADER_REV(header); + if (revision == REVISION_3) + return EC_SUCCESS; + + /* + * otherwise the Tester verifies: + * 1. Number of Data Objects field equals the number of Src_PDOs + * in the message and is not 000b. + * 2. Port Power Role field = 1b (Source) + * 3. Specification Revision field = 01b (Rev 2.0) + * 4. Port Data Role field = 1b (DFP) + * 5. Message Type field = 0001b (Source Capabilities) + * 6. Bit 15 = 0b (Reserved) + * 7. Bit 4 = 0b (Reserved) + */ + pd_cnt = PD_HEADER_CNT(header); + TEST_NE(pd_cnt, 0, "%d"); + TEST_EQ(msg_len, HEADER_BYTE_CNT + (pd_cnt * PDO_BYTE_CNT) + 1, "%d"); + TEST_EQ(PD_HEADER_PROLE(header), PD_ROLE_SOURCE, "%d"); + TEST_EQ(revision, REVISION_2, "%d"); + TEST_EQ(PD_HEADER_DROLE(header), PD_ROLE_DFP, "%d"); + TEST_EQ(PD_HEADER_TYPE(header), PD_DATA_SOURCE_CAP, "%d"); + TEST_EQ(header & (BIT(4)|BIT(15)), 0, "%d"); + + /* + * c) For the first PDO, the Tester verifies: + * 1. Bits 31..30 (PDO type) are 00b (Fixed Supply). + * 2. Voltage field = 100 (5 V) + * 3. Bits 24..22 = 000b (Reserved) + */ + pdo = UINT32_FROM_BYTE_ARRAY_LE(&data[2], 1); + + type = pdo & PDO_TYPE_MASK; + TEST_EQ(type, PDO_TYPE_FIXED, "%d"); + + last_fixed_voltage = PDO_FIXED_VOLTAGE(pdo); + TEST_EQ(last_fixed_voltage, 5000, "%d"); + TEST_EQ(pdo & GENMASK(24, 22), 0, "%d"); + + /* + * d) For the other PDOs (if any), the Tester verifies: + * 1. Bits 31..30 (PDO type) are 00b (Fixed Supply), 01b (Battery), + * or 10b (Variable Supply). + * 2. If Bits 31..30 are 00b, Bits 29..22 are set to 0. + * 3. PDOs are in the order of Fixed Supply Objects (if present), + * Battery Supply Objects (if present) and then Variable Supply + * Objects (if present). + * 4. Fixed Supply Objects (if present) are in voltage order; lowest + * to highest. + * 5. Battery Supply Objects (if present) are in Minimum Voltage + * order; lowest to highest. + * 6. Variable Supply Objects (if present) are in Minimum Voltage + * order; lowest to highest. + */ + for (i = 1; i < pd_cnt; ++i) { + int offset; + uint32_t voltage; + + offset = HEADER_BYTE_CNT + (i * PDO_BYTE_CNT); + pdo = UINT32_FROM_BYTE_ARRAY_LE(&data[offset], 1); + + type = pdo & PDO_TYPE_MASK; + TEST_NE(type, PDO_TYPE_AUGMENTED, "%d"); + + if (type == PDO_TYPE_FIXED) { + TEST_EQ(pdo & GENMASK(29, 22), 0, "%d"); + TEST_EQ(last_battery_voltage, 0, "%d"); + TEST_EQ(last_variable_voltage, 0, "%d"); + voltage = PDO_FIXED_VOLTAGE(pdo); + TEST_GE(voltage, last_fixed_voltage, "%d"); + last_fixed_voltage = voltage; + } else if (type == PDO_TYPE_BATTERY) { + TEST_EQ(last_variable_voltage, 0, "%d"); + voltage = PDO_BATT_MIN_VOLTAGE(pdo); + TEST_GE(voltage, last_battery_voltage, "%d"); + last_battery_voltage = voltage; + } else { + voltage = PDO_VAR_MIN_VOLTAGE(pdo); + TEST_GE(voltage, last_variable_voltage, "%d"); + last_variable_voltage = voltage; + } + } + + return EC_SUCCESS; +} |