Skip to content

Conversation

@D-Veda
Copy link

@D-Veda D-Veda commented Dec 1, 2025

Dependencies:

This implementation contains all commits from #99775 & some necessary commits from #99097 and in addition:

  • Add CDC-ECM class driver usbh_cdc_ecm.c
  • Add ethernet network interface support for USB host
  • Add USB host support for sample samples/net/dhcpv4_client (CDC-ECM feature can be verified at board rd_rw612_bga )

It is fixed & improved the implementation in #99097:

  • Restructure driver to use proper Ethernet API with ETH_NET_DEVICE_DT_INST_DEFINE (better aligns with USB CDC-ECM design requirements)
  • Add network interface up/down state management
  • Implement automatic RX restart mechanism with error recovery
  • Add proper ZLP (Zero Length Packet) handling for bulk transfers
  • Use separate buffer pools for TX and RX data transfers
  • Add comprehensive CDC-ECM class requests (SET_ETHERNET_PACKET_FILTER, GET_ETHERNET_STATISTIC, SET_ETHERNET_MULTICAST_FILTERS, etc.)
  • Implement MAC address retrieval from USB string descriptors with multi-language support
  • Add support for fragmented network buffers with linearization

Josuah Demangeon and others added 30 commits December 1, 2025 16:09
Add a "struct usbh_status" that contains a bitmask of flags to keep
track of the global state of the host context, like done for the
device_next implementation.

Signed-off-by: Josuah Demangeon <[email protected]>
Add missing copyright notice for the linker script to help with
check_compliance.py.

Signed-off-by: Josuah Demangeon <[email protected]>
Add a "struct usbh_class_api" for the host implementation, and move all
the function poitners to it. Add more fields to "struct usbh_class_data".

Signed-off-by: Josuah Demangeon <[email protected]>
Add API wrappers around the function pointers in struct usbh_class_api,
while also documenting the USB host class internal API.

Signed-off-by: Josuah Demangeon <[email protected]>
Add functions to probe/remove all classes as part of a new usbh_class.c
and a matching usbh_class.h. These functions are called from the function
usbh_init_device_intl() in usbh_core.c to initialize every class upon
connection of a device. Every class driver provide filters to match the
interfaces of the device.

Co-authored-by: Aiden Hu <[email protected]>
Signed-off-by: Josuah Demangeon <[email protected]>
Move the UVC header with all the definitions from the UVC standard to
share it between USB host and device class implementation.

Signed-off-by: Josuah Demangeon <[email protected]>
Add tests making sure the USB Host class APIs introduced build
and run as expected.

Signed-off-by: Josuah Demangeon <[email protected]>
Add tests making sure the USB Host class APIs introduced build
and run as expected.

Signed-off-by: Josuah Demangeon <[email protected]>
Move the UVC header with all the definitions from the UVC standard to
share it between USB host and device class implementation.

Signed-off-by: Josuah Demangeon <[email protected]>
Move UVC helper functions to a file shared between UVC host and device.
The arrays are not visible anymore from either USB host or device, but
instead accessed through a front-end funciton.

Signed-off-by: Josuah Demangeon <[email protected]>
The USB control size field was wrong for UVC_PU_CONTRAST_CONTROL.
Correct it to the correct value from the standard.

Signed-off-by: Josuah Demangeon <[email protected]>
Loop through each of the VideoStreaming and VideoControl descriptor
to parse them. This is meant as a stub for the purpose of testing the
class API.

Signed-off-by: Josuah Demangeon <[email protected]>
Add a test to run the USB Video Class host support by using
the existing Zephyr USB Video Class device support.
This allows running implementing the host side from the device side.
A draft implementation of UVC is added leveraging this test.

Signed-off-by: Josuah Demangeon <[email protected]>
The public API file <zephyr/usb/class/usbd_uvc.h> lacked an include
to <zephyr/drivers/video.h> making it fail depending on the order of
the includes.

Signed-off-by: Josuah Demangeon <[email protected]>
Modify the USB device int sequence to read the device
descriptor only after setting a valid device address.

Signed-off-by: Santhosh Charles <[email protected]>
When hub is used, need to consider about multiple
devices are attached.

Signed-off-by: Aiden Hu <[email protected]>
add usbh_device_get_root and usbh_device_is_root
function to check root device

Signed-off-by: Aiden Hu <[email protected]>
For usb xfer, set endpoint type and interval by the
selected endpoint desc.

Signed-off-by: Aiden Hu <[email protected]>
Convert xfer's interval to actual value because
mcux_ep->interval is already calculated.

Signed-off-by: Aiden Hu <[email protected]>
maxPacketSize and numberPerUframe of pipe should
be set considering additional transactions.

Signed-off-by: Aiden Hu <[email protected]>
Add two functions:
usbh_connect_device() for device connection
usbh_disconnect_device() for device disconnection

These functions centralize the logic for device attach/detach,
including class probe and remove handling. They can be invoked
by the hub class as well as dev_connected_handler and
dev_removed_handler, improving code clarity and reuse.

Signed-off-by: Aiden Hu <[email protected]>
Add support for the USB CDC ECM (Ethernet Control Model) class to the
USB host subsystem. This implementation enables Ethernet functionality
for USB host.

Signed-off-by: Santhosh Charles <[email protected]>
Add devicetree binding file describing the USB Host CDC Ethernet
Control Model (ECM) implementation for Zephyr.

Signed-off-by: Santhosh Charles <[email protected]>
Introduce subsys/usb/common as a new directory intended to hold
sources and configuration that are shared between USB host and device
implementations. Integrate the new common directory into the build
system.

Signed-off-by: Santhosh Charles <[email protected]>
Signed-off-by: Josuah Demangeon <[email protected]>
Add missing include for usbh_class.h header file in usbh_core.c to fix
implicit declaration of function 'usbh_class_init_all' in usbh_core.c

Signed-off-by: Dv Alan <[email protected]>
Add usbh_req_desc_str() helper function to retrieve USB string
descriptors from a device. This function wraps the generic descriptor
request with proper handling for string descriptors, including memory
allocation, data copying, and endianness conversion for the bString
field.

Signed-off-by: Dv Alan <[email protected]>
Add Ethernet Statistics Feature Selector enumeration defining all
standard CDC ECM statistics counters (XMIT_OK, RCV_OK, etc.) as per
the USB CDC specification. Add CDC notification packet structure for
handling device notifications. Add CONNECTION_SPEED_CHANGE notification
code and Ethernet Power Management Pattern activation constants.

Signed-off-by: Dv Alan <[email protected]>
Complete rewrite of the USB host CDC-ECM (Ethernet Control Model) driver
with improved architecture and functionality:

- Restructure driver to use proper Ethernet API with
  ETH_NET_DEVICE_DT_INST_DEFINE
- Implement asynchronous RX handling using k_poll signals and dedicated
  thread
- Add support for fragmented network buffers with linearization
- Implement proper packet filter management (promiscuous, multicast,
  broadcast)
- Add support for connection speed change notifications and link
  capabilities
- Implement MAC address retrieval from USB string descriptors with
  multi-language support
- Add comprehensive CDC-ECM class requests (SET_ETHERNET_PACKET_FILTER,
  GET_ETHERNET_STATISTIC, SET_ETHERNET_MULTICAST_FILTERS, etc.)
- Use separate buffer pools for TX and RX data transfers
- Add proper ZLP (Zero Length Packet) handling for bulk transfers
- Implement automatic RX restart mechanism with error recovery
- Add network interface up/down state management
- Update Kconfig with configurable buffer counts and stack size
- Rename Kconfig file from Kconfig.cdc_ecm_host to Kconfig.cdc_ecm
- Change DT compatible from "zephyr,usbh-cdc-ecm" to
  "zephyr,cdc-ecm-host"
- Mark driver as EXPERIMENTAL in Kconfig

The rewritten driver provides better error handling, improved
performance through asynchronous operations, and more complete CDC-ECM
feature support.

Signed-off-by: Dv Alan <[email protected]>
Rename the CDC-ECM host device tree binding file from
zephyr,usbh-cdc-ecm.yaml to zephyr,cdc-ecm-host.yaml to align with
the updated compatible string used in the rewritten driver.

Update the binding description to clarify that each CDC-ECM instance
represents an ethernet interface visible to Zephyr's networking stack.

Remove the local-mac-address property as MAC address retrieval is now
handled directly from USB string descriptors in the driver
implementation.

Signed-off-by: Dv Alan <[email protected]>
@D-Veda D-Veda changed the title Usbh cdc ecm support subsys: usb: host: Add USB Host CDC ECM Class Support for Ethernet subsys: usb: host: support for usb host cdc-ecm class Dec 1, 2025
@jukkar jukkar removed their request for review December 1, 2025 10:15
@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 1, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
E Reliability Rating on New Code (required ≥ C)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@@ -0,0 +1,1157 @@
/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a ethernet driver, so it belongs in drivers/ethernet/. I know there are already others there, but these should probably be moved too. I don't like ethernet drivers and its api be scattered all over the tree. (should be limited to the ethernet and wifi drivers and the net subsystem)

@D-Veda D-Veda marked this pull request as draft December 1, 2025 10:42
Comment on lines +933 to +937
net_if_carrier_off(priv->iface);

usbh_cdc_ecm_stop_auto_rx(priv);

ret = net_if_down(priv->iface);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net_if_down should not be used from the ethernet driver, it is only for the user and the networking subsys. net_if_carrier_off should only be used. It is there to signal to the networking subsystem, that there is no connection.

priv->caps = 0;
(void)atomic_clear(&priv->eth_pkt_filter_bitmap);

ret = net_if_down(priv->iface);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we normally don't do net_if_down or net_if_up from the ethernet driver. Please try to get rid of them.

goto cleanup;
}

ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, data->iface, &eth_req_params,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't use net_mgmt inside a ethernet driver to control itself. use net_if_set_link_addr directly for example.

Comment on lines +303 to +330
case USB_CDC_CONNECTION_SPEED_CHANGE:
if (xfer->buf->len != (sizeof(struct cdc_notification_packet) + 8)) {
ret = -EBADMSG;
goto cleanup;
}

link_speeds = (uint32_t *)(notif + 1);

for (size_t i = 0; i < 2; i++) {
link_speeds[i] = sys_le32_to_cpu(link_speeds[i]);
switch (link_speeds[i]) {
case 2500 * 1000000U:
priv->caps |= ETHERNET_LINK_2500BASE;
case 1000 * 1000000U:
priv->caps |= ETHERNET_LINK_1000BASE;
case 100 * 1000000U:
priv->caps |= ETHERNET_LINK_100BASE;
case 10 * 1000000U:
priv->caps |= ETHERNET_LINK_10BASE;
break;
default:
break;
}
}
break;
default:
break;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the caps are just for the generally supported speeds of the device, not of the current speeds. if you want to expose this to the user, use the ethernet phy api.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants