diff options
-rw-r--r-- | zephyr/emul/tcpc/emul_tcpci_partner_common.c | 13 | ||||
-rw-r--r-- | zephyr/include/emul/tcpc/emul_tcpci_partner_common.h | 23 |
2 files changed, 35 insertions, 1 deletions
diff --git a/zephyr/emul/tcpc/emul_tcpci_partner_common.c b/zephyr/emul/tcpc/emul_tcpci_partner_common.c index 0a58799ec9..1785acda51 100644 --- a/zephyr/emul/tcpc/emul_tcpci_partner_common.c +++ b/zephyr/emul/tcpc/emul_tcpci_partner_common.c @@ -876,6 +876,12 @@ tcpci_partner_common_vconn_swap_handler(struct tcpci_partner_data *data) { tcpci_partner_common_set_ams_ctrl_msg(data, PD_CTRL_VCONN_SWAP); + if (!data->vconn_supported) { + tcpci_partner_send_control_msg(data, PD_CTRL_NOT_SUPPORTED, 0); + tcpci_partner_common_clear_ams_ctrl_msg(data); + return TCPCI_PARTNER_COMMON_MSG_HANDLED; + } + tcpci_partner_send_control_msg(data, PD_CTRL_ACCEPT, 0); if (data->vconn_role == PD_ROLE_VCONN_OFF) { @@ -1521,6 +1527,7 @@ void tcpci_partner_init(struct tcpci_partner_data *data, enum pd_rev_type rev) data->send_goodcrc = true; data->rev = rev; + data->vconn_supported = true; data->ops.transmit = tcpci_partner_transmit_op; data->ops.rx_consumed = tcpci_partner_rx_consumed_op; @@ -1536,3 +1543,9 @@ void tcpci_partner_init(struct tcpci_partner_data *data, enum pd_rev_type rev) data->cable = NULL; } + +void tcpci_partner_set_vconn_support(struct tcpci_partner_data *data, + bool vconn_supported) +{ + data->vconn_supported = vconn_supported; +} diff --git a/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h b/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h index fb715a47dc..f232724ece 100644 --- a/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h +++ b/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h @@ -75,10 +75,15 @@ struct tcpci_partner_data { enum pd_power_role power_role; /** Data role (used in message header) */ enum pd_data_role data_role; - /** VConn role (used in message header) */ + /** VCONN role */ enum pd_vconn_role vconn_role; /** Revision (used in message header) */ enum pd_rev_type rev; + /** + * Whether this partner can supply VCONN. If false, the partner will + * respond to VCONN_Swap with Not_Supported. + */ + bool vconn_supported; /** Resistor set at the CC1 line of partner emulator */ enum tcpc_cc_voltage_status cc1; /** Resistor set at the CC2 line of partner emulator */ @@ -340,6 +345,22 @@ struct tcpci_partner_extension_ops { void tcpci_partner_init(struct tcpci_partner_data *data, enum pd_rev_type rev); /** + * @brief Set the partner emulator to support or not support sourcing VCONN. If + * the partner supports VCONN, it should respond to VCONN Swap with Accept, + * Reject, or Wait. If it does not support VCONN, it should respond with + * Not_Supported. + * + * A compliant partner should not change this while attached. However, there are + * real devices that pretend to stop supporting VCONN after completing a VCONN + * Swap. + * + * @param data Pointer to USB-C partner emulator + * @param vconn_support true to support sourcing VCONN, false to not support it. + */ +void tcpci_partner_set_vconn_support(struct tcpci_partner_data *data, + bool support_vconn); + +/** * @brief Free message's memory * * @param msg Pointer to message |