Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

input: add gamepad support through evdev #10427

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

linkmauve
Copy link
Contributor

This is based on the existing SDL2 code, but without any additional dependency on Linux.

Both buttons and axes are supported, but just like in the SDL2 code, axes are transformed into buttons in order to fit into the existing mpv code. A possible future improvement would be to expose them as proper axes, and take into account their movement.

I’ve tested this code on both PS3, PS4 and Switch controllers, in USB and Bluetooth when possible, on Linux 5.18.

Unlike the SDL2 code, this supports more than one controller plugged in, as it wasn’t much more code to handle that and it’s a useful feature to me.

Copy link
Member

@philipl philipl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried it out. I had some notes on specific inputs, but my main observation is that it deadlocks on exit trying to end the input thread.

(gdb) thread apply all bt

Thread 14 (Thread 0x7fffdcff9640 (LWP 38522) "mpv/worker"):
#0  __futex_abstimed_wait_common64 (private=0, cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x555555828ec8) at ./nptl/futex-internal.c:57
#1  __futex_abstimed_wait_common (cancel=true, private=0, abstime=0x0, clockid=0, expected=0, futex_word=0x555555828ec8) at ./nptl/futex-internal.c:87
#2  __GI___futex_abstimed_wait_cancelable64 (futex_word=futex_word@entry=0x555555828ec8, expected=expected@entry=0, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=0) at ./nptl/futex-internal.c:139
#3  0x00007ffff4293ac1 in __pthread_cond_wait_common (abstime=0x0, clockid=0, mutex=0x555555828e78, cond=0x555555828ea0) at ./nptl/pthread_cond_wait.c:503
#4  ___pthread_cond_wait (cond=0x555555828ea0, mutex=mutex@entry=0x555555828e78) at ./nptl/pthread_cond_wait.c:627
#5  0x000055555560ba28 in worker_thread (arg=0x555555828e70) at ../misc/thread_pool.c:80
#6  0x00007ffff4294b43 in start_thread (arg=<optimised out>) at ./nptl/pthread_create.c:442
#7  0x00007ffff4326a00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

Thread 2 (Thread 0x7fffee4ff640 (LWP 38510) "mpv/input sourc"):
#0  0x00007ffff4318d7f in __GI___poll (fds=fds@entry=0x7fffee4fe710, nfds=nfds@entry=1, timeout=timeout@entry=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
#1  0x00007ffff43366c2 in __poll_chk (fds=fds@entry=0x7fffee4fe710, nfds=nfds@entry=1, timeout=timeout@entry=-1, fdslen=fdslen@entry=32) at ./debug/poll_chk.c:27
#2  0x0000555555698775 in poll (__timeout=-1, __nfds=1, __fds=0x7fffee4fe710) at /usr/include/x86_64-linux-gnu/bits/poll2.h:39
#3  read_gamepad_thread (src=src@entry=0x5555558a3380, param=param@entry=0x0) at ../input/evdev_gamepad.c:215
#4  0x0000555555602a1f in input_src_thread (ptr=<optimised out>) at ../input/input.c:1636
#5  0x00007ffff4294b43 in start_thread (arg=<optimised out>) at ./nptl/pthread_create.c:442
#6  0x00007ffff4326a00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

Thread 1 (Thread 0x7fffee58a600 (LWP 38507) "mpv"):
#0  __futex_abstimed_wait_common64 (private=128, cancel=true, abstime=0x0, op=265, expected=38510, futex_word=0x7fffee4ff910) at ./nptl/futex-internal.c:57
#1  __futex_abstimed_wait_common (cancel=true, private=128, abstime=0x0, clockid=0, expected=38510, futex_word=0x7fffee4ff910) at ./nptl/futex-internal.c:87
#2  __GI___futex_abstimed_wait_cancelable64 (futex_word=futex_word@entry=0x7fffee4ff910, expected=38510, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=128) at ./nptl/futex-internal.c:139
#3  0x00007ffff42966a4 in __pthread_clockjoin_ex (threadid=140737191605824, thread_return=thread_return@entry=0x0, clockid=clockid@entry=0, abstime=abstime@entry=0x0, block=block@entry=true) at ./nptl/pthread_join_common.c:105
#4  0x00007ffff4296543 in ___pthread_join (threadid=<optimised out>, thread_return=thread_return@entry=0x0) at ./nptl/pthread_join.c:24
#5  0x0000555555602b22 in mp_input_src_kill (src=0x5555558a3380) at ../input/input.c:1606
#6  0x0000555555605d1c in mp_input_src_kill (src=0x5555558a3380) at ../input/input.c:1595
--Type <RET> for more, q to quit, c to continue without paging--
#7  close_input_sources (ictx=0x55555585c160) at ../input/input.c:1589
#8  mp_input_uninit (ictx=0x55555585c160) at ../input/input.c:1421
#9  0x000055555563bf33 in mp_destroy (mpctx=0x555555828750) at ../player/main.c:188
#10 0x000055555563c7ab in mpv_main (argc=<optimised out>, argv=<optimised out>) at ../player/main.c:465
#11 0x00007ffff4229d90 in __libc_start_call_main (main=main@entry=0x5555555b95e0 <main>, argc=argc@entry=3, argv=argv@entry=0x7fffffffdea8) at ../sysdeps/nptl/libc_start_call_main.h:58
#12 0x00007ffff4229e40 in __libc_start_main_impl (main=0x5555555b95e0 <main>, argc=3, argv=0x7fffffffdea8, init=<optimised out>, fini=<optimised out>, rtld_fini=<optimised out>, stack_end=0x7fffffffde98) at ../csu/libc-start.c:392
#13 0x00005555555b9615 in _start ()

input/evdev_gamepad.c Show resolved Hide resolved
input/evdev_gamepad.c Outdated Show resolved Hide resolved
input/evdev_gamepad.c Outdated Show resolved Hide resolved
input/evdev_gamepad.c Outdated Show resolved Hide resolved
@linkmauve linkmauve force-pushed the evdev-gamepad branch 2 times, most recently from 3ee6e9b to 7ee2f46 Compare July 23, 2022 16:36
@linkmauve
Copy link
Contributor Author

In this latest version I’ve fixed all of your comments, and opted to use eventfd for the signaling that this thread should exit, this avoids a timeout in poll() which would wake up this thread in a useless context switch. I’ve also extracted EV_ABS handling to its own function.

@linkmauve linkmauve force-pushed the evdev-gamepad branch 3 times, most recently from e28b3cd to c9a85c9 Compare July 23, 2022 17:37
This is based on the existing SDL2 code, but without any additional
dependency on Linux.

Both buttons and axes are supported, but just like in the SDL2 code,
axes are transformed into buttons in order to fit into the existing mpv
code.  A possible future improvement would be to expose them as proper
axes, and take into account their movement.

I’ve tested this code on both PS3, PS4 and Switch controllers, in USB
and Bluetooth when possible, on Linux 5.18.

Unlike the SDL2 code, this supports more than one controller plugged in,
as it wasn’t much more code to handle that and it’s a useful feature to
me.
Copy link
Member

@philipl philipl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed previous issues have been fixed. Thanks.

I happened to test with two controllers and removed one of them while mpv was running and got this:

[input/#1] read() failed
[input/#1] Removed controller: Wireless Steam Controller
[input/#1] Removed controller: Logitech Gamepad F710

Do you expect it to behave this way and disconnect from both controllers?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants