Extcon Device Subsystem

Overview

The Extcon (External Connector) subsystem provides a unified framework formanaging external connectors in Linux systems. It allows drivers to reportthe state of external connectors and provides a standardized interface foruserspace to query and monitor these states.

Extcon is particularly useful in modern devices with multiple connectivityoptions, such as smartphones, tablets, and laptops. It helps manage varioustypes of connectors, including:

  1. USB connectors (e.g., USB-C, micro-USB)

  2. Charging ports (e.g., fast charging, wireless charging)

  3. Audio jacks (e.g., 3.5mm headphone jack)

  4. Video outputs (e.g., HDMI, DisplayPort)

  5. Docking stations

Real-world examples:

  1. Smartphone USB-C port:A single USB-C port on a smartphone can serve multiple functions. Extconcan manage the different states of this port, such as:- USB data connection- Charging (various types like fast charging, USB Power Delivery)- Audio output (USB-C headphones)- Video output (USB-C to HDMI adapter)

  2. Laptop docking station:When a laptop is connected to a docking station, multiple connections aremade simultaneously. Extcon can handle the state changes for:- Power delivery- External displays- USB hub connections- Ethernet connectivity

  3. Wireless charging pad:Extcon can manage the state of a wireless charging connection, allowingthe system to respond appropriately when a device is placed on or removedfrom the charging pad.

  4. Smart TV HDMI ports:In a smart TV, Extcon can manage multiple HDMI ports, detecting whendevices are connected or disconnected, and potentially identifying thetype of device (e.g., gaming console, set-top box, Blu-ray player).

The Extcon framework simplifies the development of drivers for these complexscenarios by providing a standardized way to report and query connectorstates, handle mutually exclusive connections, and manage connectorproperties. This allows for more robust and flexible handling of externalconnections in modern devices.

Key Components

extcon_dev

The core structure representing an Extcon device:

struct extcon_dev {    const char *name;    const unsigned int *supported_cable;    const u32 *mutually_exclusive;    /* Internal data */    struct device dev;    unsigned int id;    struct raw_notifier_head nh_all;    struct raw_notifier_head *nh;    struct list_head entry;    int max_supported;    spinlock_t lock;    u32 state;    /* Sysfs related */    struct device_type extcon_dev_type;    struct extcon_cable *cables;    struct attribute_group attr_g_muex;    struct attribute **attrs_muex;    struct device_attribute *d_attrs_muex;};

Key fields:

  • name: Name of the Extcon device

  • supported_cable: Array of supported cable types

  • mutually_exclusive: Array defining mutually exclusive cable typesThis field is crucial for enforcing hardware constraints. It’s an array of32-bit unsigned integers, where each element represents a set of mutuallyexclusive cable types. The array should be terminated with a 0.

    For example:

    static const u32 mutually_exclusive[] = {    BIT(0) | BIT(1),  /* Cable 0 and 1 are mutually exclusive */    BIT(2) | BIT(3) | BIT(4),  /* Cables 2, 3, and 4 are mutually exclusive */    0  /* Terminator */};

    In this example, cables 0 and 1 cannot be connected simultaneously, andcables 2, 3, and 4 are also mutually exclusive. This is useful forscenarios like a single port that can either be USB or HDMI, but not bothat the same time.

    The Extcon core uses this information to prevent invalid combinations ofcable states, ensuring that the reported states are always consistentwith the hardware capabilities.

  • state: Current state of the device (bitmap of connected cables)

extcon_cable

Represents an individual cable managed by an Extcon device:

struct extcon_cable {    struct extcon_dev *edev;    int cable_index;    struct attribute_group attr_g;    struct device_attribute attr_name;    struct device_attribute attr_state;    struct attribute *attrs[3];    union extcon_property_value usb_propval[EXTCON_PROP_USB_CNT];    union extcon_property_value chg_propval[EXTCON_PROP_CHG_CNT];    union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT];    union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT];    DECLARE_BITMAP(usb_bits, EXTCON_PROP_USB_CNT);    DECLARE_BITMAP(chg_bits, EXTCON_PROP_CHG_CNT);    DECLARE_BITMAP(jack_bits, EXTCON_PROP_JACK_CNT);    DECLARE_BITMAP(disp_bits, EXTCON_PROP_DISP_CNT);};

Core Functions

intextcon_get_state(structextcon_dev*edev,constunsignedintid)

Get the state of an external connector.

Parameters

structextcon_dev*edev

the extcon device

constunsignedintid

the unique id indicating an external connector

Description

Returns 0 if success or error number if fail.

intextcon_set_state(structextcon_dev*edev,unsignedintid,boolstate)

Set the state of an external connector.

Parameters

structextcon_dev*edev

the extcon device

unsignedintid

the unique id indicating an external connector

boolstate

the new state of an external connector.the default semantics is true: attached / false: detached.

Description

Note that this function set the state of an external connector withouta notification. To synchronize the state of an external connector,have to useextcon_set_state_sync() andextcon_sync().

Returns 0 if success or error number if fail.

intextcon_set_state_sync(structextcon_dev*edev,unsignedintid,boolstate)

Set the state of an external connector with sync.

Parameters

structextcon_dev*edev

the extcon device

unsignedintid

the unique id indicating an external connector

boolstate

the new state of external connector.the default semantics is true: attached / false: detached.

Description

Note that this function set the state of external connectorand synchronize the state by sending a notification.

Returns 0 if success or error number if fail.

intextcon_get_property(structextcon_dev*edev,unsignedintid,unsignedintprop,unionextcon_property_value*prop_val)

Get the property value of an external connector.

Parameters

structextcon_dev*edev

the extcon device

unsignedintid

the unique id indicating an external connector

unsignedintprop

the property id indicating an extcon property

unionextcon_property_value*prop_val

the pointer which store the value of extcon property

Description

Note that when getting the property value of external connector,the external connector should be attached. If detached state, functionreturn 0 without property value. Also, the each property should beincluded in the list of supported properties according to extcon type.

Returns 0 if success or error number if fail.

Sysfs Interface

Extcon devices expose the following sysfs attributes:

  • name: Name of the Extcon device

  • state: Current state of all supported cables

  • cable.N/name: Name of the Nth supported cable

  • cable.N/state: State of the Nth supported cable

Usage Example

#include<linux/module.h>#include<linux/platform_device.h>#include<linux/extcon.h>structmy_extcon_data{structextcon_dev*edev;structdevice*dev;};staticconstunsignedintmy_extcon_cable[]={EXTCON_USB,EXTCON_USB_HOST,EXTCON_NONE,};staticintmy_extcon_probe(structplatform_device*pdev){structmy_extcon_data*data;intret;data=devm_kzalloc(&pdev->dev,sizeof(*data),GFP_KERNEL);if(!data)return-ENOMEM;data->dev=&pdev->dev;/* Initialize extcon device */data->edev=devm_extcon_dev_allocate(data->dev,my_extcon_cable);if(IS_ERR(data->edev)){dev_err(data->dev,"Failed to allocate extcon device\n");returnPTR_ERR(data->edev);}/* Register extcon device */ret=devm_extcon_dev_register(data->dev,data->edev);if(ret<0){dev_err(data->dev,"Failed to register extcon device\n");returnret;}platform_set_drvdata(pdev,data);/* Example: Set initial state */extcon_set_state_sync(data->edev,EXTCON_USB,true);dev_info(data->dev,"My extcon driver probed successfully\n");return0;}staticintmy_extcon_remove(structplatform_device*pdev){structmy_extcon_data*data=platform_get_drvdata(pdev);/* Example: Clear state before removal */extcon_set_state_sync(data->edev,EXTCON_USB,false);dev_info(data->dev,"My extcon driver removed\n");return0;}staticconststructof_device_idmy_extcon_of_match[]={{.compatible="my,extcon-device",},{},};MODULE_DEVICE_TABLE(of,my_extcon_of_match);staticstructplatform_drivermy_extcon_driver={.driver={.name="my-extcon-driver",.of_match_table=my_extcon_of_match,},.probe=my_extcon_probe,.remove=my_extcon_remove,};module_platform_driver(my_extcon_driver);

This example demonstrates:

  • Defining supported cable types (USB and USB Host in this case).

  • Allocating and registering an extcon device.

  • Setting an initial state for a cable (USB connected in this example).

  • Clearing the state when the driver is removed.