diff options
-rw-r--r-- | board/chocodile_vpdmcu/board.h | 2 | ||||
-rw-r--r-- | board/host/board.h | 1 | ||||
-rw-r--r-- | common/usbc/build.mk | 1 | ||||
-rw-r--r-- | common/usbc/usb_pd_console.c | 163 | ||||
-rw-r--r-- | test/fake_usbc.c | 13 | ||||
-rw-r--r-- | test/usb_pd_console.c | 472 |
6 files changed, 648 insertions, 4 deletions
diff --git a/board/chocodile_vpdmcu/board.h b/board/chocodile_vpdmcu/board.h index 962a4935f1..6a3c632773 100644 --- a/board/chocodile_vpdmcu/board.h +++ b/board/chocodile_vpdmcu/board.h @@ -40,6 +40,8 @@ /* Optional features */ #undef CONFIG_USB_PD_CONSOLE_CMD #undef CONFIG_USB_PD_HOST_CMD +#undef CONFIG_CMD_PD +#undef CONFIG_USBC_VCONN #define CONFIG_ADC #undef CONFIG_ADC_WATCHDOG #define CONFIG_ADC_SAMPLE_TIME STM32_ADC_SMPR_41_5_CY diff --git a/board/host/board.h b/board/host/board.h index 6c0da164b3..1e5d14476f 100644 --- a/board/host/board.h +++ b/board/host/board.h @@ -11,6 +11,7 @@ /* Optional features */ /* Default-yes, override to no by including fake_battery module. */ #define CONFIG_BATTERY_PRESENT_CUSTOM +#undef CONFIG_CMD_PD #define CONFIG_EXTPOWER_GPIO #undef CONFIG_FMAP #define CONFIG_POWER_BUTTON diff --git a/common/usbc/build.mk b/common/usbc/build.mk index f8f6f5aa33..3b29d5d9ad 100644 --- a/common/usbc/build.mk +++ b/common/usbc/build.mk @@ -28,6 +28,7 @@ ifneq ($(CONFIG_USB_PE_SM),) all-obj-$(CONFIG_USB_VPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o all-obj-$(CONFIG_USB_CTVPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o all-obj-$(CONFIG_USB_DRP_ACC_TRYSRC)+=$(_usbc_dir)usb_pe_drp_sm.o +all-obj-$(CONFIG_CMD_PD)+=$(_usbc_dir)usb_pd_console.o endif # CONFIG_USB_PE_SM endif # CONFIG_USB_PD_TCPMV2 diff --git a/common/usbc/usb_pd_console.c b/common/usbc/usb_pd_console.c new file mode 100644 index 0000000000..ba2b6efeb9 --- /dev/null +++ b/common/usbc/usb_pd_console.c @@ -0,0 +1,163 @@ +/* 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 "common.h" +#include "console.h" +#include "usb_common.h" +#include "usb_pe_sm.h" +#include "usb_tc_sm.h" +#include "usb_pd.h" +#include "util.h" + +test_export_static int command_pd(int argc, char **argv) +{ + int port; + char *e; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + else if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC) && + !strcasecmp(argv[1], "trysrc")) { + enum try_src_override_t ov = tc_get_try_src_override(); + + if (argc >= 3) { + ov = strtoi(argv[2], &e, 10); + if (*e || ov > TRY_SRC_NO_OVERRIDE) + return EC_ERROR_PARAM3; + tc_try_src_override(ov); + } + + if (ov == TRY_SRC_NO_OVERRIDE) + ccprintf("Try.SRC System controlled\n"); + else + ccprintf("Try.SRC Forced %s\n", ov ? "ON" : "OFF"); + + return EC_SUCCESS; + } + + /* command: pd <port> <subcmd> [args] */ + port = strtoi(argv[1], &e, 10); + if (argc < 3) + return EC_ERROR_PARAM_COUNT; + + if (*e || port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return EC_ERROR_PARAM2; + + if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE)) { + if (!strcasecmp(argv[2], "tx")) { + pe_dpm_request(port, DPM_REQUEST_SNK_STARTUP); + } else if (!strcasecmp(argv[2], "charger")) { + pe_dpm_request(port, DPM_REQUEST_SRC_STARTUP); + } else if (!strcasecmp(argv[2], "dev")) { + int max_volt; + + if (argc >= 4) { + max_volt = strtoi(argv[3], &e, 10) * 1000; + if (*e) + return EC_ERROR_PARAM3; + } else { + max_volt = pd_get_max_voltage(); + } + pd_request_source_voltage(port, max_volt); + pe_dpm_request(port, DPM_REQUEST_NEW_POWER_LEVEL); + ccprintf("max req: %dmV\n", max_volt); + } else if (!strcasecmp(argv[2], "disable")) { + pd_comm_enable(port, 0); + ccprintf("Port C%d disable\n", port); + return EC_SUCCESS; + } else if (!strcasecmp(argv[2], "enable")) { + pd_comm_enable(port, 1); + ccprintf("Port C%d enabled\n", port); + return EC_SUCCESS; + } else if (!strcasecmp(argv[2], "hard")) { + pe_dpm_request(port, DPM_REQUEST_HARD_RESET_SEND); + } else if (!strcasecmp(argv[2], "soft")) { + pe_dpm_request(port, DPM_REQUEST_SOFT_RESET_SEND); + } else if (!strcasecmp(argv[2], "swap")) { + if (argc < 4) + return EC_ERROR_PARAM_COUNT; + + if (!strcasecmp(argv[3], "power")) + pe_dpm_request(port, DPM_REQUEST_PR_SWAP); + else if (!strcasecmp(argv[3], "data")) + pe_dpm_request(port, DPM_REQUEST_DR_SWAP); + else if (IS_ENABLED(CONFIG_USBC_VCONN_SWAP) && + !strcasecmp(argv[3], "vconn")) + pe_dpm_request(port, DPM_REQUEST_VCONN_SWAP); + else + return EC_ERROR_PARAM3; + } else if (!strcasecmp(argv[2], "dualrole")) { + if (argc < 4) { + ccprintf("dual-role toggling: "); + switch (pd_get_dual_role(port)) { + case PD_DRP_TOGGLE_ON: + ccprintf("on\n"); + break; + case PD_DRP_TOGGLE_OFF: + ccprintf("off\n"); + break; + case PD_DRP_FREEZE: + ccprintf("freeze\n"); + break; + case PD_DRP_FORCE_SINK: + ccprintf("force sink\n"); + break; + case PD_DRP_FORCE_SOURCE: + ccprintf("force source\n"); + break; + } + } else { + if (!strcasecmp(argv[3], "on")) + pd_set_dual_role(port, + PD_DRP_TOGGLE_ON); + else if (!strcasecmp(argv[3], "off")) + pd_set_dual_role(port, + PD_DRP_TOGGLE_OFF); + else if (!strcasecmp(argv[3], "freeze")) + pd_set_dual_role(port, PD_DRP_FREEZE); + else if (!strcasecmp(argv[3], "sink")) + pd_set_dual_role(port, + PD_DRP_FORCE_SINK); + else if (!strcasecmp(argv[3], "source")) + pd_set_dual_role(port, + PD_DRP_FORCE_SOURCE); + else + return EC_ERROR_PARAM4; + } + return EC_SUCCESS; + } + } + + if (!strcasecmp(argv[2], "state")) { + ccprintf("Port C%d CC%d, %s - Role: %s-%s", + port, pd_get_polarity(port) + 1, + pd_comm_is_enabled(port) ? "Enable" : "Disable", + pd_get_power_role(port) == + PD_ROLE_SOURCE ? "SRC" : "SNK", + pd_get_data_role(port) == PD_ROLE_DFP ? "DFP" : "UFP"); + + if (IS_ENABLED(CONFIG_USBC_VCONN)) + ccprintf("%s ", tc_is_vconn_src(port) ? "-VC" : ""); + + ccprintf("TC State: %s, Flags: 0x%04x\n", + tc_get_current_state(port), + tc_get_flags(port)); + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(pd, command_pd, +#ifdef CONFIG_USB_PD_TRY_SRC + "trysrc [0|1|2]" +#endif + "\n\t<port> state" +#ifdef CONFIG_USB_PD_DUAL_ROLE + "|tx|charger|dev" + "\n\t<port> disable|enable|soft|hard" + "\n\t<port> dualrole [on|off|freeze|sink|source]" + "\n\t<port> swap [power|data|vconn]" +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + , + "USB PD"); diff --git a/test/fake_usbc.c b/test/fake_usbc.c index e62fa5ac62..d98e7017f9 100644 --- a/test/fake_usbc.c +++ b/test/fake_usbc.c @@ -130,12 +130,17 @@ __overridable void pe_invalidate_explicit_contract(int port) { } -enum pd_dual_role_states pd_get_dual_role(int port) +__overridable enum pd_dual_role_states pd_get_dual_role(int port) { return PD_DRP_TOGGLE_ON; } -int pd_comm_is_enabled(int port) +__overridable void pd_dev_get_rw_hash(int port, uint16_t *dev_id, + uint8_t *rw_hash, uint32_t *current_image) +{ +} + +__overridable int pd_comm_is_enabled(int port) { return 0; } @@ -190,11 +195,11 @@ void dfp_consume_cable_response(int port, int cnt, uint32_t *payload, { } -void pd_set_dual_role(int port, enum pd_dual_role_states state) +__overridable void pd_set_dual_role(int port, enum pd_dual_role_states state) { } -enum tcpc_cc_polarity pd_get_polarity(int port) +__overridable enum tcpc_cc_polarity pd_get_polarity(int port) { return POLARITY_CC1; } diff --git a/test/usb_pd_console.c b/test/usb_pd_console.c new file mode 100644 index 0000000000..82b34d8109 --- /dev/null +++ b/test/usb_pd_console.c @@ -0,0 +1,472 @@ +/* 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. + * + * Test usb_pd_console + */ + +#include "common.h" +#include "math.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "usb_pe_sm.h" +#include "usb_pd.h" +#include "usb_tc_sm.h" +#include "util.h" +#include "test_util.h" + +/* Defined in implementation */ +int hex8tou32(char *str, uint32_t *val); +int command_pd(int argc, char **argv); +int remote_flashing(int argc, char **argv); + +static enum try_src_override_t try_src_override; +static int test_port; +static enum pe_dpm_request request; +static int max_volt; +static int comm_enable; +static int dev_info; +static int vdm_cmd; +static int vdm_count; +static int vdm_vid; +static uint32_t vdm_data[10]; +static enum pd_dual_role_states dr_state; + +/* Mock functions */ +void pe_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, + int count) +{ + int i; + + test_port = port; + vdm_cmd = cmd; + vdm_count = count; + vdm_vid = vid; + + if (data == NULL) + for (i = 0; i < 10; i++) + vdm_data[i] = -1; + else + for (i = 0; i < count; i++) + vdm_data[i] = data[i]; +} + +void pe_dpm_request(int port, enum pe_dpm_request req) +{ + test_port = port; + request = req; +} + +unsigned int pd_get_max_voltage(void) +{ + return 10000; +} + +void pd_request_source_voltage(int port, int mv) +{ + test_port = port; + max_volt = mv; +} + +void pd_comm_enable(int port, int enable) +{ + test_port = port; + comm_enable = enable; +} + +void tc_print_dev_info(int port) +{ + test_port = port; + dev_info = 1; +} + +void pd_set_dual_role(int port, enum pd_dual_role_states state) +{ + test_port = port; + dr_state = state; +} + +int pd_comm_is_enabled(int port) +{ + test_port = port; + return 0; +} + +int pd_get_polarity(int port) +{ + test_port = port; + return 0; +} + +uint32_t tc_get_flags(int port) +{ + test_port = port; + return 0; +} + +const char *tc_get_current_state(int port) +{ + test_port = port; + return 0; +} + +void tc_try_src_override(enum try_src_override_t ov) +{ + if (IS_ENABLED(CONFIG_USB_PD_TRY_SRC)) { + switch (ov) { + case TRY_SRC_OVERRIDE_OFF: /* 0 */ + try_src_override = TRY_SRC_OVERRIDE_OFF; + break; + case TRY_SRC_OVERRIDE_ON: /* 1 */ + try_src_override = TRY_SRC_OVERRIDE_ON; + break; + default: + try_src_override = TRY_SRC_NO_OVERRIDE; + } + } +} + +enum try_src_override_t tc_get_try_src_override(void) +{ + return try_src_override; +} + +static int test_hex8tou32(void) +{ + char const *tst_str[] = {"01234567", "89abcdef", + "AABBCCDD", "EEFF0011"}; + uint32_t const tst_int[] = {0x01234567, 0x89abcdef, + 0xaabbccdd, 0xeeff0011}; + uint32_t val; + int i; + + for (i = 0; i < 4; i++) { + hex8tou32(tst_str[i], &val); + TEST_ASSERT(val == tst_int[i]); + } + + return EC_SUCCESS; +} + +static int test_command_pd_arg_count(void) +{ + int argc; + char const *argv[] = {"pd", "", 0, 0, 0}; + + for (argc = 0; argc < 3; argc++) + TEST_ASSERT(command_pd(argc, argv) == EC_ERROR_PARAM_COUNT); + + return EC_SUCCESS; +} + +static int test_command_pd_port_num(void) +{ + int argc = 3; + char const *argv[10] = {"pd", "5", 0, 0, 0}; + + TEST_ASSERT(command_pd(argc, argv) == EC_ERROR_PARAM2); + + return EC_SUCCESS; +} + +static int test_command_pd_try_src(void) +{ + int argc = 3; + char const *argv[] = {"pd", "trysrc", "2", 0, 0}; + + try_src_override = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(try_src_override == TRY_SRC_NO_OVERRIDE); + + argv[2] = "1"; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(try_src_override == TRY_SRC_OVERRIDE_ON); + + argv[2] = "0"; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(try_src_override == TRY_SRC_OVERRIDE_OFF); + + return EC_SUCCESS; +} + +static int test_command_pd_tx(void) +{ + int argc = 3; + char const *argv[] = {"pd", "0", "tx", 0, 0}; + + request = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(request == DPM_REQUEST_SNK_STARTUP); + + return EC_SUCCESS; +} + +static int test_command_pd_charger(void) +{ + int argc = 3; + char const *argv[] = {"pd", "1", "charger", 0, 0}; + + request = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 1); + TEST_ASSERT(request == DPM_REQUEST_SRC_STARTUP); + + return EC_SUCCESS; +} + +static int test_command_pd_dev1(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "dev", "20", 0}; + + request = 0; + max_volt = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(request == DPM_REQUEST_NEW_POWER_LEVEL); + TEST_ASSERT(max_volt == 20000); + + return EC_SUCCESS; +} + +static int test_command_pd_dev2(void) +{ + int argc = 3; + char const *argv[] = {"pd", "1", "dev", 0, 0}; + + request = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 1); + TEST_ASSERT(request == DPM_REQUEST_NEW_POWER_LEVEL); + TEST_ASSERT(max_volt == 10000); + + return EC_SUCCESS; +} + +static int test_command_pd_disable(void) +{ + int argc = 3; + char const *argv[] = {"pd", "0", "disable", 0, 0}; + + comm_enable = 1; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(comm_enable == 0); + + return EC_SUCCESS; +} + +static int test_command_pd_enable(void) +{ + int argc = 3; + char const *argv[] = {"pd", "1", "enable", 0, 0}; + + comm_enable = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 1); + TEST_ASSERT(comm_enable == 1); + + return EC_SUCCESS; +} + +static int test_command_pd_hard(void) +{ + int argc = 3; + char const *argv[] = {"pd", "0", "hard", 0, 0}; + + request = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(request == DPM_REQUEST_HARD_RESET_SEND); + + return EC_SUCCESS; +} + +static int test_command_pd_soft(void) +{ + int argc = 3; + char const *argv[] = {"pd", "0", "soft", 0, 0}; + + request = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(request == DPM_REQUEST_SOFT_RESET_SEND); + + return EC_SUCCESS; +} + +static int test_command_pd_swap1(void) +{ + int argc = 3; + char const *argv[] = {"pd", "0", "swap", 0, 0}; + + TEST_ASSERT(command_pd(argc, argv) == EC_ERROR_PARAM_COUNT); + + return EC_SUCCESS; +} + +static int test_command_pd_swap2(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "swap", "power", 0}; + + request = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(request == DPM_REQUEST_PR_SWAP); + + return EC_SUCCESS; +} + +static int test_command_pd_swap3(void) +{ + int argc = 4; + char const *argv[] = {"pd", "1", "swap", "data", 0}; + + request = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 1); + TEST_ASSERT(request == DPM_REQUEST_DR_SWAP); + + return EC_SUCCESS; +} + +static int test_command_pd_swap4(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "swap", "vconn", 0}; + + request = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(request == DPM_REQUEST_VCONN_SWAP); + + return EC_SUCCESS; +} + +static int test_command_pd_swap5(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "swap", "xyz", 0}; + + TEST_ASSERT(command_pd(argc, argv) == EC_ERROR_PARAM3); + + return EC_SUCCESS; +} + +static int test_command_pd_dualrole1(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "dualrole", "on", 0}; + + dr_state = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(dr_state == PD_DRP_TOGGLE_ON); + + return EC_SUCCESS; +} + +static int test_command_pd_dualrole2(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "dualrole", "off", 0}; + + dr_state = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(dr_state == PD_DRP_TOGGLE_OFF); + + return EC_SUCCESS; +} + +static int test_command_pd_dualrole3(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "dualrole", "freeze", 0}; + + dr_state = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(dr_state == PD_DRP_FREEZE); + + return EC_SUCCESS; +} + +static int test_command_pd_dualrole4(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "dualrole", "sink", 0}; + + dr_state = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(dr_state == PD_DRP_FORCE_SINK); + + return EC_SUCCESS; +} + +static int test_command_pd_dualrole5(void) +{ + int argc = 4; + char const *argv[] = {"pd", "0", "dualrole", "source", 0}; + + dr_state = 0; + TEST_ASSERT(command_pd(argc, argv) == EC_SUCCESS); + TEST_ASSERT(test_port == 0); + TEST_ASSERT(dr_state == PD_DRP_FORCE_SOURCE); + + return EC_SUCCESS; +} + + +void run_test(void) +{ + test_reset(); + + RUN_TEST(test_hex8tou32); + RUN_TEST(test_command_pd_arg_count); + RUN_TEST(test_command_pd_port_num); + RUN_TEST(test_command_pd_try_src); + RUN_TEST(test_command_pd_tx); + RUN_TEST(test_command_pd_bist_tx); + RUN_TEST(test_command_pd_bist_rx); + RUN_TEST(test_command_pd_charger); + RUN_TEST(test_command_pd_dev1); + RUN_TEST(test_command_pd_dev2); + RUN_TEST(test_command_pd_disable); + RUN_TEST(test_command_pd_enable); + RUN_TEST(test_command_pd_hard); + RUN_TEST(test_command_pd_info); + RUN_TEST(test_command_pd_soft); + RUN_TEST(test_command_pd_swap1); + RUN_TEST(test_command_pd_swap2); + RUN_TEST(test_command_pd_swap3); + RUN_TEST(test_command_pd_swap4); + RUN_TEST(test_command_pd_swap5); + RUN_TEST(test_command_pd_ping); + RUN_TEST(test_command_pd_vdm1); + RUN_TEST(test_command_pd_vdm2); + RUN_TEST(test_command_pd_vdm3); + RUN_TEST(test_command_pd_vdm4); + RUN_TEST(test_command_pd_vdm5); + RUN_TEST(test_command_pd_vdm6); + RUN_TEST(test_command_pd_flash1); + RUN_TEST(test_command_pd_flash2); + RUN_TEST(test_command_pd_flash3); + RUN_TEST(test_command_pd_flash4); + RUN_TEST(test_command_pd_flash5); + RUN_TEST(test_command_pd_flash6); + RUN_TEST(test_command_pd_flash7); + RUN_TEST(test_command_pd_flash8); + RUN_TEST(test_command_pd_dualrole1); + RUN_TEST(test_command_pd_dualrole2); + RUN_TEST(test_command_pd_dualrole3); + RUN_TEST(test_command_pd_dualrole4); + RUN_TEST(test_command_pd_dualrole5); + + test_print_result(); +} + |