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

xiaoxiang781216 pushed a commit to branch releases/13.0
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/releases/13.0 by this push:
     new 51f42c824e4 drivers/usbhost: Refuse to register the same class driver 
twice.
51f42c824e4 is described below

commit 51f42c824e4521a5945b04fce643542b8f3705b1
Author: Justin Hammond <[email protected]>
AuthorDate: Wed Aug 5 19:03:17 2026 +0800

    drivers/usbhost: Refuse to register the same class driver twice.
    
    The registry is a singly linked list of static structures, so registering
    one of them a second time does not add a second entry: it points that
    entry's own link at itself, and the list stops having an end.
    
    Nothing notices while every device that turns up matches something near
    the head, because the search returns before it reaches the loop.  The
    first device that matches nothing at all, meaning anything without a
    class driver built in, walks the list to look for it and never comes back,
    holding the registry lock.  On a multiprocessor the rest of the system
    follows it down: every other processor that touches the registry spins,
    and on the one measured here that included the console, so a board with a
    USB keyboard and no keyboard driver came up and then answered nothing.
    
    Registering twice is easy to do by accident.  drivers_initialize() calls
    usbhost_drivers_initialize(), which registers every class the
    configuration selected, and board code that also registers one, which
    many boards do, gets a second call for free.
    
    So look before linking, and treat a repeat registration as the no-op the
    caller expected it to be.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Justin Hammond <[email protected]>
---
 drivers/usbhost/usbhost_registerclass.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/usbhost/usbhost_registerclass.c 
b/drivers/usbhost/usbhost_registerclass.c
index dab177ed49e..f79d2886bf5 100644
--- a/drivers/usbhost/usbhost_registerclass.c
+++ b/drivers/usbhost/usbhost_registerclass.c
@@ -81,6 +81,7 @@
 
 int usbhost_registerclass(struct usbhost_registry_s *usbclass)
 {
+  FAR struct usbhost_registry_s *curr;
   irqstate_t flags;
 
   uinfo("Registering class:%p nids:%d\n", usbclass, usbclass->nids);
@@ -93,6 +94,22 @@ int usbhost_registerclass(struct usbhost_registry_s 
*usbclass)
 
   flags = spin_lock_irqsave(&g_classregistry_lock);
 
+  /* Refuse an entry that is already registered.
+   *
+   * These are static structures, so registering one twice points the
+   * entry's own link at itself and the list loses its end.  A later search
+   * for a class that is not there never returns, holding this lock.
+   */
+
+  for (curr = g_classregistry; curr != NULL; curr = curr->flink)
+    {
+      if (curr == usbclass)
+        {
+          spin_unlock_irqrestore(&g_classregistry_lock, flags);
+          return OK;
+        }
+    }
+
   /* Add the new class ID info to the head of the list */
 
   usbclass->flink = g_classregistry;

Reply via email to