Commit Graph
57 Commits
Author SHA1 Message Date
LibretroAdmin 4d702934db wiiu/hid: hand adapters between threads lock-free
The polling thread and the frontend shared one adapter list under an
OSFastMutex, which the frontend took on every poll, and the HID attach
callbacks queued events by swapping the list head out and back in. That
swap pair is not atomic as a whole: two callbacks at once (the HID
stack calls them from more than one thread) can each take the list and
put theirs back over the other's, losing an attach or a detach. A lost
detach leaves the pad registered for good.

Each thread now keeps its own list and hands adapters across through
the lock-free stacks of mpsc_stack.h:

  attach callbacks -> hid_events  -> polling thread
  polling thread   -> hid_new     -> frontend: adapters to set up
  frontend         -> hid_retired -> polling thread: to free

An adapter's state is a retro_atomic_int_t, and each value is moved on
by one thread only, so no two ever write it from the same state. The
read completion runs the packet handler before it says READY, since
READY is when the polling thread may start winding the adapter down;
it used to say READY first. The frontend deregisters and deinitialises
a pad as it retires the adapter, the polling thread frees the adapter,
and at shutdown the polling thread tears down what is left, as before.
No lock remains, and the frontend's poll no longer takes one.

samples/input/wiiu_hid_threads runs the driver against stand-ins for
Cafe OS on pthreads: two threads attach and detach devices while the
frontend polls and an "IOS" thread completes the reads, and every pad
must be registered, fed, deregistered and deinitialised in order, on
the right threads, with nothing left at shutdown. Its negative build
loses the reads in flight at shutdown and must fail. Against the old
driver (32-bit PowerPC under qemu) it fails: a few hundred pads of
detached devices are never torn down.
2026-10-29 21:01:28 +01:00
LibretroAdmin 661fdde857 Input: motion from Switch Pro Controllers on the hid joypad driver
The Pro Controller, and the pads that pass for one (8BitDo's in Switch
mode among them), now give a core their accelerometer and gyroscope,
read as SDL reads them:

- The sensors' calibration is read from the pad's flash with the stick
  calibration: the factory's at 0x6020, then the user's origins at
  0x8026 where the user calibrated.
- Subcommand 0x40 turns the sensors on while a core asks for them and
  off when it is done, sent from the poll like the player lights.
- Each report 0x30 carries three samples; the newest one is kept. The
  values go out in g and radians a second, on the axes SDL gives them,
  which are the DualShock 4's, and so on the same axes as winraw's
  DualShock 4 and DualSense.

How it gets there:
- Pad handlers can now have set_sensor and sensor ops.
- hidraw and winusb route the driver's sensor calls to the slot's
  handler.
- The hid joypad driver passes the frontend's set_sensor_state and
  get_sensor_input on to its hid driver.
- The beside layer sends a hid pad's sensor calls to the hid driver
  rather than to the joypad driver it stands beside.

connect_parity_test checks the calibration reads, the 0x40 commands and
the values from a sample.
2026-10-22 02:33:45 +02:00
LibretroAdmin 86fc5aa7fb Input: HID pads lend their state to the snapshot bridge
The DualShock 3, DualShock 4, DualSense and both Switch Pro handlers,
and the generic pads read from their report descriptors, now keep
their state as an input_pad_view_t, decoded straight into it and read
by their getters. hidraw and winusb hand reports to the handlers only
in their poll, so the state does not change between polls and they
lend it through a new hid_driver_t view(), as udev and winraw lend
theirs: the bridge reads it in place, with nothing copied.

The beside layer passes view() through, so a WinUSB pad beside
winraw is lent, and winraw's own pads stay lent while it is there
instead of falling back to copies. A generic pad's hat is part of its
view, which the drivers' hat reads now use.

connect_parity holds each converted handler's view to its getters
after every report, and the DualShock 3's axes to the copying
handler's; hidraw_hid, winusb_hid and the frontend harness's beside
lane check the lend.
2026-10-21 22:11:49 +02:00
LibretroAdmin 8cbe988eaf Input: hid pads light the port they are read on
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.
2026-10-21 07:36:04 +02:00
LibretroAdmin 0f8649c244 DualSense: rumble and lights through the shared report, Bluetooth too
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.
2026-10-20 23:46:38 +02:00
LibretroAdmin b142dfd787 input: pair a DualShock 3 with this computer's Bluetooth from the menu
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.
2026-10-09 06:23:32 +02:00
LibretroAdmin 2b37507949 input: a joypad driver is handed what is behind the RetroPad, not the binds
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.
2026-10-07 17:50:48 +02:00
LibretroAdmin 46d69f2c81 (Wii/Wii U) Atomics for the HID poll threads' quit flags
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.
2026-09-20 19:06:30 +02:00
LibretroAdmin c57c4fbd1a Style nits 2025-02-10 13:59:25 +01:00
LibretroAdmin b211adaaca Function argument name standardization 2025-01-17 19:55:32 +01:00
LibretroAdmin 47d888364d Standardize len variables - argument should always be named 'len',
while local len variables should have '_' prefix
2025-01-13 21:53:49 +01:00
zoltanvb 49aeeee1f7 Cosmetical fix (xvfk -> xfvk), #16631 2024-06-08 11:17:42 -05:00
zoltanvb 198656eb20 Add support for multimedia keys (#16502)
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
2024-05-11 17:06:54 -07:00
libretroadmin 6728d5a2fa (Subsystem) Cleanups 2023-02-19 12:15:45 +01:00
Nathan Strong 81c6d3809a Finish up the OSX DS3 driver
== 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.
2021-10-16 14:52:56 -07:00
Nathan Strong 729c219f1a Rewrite DS3 driver
== 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.
2021-10-16 14:52:56 -07:00
Nathan Strong c832828ddb Figured out the cause of crash
== 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
2021-10-05 09:23:08 -07:00
Nathan Strong a4d8ce7753 Try to support multi-pad HID devices
== DETAILS
I tried to modify the joypad connection interface to support
multi-pad HID devices ... it doesn't work. I'm not sure why.
2021-10-05 09:23:08 -07:00
Nathan Strong 5da1cd08ff Unify the HID driver architecture
== 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
2021-10-05 09:23:08 -07:00
Nathan Strong 9edb449471 wip commit 2021-10-05 09:10:41 -07:00
twinaphex a01380f847 (WiiU) Buildfixes 2020-07-23 18:01:15 +02:00
twinaphex de73e3bff9 Buildfixes 2020-07-19 03:25:30 +02:00
twinaphex b1a6b35379 Buildfix 2020-07-19 03:23:07 +02:00
twinaphex 08ad00f5d3 Start preparing for being able to grab multiple buttons at the same time 2020-07-18 19:51:14 +02:00
Ash Logan 41541128c5 (WiiU/hid) Warning fixes 2020-05-17 16:42:31 +10:00
Ash Logan cdaf907467 (WiiU/hid) hid.h only used in drivers_hid/wiiu, don't include everywhere 2020-05-17 16:39:41 +10:00
Ash Logan f22af81e7d (WiiU/wpad) Allow hotplugging Gamepad, support >1 channel 2020-05-17 16:32:51 +10:00
twinaphex 7748ac207c Split up blissbox code into separate file
tasks/task_autodetect_blissbox.c
2020-01-19 06:40:07 +01:00
orbea e13ec54dc6 Fix --disable-overlay. 2019-07-21 10:26:42 -07:00
twinaphex ee3208ac39 Integrate video_driver.c into retroarch.c 2019-06-17 15:10:22 +02:00
Brad Parker 1120a7e490 Bliss-Box: add additional pad types from firmware 3.0 2019-06-03 23:40:31 -04:00
Twinaphex 8db0e2db7c Revert "xfree86_keycodes: Add non-evdev keycodes to fix keyboard input on non-Linux systems with X11." 2019-05-21 17:15:59 +02:00
nia cdcb819a79 xfree86_keycodes: Add non-evdev keycodes. 2019-05-18 17:11:42 +01:00
Brad Parker ed5bd8023e Bliss-Box: add PSX Jogcon ID 2019-03-09 18:04:03 -05:00
Brad Parker 4f0d61a2ac update copyright 2019-02-22 19:13:36 -05:00
orbea 8ff0b14281 Fix C89_BUILD=1. 2019-02-06 09:16:26 -08:00
orbea 28ff4b391a Clean up white space. 2019-02-03 16:00:50 -08:00
David Skywalker 347519a4d8 now X11 driver using keycodes instead keysyms, fixes international layouts problems. 2019-01-31 12:50:58 +01:00
orbea e062b98088 Remove trailing blank lines.
find . -type f -exec sed -i '${/^[[:space:]]*$/d;}' {} \+
2019-01-17 19:39:38 -08:00
orbea bfc366decc Squeeze extra blank lines with cat(1).
Example:

find . -type f -iname '*.c' | while read -r i; do
  cat -s "$i" > "$i.new"
  mv "$i.new" "$i"
done
2019-01-08 11:04:58 -08:00
gblues 84e9c93c35 quotes for some, braces for others 2018-05-02 22:37:34 -07:00
gblues 27bfcf3c77 Replace angle includes with quote includes
=== 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.
2018-05-02 21:31:00 -07:00
gblues 7448fd3157 More code re-organization
=== 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
2018-05-01 23:23:40 -07:00
gblues 1d84c0eca1 Fix analog for DS3, plus some cleanups
== 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.
2018-04-23 23:22:27 -07:00
gblues 6ab91a422e Small cleanup to adapt to upstream code changes
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.
2018-04-14 14:34:13 -07:00
gblues 4433cbebc6 Get digital inputs for Sony DualShock 3 working
== 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.
2018-04-05 23:03:38 -07:00
gblues af08e5015a More work on Dual Shock 3 driver
== 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.
2018-04-02 23:16:49 -07:00
gblues 9bc5a15c2d Enable pads to register in any order
== 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
2018-04-01 18:52:26 -07:00
gblues 2cf89feb86 Code clean-up
== 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.
2018-03-31 22:25:30 -07:00
gblues 5060c2aac4 More fixes, GC pad kinda sorta works
== 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.
2018-03-29 23:37:11 -07:00