Re: [PATCH v3 1/3] usb: typec: Add helper to check cable altmode support
From: Benson Leung
Date: Fri Jun 26 2026 - 14:35:04 EST
On Fri, Jun 26, 2026 at 02:27:00PM +0000, Andrei Kuchynski wrote:
> Introduce typec_cable_altmode_unsupported function to evaluate whether an
> alternate mode is restricted based on the connected cable's properties.
>
> Implement validation logic that parses the cable's identity to catch
> incompatible setups early. Alternate modes are restricted over:
> - cables lacking an identity header
> - passive cables with USB 2.0 speed
> - active cables unless they have corresponding plugs
>
> The function returns false if the cable is not registered or the identifier
> is not set.
>
> Suggested-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>
> Signed-off-by: Andrei Kuchynski <akuchynski@xxxxxxxxxxxx>
Reviewed-by: Benson Leung <bleung@xxxxxxxxxxxx>
> ---
> Changes in V3:
> - Extracted core verification logic into a static helper function
> - Added an enum to handle supported, unsupported, and unknown cable states
>
> drivers/usb/typec/class.c | 71 +++++++++++++++++++++++++++++++++++++++
> include/linux/usb/typec.h | 1 +
> 2 files changed, 72 insertions(+)
>
> diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
> index 0977581ad1b6e..e9f34eb14ceff 100644
> --- a/drivers/usb/typec/class.c
> +++ b/drivers/usb/typec/class.c
> @@ -1429,6 +1429,77 @@ int typec_cable_is_active(struct typec_cable *cable)
> }
> EXPORT_SYMBOL_GPL(typec_cable_is_active);
>
> +enum typec_cable_altmode_support {
> + CABLE_SUPPORT_UNKNOWN,
> + CABLE_SUPPORTED,
> + CABLE_NOT_SUPPORTED,
> +};
> +
> +static enum typec_cable_altmode_support
> +typec_cable_check_altmode_support(struct typec_cable *cable,
> + struct typec_altmode *alt)
> +{
> + struct typec_altmode *plug;
> + u32 speed;
> +
> + /*
> + * Check if the cable has an e-marker, supports modal operation, and the
> + * SOP' altmode nodes are created.
> + */
> + plug = typec_altmode_get_plug(alt, TYPEC_PLUG_SOP_P);
> + if (plug) {
> + typec_altmode_put_plug(plug);
> + return CABLE_SUPPORTED;
> + }
> +
> + /* The identity is not specified */
> + if (!cable->identity)
> + return CABLE_SUPPORT_UNKNOWN;
> +
> + /* Non-e-marked cable */
> + if (!cable->identity->id_header)
> + return CABLE_NOT_SUPPORTED;
> +
> + switch (PD_IDH_PTYPE(cable->identity->id_header)) {
> + case IDH_PTYPE_PCABLE:
> + speed = VDO_TYPEC_CABLE_SPEED(cable->identity->vdo[0]);
> + if (speed == CABLE_USB2_ONLY)
> + return CABLE_NOT_SUPPORTED;
> + return CABLE_SUPPORTED;
> + case IDH_PTYPE_ACABLE:
> + /*
> + * Active cables must establish an SOP' communication
> + * node. Since that check failed at the beginning of
> + * this function, this active cable does not support
> + * this specific altmode.
> + */
> + return CABLE_NOT_SUPPORTED;
> + }
> +
> + return CABLE_SUPPORT_UNKNOWN;
> +}
> +
> +/**
> + * typec_cable_altmode_unsupported - Check if a cable restricts altmode
> + * @alt: The Alternate Mode to evaluate
> + *
> + * Returns true if the connected cable is incapable of handling the altmode.
> + */
> +bool typec_cable_altmode_unsupported(struct typec_altmode *alt)
> +{
> + enum typec_cable_altmode_support support = CABLE_SUPPORT_UNKNOWN;
> + struct typec_cable *cable;
> +
> + cable = typec_cable_get(typec_altmode2port(alt));
> + if (cable) {
> + support = typec_cable_check_altmode_support(cable, alt);
> + typec_cable_put(cable);
> + }
> +
> + return support == CABLE_NOT_SUPPORTED;
> +}
> +EXPORT_SYMBOL_GPL(typec_cable_altmode_unsupported);
> +
> /**
> * typec_cable_set_identity - Report result from Discover Identity command
> * @cable: The cable updated identity values
> diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
> index d61ec38216fa9..10a783b738efd 100644
> --- a/include/linux/usb/typec.h
> +++ b/include/linux/usb/typec.h
> @@ -337,6 +337,7 @@ void typec_unregister_cable(struct typec_cable *cable);
> struct typec_cable *typec_cable_get(struct typec_port *port);
> void typec_cable_put(struct typec_cable *cable);
> int typec_cable_is_active(struct typec_cable *cable);
> +bool typec_cable_altmode_unsupported(struct typec_altmode *alt);
>
> struct typec_plug *typec_register_plug(struct typec_cable *cable,
> struct typec_plug_desc *desc);
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
Attachment:
signature.asc
Description: PGP signature