From d83b8aa7fd9f502c3cad258d60424075716fc6da Mon Sep 17 00:00:00 2001 From: Diana Z Date: Mon, 16 Jan 2023 17:09:17 -0700 Subject: Test: Add test for VDM:Attention delivery Add unit tests to ensure we deliver VDM:Attention properly up to the AP with messages in the correct order. BRANCH=None BUG=b:208884535 TEST=./twister -T ./zephyr/test Change-Id: I922b391e6d2fb9c969063be2b8d2e492fe8e74b3 Signed-off-by: Diana Z Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4171492 Reviewed-by: Abe Levkoy --- .../drivers/ap_vdm_control/src/ap_vdm_control.c | 247 +++++++++++++++++++++ 1 file changed, 247 insertions(+) diff --git a/zephyr/test/drivers/ap_vdm_control/src/ap_vdm_control.c b/zephyr/test/drivers/ap_vdm_control/src/ap_vdm_control.c index da6fdc5512..434335e9b4 100644 --- a/zephyr/test/drivers/ap_vdm_control/src/ap_vdm_control.c +++ b/zephyr/test/drivers/ap_vdm_control/src/ap_vdm_control.c @@ -83,6 +83,39 @@ static void add_dp_discovery(struct tcpci_partner_data *partner) partner->svids_vdos = VDO_INDEX_HDR + 2; } +static void add_displayport_mode_responses(struct tcpci_partner_data *partner) +{ + /* Add DisplayPort EnterMode response */ + partner->enter_mode_vdm[VDO_INDEX_HDR] = + VDO(USB_SID_DISPLAYPORT, /* structured VDM */ true, + VDO_CMDT(CMDT_RSP_ACK) | CMD_ENTER_MODE) | + VDO_SVDM_VERS(VDM_VER20); + partner->enter_mode_vdos = VDO_INDEX_HDR + 1; + + /* Add DisplayPort StatusUpdate response */ + partner->dp_status_vdm[VDO_INDEX_HDR] = + VDO(USB_SID_DISPLAYPORT, /* structured VDM */ true, + VDO_CMDT(CMDT_RSP_ACK) | CMD_DP_STATUS) | + VDO_SVDM_VERS(VDM_VER20); + partner->dp_status_vdm[VDO_INDEX_HDR + 1] = + VDO_DP_STATUS(0, /* IRQ_HPD */ + false, /* HPD_HI|LOW - Changed*/ + 0, /* request exit DP */ + 0, /* request exit USB */ + 1, /* MF pref */ + true, /* DP Enabled */ + 0, /* power low e.g. normal */ + 0x2 /* Connected as Sink */); + partner->dp_status_vdos = VDO_INDEX_HDR + 2; + + /* Add DisplayPort Configure Response */ + partner->dp_config_vdm[VDO_INDEX_HDR] = + VDO(USB_SID_DISPLAYPORT, /* structured VDM */ true, + VDO_CMDT(CMDT_RSP_ACK) | CMD_DP_CONFIG) | + VDO_SVDM_VERS(VDM_VER20); + partner->dp_config_vdos = VDO_INDEX_HDR + 1; +} + static void verify_vdm_req(struct ap_vdm_control_fixture *fixture, struct typec_vdm_req *req) { @@ -148,6 +181,7 @@ static void ap_vdm_control_before(void *data) /* Set up the partner as DP-capable with a passive cable */ add_dp_discovery(partner); partner->cable = &passive_usb3; + add_displayport_mode_responses(partner); /* Connect our port partner */ connect_source_to_port(&fix->partner, &fix->src_ext, 0, fix->tcpci_emul, @@ -457,3 +491,216 @@ ZTEST_F(ap_vdm_control, test_vdm_request_no_send) zassert_equal(vdm_resp.vdm_response_err, EC_RES_UNAVAILABLE, "Failed to see no message ready"); } + +/* Tests for the DP entry flow and related requirements */ +static void verify_expected_reply(enum typec_partner_type type, + int expected_num_objects, uint32_t *contents) +{ + struct ec_response_typec_status status; + struct ec_response_typec_vdm_response vdm_resp; + + status = host_cmd_typec_status(TEST_PORT); + zassert_true(status.events & PD_STATUS_EVENT_VDM_REQ_REPLY, + "Failed to see VDM ACK event"); + + vdm_resp = host_cmd_typec_vdm_response(TEST_PORT); + zassert_equal(vdm_resp.partner_type, type, + "Failed to see correct partner"); + zassert_equal(vdm_resp.vdm_data_objects, expected_num_objects, + "Failed to see correct number of objects"); + zassert_equal(memcmp(vdm_resp.vdm_response, contents, + expected_num_objects * sizeof(uint32_t)), + 0, "Failed to see correct VDM contents"); +} + +static void run_verify_dp_entry(struct ap_vdm_control_fixture *fixture, + int opos) +{ + /* + * Test the full flow of DP entry and configure, to set up for + * further test cases. + */ + struct typec_vdm_req req = { + .vdm_data = { VDO(USB_SID_DISPLAYPORT, 1, + CMD_ENTER_MODE | VDO_OPOS(opos)) | + VDO_SVDM_VERS(VDM_VER20) }, + .vdm_data_objects = 1, + .partner_type = TYPEC_PARTNER_SOP, + }; + + /* Step 1: EnterMode */ + host_cmd_typec_control_vdm_req(TEST_PORT, req); + k_sleep(K_MSEC(100)); + + verify_expected_reply(req.partner_type, + fixture->partner.enter_mode_vdos, + fixture->partner.enter_mode_vdm); + + /* Step 2: DP Status */ + req.vdm_data[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_STATUS | VDO_OPOS(opos)) | + VDO_SVDM_VERS(VDM_VER20); + req.vdm_data[1] = VDO_DP_STATUS(0, /* HPD IRQ ... not applicable */ + 0, /* HPD level ... not applicable */ + 0, /* exit DP? ... no */ + 0, /* usb mode? ... no */ + 0, /* multi-function ... no */ + 0, /* currently enabled ... no */ + 0, /* power low? ... no */ + 1 /* DP source connected */); + req.vdm_data_objects = 2; + req.partner_type = TYPEC_PARTNER_SOP; + + host_cmd_typec_control_vdm_req(TEST_PORT, req); + k_sleep(K_MSEC(100)); + + verify_expected_reply(req.partner_type, fixture->partner.dp_status_vdos, + fixture->partner.dp_status_vdm); + + /* Step 3: DP Configure */ + req.vdm_data[0] = + VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)) | + VDO_SVDM_VERS(VDM_VER20); + req.vdm_data[1] = VDO_DP_CFG(MODE_DP_PIN_D, /* pin mode */ + 1, /* DPv1.3 signaling */ + 2); /* Set that partner should be DP sink + */ + req.vdm_data_objects = 2; + req.partner_type = TYPEC_PARTNER_SOP; + + host_cmd_typec_control_vdm_req(TEST_PORT, req); + k_sleep(K_MSEC(100)); + + verify_expected_reply(req.partner_type, fixture->partner.dp_config_vdos, + fixture->partner.dp_config_vdm); +} + +ZTEST_F(ap_vdm_control, test_vdm_attention_none) +{ + struct ec_response_typec_vdm_response vdm_resp; + int opos = 1; + + run_verify_dp_entry(fixture, opos); + + /* Check that we have no Attention messages and none in the queue */ + vdm_resp = host_cmd_typec_vdm_response(TEST_PORT); + zassert_equal(vdm_resp.vdm_attention_objects, 0, + "Failed to see empty message"); + zassert_equal(vdm_resp.vdm_attention_left, 0, + "Failed to see no more messages"); +} + +ZTEST_F(ap_vdm_control, test_vdm_attention_one) +{ + uint32_t vdm_attention_data[2]; + int opos = 1; + struct ec_response_typec_status status; + struct ec_response_typec_vdm_response vdm_resp; + + run_verify_dp_entry(fixture, opos); + + /* Test that we see our Attention message */ + vdm_attention_data[0] = + VDO(USB_SID_DISPLAYPORT, 1, + VDO_OPOS(opos) | VDO_CMDT(CMDT_INIT) | CMD_ATTENTION) | + VDO_SVDM_VERS(VDM_VER20); + vdm_attention_data[1] = VDO_DP_STATUS(1, /* IRQ_HPD */ + true, /* HPD_HI|LOW - Changed*/ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ + true, /* DP Enabled */ + 0, /* power low e.g. normal */ + 0x2 /* Connected as Sink */); + tcpci_partner_send_data_msg(&fixture->partner, PD_DATA_VENDOR_DEF, + vdm_attention_data, 2, 0); + + k_sleep(K_MSEC(100)); + /* + * Verify the event and the contents of our Attention + */ + status = host_cmd_typec_status(TEST_PORT); + zassert_true(status.events & PD_STATUS_EVENT_VDM_ATTENTION, + "Failed to see VDM Attention event"); + + vdm_resp = host_cmd_typec_vdm_response(TEST_PORT); + zassert_equal(vdm_resp.vdm_attention_objects, 2, + "Failed to see correct number of objects"); + zassert_equal(vdm_resp.vdm_attention_left, 0, + "Failed to see 0 more in queue"); + zassert_equal(memcmp(vdm_resp.vdm_attention, vdm_attention_data, + vdm_resp.vdm_attention_objects * sizeof(uint32_t)), + 0, "Failed to see correct Attention VDM contents"); +} + +ZTEST_F(ap_vdm_control, test_vdm_attention_two) +{ + uint32_t vdm_attention_first[2]; + uint32_t vdm_attention_second[2]; + int opos = 1; + struct ec_response_typec_status status; + struct ec_response_typec_vdm_response vdm_resp; + + run_verify_dp_entry(fixture, opos); + + /* Test that we see our first Attention message followed by second */ + vdm_attention_first[0] = + VDO(USB_SID_DISPLAYPORT, 1, + VDO_OPOS(opos) | VDO_CMDT(CMDT_INIT) | CMD_ATTENTION) | + VDO_SVDM_VERS(VDM_VER20); + vdm_attention_first[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + false, /* HPD_HI|LOW - Changed*/ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ + true, /* DP Enabled */ + 0, /* power low e.g. normal */ + 0x2 /* Connected as Sink */); + tcpci_partner_send_data_msg(&fixture->partner, PD_DATA_VENDOR_DEF, + vdm_attention_first, 2, 0); + + k_sleep(K_MSEC(100)); + + /* Number two time */ + vdm_attention_second[0] = + VDO(USB_SID_DISPLAYPORT, 1, + VDO_OPOS(opos) | VDO_CMDT(CMDT_INIT) | CMD_ATTENTION) | + VDO_SVDM_VERS(VDM_VER20); + vdm_attention_second[1] = VDO_DP_STATUS(1, /* IRQ_HPD */ + true, /* HPD_HI|LOW - Changed*/ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ + true, /* DP Enabled */ + 0, /* power low e.g. normal */ + 0x2 /* Connected as Sink */); + tcpci_partner_send_data_msg(&fixture->partner, PD_DATA_VENDOR_DEF, + vdm_attention_second, 2, 0); + + k_sleep(K_MSEC(100)); + /* + * Verify the event and the contents of our Attention from each in + * the proper order + */ + status = host_cmd_typec_status(TEST_PORT); + zassert_true(status.events & PD_STATUS_EVENT_VDM_ATTENTION, + "Failed to see VDM Attention event"); + + vdm_resp = host_cmd_typec_vdm_response(TEST_PORT); + zassert_equal(vdm_resp.vdm_attention_objects, 2, + "Failed to see correct number of objects"); + zassert_equal(vdm_resp.vdm_attention_left, 1, + "Failed to see 1 more in queue"); + zassert_equal(memcmp(vdm_resp.vdm_attention, vdm_attention_first, + vdm_resp.vdm_attention_objects * sizeof(uint32_t)), + 0, "Failed to see correct first Attention VDM contents"); + + vdm_resp = host_cmd_typec_vdm_response(TEST_PORT); + zassert_equal(vdm_resp.vdm_attention_objects, 2, + "Failed to see correct number of objects"); + zassert_equal(vdm_resp.vdm_attention_left, 0, + "Failed to see 0 more in queue"); + zassert_equal(memcmp(vdm_resp.vdm_attention, vdm_attention_second, + vdm_resp.vdm_attention_objects * sizeof(uint32_t)), + 0, "Failed to see correct second Attention VDM contents"); +} -- cgit v1.2.1