USB mass storage writes ran at 0.03 MB/s in the firmware - to the NAND
and to the SD card alike - while the bootloader, with the same driver,
wrote the same NAND at 2 MB/s. The firmware adds a HID interface, and
without it writes ran at full speed.
The UDC's endpoints come in groups of three - bulk OUT, bulk IN,
interrupt IN: 1-3, 4-6 and so on - and allocation handed out the first
free endpoint of each type, so HID's interrupt endpoint 3 landed in the
group of mass storage's bulk endpoints 1 and 2. The host polls it every
16 ms, the idle endpoint NAKs, and each poll costs the group's bulk
traffic: writes advanced about one packet per poll. Polled every 125 us
instead, they all but stopped; moved to endpoint 6, in a group of its
own, they ran at 2.36 MB/s, as without HID.
Never give an interrupt endpoint a group with bulk endpoints in use, or
the other way round, whichever class asks first. Since which endpoints
are available then depends on what is already allocated, the driver
tracks the allocation itself - option 2 of usb_drv.h, as usb-designware
does - with its context in usb-rk27xx.h, which usb_core.c includes before
usb_drv.h. HID keeps working.
Tested on a generic rk2705 with ums_stress.py over USB mass storage to
the SD card: 0.03 MB/s with HID on endpoint 3, 2.36 MB/s with it on
endpoint 6 - the allocation this change produces for mass storage plus
HID. (Measured with the driver's earlier allocator, before the USB core
took allocation over; this carries the same rule into the new scheme.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ib80ed206a3705f2c76fc8457b5c0a54d60a46402
Thanks for the SET_ADDRESS rework. I think it leaves one case uncovered:
a host whose first request is SET_ADDRESS ends up with a device whose
interfaces are all numbered 0.
Two things still depend on the core seeing a request before the address arrives:
1. usb_core assigns interfaces and endpoints only on the first control
request it handles in DEFAULT. When SET_ADDRESS comes first, the driver
completes it and usb_core_set_address() moves the state to ADDRESS. So
allocate_interfaces_and_endpoints() never runs.
2. Under USB_DETECT_BY_REQUEST, usb.c enables the class drivers only
on a USB_TRANSFER_COMPLETION event. The SET_ADDRESS status stage now
completes inside the driver, so the drivers are still disabled when the
address arrives.
Change-Id: Ifacb8b07cbdefb0dee3d414c2257a50a08759f3d
A host can replace an unfinished control transfer with a new SETUP. ARC
and DesignWare flush EP0 without reporting completion callbacks, leaving
the core waiting for a data/status packet that will never arrive.
Explicitly notify the core after both directions and stale completion
bits have been cancelled. Return an abandoned data/status stage to READY.
If a queued or running handler still owns the request and data buffer,
keep that ownership and suppress its response; dispatch only the latest
replacement when it returns. A driver-owned SET_ADDRESS can also cancel
a deferred request without passing its SETUP to the core.
Do not overwrite an arbitrary busy state in usb_core_setup_received().
ARC cancellation is a prerequisite in the preceding patch; DesignWare
cancels both EP0 directions before notifying and rearming reception.
Change-Id: Ia8e0a68fe47ccab952168da24a2f76e311ca2b15
Handle SET_ADDRESS directly when each controller receives SETUP, before
passing other requests to the core. Cancel transfers, send the status
response in the driver and queue usb_core_notify_set_address(); the core
only updates its address/configuration state. Remove usb_drv_set_address
and avoid a request callback from the core back into the controller.
Keep status completions for this driver-owned request out of the core EP0
state machine. ARC writes DEVICEADDR and notifies after successful status
IN completion; other controllers retain their existing register/status
ordering or automatic address handling. Use IRQ-local operations on
DesignWare rather than helpers which unconditionally re-enable its IRQ.
Take the low seven bits of wValue; do not impose new validation on the
unspecified wIndex/wLength fields. Convert all eleven firmware backends;
the separate hwstub API is unchanged.
Change-Id: I7b96275df90c14ef4a9954f04ac6fdc004ec8d6c
Do not release and reacquire the disk when a host repeats configuration
or resets the bus before selecting mass storage again. This avoids
remounting local filesystems while the host still owns the disk.
After reset the filesystems remain unmounted until the host selects a
configuration which releases storage, or the cable is unplugged. A host
normally reconfigures promptly; one that never does leaves the disk
unavailable locally until unplug, rather than risking simultaneous access.
Change-Id: I6e296247dd2227e549105d85760613c1a81554a1
Reject the first out-of-range configuration index and omit class descriptors for drivers whose initialization failed.
Change-Id: I1f74dcceb69f19b52650aa6ae3f38331e320b151
Results in cleaner code versus effectively cut-n-pasting the driver's
completion callbacks into the endpoint structure.
Change-Id: I043c46c91796f787dec098a7db043481834950a0
this commit is a combination of the following changes, which
significantly refactors usb core and class drivers.
1. unify usb buffers of each class driver to reduce iram usage
currently, many class drivers allocate their own buffer to receive
control out data, which is a waste of iram.
share one common buffer for that usage to address the issue.
2. simplify control request handling by implicitly receiving write
request data packets
change 1 above fixed the data destination. therefore, having the core
receive the data allows us to reduce the class driver's work and
simplifies the api.
3. enhance usb core's control request handling and unify the legacy
driver api
in order to implement change 2, both the legacy and new driver apis
should be supported. so that, using the designware driver as a
reference, the new driver api functionality is move into usb core.
this simplifies the usb device drivers by requiring them to implement
only the functionalities equivalent to the legacy api.
tested with ipodvideo(arc) and erosqnative(designware)
Change-Id: I3627daa90278751f599e2108ec150ec3f8f6c524
the capabilities of endpoint of several devices such as dwc2 change during
runtime, so they cannot be determined during driver initialization.
therefore, allocation using ep_specs is inappropriate.
to support these devices, add functions to the driver that determine whether
endpoints are available and make allocation more flexible.
tested with ipodvideo(arc) and erosqnative(designware)
Change-Id: I8005c17f3d763cd17306bf49918e1cd8084bdeff
add needs_cpu_boost field to usb_class_driver and manage boost state in
usb_core, similar to needs_exclusive_storage.
Change-Id: Ieb0cd7bedda5b24bb0d209d5ce907db30f4815db
this is required to make hid endpoint of iap class driver work,
especially on ipodvideo(arc).
at least for arc, it is required to set mps as 64 instead of 512 on
highspeed, or some accessories ignore incoming hid reports.
Change-Id: I242060faced28a66204146a9c36ef10626d6d265
add class driver source files.
also register iap audio sink.
usbstack/iap/libiap directory is imported from libiap.
Change-Id: I776c5caec33fe9efadc448e2e3b37d500bf19c9f
some targets can process requests fast enough without dedicated
batch api implementation.
provide generic implementationn for such targets.
Change-Id: I152681441e70e0e98396274d9305d371d2bbfbe3
Bootloaders with HAVE_USBSTACK but without HAVE_BOOTLOADER_USB_MODE end
up with USB_NUM_DRIVERS of 0 which leads to a warning due to a signed
number being checked to see if it's >= 0.
Work around this temporarily; the proper fix is to not build usb_core
and its class drivers when BOOTLOADER & !HAVE_BOOTLOADER_USB_MODE
Change-Id: I1b41140d31ba9df6b4c760478c4265d4e5584963
this invokes specified class driver's notify_event method.
initial purpose is to trigger a callback from isr, like a timer event.
Change-Id: Id600e9f0d8840a12da779d5a15783edf14bd76b5
currently, exclusive disk mode was enabled at the same time as the
usb insertion. when multiple usb configurations exist, this is not
appropriate.
manage it in the core and enable it only when necessary.
Change-Id: Iadbec05fad1d1319471233227ae0e72c12079295
- existing class drivers are placed to config 1
- drivers_connected==true is replaced with usb_config!=0
- supports config transition between nonzero configs
- STALL if request set_config was invalid
Change-Id: Ia775ae2dcb7d0cc08d2f3ee5ca41683837b04259
this commit has following changes:
- introduce `usb_drv_ep_spec` table to udc drivers, which represents
endpoint characteristics.
- introduce 'ep_allocs' table to class drivers, which represents what
endpoint type does the class driver want.
- implement endpoint matching logic to usb core.
this is a required step to implement usb config switching, because we
need to create config descriptors without actually initializing endpoints.
Change-Id: I11c324cd35189ab636744488f6259d0cdb2179f0
Original commit credit to Amaury Pouly, Moshe Piekarski
Pushed across the finish line by Dana Conrad
To enable, see setting under General Settings --> System --> USB-DAC.
On devices with few endpoints, this may not work while HID and/or
mass storage is enabled.
Adds new dedicated mixer channel.
setting usb-dac can have values:
- never (0)
- always (1)
- while_charge_only (2)
- while_mass_storage (3)
Relevant devices are DWC2 and ARC usb controller devices. That being:
x1000 Native targets (m3k, erosqnative, q1, others...?),
sansac200, creativezenxfi2, vibe500, ipodmini2g,
ipod4g, creativezenxfi, creativezenxfi3, sansaview, ipodcolor,
creativezenxfistyle, samsungypz5, sansafuzeplus, iriverh10_5gb,
tatungtpj1022, gigabeats, faketarget, samsungyh820, gogearhdd1630, samsungyh925, ipodmini1g, ipodvideo, creativezenmozaic, sonynwze370, creativezen, gogearsa9200, gogearhdd6330, sonynwze360, sansae200, mrobe100, iriverh10, creativezenv, ipodnano1g, samsungyh920
USB Driver-wise, it should be noted that this patch requires some
slight changes:
- proper blocking on control OUT transfers, to make sure the data is
received *before* using it, the usb_core should probably use that too
- drivers can now support interface alternate settings
- drivers can be notified of completion by a new fast handler, which
is called directly from the driver; this is is necessary for
isochronous transfers because going through the usb queue is way too
slow
Designware changes:
- enable for USBOTG_DESIGNWARE
- set maxpacketsize to 1023 for ISO endpoints
Change-Id: I570871884a4e4820b4312b203b07701f06ecacc6
Leading spaces in particular were resulting in Linux warnings/panics, but
to be safe strip out all spaces, including those in the middle.
This was noticed on an ipod6g with the stock hard drive; it reported
a serial number of ' xxxxxxxx', which is technically legal
per ATA specs, but needs to be properly trimmed.
Change-Id: I34309fe64b341caefd5b18f6d0cf539cb97d4a38
On PortalPlayer iPods, it looks like the serial number is available in a
specific memory location. When adding support for Samsung S5L87xx-based
iPods, this algorithm has not been limited to PP-only, so it sets the
serial number USB descriptor to random memory data.
With this change, it will use the ATA HDD serial number on iPod 6G. On
Nano 2G it won't provide a serial number at all.
Change-Id: I53d48915d629dbd87b2dbbcba5f228ca5949fa9b
Apparently a response is coming out of nowhere and tripping this
check. I can't be bothered to look into it; it would be better to
just update the ARC USB driver to the new control request API...
Change-Id: Ic5062443e060534f170d3afe17c00d3c25d1d3bd
It seems connecting an iPod Video to a Mac triggers the null
request check, resulting in a panic. Ignoring the error with
a bare return "fixes" it and allows the iPod to connect. This
isn't ideal though, because it could silently introduce bugs
on other targets.
The likely cause of this is the host sending control requests
too fast, or a driver problem (the Video uses the ARC driver,
which is still on the legacy interface), with multiple requests
getting queued at once. Since the USB core expects to deal with
only one request at a time, the second response trips the check.
Try to handle this situation a bit more gracefully by detecting
overlapped requests and returning a STALL to the host when it
occurs. At this point the USB stack is able to safely handle a
new request.
Link: https://forums.rockbox.org/index.php/topic,54414.0.html
Change-Id: I9a2b7e35620ff540ebdb39f81671377062a4917d
Due to how the old control request API worked, the request
pointer (and the pointed-to contents) passed by the driver
must remain valid for the lifetime of the request.
The buffered copy wasn't used consistently anyway, so it
should be safe to just get rid of it.
(This only affects the old API compatibility layer.)
Change-Id: I00294c718a7515a91b84f7c7cae5220c73aa5960
In the old API, usb_core_transfer_complete() would ignore
any completions on EP0. The legacy control API will also
ignore most completions on EP0, but it only did so after
filling in the completion event.
If the driver submits a spurious completion on EP0, then
this could clobber a previously queued completion event.
Fix this by deciding whether to ignore the completion
*before* modifying the event data.
Change-Id: I68526898a96efa594ada4e94bb6851aaaf12e92a
The address from the packet needs to be saved before sending
the response -- after the response the request being pointed
to could get overwritten. This used to be done correctly but
I unintentionally broke it when updating the handler to the
new control request API.
Change-Id: I9b11548baf20dce44a82301731405dc8e8f1cef3
Because usb_core_legacy_control_request() is called by an
interrupt handler the global variables used to track the
current control request at the very least need to be volatile.
It might also be necessary to disable IRQs but I'm not sure
of that.
Change-Id: I0f0bb86d0ad63734e8d3c73cb1c52fedf5a98120
All existing USB drivers now define USB_LEGACY_CONTROL_API to
enable the emulation layer.
Control request handlers will be ported in follow-up commits.
Change-Id: I4be1ce7c372f2f6fee5978a4858c841b72e77405
This makes it possible for macros of conditionally included string
descriptors to get a correct index no matter what other usb drivers
are enabled or disabled due to the nature behavior of enums.
Change-Id: I8ccebbd316605bed0f5d90b6b73fab4a333c02fa
Upon getting a USB reset, the USB core will update charging
current by calling usb_charging_maxcurrent_change(). On all
current X1000 targets this may cause a hang, since changing
the charge current involves a blocking I2C transaction.
Eg. if the host issues a reset when we're already configured
as part of error recovery, the change from 500 mA -> 100 mA
will cause a hang.
Change-Id: I5b45272c01fa16b179ae3d16bbc50c7fab9a416b
IMHO the current name is somewhat misleading:
- usb_drv_send() is blocking and we have usb_drv_send_nonblocking()
for the non-blocking case. This inconsistent naming can only
promote confusion. (And what would we call a blocking receive?)
- Other hardware abstraction APIs in Rockbox are usually blocking:
storage, LCD, backlight, audio... in other words, blocking is the
default expected behavior, with non-blocking calls being a rarity.
Change-Id: I05b41088d09eab582697674f4f06fdca0c8950af
Atmel AT88SC6416C CryptoMemory is almost I2C compatible. The device
is connected to bitbanged I2C bus shared with compliant I2C devices.
Change-Id: Iec54702db1bdfb93c01291eef18ec60391c63b16
This uses the new unicode string literal feature that is available
now to greatly simplify the initialization of these special string
types. This makes them much more readable at a quick glance.
Change-Id: Iad8b49aa763486608e3bb7e83fb8abfb48ce0a7b