TheDrHax / ds4drv-cemuhook

A Sony DualShock 4 userspace driver for Linux with basic support of cemuhook's UDP protocol
MIT License
55 stars 20 forks source link

Trying to connect two Dualshocks via ds4drv, but only one is detected #16

Closed ee5cd7d5d closed 3 years ago

ee5cd7d5d commented 3 years ago

What's the problem? Describe what went wrong.

I tried connecting two DualsShocks 4 via DSU Client to the Dolphin emulator as described here: https://wiki.dolphin-emu.org/index.php?title=DSU_Client but only one is recognized (DSUClient/0/xxx, DSUClient/1/xxx is missing). I tried testing with the DSU Pad Test application over wine, same thing only one DS4 is recognized.

What steps will reproduce the problem?

Connect two DS4 via Bluetooth, open devices configuration on Dolphin, add DSU source.

What is the system information?

                   -`                    pedro@arctic 
                  .o+`                   ------------ 
                 `ooo/                   OS: Arch Linux x86_64 
                `+oooo:                  Host: Skylake Platform 0.1 
               `+oooooo:                 Kernel: 5.11.13-arch1-1 
               -+oooooo+:                Uptime: 9 hours, 41 mins 
             `/:-:++oooo+:               Packages: 1692 (pacman) 
            `/++++/+++++++:              Shell: zsh 5.8 
           `/++++++++++++++:             Resolution: 1920x1080 
          `/+++ooooooooooooo/`           DE: Plasma 5.21.4 
         ./ooosssso++osssssso+`          WM: KWin 
        .oossssso-````/ossssss+`         WM Theme: ChromeOS-dark 
       -osssssso.      :ssssssso.        Theme: ChromeOSDark [Plasma], Breeze [GTK3] 
      :osssssss/        osssso+++.       Icons: Tela-dark [Plasma], Tela-dark [GTK2/3] 
     /ossssssss/        +ssssooo/-       Terminal: yakuake 
   `/ossssso+/:-        -:/+osssso+-     CPU: Intel i7-6500U (4) @ 3.100GHz 
  `+sso+:-`                 `.-/+oso:    GPU: Intel Skylake GT2 [HD Graphics 520] 
 `++:.                           `-/+/   Memory: 3087MiB / 7868MiB 
 .`                                 `/

Dolphin Version: 5.0-14002

Tested with ds4drv 0.5.1

TheDrHax commented 3 years ago

Current implementation of UDP server only supports one controller at a time. The driver, in theory, does support multiple controllers, but I do not have the second one to test this.

ee5cd7d5d commented 3 years ago

I could actually try to implement it myself when I have time :) could you give me a rough idea of what I would need to do in order to achieve that? Like how would I need to change the UDP packet...

TheDrHax commented 3 years ago
  1. Right now UDP server is being started inside controller's thread, so when there are two controllers, there will be two servers. We probably need to initialize a single UDP server instance before any controllers are registered in __main__.py instead of doing it in input.py;

https://github.com/TheDrHax/ds4drv-cemuhook/blob/28aa88cc8b3599227d95a3fb89c0df12a0e08fd6/ds4drv/actions/input.py#L100-L104

https://github.com/TheDrHax/ds4drv-cemuhook/blob/28aa88cc8b3599227d95a3fb89c0df12a0e08fd6/ds4drv/__main__.py#L176-L178

  1. For client to be able to detect multiple controllers, we need to send multiple packets from UDPServer._req_ports. This part is almost ready, we just need to keep count of active controllers and populate responses with real data (MAC address);

https://github.com/TheDrHax/ds4drv-cemuhook/blob/28aa88cc8b3599227d95a3fb89c0df12a0e08fd6/ds4drv/servers/udp.py#L64-L72

  1. In UDPServer.report "pad id" field will depend on the source of the report. Right now it is hard coded to 0 (first controller);

https://github.com/TheDrHax/ds4drv-cemuhook/blob/28aa88cc8b3599227d95a3fb89c0df12a0e08fd6/ds4drv/servers/udp.py#L109-L115

  1. To read input events from each controller we can probably use DS4Controller.loop.register_event("device-report", callback) instead of modifying ReportActionInput.handle_report.

https://github.com/TheDrHax/ds4drv-cemuhook/blob/28aa88cc8b3599227d95a3fb89c0df12a0e08fd6/ds4drv/actions/input.py#L133-L135

I will try to make it work with a single controller. Probably it will then start working with multiple controllers as well :)

TheDrHax commented 3 years ago

I've created a separate branch for this feature. Could you please test it?

ee5cd7d5d commented 3 years ago

Hi! It's working better now, at least there is data from both controllers, but it seems to be mixing up the packets. Now Dolphin is detecting both controllers but it's showing the sensors from both in both, switching very rapidly between the values of each controller (like several times per second)

Padtest + wine seems to not have the problem, but I think it is filtering the packets clientside using the MAC Address

TheDrHax commented 3 years ago

I was able to reproduce this issue with a single controller by copying reports to another slot and changing them slightly.

Apparently, Dolphin creates a separate connection for each controller, ignores pad id byte and expects only updates for a single controller per connection. So the server needs to keep track of each client's requests.

TheDrHax commented 3 years ago

Oh, this TODO is exactly what we need:

https://github.com/TheDrHax/ds4drv-cemuhook/blob/28aa88cc8b3599227d95a3fb89c0df12a0e08fd6/ds4drv/servers/udp.py#L74-L81

The protocol supports two different modes for registration: slot-based and MAC-based.

ee5cd7d5d commented 3 years ago

I checked with a newer build of dolphin to see if it improved, but the problem remains. I will not get to look into it right away, but let me know if I can do anything to help 😊

TheDrHax commented 3 years ago

I pushed another change to the same branch. It works with Dolphin now (at least on my side) :)

ee5cd7d5d commented 3 years ago

Yes! It works! Thank you so much!

TheDrHax commented 3 years ago

Nice! I will merge it with master now :+1:

oblitum commented 2 years ago

This seems to not have fixed on cemu's side.. I can only get one game pad motion source (DSU1) listed in options, all others show as disconnected, despite the ds4drv logs showing two controllers got connected.