summaryrefslogtreecommitdiff
path: root/test/usb_pd.c
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-10-01 13:46:18 +0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-04 21:08:48 +0000
commitf0dc012cf75a02110f3ac98a4dbd1a395a70e794 (patch)
tree7b3e93ec612d16d8acd54b674c02a5c1507fdd66 /test/usb_pd.c
parent15eced037401c1749b634786754df17d8c58285f (diff)
downloadchrome-ec-f0dc012cf75a02110f3ac98a4dbd1a395a70e794.tar.gz
Add back unit test for usb_pd"
This is mostly the same as previous commits, but with increased delay. Previously, we have short delays (e.g. 3ms) which is too short and may cause instability. Now that we have slowed down the time when running unit tests and increased the delay, this shouldn't cause problems anymore. BUG=chrome-os-partner:31200 TEST=Repeatedly run multiple unit tests in parallel. BRANCH=Samus Change-Id: Ib55e3adc5fd27a8e233996b4799dab3cefd62318 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/220734 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'test/usb_pd.c')
-rw-r--r--test/usb_pd.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/test/usb_pd.c b/test/usb_pd.c
new file mode 100644
index 0000000000..208836fe5b
--- /dev/null
+++ b/test/usb_pd.c
@@ -0,0 +1,212 @@
+/* Copyright 2014 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.
+ *
+ * Test USB PD module.
+ */
+
+#include "common.h"
+#include "crc.h"
+#include "task.h"
+#include "test_util.h"
+#include "timer.h"
+#include "usb_pd.h"
+#include "usb_pd_config.h"
+#include "usb_pd_test_util.h"
+#include "util.h"
+
+struct pd_port_t {
+ int host_mode;
+ int cc_volt[2]; /* -1 for Hi-Z */
+ int has_vbus;
+ int msg_tx_id;
+ int msg_rx_id;
+ int polarity;
+} pd_port[PD_PORT_COUNT];
+
+/* Mock functions */
+
+int pd_adc_read(int port, int cc)
+{
+ int val = pd_port[port].cc_volt[cc];
+ if (val == -1)
+ return pd_port[port].host_mode ? 3000 : 0;
+ return val;
+}
+
+int pd_snk_is_vbus_provided(int port)
+{
+ return pd_port[port].has_vbus;
+}
+
+void pd_set_host_mode(int port, int enable)
+{
+ pd_port[port].host_mode = enable;
+}
+
+void pd_select_polarity(int port, int polarity)
+{
+ pd_port[port].polarity = polarity;
+}
+
+/* Tests */
+
+void inc_tx_id(int port)
+{
+ pd_port[port].msg_tx_id = (pd_port[port].msg_tx_id + 1) % 7;
+}
+
+void inc_rx_id(int port)
+{
+ pd_port[port].msg_rx_id = (pd_port[port].msg_rx_id + 1) % 7;
+}
+
+static void init_ports(void)
+{
+ int i;
+
+ for (i = 0; i < PD_PORT_COUNT; ++i) {
+ pd_port[i].host_mode = 0;
+ pd_port[i].cc_volt[0] = pd_port[i].cc_volt[1] = -1;
+ pd_port[i].has_vbus = 0;
+ }
+}
+
+static void simulate_rx_msg(int port, uint16_t header, int cnt,
+ const uint32_t *data)
+{
+ int i;
+
+ pd_test_rx_set_preamble(port, 1);
+ pd_test_rx_msg_append_sop(port);
+ pd_test_rx_msg_append_short(port, header);
+
+ crc32_init();
+ crc32_hash16(header);
+ for (i = 0; i < cnt; ++i) {
+ pd_test_rx_msg_append_word(port, data[i]);
+ crc32_hash32(data[i]);
+ }
+ pd_test_rx_msg_append_word(port, crc32_result());
+
+ pd_test_rx_msg_append_eop(port);
+
+ pd_simulate_rx(port);
+}
+
+static void simulate_source_cap(int port)
+{
+ uint16_t header = PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
+ pd_port[port].msg_rx_id, pd_src_pdo_cnt);
+ simulate_rx_msg(port, header, pd_src_pdo_cnt, pd_src_pdo);
+}
+
+static void simulate_goodcrc(int port, int role, int id)
+{
+ simulate_rx_msg(port, PD_HEADER(PD_CTRL_GOOD_CRC, role, id, 0),
+ 0, NULL);
+}
+
+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,
+ role, id, 0)) &&
+ pd_test_tx_msg_verify_crc(0) &&
+ pd_test_tx_msg_verify_eop(0);
+}
+
+static void plug_in_source(int port, int polarity)
+{
+ pd_port[port].has_vbus = 1;
+ pd_port[port].cc_volt[polarity] = 3000;
+}
+
+static void plug_in_sink(int port, int polarity)
+{
+ pd_port[port].has_vbus = 0;
+ pd_port[port].cc_volt[polarity] = 400; /* V_rd */
+}
+
+static void unplug(int port)
+{
+ pd_port[port].has_vbus = 0;
+ pd_port[port].cc_volt[0] = -1;
+ pd_port[port].cc_volt[1] = -1;
+ task_wake(PORT_TO_TASK_ID(port));
+ usleep(30 * MSEC);
+}
+
+static int test_request(void)
+{
+ plug_in_source(0, 0);
+ task_wake(PORT_TO_TASK_ID(0));
+ task_wait_event(100 * MSEC);
+ TEST_ASSERT(pd_port[0].polarity == 0);
+
+ /* We're in SNK_DISCOVERY now. Let's send the source cap. */
+ simulate_source_cap(0);
+ task_wait_event(30 * MSEC);
+ TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[0].msg_rx_id));
+
+ /* Wait for the power request */
+ task_wake(PORT_TO_TASK_ID(0));
+ task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */
+ inc_rx_id(0);
+
+ /* Process the request */
+ TEST_ASSERT(pd_test_tx_msg_verify_sop(0));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(0,
+ PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK,
+ pd_port[0].msg_tx_id, 1)));
+ TEST_ASSERT(pd_test_tx_msg_verify_word(0, RDO_FIXED(2, 450, 900, 0)));
+ TEST_ASSERT(pd_test_tx_msg_verify_crc(0));
+ TEST_ASSERT(pd_test_tx_msg_verify_eop(0));
+ inc_tx_id(0);
+
+ /* We're done */
+ unplug(0);
+ return EC_SUCCESS;
+}
+
+static int test_sink(void)
+{
+ int i;
+
+ plug_in_sink(1, 1);
+ task_wake(PORT_TO_TASK_ID(1));
+ task_wait_event(250 * MSEC); /* tTypeCSinkWaitCap: 210~250 ms */
+ TEST_ASSERT(pd_port[1].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,
+ PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
+ pd_port[1].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));
+
+ /* Looks good. Ack the source cap. */
+ simulate_goodcrc(1, PD_ROLE_SINK, pd_port[1].msg_tx_id);
+ task_wake(PORT_TO_TASK_ID(1));
+ usleep(30 * MSEC);
+ inc_tx_id(1);
+
+ /* We're done */
+ unplug(1);
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ test_reset();
+ init_ports();
+ pd_set_dual_role(PD_DRP_TOGGLE_ON);
+
+ RUN_TEST(test_request);
+ RUN_TEST(test_sink);
+
+ test_print_result();
+}