Not changing much for now, just distilling them into hardware/OS/render
macros. Later on the rendering stuff will become more dynamic and down
the line I want to unify the APIs more.
The previous scheme was really unclear. Now, an endpoint_t carries all
of the endpoint info (instead of the global address being implicitly
its array index, which couldn't be returned).
An _endpoint address_ is the 8-bit value consisting of an endpoint
number (bits 0x0f) and a direction (bit 0x80).
The _global address_ of an endpoint is the address used to communicate
with the host, and it is unique. The _local address_ of an endpoint is
the interface-specific numbering that gint provides to allow interfaces
to compose without risks of address collisions.
The complete data for an endpoint can be queried with the new functions
usb_get_endpoint_by_*() which accept global addresses, local addresses,
and pipe numbers.
* Move logic around tracking transfers to asyncio.c.
* Add a "short buffer" holding 0-3 bytes between writes, so that the
driver performs only 4-byte writes in the FIFO and a short write in
the commit, if needed.
- This is partially due to me thinking at some point that degrading
writing size was impossible, but it might actually be possible by
writing to FIFO/FIFO+2 or FIFO/FIFO+1/FIFO+2/FIFO+3.
- In any case I think this new approach wins on performance.
* Get rid of unit_size since we now always use 4 bytes.
* Add a waiting function which is used in usb_close() (and once tested
should be used in world switches too).
* Eliminate some of the special cases for the DCP, though not all (in
particular I can't get the commit to rely on the BEMP interrupt yet,
nor can I properly clear PID to NAK when unbinding).
This changes fixes the way gint uses the FIFO controllers D0F and D1F
to access the FIFO. It previously used D0F in the main thread and D1F
during interrupt handling, but this is incorrect for several reasons,
mainly the possible change of controllers between a write and a commit,
and numerous instances of two FIFOs managing the same pipe caused by
the constant switching.
gint now treats FIFO controllers as resources allocated to pipes for
the duration of a commit-terminated sequence of writes. The same
controller is used for a single pipe in both normal and interrupt
modes, and released when the pipe is committed. If no controller is
available, asynchronous writes fail and synchronous ones wait.
The fxlink API is also added with a small amount of functions, namely
to transfer screenshots and raw text. Currently these are synchronous
and do not use the DMA, this will be improved later.
Finally:
* Removed pipe logic from src/usb/setup.c, instead letting pipes.c
handle the special case of the DCP (which might be regularized later)
* Removed the usb_pipe_mode_{read,write} functions as they're actually
about FIFo controllers and it's not clear yet how a pipe with both
read and write should be handled. This is left for the future.
* Clarified end-of-sequence semantics after a successful commit.
* Add the power management functions (mostly stable even under
overclock; requires some testing, but no known issue)
* Add a dynamic configuration system where interfaces can declare
descriptors with arbitrary endpoint numbers and additional
parameters, and the driver allocates USB resources (endpoints, pipes
and FIFO memory) between interfaces at startup. This allows
implementations of different classes to be independent from each
other.
* Add responses to common SETUP requests.
* Add pipe logic that allows programs to write data synchronously or
asynchronously to pipes, in a single or several fragments, regardless
of the buffer size (still WIP with a few details to polish and the
API is not public yet).
* Add a WIP bulk IN interface that allows sending data to the host.
This will eventually support the fxlink protocol.