Skip to content

Conversation

@adamgreloch
Copy link
Member

@adamgreloch adamgreloch commented Jun 6, 2025

Description

Fast forwards USB rework and devinfo API addition into the 3.3 release branch.

Motivation and Context

Types of changes

How Has This Been Tested?

  • Already covered by automatic testing.
  • New test added: (add PR link here).
  • Tested by hand on: (list targets here).

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing linter checks and tests passed.
  • My changes generate no new compilation warnings for any of the targets.

Special treatment

The reply data was not copied by the responder to the buffer address
provided by the sender.

JIRA: RTOS-937
This allows usb to be loaded from syspage (e.g. so that umass can be
used for rootfs mounting)

JIRA: RTOS-937
drvBind always succeeded even when no driver has been found for a device

JIRA: RTOS-937
drvBind races with drvAdd. This change ensures that devices won't be
orphaned if added by hcd before adding the corresponding driver in the
single-driver scenario. This does not fix the race in case of
multi-driver scenario, though, hence the "orphaned" todo is left
untouched

JIRA: RTOS-937
Every driver talking to usb host implements some sort of this handling
loop, so it's better to move it to libusb to eliminate redundancy.
This is also a first step in making the driver logic expressible via
handler functions API only

JIRA: RTOS-970
It is now possible to substitute driver-side pipe operations (e.g. the
hostdriver can now provide its own implementations that does not use msg
API and call the host functions directly)

JIRA: RTOS-970
This makes it possible to run drivers straight from the usbhost process
thereby allowing for various optimizations based on shared memory
between device driver and host driver -- ability to bypass msg-passing,
as included in this change, being a prime example.

It also moves out procdrv implementation details to seperate file
from libusb/driver.c

JIRA: RTOS-970
Adds options to exclude external driver logic from the usbhost driver if
for instance no such driver is ever expected to be run.

JIRA: RTOS-970
If hcd became operational before returning from hcd init, it could try to
access hcd->roothub while it was still uninitialized

JIRA: RTOS-970
Drivers can now return some useful information back to the usbhost about
the state of inserted device

JIRA: RTOS-1024
Some devices store information in device descriptors in ASCII (even
though string descriptors are to be treated as UTF16 per USB spec...),
in which case converting from UTF16 to ASCII no matter what would cause
loss of information

JIRA: RTOS-1024
Multifunction (multi-interface) devices may be served by multiple drivers

JIRA: RTOS-1024
The usbhost now also creates symlinks to these driver devices named
`/dev/usb-<vid>-<pid>-if<ifnum>" that can be looked up on and resolved
via `canonicalize_file_name(path)` to acquire the needed oid.

JIRA: RTOS-1024
Not resetting caused subsequent msgSend calls to send the modified and
incorrect messages

JIRA: RTOS-1024
@adamgreloch adamgreloch requested review from Darchiv and nalajcie June 6, 2025 08:38
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Hello @adamgreloch, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

As gemini-code-assist, I've reviewed this pull request which backports a significant rework of the USB stack and introduces a new event-driven API to the 3.3 release branch. This involves a major refactoring of the core USB host logic and the user-space library (libusb) to support both in-process (internal) and out-of-process (external) USB drivers. A new API for retrieving detailed device information by OID has been added, along with automatic device symlink creation upon driver binding. The changes are marked as breaking, as existing user-space USB drivers will need to be updated to use the new API and driver model.

Highlights

  • New Driver Model and Event API: Introduces a new event-driven API and a refactored driver model in libusb and the USB host process. This allows for USB drivers to run either directly within the host process (internal) or as separate user-space processes (external), communicating via messages. The core USB functions now take a usb_driver_t parameter to support this.
  • Process-based Driver Support: Adds libusb/procdriver.c and libusb/include/usbprocdriver.h to provide the necessary infrastructure for USB drivers running as separate processes. This includes message handling threads and functions to communicate with the USB host process.
  • Device Information API: Adds a new API (libusb/devinfo.c, libusb/include/usbdevinfo.h) allowing user-space applications to retrieve detailed device information (descriptors, strings) using the device's OID.
  • Automatic Device Symlinks: The USB host process now automatically creates symlinks in /dev for bound USB interfaces in the format /dev/usb-VID-PID-ifIFACE, making it easier to access specific devices from user-space.
  • Refactored Device and Driver Management: Significant changes in usb/dev.c and usb/drv.c to manage devices and drivers under the new model, including handling device OIDs, string descriptors (with fallbacks), and the binding/unbinding process for both internal and external drivers.
  • Updated Logging: New logging headers (libusb/log.h, usb/log.h) and macros (log_info, log_msg, log_trace, log_error) are introduced and used throughout the codebase for better debugging and information output.

Changelog

Click here to see the changelog
  • libusb/Makefile
    • Added new source files: procdriver.c, internal.c, devinfo.c.
    • Removed wildcard header inclusion.
    • Updated copyright year to 2025.
  • libusb/devinfo.c
    • New file implementing usb_devinfoGet to query device information from the host via messages.
  • libusb/driver.c
    • Removed old usb_connect and usb_eventsWait functions.
    • Added usb_driverRegister and usb_registeredDriverPop for driver registration.
    • Modified core USB transfer/configuration functions (usb_open, usb_urbAlloc, usb_transferControl, etc.) to accept a usb_driver_t * and delegate operations via pipeOps.
  • libusb/include/usb.h
    • Added #define USB_CLASS_HID 0x3.
  • libusb/include/usbdevinfo.h
    • New file defining usb_devinfo_desc_t and declaring usb_devinfoGet.
  • libusb/include/usbdriver.h
    • New file defining core structures for the new API: usb_driver_t, usb_pipeOps_t, usb_handlers_t, message types (usb_msg_t), and event structures (usb_event_insertion_t).
    • Declares the new API functions, many taking usb_driver_t *.
  • libusb/include/usbprocdriver.h
    • New file declaring usb_driverProcRun for process-based drivers.
  • libusb/internal.c
    • New file implementing usb_hostLookup to find the USB host device node.
  • libusb/log.h
    • New file defining logging macros for libusb.
  • libusb/procdriver.c
    • New file implementing the process-based driver framework.
    • Defines usbprocdrv_pipeOps to send messages to the host.
    • Implements usb_thread to handle host messages (insertion, deletion, completion).
    • Implements usb_connect to register the driver with the host.
    • Implements usb_driverProcRun as the entry point for process drivers.
  • libusb/usbinternal.h
    • New file declaring usb_hostLookup.
  • usb/Makefile
    • Added libusb and $(USB_HOSTDRV_LIBS) to LIBS.
    • Added libusb to DEPS.
    • Added conditional CFLAG -DUSB_INTERNAL_ONLY.
  • usb/dev.c
    • Added includes for limits.h, unistd.h, sys/rb.h, log.h.
    • Introduced usb_devOid_t and usbdev_common.devOids to track driver-created device OIDs.
    • Added recipient field to usb_transfer_t initialization.
    • Modified string handling to use usb_lenStr_t and added fallback string functions.
    • Added usb_utf16ToAscii helper.
    • Implemented usb_devSymlinksCreate and usb_devSymlinksDestroy for /dev symlinks.
    • Added usb_devOnDrvBindCb callback for driver binding events.
    • Updated usb_devEnumerate to use new string handling, logging, and driver binding with callback.
    • Added _usb_devOidFind and usb_devFreeOids.
    • Modified usb_devUnbind to free OIDs and destroy symlinks.
    • Added usb_devFindDescFromOid to find device info by OID.
    • Modified usb_devDisconnected to accept a silent flag and call usb_devUnbind.
  • usb/dev.h
    • Added usb_lenStr_t struct.
    • Changed usb_iface_t::str to name (type usb_lenStr_t).
    • Changed usb_iface_t::driver type to struct usb_drvpriv *.
    • Added usb_dev_oid_t struct.
    • Added linked list pointers (next, prev) to usb_dev_t.
    • Changed string fields in usb_dev_t to usb_lenStr_t.
    • Changed usb_dev::statusTransfer type to usb_transfer_t *.
    • Modified usb_devDisconnected signature.
    • Added usb_devFindDescFromOid declaration.
  • usb/drv.c
    • Added includes for sys/minmax.h, log.h.
    • Replaced internal usage of usb_drv_t with usb_drvpriv_t.
    • Added drvAddedCond for driver registration signaling.
    • Modified driver finding, adding, and pipe/transfer functions to work with usb_drvpriv_t.
    • Modified usb_drvMatchIface to wait for drivers if none are registered.
    • Modified usb_drvBind to accept a callback and handle internal/external driver insertion.
    • Modified URB handling functions (_usb_handleUrbcmd, usb_handleUrbcmd, _usb_handleUrb) to use usb_drvpriv_t and handle recipients.
    • Added usb_drvInit to initialize locks/conds.
    • Added usblibdrv_* functions and usblibdrv_pipeOps/usblibdrv_transferOps for internal driver handling.
    • Added usb_libDrvInit and usb_libDrvDestroy.
  • usb/drv.h
    • Added PORT_INTERNAL define.
    • Added usb_drvOnBindCb_t typedef.
    • Defined struct usb_drvpriv to distinguish internal/external drivers.
    • Updated function declarations to use usb_drvpriv_t *.
    • Added declarations for usb_libDrvInit and usb_libDrvDestroy.
  • usb/hcd.c
    • Added include for log.h and USB_LOG_TAG.
    • Modified hcd_roothubInit to return EOK.
    • Modified hcd_init to initialize roothub before HCD init and enumerate devices after, updating logging.
  • usb/hcd.h
    • Modified hcd_info_t to use a union for physical address or PCI device ID.
    • Changed hcd_t::base and hcd_t::phybase types to volatile uint32_t *.
  • usb/hub.c
    • Removed sys/msg.h include.
    • Added include for log.h and USB_LOG_TAG.
    • Added HUB_TT_POLL_DELAY_MS define.
    • Added hub_common.tts for tracking TT hubs.
    • Added recipient field to usb_transfer_t initialization in hub_interruptInit.
    • Added hub_isTT, hub_ttAdd, hub_ttRemove.
    • Renamed hub_poll to hub_requestStatus.
    • Added hub_devDisconnect helper.
    • Modified hub_devConnected and hub_connectstatus to use hub_devDisconnect and updated logging.
    • Added hub_ttStatus to poll TT hubs.
    • Modified hub_thread to call hub_ttStatus periodically.
    • Modified hub_conf to check for TT hubs and add them to the list, and call hub_requestStatus.
  • usb/hub.h
    • Added hub protocol defines (USB_HUB_PROTO_ROOT, USB_HUB_PROTO_SINGLE_TT).
  • usb/log.h
    • New file defining logging macros for the USB host process.
  • usb/usb.c
    • Added includes for sys/minmax.h, log.h.
    • Added usb_common.ustack.
    • Changed usb_common.drvs type to usb_drvpriv_t *.
    • Added usb_internalDriverInit for host-side drivers.
    • Changed usb_transferCheck return type to bool.
    • Modified usb_transferSubmit to check recipient and initialize finished.
    • Modified usb_transferFinished to use bool urbtrans, check recipient, use t->ops callbacks, and handle internal/external transfers.
    • Removed old usb_statusthr implementation.
    • Modified usb_msgthr to handle usb_msg_devdesc, use logging, and control msgRespond with a flag.
    • Added usbprocdrv_transferOps and usbprocdrv_transferOpsGet (conditional).
    • Added new usb_statusthr implementation using t->ops.
    • Modified main to initialize usb_devInit, initialize registered internal drivers, then hub_init, hcd_init, create /dev/usb, and start threads.
    • Added usblibdrv_open implementation.
  • usb/usbhost.h
    • Removed sys/msg.h include.
    • Included usbdriver.h.
    • Changed usb_transfer::drv type to struct usb_drvpriv *.
    • Added usb_transfer_t forward declaration.
    • Added usb_transferOps_t struct.
    • Added declarations for usblibdrv_transferOpsGet and usbprocdrv_transferOpsGet.
    • Changed usb_transfer::finished type to volatile bool.
    • Added usb_transfer::recipient field.
    • Added usb_transfer union for internal/external data.
    • Added usb_transfer::ops field.
    • Removed old USB_LOG macro.
    • Changed usb_transferCheck return type to bool.
    • Added declaration for usblibdrv_open.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request backports a significant USB rework and event API addition to the 3.3 release branch. The changes are extensive, introducing new structures for USB drivers, new APIs, and refactoring existing code to support different driver models (internal library-based and external process-based). The architectural changes, like the introduction of usb_driver_t and pipeOps, are positive steps towards modularity.

However, there are a few issues that need attention, particularly a potential build problem in the libusb Makefile and some correctness/consistency concerns detailed below.

Summary of Findings

  • Build Configuration: The libusb/Makefile has a LOCAL_CFLAGS setting that might prevent headers in libusb/include/ from being found correctly during compilation, potentially leading to build failures.
  • Copyright Year: Several new files have the copyright year set to 2025, which should be corrected to the actual year of creation or last significant modification.
  • String Conversion: The UTF-16 to ASCII conversion in usb/dev.c is basic and will lead to data loss for non-ASCII characters in device strings.

Merge Readiness

This pull request introduces significant and valuable changes to the USB stack. However, due to the potential build issue identified in libusb/Makefile (high severity) and other medium severity concerns, I recommend addressing these points before merging. As an AI, I am not authorized to approve pull requests; please ensure further review and approval by authorized team members after addressing the feedback.

Comment on lines +393 to +409
static unsigned int usb_utf16ToAscii(char *dest, const char *src, unsigned int len)
{
unsigned int asciilen = len / 2;
int i;

if (len < 2) {
return 0;
}

for (i = 0; i < asciilen; i++) {
dest[i] = src[i * 2];
}

dest[asciilen] = 0;

return asciilen;
}

Choose a reason for hiding this comment

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

medium

The usb_utf16ToAscii function converts UTF-16 strings to ASCII by taking the low byte of each UTF-16 character (dest[i] = src[i * 2];). This approach will correctly convert characters within the standard ASCII range (U+0000 to U+007F).

However, for any characters outside this range (e.g., accented letters, symbols, characters from non-Latin scripts), this conversion will result in data loss or incorrect representation. While this might be a common simplification in embedded contexts, it could lead to garbled display of manufacturer, product, or serial number strings if they use non-ASCII characters.

Is this limitation acceptable, or should a more robust UTF-16 to a supported character set (like UTF-8, or a locale-specific encoding if applicable) conversion be considered for broader international character support, if feasible within the system constraints?

@adamgreloch adamgreloch changed the title Backport USB rework and event API addition to 3.3 release Backport USB rework and devinfo API addition to 3.3 release Jun 12, 2025
Copy link
Member

@anglov anglov left a comment

Choose a reason for hiding this comment

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

LGTM +2

@anglov anglov merged commit 991746f into release/3.3 Jul 9, 2025
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants