From d6444d0a7bd15c266b715e371b0ba520e7a8bc10 Mon Sep 17 00:00:00 2001 From: Ricard Rosson Date: Wed, 29 Jul 2026 11:07:18 +0100 Subject: [PATCH] drivers/usbdev: re-assert soft connect in cdcecm/cdcncm disconnect() The USB device controller drivers invoke CLASS_DISCONNECT() on every USB bus reset, and a bus reset is the first step of normal host enumeration. Every other class driver (cdcacm, usbmsc, rndis) re-asserts DEV_CONNECT() at the end of its disconnect() handler so that the device remains attached; cdcecm and cdcncm did not, so on controllers that soft-disconnect around bus reset (e.g. rp2040, which drops the pull-up in its bus-reset handler) a standalone CDC-ECM or CDC-NCM device is left soft-disconnected by the first bus reset and never enumerates on the host. Mirror the cdcacm behavior and perform the soft connect in the disconnect() methods, unless part of a composite device (composite.c already re-connects in its own disconnect handler). Fixes the standalone CDC-ECM case of issue #15880. Validated on raspberrypi-pico (RP2040): with this change a standalone CONFIG_NET_CDCECM device that previously never appeared on the host enumerates via cdc_ether and pings with 0% loss. cdcncm has the identical defect and receives the identical fix. Signed-off-by: Ricard Rosson Co-authored-by: Xiang Xiao Assisted-by: Claude (Anthropic Claude Code) --- drivers/usbdev/cdcecm.c | 11 +++++++++++ drivers/usbdev/cdcncm.c | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/usbdev/cdcecm.c b/drivers/usbdev/cdcecm.c index 2ce7e93cadf..c39f84d4228 100644 --- a/drivers/usbdev/cdcecm.c +++ b/drivers/usbdev/cdcecm.c @@ -1916,6 +1916,17 @@ static void cdcecm_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) { uinfo("\n"); + + /* Perform the soft connect function so that we will we can be + * re-enumerated (unless we are part of a composite device). The USB + * device controller calls CLASS_DISCONNECT() on every bus reset, which + * is the first step of any enumeration, so without this the device is + * left soft-disconnected and never enumerates on the host. + */ + +#ifndef CONFIG_CDCECM_COMPOSITE + DEV_CONNECT(dev); +#endif } /**************************************************************************** diff --git a/drivers/usbdev/cdcncm.c b/drivers/usbdev/cdcncm.c index 7f10e5355e3..c7046c4ca74 100644 --- a/drivers/usbdev/cdcncm.c +++ b/drivers/usbdev/cdcncm.c @@ -2902,6 +2902,17 @@ static void cdcncm_disconnect(FAR struct usbdevclass_driver_s *driver, cdcncm_resetconfig(self); uinfo("\n"); + + /* Perform the soft connect function so that we can be + * re-enumerated (unless we are part of a composite device). The USB + * device controller calls CLASS_DISCONNECT() on every bus reset, which + * is the first step of any enumeration, so without this the device is + * left soft-disconnected and never enumerates on the host. + */ + +#ifndef CONFIG_CDCNCM_COMPOSITE + DEV_CONNECT(dev); +#endif } /****************************************************************************