This looks like it could work in the long term. The only issue that
really hasn't been addressed is how to use packet counters to cut
transactions when there's no ZLP, but we can leave that for later.
* Clear pipes and FIFOs during world switches to avoid interference
with the OS. LINK uses pipes 3 and 4, and attempts to add a second
pipe to the fxlink interface (thus using pipe 4) would interfere with
LINK and somehow prevent the pipe from being used (Wireshark captures
showed no responses on that pipe). Forcing a blank state is a valid
move because that state occurs naturally after a RESET, thus LINK and
other add-ins must support it as well.
* Delay the application of configuration to the USB configuration stage
(specifically, the DVST configured interrupt, even though technically
we should do that in SET_CONFIGURATION 0). This is because we
previously relied on world switches preserving pipe settings (by not
changing them) to reconnect the gint driver after a world switch.
This is no longer possible as the world switch now clears the pipes.
The new timing makes the driver automatically re-configure as the
connection restarts.
* 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).
* Finish updating the register list
* Use RTC-based timeouts to not involve more interrupts
* Be a lot more conservative about PID=BUF
* Start setting up parameters and checking invariants for future
bidirectional communications
We're not using them yet (specifically in fxlink) because timeouts
leave the pipes in undesirable states that currently end up crashing.
Some reset mechanism is needed, plus support from the protocol for
canceling messages, etc.
Having repeat settings only for getkey() meant that repeats that occur
while getkey() is not running (i.e., all of them) would be lost. This is
due to e57efb5e3 which replaced on-demand repeats with normal event
generation.
Now the settings are applied globally, which allows repeats to be
enabled even when getkey() is not active. This also reduces the feature
gap between getkey() and raw events, which reduces the risk of running
into edges cases by using both.
The previous API is retained for source compatibility until gint 3.0 but
the changes are now applied globally so the semantics are slightly
different.