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

Improve XID based on tests with real hardware #4

Closed
wants to merge 1 commit into from

Conversation

JayFoxRox
Copy link
Owner

@JayFoxRox JayFoxRox commented Jul 5, 2018

This PR implements XID_GET_CAPABILITIES; corrects behaviour with interrupt-out; more accurately implements STALL conditions and truncations to actual length. The XID descriptor has also been dumped from a real gamepad.

I used a small test script to test behaviour of a real gamepad and then documented my findings on XboxDevWiki.

This fix is intended for Rallisport Challenge, but the following list of games was known to have input issues in XQEMU and should be tested again:

When testing this PR, don't forget to add ,port=3 to your input option to use "Port 1" on the virtual Xbox. Not all games accept gamepads of controllers plugged into other ports.

Working input after this change (most of which previously weren't working):

  • Batman Vengeance
  • Big Mutha Truckers 2
  • Broken Sword: The Sleeping Dragon
  • DRIV3R
  • Driver: Parallel Lines
  • Ford Mustang: The Legend Lives
  • Ford vs. Chevy
  • Gladiator: Sword of Vengeance
  • Gunvalkyrie
  • Hummer Badlands
  • Jet Set Radio Future
  • Just Cause
  • Melbourne Cup Challenge
  • Panzer Dragoon Orta
  • Peter Jackson's King Kong
  • Pulse Racer
  • Rallisport Challenge
  • Re-Volt
  • Rugby League 2
  • Second Sight
  • Star Wars: Knights of the Old Republic
  • Star Wars: Obi-Wan
  • Street Racing Syndicate
  • TimeSplitters 2
  • Tom and Jerry in War of the Whiskers

Probably errornously mentioned as input issues, not affected by PR:

  • Batman: Rise of Sin Tzu (working menus; Challenge mode: black rectangle covering screen; Story mode: stuck after selecting character. Might have had input issues in menus prior to change?)
  • Maximum Chase (working until title screen, then seems to hang, performance issue or broken graphics updates)
  • Painkiller: Hell Wars (It's another issue - performance)
  • Soldier of Fortune II: Double Helix (black screen after game logo splash screen)

Remaining work

This only patches xid.c (which was enough work already and required hours of testing). I hope someone else solves FIXME PR or manually moves these changes xid-sdl.c temporarily.

Furthermore the handling out output packets / force feedback was not checked.
Due to the importance of this PR (fixes many games) I do not want to delay it further.
As I'm unfamiliar with the QEMU API (which I find weird), the output-specific code can be considered pseudo-code only.
When moving changes to xid-sdl this definitely has to be reviewed (as that provides an implementation of force feedback for the host).

I originally wanted to test this PR on Linux, comparing a real gamepad to the xid.c using my script.
However, I did not find time for this.
I'm confident this change is mostly correct, and direct comparisons with real hardware can be done later.

@JayFoxRox JayFoxRox mentioned this pull request Jul 5, 2018
@JayFoxRox
Copy link
Owner Author

I have some of those games and will re-test them, then send a PR upstream - I'll create an issue about xid-sdl seperately.

(Also great idea to use a diff to color-code them! I'll probably adopt that technique, but use # to mark lines without changes)

@JayFoxRox
Copy link
Owner Author

TODO: Test like this on arch with this:

 make && x86_64-softmmu/qemu-system-x86_64 ~/Data/Downloads/archlinux-2018.07.01-x86_64.iso -m 512 -machine accel=kvm -fsdev local,security_model=passthrough,id=fsdev0,path=/home/fox/Data/Projects/xqemu-controller-test/ -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=h -nic user,model=virtio-net-pci -usb -device usb-xbox-gamepad -device usb-host,vendorid=0x45e,productid=0x289

In guest (maybe not entirely correct?):

mkdir h
mount -t 9p -o trans=virtio h h
pacman -S python-pip
pip3 install libusb1

@JayFoxRox JayFoxRox force-pushed the xid-improvements branch 2 times, most recently from c99f8f7 to 6eecb20 Compare July 15, 2018 18:33
Repository owner deleted a comment from DarkGabbz Jul 15, 2018
Repository owner deleted a comment from JohnGodgames Jul 15, 2018
Repository owner deleted a comment from JohnGodgames Jul 15, 2018
Repository owner deleted a comment from JohnGodgames Jul 15, 2018
@JayFoxRox
Copy link
Owner Author

Moved upstream.. finally!

@JayFoxRox JayFoxRox closed this Jul 16, 2018
JayFoxRox pushed a commit that referenced this pull request Sep 11, 2018
The way we determine if we can start the incoming migration was
changed to use migration_has_all_channels() in:

  commit 428d890
  Author: Juan Quintela <quintela@redhat.com>
  Date:   Mon Jul 24 13:06:25 2017 +0200

    migration: Create migration_has_all_channels

This method in turn calls multifd_recv_all_channels_created()
which is hardcoded to always return 'true' when multifd is
not in use. This is a latent bug...

...activated in a following commit where that return result
ends up acting as the flag to indicate whether it is possible
to start processing the migration:

  commit 36c2f8b
  Author: Juan Quintela <quintela@redhat.com>
  Date:   Wed Mar 7 08:40:52 2018 +0100

    migration: Delay start of migration main routines

This means that if channel initialization fails with normal
migration, it'll never notice and attempt to start the
incoming migration regardless and crash on a NULL pointer.

This can be seen, for example, if a client connects to a server
requiring TLS, but has an invalid x509 certificate:

qemu-system-x86_64: The certificate hasn't got a known issuer
qemu-system-x86_64: migration/migration.c:386: process_incoming_migration_co: Assertion `mis->from_src_file' failed.

 #0  0x00007fffebd24f2b in raise () at /lib64/libc.so.6
 #1  0x00007fffebd0f561 in abort () at /lib64/libc.so.6
 #2  0x00007fffebd0f431 in _nl_load_domain.cold.0 () at /lib64/libc.so.6
 #3  0x00007fffebd1d692 in  () at /lib64/libc.so.6
 #4  0x0000555555ad027e in process_incoming_migration_co (opaque=<optimized out>) at migration/migration.c:386
 #5  0x0000555555c45e8b in coroutine_trampoline (i0=<optimized out>, i1=<optimized out>) at util/coroutine-ucontext.c:116
 #6  0x00007fffebd3a6a0 in __start_context () at /lib64/libc.so.6
 #7  0x0000000000000000 in  ()

To handle the non-multifd case, we check whether mis->from_src_file
is non-NULL. With this in place, the migration server drops the
rejected client and stays around waiting for another, hopefully
valid, client to arrive.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20180619163552.18206-1-berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
JayFoxRox pushed a commit that referenced this pull request Sep 11, 2018
With a Spice port chardev, it is possible to reenter
monitor_qapi_event_queue() (when the client disconnects for
example). This will dead-lock on monitor_lock.

Instead, use some TLS variables to check for recursion and queue the
events.

Fixes:
 (gdb) bt
 #0  0x00007fa69e7217fd in __lll_lock_wait () at /lib64/libpthread.so.0
 #1  0x00007fa69e71acf4 in pthread_mutex_lock () at /lib64/libpthread.so.0
 #2  0x0000563303567619 in qemu_mutex_lock_impl (mutex=0x563303d3e220 <monitor_lock>, file=0x5633036589a8 "/home/elmarco/src/qq/monitor.c", line=645) at /home/elmarco/src/qq/util/qemu-thread-posix.c:66
 #3  0x0000563302fa6c25 in monitor_qapi_event_queue (event=QAPI_EVENT_SPICE_DISCONNECTED, qdict=0x56330602bde0, errp=0x7ffc6ab5e728) at /home/elmarco/src/qq/monitor.c:645
 #4  0x0000563303549aca in qapi_event_send_spice_disconnected (server=0x563305afd630, client=0x563305745360, errp=0x563303d8d0f0 <error_abort>) at qapi/qapi-events-ui.c:149
 #5  0x00005633033e600f in channel_event (event=3, info=0x5633061b0050) at /home/elmarco/src/qq/ui/spice-core.c:235
 #6  0x00007fa69f6c86bb in reds_handle_channel_event (reds=<optimized out>, event=3, info=0x5633061b0050) at reds.c:316
 #7  0x00007fa69f6b193b in main_dispatcher_self_handle_channel_event (info=0x5633061b0050, event=3, self=0x563304e088c0) at main-dispatcher.c:197
 #8  0x00007fa69f6b193b in main_dispatcher_channel_event (self=0x563304e088c0, event=event@entry=3, info=0x5633061b0050) at main-dispatcher.c:197
 #9  0x00007fa69f6d0833 in red_stream_push_channel_event (s=s@entry=0x563305ad8f50, event=event@entry=3) at red-stream.c:414
 #10 0x00007fa69f6d086b in red_stream_free (s=0x563305ad8f50) at red-stream.c:388
 #11 0x00007fa69f6b7ddc in red_channel_client_finalize (object=0x563304df2360) at red-channel-client.c:347
 #12 0x00007fa6a56b7fb9 in g_object_unref () at /lib64/libgobject-2.0.so.0
 #13 0x00007fa69f6ba212 in red_channel_client_push (rcc=0x563304df2360) at red-channel-client.c:1341
 #14 0x00007fa69f68b259 in red_char_device_send_msg_to_client (client=<optimized out>, msg=0x5633059b6310, dev=0x563304e08bc0) at char-device.c:305
 #15 0x00007fa69f68b259 in red_char_device_send_msg_to_clients (msg=0x5633059b6310, dev=0x563304e08bc0) at char-device.c:305
 #16 0x00007fa69f68b259 in red_char_device_read_from_device (dev=0x563304e08bc0) at char-device.c:353
 #17 0x000056330317d01d in spice_chr_write (chr=0x563304cafe20, buf=0x563304cc50b0 "{\"timestamp\": {\"seconds\": 1532944763, \"microseconds\": 326636}, \"event\": \"SHUTDOWN\", \"data\": {\"guest\": false}}\r\n", len=111) at /home/elmarco/src/qq/chardev/spice.c:199
 #18 0x00005633034deee7 in qemu_chr_write_buffer (s=0x563304cafe20, buf=0x563304cc50b0 "{\"timestamp\": {\"seconds\": 1532944763, \"microseconds\": 326636}, \"event\": \"SHUTDOWN\", \"data\": {\"guest\": false}}\r\n", len=111, offset=0x7ffc6ab5ea70, write_all=false) at /home/elmarco/src/qq/chardev/char.c:112
 #19 0x00005633034df054 in qemu_chr_write (s=0x563304cafe20, buf=0x563304cc50b0 "{\"timestamp\": {\"seconds\": 1532944763, \"microseconds\": 326636}, \"event\": \"SHUTDOWN\", \"data\": {\"guest\": false}}\r\n", len=111, write_all=false) at /home/elmarco/src/qq/chardev/char.c:147
 #20 0x00005633034e1e13 in qemu_chr_fe_write (be=0x563304dbb800, buf=0x563304cc50b0 "{\"timestamp\": {\"seconds\": 1532944763, \"microseconds\": 326636}, \"event\": \"SHUTDOWN\", \"data\": {\"guest\": false}}\r\n", len=111) at /home/elmarco/src/qq/chardev/char-fe.c:42
 #21 0x0000563302fa6334 in monitor_flush_locked (mon=0x563304dbb800) at /home/elmarco/src/qq/monitor.c:425
 #22 0x0000563302fa6520 in monitor_puts (mon=0x563304dbb800, str=0x563305de7e9e "") at /home/elmarco/src/qq/monitor.c:468
 #23 0x0000563302fa680c in qmp_send_response (mon=0x563304dbb800, rsp=0x563304df5730) at /home/elmarco/src/qq/monitor.c:517
 #24 0x0000563302fa6905 in qmp_queue_response (mon=0x563304dbb800, rsp=0x563304df5730) at /home/elmarco/src/qq/monitor.c:538
 #25 0x0000563302fa6b5b in monitor_qapi_event_emit (event=QAPI_EVENT_SHUTDOWN, qdict=0x563304df5730) at /home/elmarco/src/qq/monitor.c:624
 #26 0x0000563302fa6c4b in monitor_qapi_event_queue (event=QAPI_EVENT_SHUTDOWN, qdict=0x563304df5730, errp=0x7ffc6ab5ed00) at /home/elmarco/src/qq/monitor.c:649
 #27 0x0000563303548cce in qapi_event_send_shutdown (guest=false, errp=0x563303d8d0f0 <error_abort>) at qapi/qapi-events-run-state.c:58
 #28 0x000056330313bcd7 in main_loop_should_exit () at /home/elmarco/src/qq/vl.c:1822
 #29 0x000056330313bde3 in main_loop () at /home/elmarco/src/qq/vl.c:1862
 #30 0x0000563303143781 in main (argc=3, argv=0x7ffc6ab5f068, envp=0x7ffc6ab5f088) at /home/elmarco/src/qq/vl.c:4644

Note that error report is now moved to the first caller, which may
receive an error for a recursed event. This is probably fine (95% of
callers use &error_abort, the rest have NULL error and ignore it)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20180731150144.14022-1-marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[*_no_recurse renamed to *_no_reenter, local variables reordered]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant