Every hid pad handler that lights the pad - the DualShock 3, DualSense
and Edge, Switch Pro, Switch 2 Pro and Wii Remote - lit its hid slot,
once, when it started. After a driver restart the pads can come back in
other slots and are moved back to the ports they had, and a port can be
pointed at another pad in the menu or by a reservation: the lights then
showed the wrong player, and a pad no port reads was still lit.
The frontend now tells the joypad driver which port reads each pad,
and the hid drivers pass it to the pad's handler, which relights from
its packet handler - the pad's own thread - so nothing waits. The lowest
port reading a pad is shown; on none, the lights go out. The Switch
pads take the console's patterns past player 4.
It costs one countdown a poll: every 32 polls the ports are compared
with what the driver was last told, and only a change, a driver start
or a pad starting beside the joypad driver tells it again. The player
is kept for each slot, so a pad plugged in is lit for its port as it
starts. A handler never told, under a hid driver that does not pass it
on, lights its slot as before.
joypad_slots covers the slot's player across pads and threads;
connect_parity the DualSense and Switch Pro relighting.
The DualSense handler built its own USB output report and sent nothing
over Bluetooth. It now sends what raw input's driver sends for these
pads (input/common/sony_pad_output.h): over USB or Bluetooth as the
pad came, with Bluetooth's checksum, the player's lights at the first
report and rumble at the poll after a change. The motors are driven
the newer way on a DualSense Edge, which now has an interface of its
own, and on a DualSense from firmware 2.21, which its feature report
0x20 tells. Nothing is sent behind a Bluetooth stack's own header,
whose framing of output is that stack's.
A HID driver can now say a device is on Bluetooth (is_bluetooth): on
Windows every report comes at the longest one's length, so a
DualSense's 10-byte Bluetooth report cannot be told from USB's by it.
connect_parity_test holds the reports sent to the shared builder's,
over USB, over Bluetooth and on a padded report the driver says is
Bluetooth's, and checks the Edge and firmware 2.21 get the newer
motor control.
A DualShock 3 connects over Bluetooth to the address it was last given
over USB, in its feature report 0xF5. Joypad drivers can now read and
set that address for a pad that keeps one (get_bt_host/set_bt_host,
also on the HID driver interface): the udev driver through the hidraw
node it reads the pressures from, and hidraw_hid through the pad's own
node, both for a pad on USB.
This computer's Bluetooth address is read on Linux from the kernel's
HCI socket, the first adapter that is up, with no BlueZ library.
Information > Input Information lists the adapter with its address,
and under a controller that keeps one the address it connects to -
"This Computer" when it is this one's - with "Pair with This Computer"
to set it when it is not.
samples/input/hidraw_hid checks that the address is read and set as
0xF5 most significant byte first.
A joypad driver's state call answers the RetroPad's sixteen as a mask.
It was handed the port's binds for it, and every driver chose, for
each of the sixteen at every call, between the port's own bind and
its controller's profile's: thirty-eight copies of the same two
lines, each a reason the binds' records cannot change shape.
The frontend has made that choice already and keeps it - the port's
resolved set, worked out when a bind changes. The state call takes
two lists from it instead: the pad's button behind each of the
sixteen (NO_BTN for none) and the pad's axis (AXIS_NONE for none).
int16_t (*state)(rarch_joypad_info_t *joypad_info,
const uint16_t *joykeys, const uint32_t *joyaxes, unsigned port);
and the same for an HID backend's. In the 29 joypad drivers, the Wii
U's three and the six HID backends that is the signature and the two
lines, by script: each keeps its own loop and whatever is its own
about it (the DOS one answers nothing, the PS4's and the parallel
port's go by buttons alone, and so on). No file of theirs names a
bind, a set of binds or a profile's any more, and
tools/input_state_grab_check.py holds them to it (a selftest case
with it).
The frontend's side:
- input_joypad_port_state() makes the call. For a port read by its
own controller it hands over the resolved set's lists as they
stand, and answers "none" itself where no pad is behind any of the
sixteen. For a read by another controller it resolves the sixteen
for that call, from the port's binds and that controller's profile.
- The resolved set writes the sixteen's places whatever is behind
them, so the lists can be handed over whole.
- The frontend's own loop, which stands in for the drivers read
through a snapshot, takes the same two lists; it found the port's
set from the address of the binds, and finds it from the address
of the list.
- Learning a trigger's rest asks whether the axis's other direction
is bound to anything: of the port's resolved set, where there is
one. For a read by another controller it sees the sixteen it was
handed, where it used to see every bind of the port.
Measured, the frame's input work over 300 frames (X11):
- no controller: 3,796,163 instructions before, 3,786,758 after;
- a controller with a hotkey enabler, through a driver that is read
directly: 4,478,984 before, 4,458,394 after. Its state call alone:
190,376 to 147,272.
Checked:
- samples/input/joypad_bridge_checked, which holds six drivers'
state calls (udev, linuxraw, SDL2, SDL3, DirectInput and the
XInput-only one) to the frontend's loop from the binds, over
thousands of random pads, binds and thresholds: all six pass with
the lists.
- The X11 keyboard session logs the same as before; the hotkey and
quit-combination sessions log the same lines on master's binary
and this one; the frontend harness passes every lane; the
multimedia joystick driver's test passes under Wine.
- Built: Linux in full, and the parallel port, SDL2, HID and libusb
files compiled beside it; Windows in full with a mingw cross
compiler (the XInput and DirectInput driver, the DirectInput one,
raw input and the multimedia joystick among it), and run through
the scripted session under Wine; the Android unity build with the
NDK, with OpenXR on; the Visual C++ 6 project and the QNX drivers
on their stand-ins; a build with the optional features off.
- Not compiled, there being no compiler for them here: the console
drivers (3DS, DOS, GameCube and Wii, PS2, PS3, PS4, PSP and Vita,
Switch, Wii U, Xbox, web), the Apple one, SDL 1, and the HID
backends but libusb's. Their edits are the script's, the same in
every file.
The seventh piece of the mapping compiler's fifth step (plan, section
21). Counted as before, binds are read from the tables at 107 places
in 26 functions of the frontend's file, from 113 in 28 - and in no
driver's.
Both drivers park a poll thread on a flag the teardown sets from another
thread, with no lock either side, as volatile bools that ordered nothing
between the two. The flags are initialised before their thread is
created, and on the Wii USB side before the first goto error, since free
stores through it.
wiiusb_hid's device_detected goes the other way. It is raised by
wiiusb_hid_change_cb, which libogc runs in interrupt context, so an
atomic is not what it wants - the writer is not a thread, and this file's
other interrupt-shared state is volatile for that reason. It was a plain
bool, which left the poll thread free to hold it in a register across the
loop; volatile is the smallest thing that fixes that.
Both files build against the headers already in the tree - libogc under
wii/, wut under wiiu/ - on a 32-bit PowerPC compiler and on all five
retro_atomic backends, unmodified first and then with the change.
Extended RETROK_ values with 18 new items, commonly found on
"multimedia" keyboards.
Mapping added for SDL, X11, Wayland, dinput, winraw keymaps.
Keyboard tester function of Remote Retropad extended to cover new keys.
One fix in Android mapping for #12986
== DETAILS
Put the finishing touches on getting the DS3 to work on Mac OSX.
Basically, there's some differences in the HID interface bewtween
wiiu and osx where OSX expects the first byte of the report to be
the report ID, while wiiu expects that byte to be trimmed off.
I was able to put this behavior in the respective HID
implementations, which eliminated the confusing packet offset
ifdefs.
And, I was able to get the LEDs working again.
== DETAILS
The DS3 driver previously only worked with the Wii U HID implementation.
I adapted this driver from the Linux driver for the DS3. It's not quite
100%--I haven't got the LEDs to work properly--but it's functional.
Going to continue tweaking it to see if I can get the LEDs to work.
== DETAILS
cause of crash: trying to deference init when it's null
the reason it was going into deregister: the HID/VID lookup was
failing because it wasn't getting initialized first
cause of 2nd crash: the "end of pad list" method looked for an entry
with a magic value, so we add an end marker
== DETAILS
When I first implemented the Wii U HID architecture, I ended up
having to design my own implementation because, at the time, I did
not have a way to read the HID device string to allow the existing
code to successfully detect the gamepad.
After spending some time experimenting, I've figured out how to
do this. And that means I can better align the HID driver with other
platforms.
change summary:
- create a single state structure for all three sub-types of wiiu pads
(kpad, wpad, and hid)
- eliminate confusing duplicate pad lists
- eliminate confusing duplicate HID pad drivers (ds3, gamecube
adapter, etc)
- ensure the ds3 driver still works
=== DETAILS
Replaced includes for things that aren't standard library headers so
they use quotes instead of brackets.
Also fixed up a couple of headers that had include-order dependencies.
=== DETAILS
Since @aliaspider wants the `wiiu/` to be something of a mini-SDK, I've
reorganized the code I put in there:
- `wiiu/main.c` now only has the ELF/RPX entrypoints, and the code used
by those entrypoints, with RA code removed (e.g. swapped retro_sleep()
for usleep()). These entrypoints then call main() ...
- Moved `main()` and its support functions back into `frontend/drivers/platform_wiiu.c`
I also renamed some of the support functions I wrote, and better
organized them within the code.
- Moved `wiiu/input/` into the `input/` hierarchy:
* The joypad drivers now live in `input/drivers_joypad/wiiu/`
* The HID driver now lives in `input/drivers_hid/`
* The Wii U specific headers now live in `input/include/wiiu`
* I added `input/include` into the include search path to avoid
using really ugly relative includes
== DETAILS
- DS3 analog wasn't working mainly because I forgot to actually declare the
axes in input/input_autoconfig.c when declaring the pad. Whoops.
- I also moved the axis decoding logic to a more central place, because it
clearly is not Wii U specific.
- Removed some dead commented-out code
== TESTING
Can use analog inputs on both GCA and DS3. Tested in Mario 3 on Nestopia core.
Haven't tested with any actual analog games, but I did confirm via logging
that the correct ranges are produced.
retro_bits_t turned into input_bits_t and there were parts of my
code that needed to update.
== TESTING
No idea if upstream changes broke anything, but it compiles cleanly
now.
== DETAILS
- fix the bitshift math
- read the right bytes out of the ds3 data packet
- remove verbose logging in critical path
- stop caring about errors in the hid read loop -- seems to just
be benign "device not ready" -- or at least, that's what I'm assuming
given that the read eventually succeeds.
== TESTING
Played Mario 3 with the DS3 with no issues.
== DETAILS
- update to not try starting the read loop until after the device
is successfully initialized
- add new HID wrapper macros needed by ds3 driver
- add some debug logging to help with troubleshooting
- add button map for DS3
== TESTING
Tested with local build. DS3 init is not working.
== DETAILS
Whereas the last commit had a hack (that disabled the wiimote
driver in the process), this has.. well, a *different* hack that
allows pads to register in any order.
Note that due to the initialization routines, the gamepad will still
likely always get slot 0. Not sure if this can be overridden via config
or not.
== TESTING
Tested locally with GC adapter
== DETAILS
Now that I have a working implementation, it's time to tidy up a bit:
- there was no need for the HID subsystem's object data to have a reference
to the global hid state (since it's global), so removed it.
- refactored the users of that member to use the global state, defining
reusable macros.
- reorganized the information in *.h files
- removing the hid state also made the constructor changes to the hid driver
unneeded, so I reverted those changes.
== TESTING
Confirmed clean build. Haven't tested the build yet to make sure everything
still works, though.
== DETAILS
- Added a new method to the joypad_connection_t interface for
getting a single button
- wired everything into the hidpad driver
- for testing purposes, hacking the top-level joypad driver
so that kpad isn't used
- add a new RARCH_LOG_BUFFER method to verbosity for logging the
contents of a binary buffer (useful for writing/debugging pad drivers)
- fix a few bugs in the wiiu GC pad driver
The button mapping isn't quite right, and I'm not sure what's
going wrong.
== DETAILS
I've created the concept of a hid_driver_instance_t which is basically
a central place to store the hid pad driver, hid subsystem driver,
the pad list, and the instance data for the above in a central location.
The HID pad device drivers can use it to perform HID operations in a
generic manner.
This is more-or-less a pause point so I can catch up with upstream.
== TESTING
Haven't tested this yet. Compiles without warnings though!