ricardgb opened a new pull request, #19378:
URL: https://github.com/apache/nuttx/pull/19378

   ## Summary
   
   Fixes three endpoint-handling bugs in the RP2040/RP2350 USB device driver
   (`rp2040_usbdev.c`, and its line-for-line copy `rp23xx_usbdev.c`).  Together 
they
   prevent CDC-NCM (and, for the second one, likely RNDIS) from working on these
   controllers; with all three applied, a `CONFIG_NET_CDCNCM` gadget on a
   Raspberry Pi Pico passes traffic in both directions with 0% packet loss.
   
   The bugs were found by comparing the driver against the Pico SDK's TinyUSB
   device controller driver (`dcd_rp2040.c` / `rp2040_usb.c`).
   
   **1. Bulk OUT read length not clamped to the endpoint max packet size.**
   `rp2040_epread()` armed the DPSRAM buffer-control register with the full 
usbdev
   request length. The buffer-control `LEN` field is only 10 bits (max 1023), 
so a
   class driver that posts a larger read request — cdcncm allocates a 16 KiB 
NTB read
   buffer — overflows `LEN` (`16384 & 0x3ff == 0`) and corrupts the neighbouring
   control bits. The controller then completes the transfer immediately with 
zero
   bytes, forever, and no OUT data is ever received (cdcncm floods
   `Wrong NTH SIGN, skblen 0`). The receive path already accumulates a request 
across
   multiple packets, so the buffer only ever needs to be armed for one max-size
   packet. This matches the transmit path, which already chunks to 
`ep.maxpacket`.
   Bulk classes with small reads (cdcacm, usbmsc) were unaffected, which is why 
the
   defect only surfaced on cdcncm.
   
   **2. An endpoint request resubmitted from its own completion callback is 
armed
   twice.** `rp2040_txcomplete()` / `rp2040_rxcomplete()` unconditionally 
started the
   next transfer after invoking a request's completion callback. When that 
callback
   resubmits a request on the same, now-idle endpoint — which cdcncm and rndis 
do from
   their notify/interrupt completion handlers — `rp2040_epsubmit()` already 
armed the
   hardware buffer, and the unconditional re-arm toggles the DATA0/DATA1 PID a 
second
   time. The host discards the packet as a stale retransmission, so e.g. the 
cdcncm
   `NETWORK_CONNECTION` / `SPEED_CHANGE` notifications never arrive and the 
interface
   stays `NO-CARRIER`. A per-request `armed` flag now guards the redundant 
re-arm.
   This is also the likely cause of the long-standing rndis control-response 
`-110`
   timeout on this controller.
   
   **3. Buffer `AVAILABLE` bit written together with length/PID.** The RP2040 
datasheet
   §4.1.2.5.1 requires the `AVAILABLE` bit to be set *after* the rest of buffer 
control
   and after a short settle, because buffer control crosses into the USB clock 
domain.
   `rp2040_update_buffer_control()` wrote the whole word at once. Now it writes 
the
   control word with `AVAILABLE` cleared, waits ~12 CPU cycles, then sets 
`AVAILABLE`
   — the sequence the datasheet and the Pico SDK use.
   
   ## Impact
   
   - **CDC-NCM** now works on RP2040/RP2350 (previously enumerated but never 
passed
     data). Likely also fixes **RNDIS** (bug 2).
   - No functional change for bulk classes that already worked (cdcacm, usbmsc) 
— their
     read lengths already fit in `LEN` and they don't resubmit from completion 
callbacks.
   - Applies to both `rp2040_usbdev.c` and `rp23xx_usbdev.c` (RP2350), which is 
a
     byte-identical copy of the affected functions.
   
   ## Testing
   
   Built and run on a Raspberry Pi Pico (RP2040), Linux host:
   
   - **CDC-NCM, all three fixes:** `ping` 20/20 host→board and 4/4 board→host, 
0% loss,
     ARP resolves, board `REACHABLE`. Before the fixes the board received 
nothing
     (`Wrong NTH SIGN, skblen 0` flood).
   - **Bug 2 in isolation** confirmed with `usbmon`: the cdcncm interrupt-IN
     `SPEED_CHANGE` notification now completes and reaches the host
     (`C Ii:3:NN:1 0:4 16 = a12a...`); previously it never did.
   - **No regression** on cdcacm / usbmsc.
   
   RP2350: the affected functions in `rp23xx_usbdev.c` are byte-identical to 
their
   RP2040 counterparts and the change compiles cleanly for 
`raspberrypi-pico-2`, but it
   was not separately re-tested on RP2350 silicon.
   
   Host-side note for reviewers reproducing this: NuttX gadgets ship with the
   Linux-gadget VID/PID `0525:a4a2`, which is also claimed by the host 
`cdc_subset`
   driver; if `cdc_subset` binds the data interface first you'll see
   `cdc_ncm: failed to claim data intf`. Force NCM with
   `echo 3-1:1.1 > /sys/bus/usb/drivers/cdc_subset/unbind; echo 3-1:1.0 > 
/sys/bus/usb/drivers/cdc_ncm/bind`.
   
   ---
   
   *Disclosure: this change — the code, its validation, and this description — 
was
   produced by an AI agent (Claude Code), operated and directed by me, and 
reviewed by
   me before submission.*
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to