This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 7e53ba18f896df92fb563b20bfd5835a50abb563
Author: wangjianyu3 <[email protected]>
AuthorDate: Mon Sep 7 12:56:21 2026 +0800

    arch/arm/rp2040: fix IN endpoint DPSRAM index for bare-eplog callers
    
    rp2040_allocep() indexes the endpoint's DPSRAM buffer/control
    registers via RP2040_DPINDEX(eplog) and RP2040_EPINDEX(eplog), both
    of which take the transfer direction from the direction bit of
    'eplog' itself instead of trusting the explicit 'in' argument that
    is also passed to this function.
    
    This is harmless for callers that always encode the direction bit
    into 'eplog' (e.g. CDC/ACM's CDCACM_MKEPBULKIN()/MKEPINTIN(), which
    OR in USB_DIR_IN), since 'in' then always agrees with that bit.  But
    drivers/usbdev/usbdev_fs.c (the generic ADB/fastboot class driver)
    calls DEV_ALLOCEP() with a bare endpoint number in 'eplog' (no
    direction bit) and passes the direction only via the separate 'in'
    parameter - matching this function's own "direction bit ignored"
    contract for 'eplog' (see its Input Parameters doc, and the
    pre-existing "Ignore any direction bits in the logical address"
    comment, both dating back to the original driver in b860e3c4ad3).
    For such a bare-number IN endpoint, USB_ISEPOUT(eplog) always
    evaluates true (the IN bit is never set on a plain number), so
    RP2040_DPINDEX(eplog) silently pointed the endpoint's buffer/control
    registers at its OUT slot instead of its IN slot.  The real IN slot
    was left unconfigured, so the SIE responded to every IN token on
    that endpoint with a STALL - confirmed on real hardware via usbmon:
    'C Bi:1:050:6 -32 0' (EPIPE) on every attempt, while the paired OUT
    endpoint (which "accidentally" resolved to the correct slot for the
    same reason) worked fine.
    
    Fix: normalize 'eplog' to agree with the explicit 'in' argument
    before it is used by RP2040_EPINDEX()/RP2040_DPINDEX(), so both
    macros keep their original, single-argument form and every use of
    eplog's direction bit below this point is consistent with 'in'.
    Existing 0x80-encoded callers (EP0, CDC/ACM) already agree with 'in'
    and are unaffected by the normalization.
    
    Also fix two pre-existing nxstyle violations in this same file
    (a misaligned comment block under USB_REQ_SYNCHFRAME, and a bare
    ';' body instead of empty braces on a while loop), both dating back
    to the original driver in b860e3c4ad3 as well; CI runs nxstyle on
    the whole file whenever it is touched.
    
    Assisted-by: OpenCode:claude-sonnet-5
    Signed-off-by: wangjianyu3 <[email protected]>
---
 arch/arm/src/rp2040/rp2040_usbdev.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/arm/src/rp2040/rp2040_usbdev.c 
b/arch/arm/src/rp2040/rp2040_usbdev.c
index ee44f051822..bafecdcbc25 100644
--- a/arch/arm/src/rp2040/rp2040_usbdev.c
+++ b/arch/arm/src/rp2040/rp2040_usbdev.c
@@ -1247,11 +1247,11 @@ static void rp2040_ep0setup(struct rp2040_usbdev_s 
*priv)
             break;
 
           case USB_REQ_SYNCHFRAME:
-              /* type:  device-to-host; recipient = endpoint
-               * value: 0
-               * index: endpoint;
-               * len:   2; data = frame number
-               */
+            /* type:  device-to-host; recipient = endpoint
+             * value: 0
+             * index: endpoint;
+             * len:   2; data = frame number
+             */
 
             {
               usbtrace(TRACE_INTDECODE(RP2040_TRACEINTID_SYNCHFRAME), 0);
@@ -1497,7 +1497,8 @@ static int rp2040_usbinterrupt(int irq, void *context, 
void *arg)
   if (stat & RP2040_USBCTRL_REGS_INTR_BUFF_STATUS)
     {
       while (rp2040_usbintr_buffstat(priv))
-        ;
+        {
+        }
     }
 
   if (stat & RP2040_USBCTRL_REGS_INTR_SETUP_REQ)
@@ -1972,6 +1973,13 @@ static struct usbdev_ep_s *rp2040_allocep(struct 
usbdev_s *dev,
 
   usbtrace(TRACE_DEVALLOCEP, (uint16_t)eplog);
 
+  /* Some callers (e.g. usbdev_fs.c) pass a bare endpoint number in eplog
+   * and rely solely on 'in' for direction, so make eplog agree with 'in'
+   * before it is used by RP2040_EPINDEX()/RP2040_DPINDEX() below.
+   */
+
+  eplog = in ? (USB_EPNO(eplog) | USB_DIR_IN) : USB_EPNO(eplog);
+
   /* Ignore any direction bits in the logical address */
 
   epphy = USB_EPNO(eplog);

Reply via email to