diff options
author | Tom Hughes <tomhughes@chromium.org> | 2022-09-21 14:08:36 -0700 |
---|---|---|
committer | Tom Hughes <tomhughes@chromium.org> | 2022-09-22 12:59:38 -0700 |
commit | c453fd704268ef72de871b0c5ac7a989de662334 (patch) | |
tree | fcf6ce5810f9ff9e3c8cce434812dd75492269ed /zephyr/test/drivers/default/src/integration/usbc/usb_attach_src_snk.c | |
parent | 6c1587ca70f558b4f96b3f0b18ad8b027d3ba99d (diff) | |
parent | 28712dae9d7ed1e694f7622cc083afa71090d4d5 (diff) | |
download | chrome-ec-c453fd704268ef72de871b0c5ac7a989de662334.tar.gz |
Merge remote-tracking branch cros/main into firmware-fpmcu-dartmonkey-releasefirmware-fpmcu-dartmonkey-release
Generated by: ./util/update_release_branch.py --board dartmonkey --relevant_paths_file
./util/fingerprint-relevant-paths.txt firmware-fpmcu-dartmonkey-release
Relevant changes:
git log --oneline 6c1587ca70..28712dae9d -- board/nocturne_fp
board/dartmonkey common/fpsensor docs/fingerprint driver/fingerprint
util/getversion.sh
ded9307b79 util/getversion.sh: Fix version when not in a git repo
956055e692 board: change Google USB vendor info
71b2ef709d Update license boilerplate text in source code files
33e11afda0 Revert "fpsensor: Build fpsensor source file with C++"
c8d0360723 fpsensor: Build fpsensor source file with C++
bc113abd53 fpsensor: Fix g++ compiler error
150a58a0dc fpsensor: Fix fp_set_sensor_mode return type
b33b5ce85b fpsensor: Remove nested designators for C++ compatibility
2e864b2539 tree-wide: const-ify argv for console commands
56d8b360f9 test: Add test for get ikm failure when seed not set
3a3d6c3690 test: Add test for fpsensor trivial key failure
233e6bbd08 fpsensor_crypto: Abstract calls to hmac_SHA256
0a041b285b docs/fingerprint: Typo correction
c03fab67e2 docs/fingerprint: Fix the path of fputils.py
0b5d4baf5a util/getversion.sh: Fix empty file list handling
6e128fe760 FPMCU dev board environment with Satlab
3eb29b6aa5 builtin: Move ssize_t to sys/types.h
345d62ebd1 docs/fingerprint: Update power numbers for latest dartmonkey release
c25ffdb316 common: Conditionally support printf %l and %i modifiers
9a3c514b45 test: Add a test to check if the debugger is connected
54e603413f Move standard library tests to their own file
43fa6b4bf8 docs/fingerprint: Update power numbers for latest bloonchipper release
25536f9a84 driver/fingerprint/fpc/bep/fpc_sensor_spi.c: Format with clang-format
4face99efd driver/fingerprint/fpc/libfp/fpc_sensor_pal.h: Format with clang-format
738de2b575 trng: Rename rand to trng_rand
14b8270edd docs/fingerprint: Update dragonclaw power numbers
0b268f93d1 driver/fingerprint/fpc/libfp/fpc_private.c: Format with clang-format
f80da163f2 driver/fingerprint/fpc/libfp/fpc_private.h: Format with clang-format
a0751778f4 board/nocturne_fp/ro_workarounds.c: Format with clang-format
5e9c85c9b1 driver/fingerprint/fpc/libfp/fpc_sensor_pal.c: Format with clang-format
c1f9dd3cf8 driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h: Format with clang-format
eb1e1bed8d driver/fingerprint/fpc/libfp/fpc1145_private.h: Format with clang-format
6e7b611821 driver/fingerprint/fpc/bep/fpc_bio_algorithm.h: Format with clang-format
e0589cd5e2 driver/fingerprint/fpc/bep/fpc1035_private.h: Format with clang-format
58f0246dbe board/nocturne_fp/board_ro.c: Format with clang-format
7905e556a0 common/fpsensor/fpsensor_crypto.c: Format with clang-format
21289d170c driver/fingerprint/fpc/bep/fpc1025_private.h: Format with clang-format
98a20f937e common/fpsensor/fpsensor_state.c: Format with clang-format
a2d255d8af common/fpsensor/fpsensor.c: Format with clang-format
84e53a65da board/nocturne_fp/board.h: Format with clang-format
73055eeb3f driver/fingerprint/fpc/bep/fpc_private.c: Format with clang-format
0f7b5cb509 common/fpsensor/fpsensor_private.h: Format with clang-format
1ceade6e65 driver/fingerprint/fpc/bep/fpc_private.h: Format with clang-format
dca9d74321 Revert "trng: Rename rand to trng_rand"
a6b0b3554f trng: Rename rand to trng_rand
28d0b75b70 third_party/boringssl: Remove unused header
BRANCH=None
BUG=b:244387210 b:242720240 b:215613183 b:242720910 b:236386294
BUG=b:234181908 b:244781166 b:234781655 b:234143158 b:234181908
BUG=b:237344361 b:236025198 b:234181908 b:180945056 chromium:1098010
BUG=b:246424843 b:234181908 b:131913998
TEST=`make -j buildall`
TEST=./util/run_device_tests.py --board dartmonkey
Test "aes": PASSED
Test "cec": PASSED
Test "cortexm_fpu": PASSED
Test "crc": PASSED
Test "flash_physical": PASSED
Test "flash_write_protect": PASSED
Test "fpsensor_hw": PASSED
Test "fpsensor_spi_ro": PASSED
Test "fpsensor_spi_rw": PASSED
Test "fpsensor_uart_ro": PASSED
Test "fpsensor_uart_rw": PASSED
Test "mpu_ro": PASSED
Test "mpu_rw": PASSED
Test "mutex": PASSED
Test "pingpong": PASSED
Test "printf": PASSED
Test "queue": PASSED
Test "rollback_region0": PASSED
Test "rollback_region1": PASSED
Test "rollback_entropy": PASSED
Test "rtc": PASSED
Test "sha256": PASSED
Test "sha256_unrolled": PASSED
Test "static_if": PASSED
Test "stdlib": PASSED
Test "system_is_locked_wp_on": PASSED
Test "system_is_locked_wp_off": PASSED
Test "timer_dos": PASSED
Test "utils": PASSED
Test "utils_str": PASSED
Test "panic_data_dartmonkey_v2.0.2887": PASSED
Test "panic_data_nocturne_fp_v2.2.64": PASSED
Test "panic_data_nami_fp_v2.2.144": PASSED
Force-Relevant-Builds: all
Signed-off-by: Tom Hughes <tomhughes@chromium.org>
Change-Id: I2c312583a709fedae8fe11d92c22328c3b634bc7
Diffstat (limited to 'zephyr/test/drivers/default/src/integration/usbc/usb_attach_src_snk.c')
-rw-r--r-- | zephyr/test/drivers/default/src/integration/usbc/usb_attach_src_snk.c | 792 |
1 files changed, 792 insertions, 0 deletions
diff --git a/zephyr/test/drivers/default/src/integration/usbc/usb_attach_src_snk.c b/zephyr/test/drivers/default/src/integration/usbc/usb_attach_src_snk.c new file mode 100644 index 0000000000..761bb9daf1 --- /dev/null +++ b/zephyr/test/drivers/default/src/integration/usbc/usb_attach_src_snk.c @@ -0,0 +1,792 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <zephyr/kernel.h> +#include <zephyr/ztest.h> +#include <zephyr/drivers/gpio/gpio_emul.h> + +#include "ec_commands.h" +#include "ec_tasks.h" +#include "driver/tcpm/ps8xxx_public.h" +#include "emul/emul_isl923x.h" +#include "emul/tcpc/emul_ps8xxx.h" +#include "emul/tcpc/emul_tcpci.h" +#include "emul/tcpc/emul_tcpci_partner_snk.h" +#include "emul/tcpc/emul_tcpci_partner_src.h" +#include "host_command.h" +#include "test/drivers/stubs.h" +#include "tcpm/tcpci.h" +#include "test/usb_pe.h" +#include "test/drivers/utils.h" +#include "test/drivers/test_state.h" + +#define SNK_PORT USBC_PORT_C0 +#define SRC_PORT USBC_PORT_C1 + +#define DEFAULT_VBUS_MV 5000 + +/* Determined by CONFIG_PLATFORM_EC_USB_PD_PULLUP */ +#define DEFAULT_VBUS_SRC_PORT_MA 1500 + +/* SRC TCPCI Emulator attaches as TYPEC_CC_VOLT_RP_3_0 */ +#define DEFAULT_VBUS_SNK_PORT_MA 3000 + +#define DEFAULT_SINK_SENT_TO_SOURCE_CAP_COUNT 1 +#define DEFAULT_SOURCE_SENT_TO_SINK_CAP_COUNT 1 + +struct emul_state { + /* TODO(b/217737667): Remove driver specific code. */ + const struct emul *tcpci_generic_emul; + const struct emul *tcpci_ps8xxx_emul; + const struct emul *charger_isl923x_emul; + struct tcpci_partner_data my_src; + struct tcpci_src_emul_data src_ext; + struct tcpci_partner_data my_snk; + struct tcpci_snk_emul_data snk_ext; +}; + +struct integration_usb_attach_src_then_snk_fixture { + struct emul_state my_emulator_state; +}; + +struct integration_usb_attach_snk_then_src_fixture { + struct emul_state my_emulator_state; +}; + +static void integration_usb_setup(struct emul_state *fixture) +{ + const struct emul *tcpci_emul = EMUL_GET_USBC_BINDING(0, tcpc); + const struct emul *tcpci_emul2 = EMUL_GET_USBC_BINDING(1, tcpc); + const struct emul *charger_emul = EMUL_GET_USBC_BINDING(0, chg); + + /* Setting these are required because compiler believes these values are + * not compile time constants. + */ + /* + * TODO(b/217758708): emuls should be identified at compile-time. + */ + fixture->tcpci_generic_emul = tcpci_emul; + fixture->tcpci_ps8xxx_emul = tcpci_emul2; + fixture->charger_isl923x_emul = charger_emul; + + tcpci_partner_init(&fixture->my_snk, PD_REV20); + fixture->my_snk.extensions = + tcpci_snk_emul_init(&fixture->snk_ext, &fixture->my_snk, NULL); + + tcpci_partner_init(&fixture->my_src, PD_REV20); + fixture->my_src.extensions = + tcpci_src_emul_init(&fixture->src_ext, &fixture->my_src, NULL); + + /* + * TODO(b/221288815): TCPCI config flags should be compile-time + * constants + * TODO(b/209907615): Verify TCPCI rev1 on non-port partner. + */ + /* Turn TCPCI rev 2 ON */ + tcpc_config[SNK_PORT].flags |= TCPC_FLAGS_TCPCI_REV2_0; + tcpc_config[SRC_PORT].flags |= TCPC_FLAGS_TCPCI_REV2_0; +} + +static void *integration_usb_src_snk_setup(void) +{ + static struct integration_usb_attach_src_then_snk_fixture fixture_state; + + integration_usb_setup(&fixture_state.my_emulator_state); + + return &fixture_state; +} + +static void *integration_usb_snk_src_setup(void) +{ + static struct integration_usb_attach_snk_then_src_fixture fixture_state; + + integration_usb_setup(&fixture_state.my_emulator_state); + + return &fixture_state; +} + +static void attach_src_snk_common_before(struct emul_state *my_emul_state) +{ + const struct emul *tcpci_emul_src = my_emul_state->tcpci_generic_emul; + const struct emul *tcpci_emul_snk = my_emul_state->tcpci_ps8xxx_emul; + const struct emul *charger_emul = my_emul_state->charger_isl923x_emul; + + /* Reset vbus to 0mV */ + /* TODO(b/217737667): Remove driver specific code. */ + isl923x_emul_set_adc_vbus(charger_emul, 0); + + zassume_ok(tcpc_config[SNK_PORT].drv->init(SNK_PORT), NULL); + /* + * Arbitrary FW ver. The emulator should really be setting this + * during its init. + */ + tcpci_emul_set_reg(tcpci_emul_snk, PS8XXX_REG_FW_REV, 0x31); + + zassume_ok(tcpc_config[SRC_PORT].drv->init(SRC_PORT), NULL); + + pd_set_suspend(SNK_PORT, false); + pd_set_suspend(SRC_PORT, false); + + /* Reset to disconnected state. */ + zassume_ok(tcpci_emul_disconnect_partner(tcpci_emul_src), NULL); + zassume_ok(tcpci_emul_disconnect_partner(tcpci_emul_snk), NULL); + + /* Set chipset to ON, this will set TCPM to DRP */ + test_set_chipset_to_s0(); +} + +static void attach_src_snk_common_after(struct emul_state *my_emul_state) +{ + const struct emul *tcpci_generic_emul = + my_emul_state->tcpci_generic_emul; + const struct emul *tcpci_ps8xxx_emul = my_emul_state->tcpci_ps8xxx_emul; + const struct emul *charger_emul = my_emul_state->charger_isl923x_emul; + + tcpci_emul_disconnect_partner(tcpci_generic_emul); + tcpci_emul_disconnect_partner(tcpci_ps8xxx_emul); + + /* Give time to actually disconnect */ + k_sleep(K_SECONDS(1)); + + /* Reset vbus to 0mV */ + /* TODO(b/217737667): Remove driver specific code. */ + isl923x_emul_set_adc_vbus(charger_emul, 0); +} + +static void attach_emulated_snk(struct emul_state *my_emul_state) +{ + const struct emul *tcpci_emul_snk = my_emul_state->tcpci_ps8xxx_emul; + struct tcpci_partner_data *my_snk = &my_emul_state->my_snk; + uint16_t power_reg_val; + + /* Turn on VBUS detection */ + /* + * TODO(b/223901282): integration tests should not be setting vbus + * detection via registers, also this should be turned on by default. + */ + tcpci_emul_get_reg(tcpci_emul_snk, TCPC_REG_POWER_STATUS, + &power_reg_val); + tcpci_emul_set_reg(tcpci_emul_snk, TCPC_REG_POWER_STATUS, + power_reg_val | TCPC_REG_POWER_STATUS_VBUS_DET); + + /* Necessary for TCPCIv2 vSave0V detection on VBUS to reach attached + * state + */ + tcpci_emul_set_reg(tcpci_emul_snk, TCPC_REG_EXT_STATUS, + TCPC_REG_EXT_STATUS_SAFE0V); + + zassume_ok(tcpci_partner_connect_to_tcpci(my_snk, tcpci_emul_snk), + NULL); + + /* TODO(b/214401892): Check why need to give time TCPM to spin */ + k_sleep(K_SECONDS(1)); +} + +static void attach_emulated_src(struct emul_state *my_emul_state) +{ + const struct emul *tcpci_emul_src = my_emul_state->tcpci_generic_emul; + const struct emul *charger_emul = my_emul_state->charger_isl923x_emul; + struct tcpci_partner_data *my_src = &my_emul_state->my_src; + uint16_t power_reg_val; + + /* Turn on VBUS detection */ + /* + * TODO(b/223901282): integration tests should not be setting vbus + * detection via registers, also this should be turned on by default. + */ + tcpci_emul_get_reg(tcpci_emul_src, TCPC_REG_POWER_STATUS, + &power_reg_val); + tcpci_emul_set_reg(tcpci_emul_src, TCPC_REG_POWER_STATUS, + power_reg_val | TCPC_REG_POWER_STATUS_VBUS_DET); + + /* Necessary for TCPCIv2 vSave0V detection on VBUS to reach attached + * state + */ + tcpci_emul_set_reg(tcpci_emul_src, TCPC_REG_EXT_STATUS, + TCPC_REG_EXT_STATUS_SAFE0V); + + zassume_ok(tcpci_partner_connect_to_tcpci(my_src, tcpci_emul_src), + NULL); + isl923x_emul_set_adc_vbus(charger_emul, DEFAULT_VBUS_MV); +} + +static void integration_usb_attach_snk_then_src_before(void *state) +{ + struct integration_usb_attach_src_then_snk_fixture *fixture = state; + struct emul_state *my_state = &fixture->my_emulator_state; + + attach_src_snk_common_before(my_state); + + /* 1) Attach SINK */ + attach_emulated_snk(my_state); + + /* Wait for PD negotiation */ + k_sleep(K_SECONDS(10)); + + /* 2) Attach SOURCE */ + attach_emulated_src(my_state); + + /* Wait for PD negotiation */ + k_sleep(K_SECONDS(10)); +} + +static void integration_usb_attach_src_then_snk_before(void *state) +{ + struct integration_usb_attach_src_then_snk_fixture *fixture = state; + struct emul_state *my_state = &fixture->my_emulator_state; + + attach_src_snk_common_before(my_state); + + /* 1) Attach SOURCE */ + attach_emulated_src(my_state); + + /* Wait for PD negotiation */ + k_sleep(K_SECONDS(10)); + + /* 2) Attach SINK */ + attach_emulated_snk(my_state); + + /* Wait for PD negotiation */ + k_sleep(K_SECONDS(10)); +} + +static void integration_usb_attach_src_then_snk_after(void *state) +{ + struct integration_usb_attach_src_then_snk_fixture *fixture = state; + + attach_src_snk_common_after(&fixture->my_emulator_state); +} + +static void integration_usb_attach_snk_then_src_after(void *state) +{ + struct integration_usb_attach_snk_then_src_fixture *fixture = state; + + attach_src_snk_common_after(&fixture->my_emulator_state); +} + +ZTEST_F(integration_usb_attach_src_then_snk, verify_snk_port_pd_info) +{ + struct ec_response_usb_pd_power_info response; + + response = host_cmd_power_info(SNK_PORT); + + /* Assert */ + zassert_equal(response.role, USB_PD_PORT_POWER_SINK, + "Power role %d, but PD reports role %d", + USB_PD_PORT_POWER_SINK, response.role); + zassert_equal(response.type, USB_CHG_TYPE_PD, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_PD, response.type); + + zassert_equal(response.meas.voltage_max, DEFAULT_VBUS_MV, + "Charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, response.meas.voltage_max); + + zassert_within(response.meas.voltage_now, DEFAULT_VBUS_MV, + DEFAULT_VBUS_MV / 10, + "Actually charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, response.meas.voltage_now); + + zassert_equal(response.meas.current_max, DEFAULT_VBUS_SNK_PORT_MA, + "Charging at VBUS max %dmA, but PD reports %dmA", + DEFAULT_VBUS_SNK_PORT_MA, response.meas.current_max); + + zassert_true(response.meas.current_lim >= DEFAULT_VBUS_SNK_PORT_MA, + "Charging at VBUS max %dmA, but PD current limit %dmA", + DEFAULT_VBUS_SNK_PORT_MA, response.meas.current_lim); + + zassert_equal(response.max_power, + DEFAULT_VBUS_MV * DEFAULT_VBUS_SNK_PORT_MA, + "Charging up to %duW, PD max power %duW", + DEFAULT_VBUS_MV * DEFAULT_VBUS_SNK_PORT_MA, + response.max_power); +} + +ZTEST_F(integration_usb_attach_src_then_snk, verify_src_port_pd_info) +{ + struct ec_response_usb_pd_power_info response; + + response = host_cmd_power_info(SRC_PORT); + + /* Assert */ + zassert_equal(response.role, USB_PD_PORT_POWER_SOURCE, + "Power role %d, but PD reports role %d", PD_ROLE_SOURCE, + response.role); + + zassert_equal(response.type, USB_CHG_TYPE_NONE, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_NONE, response.type); + + /* TODO(b/209907615): Confirm measure value requirements */ + zassert_within(response.meas.voltage_now, DEFAULT_VBUS_MV, + DEFAULT_VBUS_MV / 10, + "Expected Charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, response.meas.voltage_now); + + zassert_equal(response.meas.current_max, DEFAULT_VBUS_SRC_PORT_MA, + "Charging at VBUS max %dmA, but PD reports %dmA", + DEFAULT_VBUS_SRC_PORT_MA, response.meas.current_max); + + /* Note: We are the source so we skip checking: */ + /* meas.voltage_max */ + /* max_power */ + /* current limit */ +} + +ZTEST_F(integration_usb_attach_snk_then_src, verify_snk_port_pd_info) +{ + struct ec_response_usb_pd_power_info response; + + response = host_cmd_power_info(SNK_PORT); + + /* Assert */ + zassert_equal(response.role, USB_PD_PORT_POWER_SINK, + "Power role %d, but PD reports role %d", + USB_PD_PORT_POWER_SINK, response.role); + zassert_equal(response.type, USB_CHG_TYPE_PD, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_PD, response.type); + + /* Verify Default 5V and 3A */ + zassert_equal(response.meas.voltage_max, DEFAULT_VBUS_MV, + "Charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, response.meas.voltage_max); + + zassert_within(response.meas.voltage_now, DEFAULT_VBUS_MV, + DEFAULT_VBUS_MV / 10, + "Actually charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, response.meas.voltage_now); + + zassert_equal(response.meas.current_max, DEFAULT_VBUS_SNK_PORT_MA, + "Charging at VBUS max %dmA, but PD reports %dmA", + DEFAULT_VBUS_SNK_PORT_MA, response.meas.current_max); + + zassert_true(response.meas.current_lim >= DEFAULT_VBUS_SNK_PORT_MA, + "Charging at VBUS max %dmA, but PD current limit %dmA", + DEFAULT_VBUS_SNK_PORT_MA, response.meas.current_lim); + + zassert_equal(response.max_power, + DEFAULT_VBUS_MV * DEFAULT_VBUS_SNK_PORT_MA, + "Charging up to %duW, PD max power %duW", + DEFAULT_VBUS_MV * DEFAULT_VBUS_SNK_PORT_MA, + response.max_power); +} + +ZTEST_F(integration_usb_attach_snk_then_src, verify_src_port_pd_info) +{ + struct ec_response_usb_pd_power_info response; + + response = host_cmd_power_info(SRC_PORT); + + /* Assert */ + zassert_equal(response.role, USB_PD_PORT_POWER_SOURCE, + "Power role %d, but PD reports role %d", PD_ROLE_SOURCE, + response.role); + + zassert_equal(response.type, USB_CHG_TYPE_NONE, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_NONE, response.type); + + /* Verify Default 5V and 3A */ + /* TODO(b/209907615): Confirm measure value requirements */ + zassert_within(response.meas.voltage_now, DEFAULT_VBUS_MV, + DEFAULT_VBUS_MV / 10, + "Expected Charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, response.meas.voltage_now); + + zassert_equal(response.meas.current_max, DEFAULT_VBUS_SRC_PORT_MA, + "Charging at VBUS max %dmA, but PD reports %dmA", + DEFAULT_VBUS_SRC_PORT_MA, response.meas.current_max); + + /* Note: We are the source so we skip checking: */ + /* meas.voltage_max */ + /* max_power */ + /* current limit */ +} + +ZTEST_F(integration_usb_attach_src_then_snk, verify_snk_port_typec_status) +{ + struct ec_response_typec_status response = + host_cmd_typec_status(SNK_PORT); + + zassert_true(response.pd_enabled, "Source attached but PD disabled"); + + zassert_true(response.dev_connected, + "Source attached but device disconnected"); + + zassert_true(response.sop_connected, + "Source attached but not SOP capable"); + + zassert_equal(response.source_cap_count, + DEFAULT_SOURCE_SENT_TO_SINK_CAP_COUNT, + "Source received %d source PDOs", + response.source_cap_count); + + /* The source emulator is being attached to a sink port (our policy + * engine) so it does not send any sink caps, so sink port received no + * sink caps. + */ + zassert_equal(response.sink_cap_count, 0, "Port received %d sink PDOs", + response.sink_cap_count); + + zassert_equal(response.power_role, PD_ROLE_SINK, + "Source attached, but TCPM power role is %d", + response.power_role); +} + +ZTEST_F(integration_usb_attach_src_then_snk, verify_src_port_typec_status) +{ + struct ec_response_typec_status response = + host_cmd_typec_status(SRC_PORT); + + zassert_true(response.pd_enabled, "Sink attached but PD disabled"); + + zassert_true(response.dev_connected, + "Sink attached but device disconnected"); + + zassert_true(response.sop_connected, + "Sink attached but not SOP capable"); + + /* The sink emulator is being attached to a source port (our policy + * engine) so it does not send any sink caps, so source port received no + * sink caps. + */ + zassert_equal(response.source_cap_count, 0, + "Port received %d source PDOs", + response.source_cap_count); + + zassert_equal(response.sink_cap_count, + DEFAULT_SINK_SENT_TO_SOURCE_CAP_COUNT, + "Port received %d sink PDOs", response.sink_cap_count); + + zassert_equal(response.power_role, PD_ROLE_SOURCE, + "Sink attached, but TCPM power role is %d", + response.power_role); +} + +ZTEST_F(integration_usb_attach_snk_then_src, verify_snk_port_typec_status) +{ + struct ec_response_typec_status response = + host_cmd_typec_status(SNK_PORT); + + zassert_true(response.pd_enabled, "Source attached but PD disabled"); + + zassert_true(response.dev_connected, + "Source attached but device disconnected"); + + zassert_true(response.sop_connected, + "Source attached but not SOP capable"); + + zassert_equal(response.source_cap_count, + DEFAULT_SOURCE_SENT_TO_SINK_CAP_COUNT, + "Source received %d source PDOs", + response.source_cap_count); + + /* The source emulator is being attached to a sink port (our policy + * engine) so it does not send any sink caps, so sink port received no + * sink caps. + */ + zassert_equal(response.sink_cap_count, 0, "Port received %d sink PDOs", + response.sink_cap_count); + + zassert_equal(response.power_role, PD_ROLE_SINK, + "Source attached, but TCPM power role is %d", + response.power_role); +} + +ZTEST_F(integration_usb_attach_snk_then_src, verify_src_port_typec_status) +{ + struct ec_response_typec_status response = + host_cmd_typec_status(SRC_PORT); + + zassert_true(response.pd_enabled, "Sink attached but PD disabled"); + + zassert_true(response.dev_connected, + "Sink attached but device disconnected"); + + zassert_true(response.sop_connected, + "Sink attached but not SOP capable"); + + /* The sink emulator is being attached to a source port (our policy + * engine) so it does not send any sink caps, so source port received no + * sink caps. + */ + zassert_equal(response.source_cap_count, 0, + "Port received %d source PDOs", + response.source_cap_count); + + zassert_equal(response.sink_cap_count, + DEFAULT_SINK_SENT_TO_SOURCE_CAP_COUNT, + "Port received %d sink PDOs", response.sink_cap_count); + + zassert_equal(response.power_role, PD_ROLE_SOURCE, + "Sink attached, but TCPM power role is %d", + response.power_role); +} + +ZTEST_SUITE(integration_usb_attach_src_then_snk, drivers_predicate_post_main, + integration_usb_src_snk_setup, + integration_usb_attach_src_then_snk_before, + integration_usb_attach_src_then_snk_after, NULL); + +ZTEST_SUITE(integration_usb_attach_snk_then_src, drivers_predicate_post_main, + integration_usb_snk_src_setup, + integration_usb_attach_snk_then_src_before, + integration_usb_attach_snk_then_src_after, NULL); + +struct usb_detach_test_fixture { + struct emul_state fixture; +}; + +static void integration_usb_test_detach(const struct emul *e) +{ + zassume_ok(tcpci_emul_disconnect_partner(e), NULL); +} + +static void integration_usb_test_sink_detach(struct emul_state *fixture) +{ + integration_usb_test_detach(fixture->tcpci_ps8xxx_emul); +} + +static void integration_usb_test_source_detach(struct emul_state *fixture) +{ + integration_usb_test_detach(fixture->tcpci_generic_emul); +} + +void *usb_detach_test_setup(void) +{ + static struct usb_detach_test_fixture usb_detach_fixture = { 0 }; + + integration_usb_setup(&usb_detach_fixture.fixture); + + return &usb_detach_fixture; +} + +static void usb_detach_test_before(void *state) +{ + struct usb_detach_test_fixture *fixture = state; + struct emul_state *my_state = &fixture->fixture; + + attach_src_snk_common_before(my_state); + + /* 1) Attach SINK */ + attach_emulated_snk(my_state); + + /* Wait for PD negotiation */ + k_sleep(K_SECONDS(10)); + + /* 2) Attach SOURCE */ + attach_emulated_src(my_state); + + /* Wait for PD negotiation */ + k_sleep(K_SECONDS(10)); +} + +static void usb_detach_test_after(void *state) +{ + struct usb_detach_test_fixture *fixture = state; + + attach_src_snk_common_after(&fixture->fixture); +} + +ZTEST_F(usb_detach_test, verify_detach_src_snk) +{ + struct emul_state *emul_state = &fixture->fixture; + struct ec_response_usb_pd_power_info src_power_info = { 0 }; + struct ec_response_usb_pd_power_info snk_power_info = { 0 }; + + integration_usb_test_source_detach(emul_state); + integration_usb_test_sink_detach(emul_state); + + k_sleep(K_SECONDS(10)); + isl923x_emul_set_adc_vbus(emul_state->charger_isl923x_emul, 0); + + snk_power_info = host_cmd_power_info(SNK_PORT); + src_power_info = host_cmd_power_info(SRC_PORT); + + /* Validate Sink power info */ + zassert_equal(snk_power_info.role, USB_PD_PORT_POWER_DISCONNECTED, + "Power role %d, but PD reports role %d", + USB_PD_PORT_POWER_DISCONNECTED, snk_power_info.role); + zassert_equal(snk_power_info.type, USB_CHG_TYPE_NONE, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_NONE, snk_power_info.type); + + zassert_equal(snk_power_info.meas.voltage_max, 0, + "Charging at VBUS %dmV, but PD reports %dmV", 0, + snk_power_info.meas.voltage_max); + + zassert_within(snk_power_info.meas.voltage_now, 0, 10, + "Actually charging at VBUS %dmV, but PD reports %dmV", 0, + snk_power_info.meas.voltage_now); + + zassert_equal(snk_power_info.meas.current_max, 0, + "Charging at VBUS max %dmA, but PD reports %dmA", 0, + snk_power_info.meas.current_max); + + zassert_true(snk_power_info.meas.current_lim >= 0, + "Charging at VBUS max %dmA, but PD current limit %dmA", 0, + snk_power_info.meas.current_lim); + + zassert_equal(snk_power_info.max_power, 0, + "Charging up to %duW, PD max power %duW", 0, + snk_power_info.max_power); + + /* Validate Source power info */ + zassert_equal(src_power_info.role, USB_PD_PORT_POWER_DISCONNECTED, + "Power role %d, but PD reports role %d", + USB_PD_PORT_POWER_DISCONNECTED, src_power_info.role); + + zassert_equal(src_power_info.type, USB_CHG_TYPE_NONE, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_NONE, src_power_info.type); + + /* TODO(b/209907615): Confirm measure value requirements */ + zassert_within(src_power_info.meas.voltage_now, 0, 10, + "Expected Charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, src_power_info.meas.voltage_now); + + zassert_equal(src_power_info.meas.current_max, 0, + "Charging at VBUS max %dmA, but PD reports %dmA", 0, + src_power_info.meas.current_max); +} + +ZTEST_F(usb_detach_test, verify_detach_snk_src) +{ + struct emul_state *emul_state = &fixture->fixture; + struct ec_response_usb_pd_power_info src_power_info = { 0 }; + struct ec_response_usb_pd_power_info snk_power_info = { 0 }; + + integration_usb_test_sink_detach(emul_state); + integration_usb_test_source_detach(emul_state); + + k_sleep(K_SECONDS(10)); + isl923x_emul_set_adc_vbus(emul_state->charger_isl923x_emul, 0); + + snk_power_info = host_cmd_power_info(SNK_PORT); + src_power_info = host_cmd_power_info(SRC_PORT); + + /* Validate Sink power info */ + zassert_equal(snk_power_info.role, USB_PD_PORT_POWER_DISCONNECTED, + "Power role %d, but PD reports role %d", + USB_PD_PORT_POWER_DISCONNECTED, snk_power_info.role); + zassert_equal(snk_power_info.type, USB_CHG_TYPE_NONE, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_NONE, snk_power_info.type); + + zassert_equal(snk_power_info.meas.voltage_max, 0, + "Charging at VBUS %dmV, but PD reports %dmV", 0, + snk_power_info.meas.voltage_max); + + zassert_within(snk_power_info.meas.voltage_now, 0, 10, + "Actually charging at VBUS %dmV, but PD reports %dmV", 0, + snk_power_info.meas.voltage_now); + + zassert_equal(snk_power_info.meas.current_max, 0, + "Charging at VBUS max %dmA, but PD reports %dmA", 0, + snk_power_info.meas.current_max); + + zassert_true(snk_power_info.meas.current_lim >= 0, + "Charging at VBUS max %dmA, but PD current limit %dmA", 0, + snk_power_info.meas.current_lim); + + zassert_equal(snk_power_info.max_power, 0, + "Charging up to %duW, PD max power %duW", 0, + snk_power_info.max_power); + + /* Validate Source power info */ + zassert_equal(src_power_info.role, USB_PD_PORT_POWER_DISCONNECTED, + "Power role %d, but PD reports role %d", + USB_PD_PORT_POWER_DISCONNECTED, src_power_info.role); + + zassert_equal(src_power_info.type, USB_CHG_TYPE_NONE, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_NONE, src_power_info.type); + + /* TODO(b/209907615): Confirm measure value requirements */ + zassert_within(src_power_info.meas.voltage_now, 0, 10, + "Expected Charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, src_power_info.meas.voltage_now); + + zassert_equal(src_power_info.meas.current_max, 0, + "Charging at VBUS max %dmA, but PD reports %dmA", 0, + src_power_info.meas.current_max); +} + +ZTEST_F(usb_detach_test, verify_detach_sink) +{ + struct emul_state *emul_state = &fixture->fixture; + struct ec_response_usb_pd_power_info pd_power_info = { 0 }; + + integration_usb_test_sink_detach(emul_state); + k_sleep(K_SECONDS(10)); + isl923x_emul_set_adc_vbus(emul_state->charger_isl923x_emul, 0); + + pd_power_info = host_cmd_power_info(SNK_PORT); + + /* Assert */ + zassert_equal(pd_power_info.role, USB_PD_PORT_POWER_SINK, + "Power role %d, but PD reports role %d", + USB_PD_PORT_POWER_SINK, pd_power_info.role); + zassert_equal(pd_power_info.type, USB_CHG_TYPE_PD, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_PD, pd_power_info.type); + + zassert_equal(pd_power_info.meas.voltage_max, DEFAULT_VBUS_MV, + "Charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, pd_power_info.meas.voltage_max); + + zassert_within(pd_power_info.meas.voltage_now, 0, 10, + "Actually charging at VBUS %dmV, but PD reports %dmV", 0, + pd_power_info.meas.voltage_now); + + zassert_equal(pd_power_info.meas.current_max, DEFAULT_VBUS_SNK_PORT_MA, + "Charging at VBUS max %dmA, but PD reports %dmA", + DEFAULT_VBUS_SNK_PORT_MA, pd_power_info.meas.current_max); + + zassert_true(pd_power_info.meas.current_lim >= 500, + "Charging at VBUS max %dmA, but PD current limit %dmA", + 500, pd_power_info.meas.current_lim); + + zassert_equal(pd_power_info.max_power, + DEFAULT_VBUS_MV * DEFAULT_VBUS_SNK_PORT_MA, + "Charging up to %duW, PD max power %duW", + DEFAULT_VBUS_MV * DEFAULT_VBUS_SNK_PORT_MA, + pd_power_info.max_power); +} + +ZTEST_F(usb_detach_test, verify_detach_source) +{ + struct emul_state *emul_state = &fixture->fixture; + struct ec_response_usb_pd_power_info pd_power_info = { SNK_PORT }; + + integration_usb_test_source_detach(emul_state); + k_sleep(K_SECONDS(10)); + isl923x_emul_set_adc_vbus(emul_state->charger_isl923x_emul, 0); + + pd_power_info = host_cmd_power_info(SNK_PORT); + + /* Assert */ + zassert_equal(pd_power_info.role, USB_PD_PORT_POWER_DISCONNECTED, + "Power role %d, but PD reports role %d", + USB_PD_PORT_POWER_DISCONNECTED, pd_power_info.role); + + zassert_equal(pd_power_info.type, USB_CHG_TYPE_NONE, + "Charger type %d, but PD reports type %d", + USB_CHG_TYPE_NONE, pd_power_info.type); + + /* TODO(b/209907615): Confirm measure value requirements */ + zassert_within(pd_power_info.meas.voltage_now, 0, 10, + "Expected Charging at VBUS %dmV, but PD reports %dmV", + DEFAULT_VBUS_MV, pd_power_info.meas.voltage_now); + + zassert_equal(pd_power_info.meas.current_max, 0, + "Charging at VBUS max %dmA, but PD reports %dmA", 0, + pd_power_info.meas.current_max); +} + +ZTEST_SUITE(usb_detach_test, drivers_predicate_post_main, + integration_usb_src_snk_setup, usb_detach_test_before, + usb_detach_test_after, NULL); |