udc_virtual reports High-Speed from devicetree alone, so on a
Full-Speed-only build "usbd defaults" added a High-Speed configuration
and failed with -ENOTSUP. Guard it with USBD_SUPPORTS_HIGH_SPEED, as
sample_usbd_init.c already does.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
USB 2.0 Test Mode is only required of High-Speed capable devices.
Build it only with High-Speed support, so a Full-Speed-only device
stalls SetFeature(TEST_MODE).
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
Utilize a code spell-checking tool to scan for and correct spelling errors
in all files within:
- `subsys/usb/device_next`
Assisted-by: Claude:claude-sonnet-5-5 codespell
Signed-off-by: Pisit Sawangvonganan <pisit@ndrsolution.com>
In the to-device callbacks implementation, explicitly check the wLength
value where a data stage is required. The host may submit a control
transfer without a data stage. In that case, the buf parameter will
always be NULL.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Do not bind the driver instance if the usbh_class_probe() return value
is not 0.
Reported-by: Github user zups
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Similar to interrupt endpoints, the Linux kernel usbtest driver expects
isochronous endpoints to be in the same interface as the bulk endpoint
by default. This is very experimental and is disabled by default.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Add interrupt transfer support to allow broader testing of Zephyr USB
support. The Linux kernel usbtest driver expects interrupt endpoints to
be in the same interface as the bulk endpoint by default. Move the
interrupt endpoints to first interface and drop everything else.
Rework how the transfers are submitted, and add interrupt transfer
handling.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
uvc_add_vs_frame_desc() sorts the discrete frame intervals with
qsort(dwFrameInterval, *bFrameIntervalType, sizeof(*dwFrameInterval),
uvc_compare_frmival_desc).
dwFrameInterval is a uint8_t *, so sizeof(*dwFrameInterval) is 1 while
each interval is a packed 4-byte (le32) value. qsort therefore reorders
individual bytes instead of whole intervals, corrupting every entry and
producing an unsorted dwFrameInterval array.
A frame descriptor that enumerates two or more frame intervals then
carries a malformed list. Hosts that require the intervals to be sorted
(e.g. Windows) fail to start the stream: the camera enumerates but
cannot be opened. A camera exposing a single frame interval is
unaffected, which is why this has gone unnoticed.
Pass sizeof(uint32_t) so qsort sorts whole intervals.
Signed-off-by: Ugur Sayar <ugursayar@gmail.com>
Assigned-by: Claude Opus 4.8 <noreply@anthropic.com>
Implements tx throughput improvements by storing data in net_bufs
allocated from per instance buf pool instead of copying the data through
ringbuf.
Signed-off-by: Antoni Duda <antoni.duda@nordicsemi.no>
Add usbh_hub to enable connecting USB hubs and managing
downstream devices through multi-tier hub topology.
The host hub implements two state machines for hub lifecycle.
The hub state machine handles hub enumeration, descriptor
retrieval, and port power configuration. The port state machine
manages device connection detection, port reset sequences, device
enumeration coordination, and disconnection handling.
Hub status changes are monitored through interrupt endpoint with
automatic transfer resubmission. The implementation supports recursive
hub topology with configurable chain depth limits. When a hub is
removed, all downstream devices and child hubs are recursively
disconnected to maintain topology consistency.
This builds upon Chapter 11 control requests to provide complete
hub class driver functionality in usbh_hub.c and usbh_hub.h.
Co-authored-by: Mark Wang <yichang.wang@nxp.com>
Signed-off-by: Aiden Hu <weiwei.hu@nxp.com>
Change usbh_device_connect() return type from void to int so callers
can detect enumeration failure. The function already frees udev on
failure; callers can now act on the error code instead of using a
freed pointer.
Signed-off-by: Aiden Hu <weiwei.hu@nxp.com>
Move hub control requests from usbh_ch9 to new usbh_ch11 files
to align with USB 2.0 specification structure. Chapter 11 defines
hub-specific requests which are distinct from the general USB
device requests in Chapter 9.
The new implementation provides all hub and port control requests
defined in the specification, including feature control, status
queries, and descriptor retrieval. This provides the foundation
for the hub class driver implementation.
Signed-off-by: Aiden Hu <weiwei.hu@nxp.com>
The bitmap maps OUT endpoints to bits 0 to 15 and IN endpoints to bits
16 to 31, but every helper rediscovered that mapping, and both walks
over a whole bitmap iterated indices 1 to 15 testing the IN and the OUT
bit separately.
Add usbd_ep_bm_bit() and usbd_ep_bm_get_first() and build on them.
unassign_eps() becomes three bitmask operations and no longer needs
uds_ctx. usbd_interface_shutdown() loops over the lowest set bit, as
usbd_ep_disable() clears the bit whenever it succeeds.
Both walks now cover the control endpoint bits that the index-ordered
loops skipped, but assign_ep_addr() only hands out indices 1 to 15, so
those bits are never set. Endpoints are disabled in ascending bit order
rather than interleaved per index, and unassign_eps() reports the
lowest offending endpoint without partially clearing what it already
processed. That error path is unreachable, as assign_ep_addr() always
sets the class and the configuration bit together.
Saves 96 bytes of ROM in a cdc_acm build for nrf52840dk/nrf52840.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
usbh_req_setup() waits on a single global semaphore with no mutual
exclusion, so two threads can be inside it at once: enumeration runs
on the bus thread while the shell and class drivers call in from
their own. The first completion wakes an arbitrary waiter, which then
reads xfer->err on a transfer that has not finished. Serialize the
request with a mutex so the semaphore has one owner at a time.
Timing out also released the transfer while the controller still
owned it. uhc_ep_dequeue() only requests cancellation: the transfer
stays with the driver until it is returned through the completion
callback, and the driver may still write into its buffer. Callers
such as usbh_req_desc_dev() free that buffer as soon as
usbh_req_setup() returns, so a cancelled transfer could land in a
recycled net_buf. Wait for the completion callback before freeing,
and drop the callback's -ECONNRESET path now that the caller always
owns the transfer.
Signed-off-by: Ofir Shemesh <ofirshemesh777@gmail.com>
Some USB class drivers register filter entries for both device-level
and interface-level descriptors. This causes the probe function to be
called twice for the same device.
Return early after device-level binding succeeds, as interface scanning
is not needed for single-function devices.
Signed-off-by: Aiden Hu <weiwei.hu@nxp.com>
Fixes various issues with Kconfigs, including:
- Using the wrong indentation
- Not having [EXPERIMENTAL] in the prompt, or not having it at
the end
- Wrongly stating the CONFIG_EXPERIMENTAL is needed to enable
an experimental Kconfig
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
Fixes various issues with Kconfigs, including:
- Redundent `default n` on bools
- Not select deprecated on supposed deprecated symbols
- Using the wrong indentation
- Not having [DEPRECATED] in the prompt, or not having it at the
end
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
If a device has multiple configurations, choose the first one that is
used by any driver.
Other attempts to chosse a configuraton, such as matching filter rules,
only narrow candidates by class, subclass, protocol, or VID/PID. The
only reliable way to determine whether a driver supports a function is
through the driver's probe() callback. This requires the device to be in
the configured state for the driver's own descriptor parsing and setup.
Therefore, there is no way to test a configuration without setting it.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
A successful usbh_class_*probe() is the only reliable signal that a
driver supports a function. Add helper to check if any drivers are bound
to a device interface.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Class driver can only decide whether they support an interface or
function once the device is in configured state. Move
usbh_class_probe_device() into usbh_device_set_configuration(), so
binding alsway happens agains an configured device.
It also fixes the assumption that usbh_class_probe_function() is called
with the device mutex locked.
When the configuration changes, any drivers using it should be unbound.
Keep the device in the addressed state, even if there is an error during
configuration set.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
The user or application should be able to set a specific USB device
configuration. This is, therefore, a required function that a host stack
must provide and it needs to be safe to call again on an already
configured device.
usbh_device_set_configuration() is not yet ready to be a public
interface. It leaks memory buffers when called in the configured state.
Note that this is not reachable in the current state of the host stack.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Align with the usual style and move usbh_device_connect() and
usbh_device_disconnect() behind their dependencies.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
The slim ring buffer API is now header-only and always available and the
tree has already migrated from the _claim/_finish API, so the RING_BUFFER
symbol no longer gates any code.
Remove the now-redundant "select RING_BUFFER" and CONFIG_RING_BUFFER=y
entries across drivers, subsystems, samples and tests.
Signed-off-by: Måns Ansgariusson <mansgariusson@gmail.com>
Handle low-speed connection events and record the device speed before
enumeration. Accept low-speed devices with the eight-byte endpoint zero
maximum packet size required by the USB specification.
Continue to reject unsupported SuperSpeed devices and reject low-speed
devices that report an invalid endpoint zero maximum packet size.
Signed-off-by: Benjamin Jurewicz <bjurewicz@internships.antmicro.com>
Set D0 (SetEthernetPacketFilter) in bmNetworkCapabilities of the NCM
Functional Descriptor and add the Network Capabilities bitmap values
from NCM 1.0, 5.2.1, Table 5-2 to usb_cdc.h.
The request handler already accepts SET_ETHERNET_PACKET_FILTER, but
without D0 the macOS NCM host driver refuses to enable promiscuous mode
on the interface, so Internet Sharing cannot add it to its bridge and
starts no DHCP or DNS service for it. There is no filtering on the
device side, as with commit 89e778d5b2
("usb: device_next: usbd_cdc_{ecm,ncm}: support promisc mode").
Assisted-by: Claude:claude-opus-5
Signed-off-by: Jeff Welder <Jeff.Welder@ellenbytech.com>
usbh_desc_get_next_function() sets skip_num=1 when starting from
a plain interface descriptor. usbh_desc_get_next() already advances
past the input, so an additional skip_num=1 makes the loop consume
one extra interface beyond the current one.
Devices with consecutive plain interfaces
(e.g. Quectel EG916Q-GL with 4 vendor interfaces) only get
ifaces 0 and 2 probed; 1 and 3 are silently skipped.
Drop the assignment. The IAD branch is unaffected since its skip_num
comes from bInterfaceCount, which counts interfaces grouped inside
the IAD, not the IAD descriptor itself.
Signed-off-by: Girinandha Manivelpandiyan <girinandha@linumiz.com>
Move alloc_device_address() and usbh_device_set_address()
before reading the full device descriptor.
The current sequence reads the full 18-byte device descriptor
while the device is in the Default state before transitioning
it to the Address state. This causes enumeration failure on the
Quectel EG916Q-GL, which returns bNumConfigurations=0 on the
second Get Descriptor request while in the Default state.
Reorder the sequence to transition the device to the Address
state after the initial 8-byte read, and fetch the full 18-byte
descriptor using the newly assigned address. The new order works
around devices that fail the second Get Descriptor request in the
Default state, while remaining functional on devices that
enumerate correctly with the original order (verified on ECM dongle).
Signed-off-by: Girinandha Manivelpandiyan <girinandha@linumiz.com>
Add the missing const (and static, where the symbol is file-local) to
the class API vtables and the per-instance arrays of descriptor
pointers, which nothing writes after initialization.
That requires usbd_class_api::get_desc() to return "const void *". The
stack walks the result as "struct usb_desc_header *const *", so the
descriptors stay writable for the bInterfaceNumber and
bEndpointAddress patching done at init. Classes outside subsys/usb
only get the new return type here.
With the previous commit, this saves 86 to 180 bytes of RAM per class
on nrf52840dk/nrf52840, with no flash increase.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
tc_init() unconditionally sets the Type-C state to TC_DISABLED_STATE
and then TC_ERROR_RECOVERY_STATE. Both descend from TC_CC_OPEN_SUPER_STATE,
whose entry action opens the CC lines. Once the board boots from VBUS
and runs tc_init(), the CC lines go to open state. To the Source that
will look like a detach, so it removes VBUS and the board powers down.
Transition directly to TC_UNATTACHED_SNK_STATE instead when the port's
Type-C Port Controller reports that it applies the dead battery
terminations, so that the Rd super state takes them over without the CC
lines ever being opened. A controller that reports no dead battery
resistors, and any build that cannot act as a Sink, keeps the previous
behaviour.
Signed-off-by: Nicholas Cadieux <ncadieux@qti.qualcomm.com>
Add new optional callback that the HID class can use to determine buffer
size necessary for Get Report response. This allows applications to
bound the maximum memory usage to actual supported report size instead
of having it depend on host-supplied wLength.
Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
The handle_get_status() sends data->state. The
dfu_mode_control_to_host() assigns data->state = data->next only after
the response has been built. In this case the host receives the state
the device is leaving instead the state is entering.
In the DFU 1.1 Table 6-2 bState is defined as "the state that the
device is going to enter immediately following transmission of this
response". The difference matters for exactly one case: an image
backend that answers false from its next_cb puts the device into
DFU_DNBUSY instead report DFU_DNLOAD_SYNC.
The dfu-util does not notice because it loop polls until the state
becomes DFU_DNLOAD_IDLE and the fwupd can wait only while the reported
state is DFU_DNBUSY. This means that the application can send the
next block into a busy device and the transfer dies on a stall:
failed to write-firmware: failed to write chunk 1: cannot download data:
USB error: Pipe error [-9]
In this fix the send data->next GET_STATE is unaffected once it reports
the current state by definition.
Signed-off-by: BUDKE Gerson Fernando <gerson.budke@leica-geosystems.com>
The dfu_mode_init() runs once per configuration. A device that offers
multiple speeds may add each image's string descriptor multiple times.
In the current implementation in the second attempt and forward the
class answer with -EALREADY. This leads to usbd_add_descriptor() report
when the node is already linked, and the class logs it at error level
on every boot:
<err> usbd_dfu: Failed to add string descriptor
<err> usbd_dfu: Failed to add string descriptor
The descriptor registered on the first pass is the one the host reads
and usbd_str_desc_get_idx() returns its index either way. Fix the
miss-leading error message.
Signed-off-by: BUDKE Gerson Fernando <gerson.budke@leica-geosystems.com>
The error was logged but the device initialization returned success,
so the device was probed against the class instances without a
configuration descriptor and the stack dereferenced a NULL pointer.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
dfu_flash_write() used flash_img_init(), which targets one partition
fixed at build time (slot1_partition when the application runs from
slot0_partition, slot0_partition otherwise), rather than the image's
own area ID that dfu_flash_read() already uses. Downloads therefore all
landed in that partition, whichever alternate setting was selected.
Any image that is not that partition is affected: enabling both
CONFIG_USBD_DFU_FLASH_SLOT0 and CONFIG_USBD_DFU_FLASH_SLOT1 always
mis-targets one of the two. A lone image, as in samples/subsys/usb/dfu,
happens to match, which is why this went unnoticed; the legacy class
writes to a single hardcoded area and rejects downloads to any other.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
Add PD_CTRL/DATA/EXT_MSG_COUNT enum sentinels and name lookup tables
for PD message types. Add a SEND log line, matching the existing RECV
log line, and log the human-readable message name alongside the raw
header on both SEND and RECV.
BUILD_ASSERT verifies that each lookup table remains synchronized with
its corresponding enum. The name tables are gated behind a new Kconfig
option, CONFIG_USBC_LOG_PD_MSG_NAMES, which can be disabled on
space-constrained devices.
Signed-off-by: Nicholas Cadieux <ncadieux@qti.qualcomm.com>
Ping is deprecated, so there is no need to special-case it out of the
RECV log dump. Always log the received packet content, regardless of
message type.
Signed-off-by: Nicholas Cadieux <ncadieux@qti.qualcomm.com>
Always use the pe_set_data_role function to switch the datarole.
Move the notify call to this function, so that there is
always a notification when the data-role is set.
Signed-off-by: Alexander Wachter <alexander@wachter.cloud>
After the changes to the RX transfer path, there is a pool per instance
for the RX path and OUT transfers. The existing bulk endpoints pool and
relevant Kconfig options are limited to the bulk IN endpoint. Update
their descriptions.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
Instead of storing RX data in ring_buf and copying it, store it in
k_fifo of net_bufs allocated from per instance buf pool.
Signed-off-by: Antoni Duda <antoni.duda@nordicsemi.no>
This commit updates the usage of ring_buf to utilize the new
put_ptr/commit/get_ptr/consume pattern instead of the traditional
claim/finish approach. This change is part of a larger refactor aimed at
streamlining the ring_buf API and improving its efficiency.
Signed-off-by: Måns Ansgariusson <mansgariusson@gmail.com>
The BT HCI endpoint buffers are limited to USBD_MAX_BULK_MPS, which is
64 bytes on full-speed controllers. Configured HCI ACL or event packets
can be larger, causing an assertion or buffer overflow when copied.
Use separate IN and OUT pools. Size the IN pool for the largest configured
HCI packet and keep the OUT pool limited to USBD_MAX_BULK_MPS. This allows
each HCI packet to be submitted in one USB request without increasing all
endpoint buffers.
Signed-off-by: Dominik Michalczyk <dominik.michalczyk@nordicsemi.no>
MISRA C:2012 Rule 8.2 requires every parameter in a function type to be
named, including the parameters of function pointer parameters.
usb_transfer_ep_callback() and the endpoint iteration helper declared
their parameters with bare types.
Name them after the arguments the documentation or the
definitions already use. No functional change.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Use #include <> instead of #include "" to include a header file which path
is not relative to the directory path of the file emitting the #include
directive.
This change was made running scripts/check_quoted_includes.py script
proposed in https://github.com/zephyrproject-rtos/zephyr/pull/112135
with the Linux shell command below and manually selecting the applicable
changes:
$ ./scripts/check_quoted_includes.py -w subsys/usb/
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
This macro eliminates manual size/alignment management and prevents
namespace collisions by moving internal queues to file-private scope.
Signed-off-by: Cesar Vandevelde <cesar.vandevelde@gmail.com>
Correct the trace message %zu specifier added by commit e5bc5c7a6d
that that should rather be %u since argument is not of size_t or like
type.
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
rndis_bulk_out() treats any single 0x00 byte received on the bulk OUT
endpoint as a frame delimiter and skips it unconditionally. When the
total length of an RNDIS data frame is not a multiple of the bulk
endpoint packet size and the last USB packet carries a single 0x00
payload byte, that genuine payload byte is dropped.
Dropping the byte leaves the in-progress packet one byte short, so the
frame is never completed. The next transfer is then written into the
still-open packet, the RNDIS header of the following frame is
misparsed, and the receive path desynchronises (observed as repeated
"Error parsing RNDIS header" / "Too small packet len" errors).
Only treat a single 0x00 byte as a frame delimiter when no packet is
currently being assembled (rndis.in_pkt == NULL). While a packet is in
progress the byte is written normally, completing the frame and
keeping the receive stream in sync.
Assisted-by: GitHub Copilot: Claude Opus 4.8
Signed-off-by: Ram Pingle <RamPingle@eaton.com>
Upon failure to read a configuration descriptor, usbh_req_desc_cfg
ends-up being freed twice: once by usbh_device_set_configuration()
which did allocate it, once by usbh_device_free() as a clean-up measure.
Deduplicate all possible k_heap_free() by setting the pointer to NULL
every time.
Signed-off-by: Josuah Demangeon <josuah.demangeon@nordicsemi.no>