For now we only support USB <3.0 devices, as we don't support streams.
We also don't leverage the benefits of UAS, as we pretend to have a
queue depth of 1, ie are single threaded.
To test this driver, you can use the following command:
```
SERENITY_BOOT_DRIVE=usb-uas Meta/serenity.sh run x86_64 Clang
```
This change has many improvements:
- We don't use `LockRefPtr` to hold instances of many base devices as
with the DeviceManagement class. Instead, we have a saner pattern of
holding them in a `NonnullRefPtr<T> const`, in a small-text footprint
class definition in the `Device.cpp` file.
- The awkwardness of using `::the()` each time we need to get references
to mostly-static objects (like the Event queue) in runtime is now gone
in the migration to using the `Device` class.
- Acquiring a device feel more obvious because we use now the Device
class for this method. The method name is improved as well.
This will allow us to make send_scsi_command a member function. This is
necessary because we need to execute some SCSI commands
(with send_scsi_command) to get all arguments necessary for the
StorageDevice constructor.
This change should will likely also be necessary to support USB mass
storage devices with multiple LUNs.
The Short Packet Completion Code just means that the xHC received fewer
bytes than expected.
We shouldn't treat them as errors, since our transfer functions already
return the actual transfer size.
"Endpoint Address" refers to "[t]he combination of an endpoint number
and an endpoint direction on a USB device."
(USB 2.0 Specification, Chapter 2)
The USB::Pipe m_endpoint_address member doesn't have the direction part,
so rename it and all variables/functions associated with it
appropriately.
A lot of USB structures contain back pointers to their parents,
so we need to be careful about how we copy them around, and update
the back pointers as necessary.
VariadicFormatParams only stores pointers to the parameters, so
the device.device_name() parameter will dangle.
This fixes broken dmesgln_pci output on riscv64 GCC.
Linux did the same thing 18 years ago and their reasons for the change
are similar to ours - https://github.com/torvalds/linux/commit/7d12e78
Most interrupt handlers (i.e. IRQ handlers) never used the register
state reference anywhere so there's simply no need of passing it around.
I didn't measure the performance boost but surely this change can't make
things worse anyway.
This is apparently what bootloaders do before using a USB storage device
so we should likely do so as well, especially when no BIOS is present,
like on riscv.
Co-Authored-By: Sönke Holz <sholz8530@gmail.com>
Bulk transfers also use Normal TRBs, so move the reusable normal TRB
setup code from submit_async_interrupt_transfer into a new function
prepare_normal_transfer.
submit_bulk_transfer and submit_async_interrupt_transfer use this
function and then either block on the completion or submit it
asynchronously and wrap it into a PeriodicPendingTransfer.
This fixes incorrect assumptions about the layout of descriptors and
gets rid of all the pointer arithmetic.
The USB spec doesn't define a strict order for all descriptors to appear
in.
It just says that endpoint descriptors follow its interface descriptor.
We also have to skip all unknown descriptors (which also can appear
anywhere), not just HID descriptors.
All USB Devices (including hubs) need to have a configuration set before
you can use them. We already do this in other USB drivers, but forgot to
do it for USB hubs as well.
This adds a minimal (that is, just enough to make USB mouse/keyboard
work) implementation of an xHCI driver, to let us use serenity on
modern baremetal machines.
Both the calculation for the interface descriptor address and the
endpoint descriptors addresses (for second interface and above) were
incorrect, and would read the wrong data (and go out-of-bounds as well)
Previously USB::Pipe would just try to poorly maintain copies of some
of the relevant properties of USB::Device. (address & speed)
Now it just holds a reference to it's owning device and can query them
when needed.
The current USB::Device::enumerate_device() implementation is UHCI
specific, and is not relevant for xHCI controllers.
Move it to a USBController virtual method to allow different
implementations for the other controller types.