DanielOgorchock / linux

Other
49 stars 7 forks source link

Pro Controller disconnects when connected via Bluetooth #33

Open twoxa opened 2 years ago

twoxa commented 2 years ago

When using the Pro Controller in Bluetooth mode it will randomly disconnect after some time, it might last a few minutes or a few hours (usually its a couple of minutes), it seems random. When using combined Joycons there is no issue, they work perfectly every time. When using the Pro Controller in wired mode it works normally. Tried pairing without joycond, with different Bluetooth adapters, nothing works. Logs when the controller connects:

Jan 13 20:04:55 Archer kernel: Bluetooth: HIDP (Human Interface Emulation) ver 1.2
Jan 13 20:04:55 Archer kernel: Bluetooth: HIDP socket layer initialized
Jan 13 20:04:55 Archer bluetoothd[1386]: profiles/input/device.c:ioctl_is_connected() Can't get HIDP connection info
Jan 13 20:04:55 Archer systemd[548]: Reached target Bluetooth.
Jan 13 20:04:58 Archer kernel: hid-generic 0005:057E:2009.0006: unknown main item tag 0x0
Jan 13 20:04:58 Archer kernel: input: Pro Controller as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.1/1-5.1.4/1-5.1.4:1.0/bluetooth/hci0/hci0:1/0005:057E:2009.0006/input/input33
Jan 13 20:04:58 Archer kernel: hid-generic 0005:057E:2009.0006: input,hidraw5: BLUETOOTH HID v0.01 Gamepad [Pro Controller] on 8c:88:2b:40:00:f1
Jan 13 20:04:58 Archer kernel: nintendo 0005:057E:2009.0006: unknown main item tag 0x0
Jan 13 20:04:58 Archer kernel: nintendo 0005:057E:2009.0006: hidraw5: BLUETOOTH HID v80.01 Gamepad [Pro Controller] on 8c:88:2b:40:00:f1
Jan 13 20:05:00 Archer kernel: nintendo 0005:057E:2009.0006: using factory cal for left stick
Jan 13 20:05:00 Archer kernel: nintendo 0005:057E:2009.0006: using factory cal for right stick
Jan 13 20:05:00 Archer kernel: nintendo 0005:057E:2009.0006: using user cal for IMU
Jan 13 20:05:00 Archer kernel: nintendo 0005:057E:2009.0006: controller MAC = 64:B5:C6:44:80:8B
Jan 13 20:05:00 Archer kernel: input: Nintendo Switch Pro Controller as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.1/1-5.1.4/1-5.1.4:1.0/bluetooth/hci0/hci0:1/0005:057E:2009.0006/input/input34
Jan 13 20:05:00 Archer kernel: input: Nintendo Switch Pro Controller IMU as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.1/1-5.1.4/1-5.1.4:1.0/bluetooth/hci0/hci0:1/0005:057E:2009.0006/input/input35
Jan 13 20:05:00 Archer joycond[436]: DEVNAME=event257 ACTION=add DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.1/1-5.1.4/1-5.1.4:1.0/bluetooth/hci0/hci0:1/0005:057E:2009.0006/input/input34/event257
Jan 13 20:05:00 Archer joycond[436]: Creating new phys_ctlr for /dev/input/event257
Jan 13 20:05:00 Archer joycond[436]: Found Pro Controller
Jan 13 20:05:00 Archer joycond[436]: driver_name: Nintendo Switch Pro Controller
Jan 13 20:05:00 Archer joycond[436]: MAC: 64:B5:C6:44:80:8B
Jan 13 20:05:01 Archer joycond[436]: adding epoll_subscriber: fd=5
Jan 13 20:05:01 Archer kernel: nintendo 0005:057E:2009.0006: compensating for 4 dropped IMU reports
Jan 13 20:05:01 Archer kernel: nintendo 0005:057E:2009.0006: delta=90 avg_delta=15

Logs when the controller disconnects:

Jan 13 20:06:29 Archer kernel: nintendo 0005:057E:2009.0006: compensating for 4 dropped IMU reports
Jan 13 20:06:29 Archer kernel: nintendo 0005:057E:2009.0006: delta=78 avg_delta=14
Jan 13 20:06:33 Archer kernel: nintendo 0005:057E:2009.0006: compensating for 5 dropped IMU reports
Jan 13 20:06:33 Archer kernel: nintendo 0005:057E:2009.0006: delta=78 avg_delta=11
Jan 13 20:06:36 Archer kernel: nintendo 0005:057E:2009.0006: compensating for 5 dropped IMU reports
Jan 13 20:06:36 Archer kernel: nintendo 0005:057E:2009.0006: delta=79 avg_delta=11
Jan 13 20:06:41 Archer kernel: nintendo 0005:057E:2009.0006: compensating for 5 dropped IMU reports
Jan 13 20:06:41 Archer kernel: nintendo 0005:057E:2009.0006: delta=77 avg_delta=11
Jan 13 20:06:50 Archer kernel: nintendo 0005:057E:2009.0006: compensating for 5 dropped IMU reports
Jan 13 20:06:50 Archer kernel: nintendo 0005:057E:2009.0006: delta=78 avg_delta=11
Jan 13 20:06:53 Archer kernel: nintendo 0005:057E:2009.0006: compensating for 5 dropped IMU reports
Jan 13 20:06:53 Archer kernel: nintendo 0005:057E:2009.0006: delta=78 avg_delta=11
Jan 13 20:06:58 Archer kernel: nintendo 0005:057E:2009.0006: timeout waiting for input report
Jan 13 20:06:58 Archer joycond[436]: Lone controller paired
Jan 13 20:06:58 Archer joycond[436]: DEVNAME=event257 ACTION=remove DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.1/1-5.1.4/1-5.1.4:1.0/bluetooth/hci0/hci0:1/0005:057E:2009.0006/input/input34/event257
nfp0 commented 1 year ago

@Soul-Miku I never noticed if that problem is exclusive to BT 5.0 or not. I gotta try it later.

I would still use bluetooth 4.0 but as always nintendo making "quality" products xD

They do not support connecting the controller to anything other than the Switch, so I was actually surprised that the controller is somewhat usable natively on PC. It was not the case for Wii U and Wii controllers, so this is an improvement.

Taywee commented 1 year ago

I have the same issue, but not exclusively with my Switch Pro Controllers. The Sony DualSense has a really weird manifestation of this. The DualSense shows up in Dolphin as three controllers: Wireless Controller, Wireless Controller Motion Sensors, and Wireless Controller Touchpad. When I'm playing in Dolphin with the Switch Pro controllers with rumble on, they will disconnect after a while and need to be reconnected and refreshed. When I'm playing with the DualSense with rumble on, after a while, only the Wireless Controller Motion Sensors disconnects, while the Wireless Controller stays connected.

Also interestingly, I'm using the virtualized Pointer (which emulates a Wii pointer using the motion controls). When I have rumble on, the pointer jumps all over the place when the rumble is active.

I wonder if the rumble is overloading the motion sensor, sending more data than the Linux bluetooth stack can cope with. On the Switch Pro Controller, because the motion sensors are registering on the same device as the buttons, it just knocks out the whole pad. On the DualSense, because it's showing up as a different device, it only knocks out the motion sensor device.

nfp0 commented 1 year ago

Interesting! Maybe we could check if the problem still occurs if we disable motion data altogether to narrow it down? @DanielOgorchock Is this easily doable?

DanielOgorchock commented 1 year ago

Attached are patches I've been testing with. In my testing they seem to eliminate the rumble-related bluetooth disconnects on my system (both when using pro controller or two joy-cons). In their current form, they degrade the rumble performance/latency, but at least it's preventing the disconnects.

I plan to give this another pass in a way which should reduce the performance hit they cause.

If anyone else is able to test with them, it'd be much appreciated.

The approach used by this patch ensures the controller's input report timestamp deltas are reasonable before attempting to send and packet to the controller (e.g. rumble packets).

EDIT: Use new patches found in subsequent comment instead.

DanielOgorchock commented 1 year ago

Updated patch set below. The first revision broke USB functionality. This revision should also somewhat lessen the performance/latency impact of the mitigation.

Please test with these patches instead: 0002-HID-nintendo-fix-rumble-rate-limiter.patch.txt 0001-HID-nintendo-prevent-rumble-queue-overruns.patch.txt

nfp0 commented 1 year ago

@DanielOgorchock Awesome to see you've got progress in fixing the issue! :slightly_smiling_face: I'll test this as soon as I can.

psycho-driver commented 1 year ago

Switching from the reddit thread back to here (same username). I did multiplayer testing (again using Assault Android Cactus) and without the moltengamepad shim and experienced the first disconnect probably five minutes into play on player 2. AAC is a pretty good game for this since there's lots of rumble and it auto-pauses the game and throws up a big notification if someone disconnects.

However, once she got reconnected we continued playing for over an hour with no further issues. We will do some more testing.

psycho-driver commented 1 year ago

It's still not clear to me why steam's user space driver doesn't run into this issue.

I can tell you absolutely without a doubt that in the past their driver had the same issue. I haven't tested it for at least a year now, maybe two, so I can't comment on the current state of it.

nfp0 commented 1 year ago

@psycho-driver Can you please link us to the Reddit thread where this was being discussed?

psycho-driver commented 1 year ago

https://www.reddit.com/r/linux_gaming/comments/104efy9/hidnintendo_bluetooth_rumble_disconnection_fix/

DanielOgorchock commented 1 year ago

Switching from the reddit thread back to here (same username). I did multiplayer testing (again using Assault Android Cactus) and without the moltengamepad shim and experienced the first disconnect probably five minutes into play on player 2. AAC is a pretty good game for this since there's lots of rumble and it auto-pauses the game and throws up a big notification if someone disconnects.

However, once she got reconnected we continued playing for over an hour with no further issues. We will do some more testing.

Thanks for testing. If you're getting disconnects, you can try bumping one or both of the following values in the patch:

JC_SUBCMD_VALID_DELTA_REQ
JC_SUBCMD_RATE_LIMITER_BT_MS

The higher those values are, the lower the likelihood of a disconnect there should be. The downside is that the higher those values are, the less often rumble packets can get sent to the controller, degrading the responsiveness/quality of the rumble effects.

DanielOgorchock commented 1 year ago

It's still not clear to me why steam's user space driver doesn't run into this issue.

I can tell you absolutely without a doubt that in the past their driver had the same issue. I haven't tested it for at least a year now, maybe two, so I can't comment on the current state of it.

I really do think it's a bluetooth stack issue at this point. I don't know for sure what steam uses for their pro controller driver internally. If they're using the libsdl2 implementation (and I think valve implemented the sdl2 drivers, so the odds are high that steam is using it), that driver tries avoiding the issue by making sure to only send rumble packets at most every 30ms: https://github.com/libsdl-org/SDL/blob/main/src/joystick/hidapi/SDL_hidapi_switch.c#L53

DanielOgorchock commented 1 year ago

I've also noticed that once the controller gets into a state where the input reports are arriving at non-standard time deltas, it will never recover. I've even tried disabling sending rumble packets during that time and toggling the controller's rumble support and IMU support off. Even disabling the controller's high frequency full report mode doesn't allow the controller to recover. Once it reaches that state, the controller will eventually turn off, no matter what recovery mechanism I try.

The patches above attempt to prevent ever allowing the controller and/or bluetooth stack to enter that state.

I don't remember for certain, but I don't recall ever hearing about BT controller disconnects on android for the switchroot project. It'd be an interesting test to stress test rumble on android's BT stack to see if the issue is non-existent there, since they don't use bluez.

nfp0 commented 1 year ago

It'd be an interesting test to stress test rumble on android's BT stack to see if the issue is non-existent there, since they don't use bluez.

Yes, that would be a nice thing to test too. Do you have any consistent testing methodology? Or do you just play a game for a while until it triggers the issue?

DanielOgorchock commented 1 year ago

The most reliable repro I've found up to this point is playing Mario Kart 8 Deluxe on yuzu. The constant rumble events consistently can place the controller in the problematic state.

IIRC though the upstream android kernels didn't bring in the rumble patches for hid-nintendo yet.

Reinachan commented 1 year ago

Do you have any consistent testing methodology? Or do you just play a game for a while until it triggers the issue? @nfp0

I was able to consistently reproduce the issue playing Mario Kart Double Dash through Dolphin after setting up rumble in the settings. Might be easier than getting Yuzu working.

Otherwise, I won't be of much help, sorry. I'd try out the above patches but not entirely sure how I'd go about that on Fedora. The only guess I have is that I'd have to clone the upstream Linux kernel, apply the patch files with git, compile Linux, and then boot off of that version? Is there any simpler way of doing it?

nfp0 commented 1 year ago

I'd try out the above patches but not entirely sure how I'd go about that on Fedora. The only guess I have is that I'd have to clone the upstream Linux kernel, apply the patch files with git, compile Linux, and then boot off of that version? Is there any simpler way of doing it?

@Reinachan Same here. Not sure how to test this. If the only way is by compiling the kernel and booting it, I might have a bit of reading to learn how to do so.

@DanielOgorchock Alternatively, do you know if I can apply your patches to https://github.com/nicman23/dkms-hid-nintendo and test it that way? I know how to compile and install the DKMS, so that would be easier for me, I think.

Reinachan commented 1 year ago

Speaking of, I bought a new and (assumedly) better bluetooth dongle and played a game with a decent amount of rumble in it (Trackmania (2020)) and it lasted for a while before it disconnected. I'll give Mario Kart Double Dash another go again tho and report back how that goes in a couple of hours.

nfp0 commented 1 year ago

@Reinachan Please do.

Although I doubt it would make a difference, as I've tested with 5 different bluetooth radios, always having the same result, as you can see on this post: https://github.com/DanielOgorchock/linux/issues/33#issuecomment-1098360786 and another a few posts below.

Reinachan commented 1 year ago

Now this is interesting. I can't even reproduce the issue using the method above anymore. Maybe I would've if I had let it go on for a long time, but previously it would disconnect within the first stage in MKDD. And I don't just mean with the new bluetooth dongle, I mean with both. Edit: For the record, I drove the first stage 5 times, two with the new dongle, three with the old dongle. I also set the rumble to max strength.

Since last I tried, I've upgraded my PC though. Not sure if that would affect anything. I'll eventually build a second PC out of the old parts and can do some testing again then, but no ETA on that as I don't currently have a need for it.

CPU RAM GPU Motherboard Kernel
Previous specs Intel i7-7700k 16 GB RAM RTX 2070 Super MSI z270 Tomahawk Linux 6.0.12
Current specs AMD Ryzen 7 5800X3D 32 GB RAM RTX 2070 Super ASUS B550 Pro Linux 6.1.9-200.fc37.x86_64 x86_64

I've added the kernel versions as well. I don't have the numbers after 6.0.12 for the old specs. I'm on Fedora Workstation 37 and that hasn't changed since last I tested.

Reinachan commented 1 year ago

Okay, drove another round, this time I changed the rumble pattern from sine to strong in Dolphin. Was able to get a disconnect at the end of the round.

Reinachan commented 1 year ago

Nope, with further testing, I was still able to replicate the issue even with sine rumble pattern. I'll try turning off rumble entirely and do 3-4 rounds with that or until I get a disconnect.

Reinachan commented 1 year ago

No disconnects in the 3 rounds I tried without rumble. Next time I play a game for an extended period of time, I'll try disabling rumble and see if I get any disconnects at all.

nfp0 commented 1 year ago

I'll try disabling rumble and see if I get any disconnects at all.

@Reinachan I believe @DanielOgorchock already confirmed the problem does not happen with rumble off.

It would be nice to test with motion data disabled though, as @Taywee found a possible correlation.

nfp0 commented 1 year ago

Please test with these patches instead: 0002-HID-nintendo-fix-rumble-rate-limiter.patch.txt 0001-HID-nintendo-prevent-rumble-queue-overruns.patch.txt

@DanielOgorchock I was trying to apply your patches but 0001 is failing (I assume that's the one to apply 1st), so I tried with git apply --reject but now I'm getting this error:

error: while searching for:
        joycon_encode_rumble(data, freq_l_low, freq_l_high, amp);

        spin_lock_irqsave(&ctlr->lock, flags);
        if (++ctlr->rumble_queue_head >= JC_RUMBLE_QUEUE_SIZE)
                ctlr->rumble_queue_head = 0;
        memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data,
               JC_RUMBLE_DATA_SIZE);

Can you help me?

EDIT: I've applied the patch manually and I'm going to do some lengthy tests tomorrow.

nfp0 commented 1 year ago

@DanielOgorchock I finally gave your patches a try and I could not get any disconnects! I've let the controller rumbling for almost an hour and it never failed, while previously it would disconnect in less than 5 minutes.

The problem is, as you said, the rumble quality and latency is severely affected. I immediately noticed that.

You mentioned we could tweak the values of JC_SUBCMD_VALID_DELTA_REQ and JC_SUBCMD_RATE_LIMITER_BT_MS (I believe you meant JC_SUBCMD_RATE_LIMITER_MS instead). I'll see how low I can go without getting disconnects. Should I prioritize one of those values over the other?

nfp0 commented 1 year ago

@DanielOgorchock I did some extensive testing and it seems the lower I can go before starting to get disconnects is about these values:

#define JC_SUBCMD_VALID_DELTA_REQ   2
#define JC_SUBCMD_RATE_LIMITER_MS   40

But the rumble quality with those values is not satisfactory at all. Isolated rumble events seem ok, but when there's a sequence of rumble events in rapid succession, the rumbling is uneven, and the latency is very noticeable. For example, if I stop the action that is causing continuous rumble, the rumble still continues for a second. Are there any other values we can toy with?

Can't we learn something from how some other projects are dealing with rumble on this controller? I know of these: https://github.com/Davidobot/BetterJoy/blob/master/BetterJoyForCemu/Joycon.cs#L146 https://github.com/Ryochan7/DS4Windows/blob/master/DS4Windows/DS4Library/InputDevices/SwitchProDevice.cs#L891

nfp0 commented 1 year ago

I did some btmon captures of the Bluetooth traffic with Steam VS hid-nintendo in the hopes that investigating the way that Steam sends the rumble commands might help us see what they do differently.

I did the Steam tests with hid-nintendo blacklisted. And I did the hid-nintendo tests without applying any patches. I did the tests with the exact same in-game action so that the output can be directly compared among drivers. I did a capture of a very simple rumble effect and a more complex, longer, effect.

Here are the results. I hope these can help you in some way @DanielOgorchock.

btmon_simple-rumble_hid-nintendo.log (rumble starts at line 626) btmon_simple-rumble_steam-input.log (rumble starts at line 554)

btmon_complex-rumble_hid-nintendo.log (rumble starts at line 632) btmon_complex-rumble_steam-input.log (rumble starts at line 458)

EricYin commented 1 year ago

someone mentioned strong rumble will cause battery loose inside the controller,making controller down.

nfp0 commented 1 year ago

@DanielOgorchock I was comparing the logs I posted above and I found a few things that might help (or not).

1) I compared the time deltas between each TX in btmon, (which only happen during rumble, so I imagine they must be rumble info being sent) and I noticed many instances where the delta is close to 25ms on hid-nintendo. In contrast, on Steam-input the TX time deltas never go lower than 50ms.

2) The number of TX events for a particular rumble pattern on hid-nintendo is 81. On Steam-input, the exact same rumble pattern only generated 34 events, which is less than half of hid-nintendo. Even though Steam-input only sent 34 events, the rumble feels better and more accurate than hid-nintendo (though this is just an opinion). EDIT: After trying it again, it does not feel better than hid-nintendo at all. But I'm still curious about the huge difference in the number of sent rumble events.

3) There is a series of HCI events happening as soon as the rumble starts, and there seems to be a difference in the sequence of these HCI events between hid-nintendo and Steam-input. Might be worth taking a look? (files below)

4) The amount of data being sent on each TX is different between hid-nintendo and Steam-input. hid-nintendo has dlen 15 while Steam-input has dlen 54. Here are examples of each:

hid-nintendo:

< ACL Data TX: Handle 4 flags 0x00 dlen 15                 #104 [hci0] 2.490591
      Channel: 69 len 11 [PSM 0 mode Basic (0x00)] {chan 65535}
        a2 10 02 00 01 40 40 00 01 40 40                 .....@@..@@     

Steam-input:

< ACL Data TX: Handle 1 flags 0x00 dlen 54                  #92 [hci0] 2.020375
      Channel: 67 len 50 [PSM 0 mode Basic (0x00)] {chan 65535}
        a2 10 0e 00 01 40 40 48 c8 54 72 00 00 00 00 00  .....@@H.Tr.....
        00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        00 00                                            ..              

This is what I was able to observe. Sorry if some or all of this is irrelevant, but I hope something in here helps us shed some light on why Steam works so well.

Here are the 2 btmon log files I used to arrive at the above observations. I have removed all the RX data to focus just on rumble data.

btmon_rumble-only_hid-nintendo.log btmon_rumble-only_steam-input.log

EDIT: Mind you this is all without any patches applied.

someone mentioned strong rumble will cause battery loose inside the controller,making controller down.

@EricYin This was mentioned somewhere on this issue already. It cannot be a loose contact because this problem does not happen on Steam or on Windows.

benjamimgois commented 1 year ago

Is it possible to disable and rumble ? would it at least make the controller more playable ? I have a pair of joycons but the constant disconectin make me swap to my xbox controller.

nfp0 commented 1 year ago

I believe the joycons are not affected by this issue. All the complaints have been for the Pro Controller. Have you tested those joycons on other systems?

benjamimgois commented 1 year ago

I believe the joycons are not affected by this issue. All the complaints have been for the Pro Controller. Have you tested those joycons on other systems?

Yes, i have the official nintendo joycons. The disconnection problem is an old problem, i recently upgraded my machine to a new build with newer bluetooth chipset and i still got the problem. I'll try to upload some logs later today

SuperSamus commented 1 year ago

What kernel version are you on? It was supposed to be fixed in Linux 6.4.

benjamimgois commented 1 year ago

What kernel version are you on? It was supposed to be fixed in Linux 6.4.

I'm on latest kernel from Arch 6.4.4

twoxa commented 1 year ago

I had the disconnects even after it got fixed, I managed to make it work by deleting the entire /var/lib/bluetooth dir, I tried many different adapters and that might have been the problem since all of them were paired with the controller. Also many workarounds that were on the arch wiki (old wiki, updated wiki) are no longer needed, so i removed all of them too. Now the controller works rumble and everything, I do however need to remove and re-pair the controller every time I turn it off.

benjamimgois commented 1 year ago

I had the disconnects even after it got fixed, I managed to make it work by deleting the entire /var/lib/bluetooth dir, I tried many different adapters and that might have been the problem since all of them were paired with the controller. Also many workarounds that were on the arch wiki (old wiki, updated wiki) are no longer needed, so i removed all of them too. Now the controller works rumble and everything, I do however need to remove and re-pair the controller every time I turn it off.

Just tried your sugestion. The problem persists... what logs would be usefull in this case ?

nfp0 commented 1 year ago

It was supposed to be fixed in Linux 6.4.

@SuperSamus Could you show me the kernel commit that fixes this?

SuperSamus commented 1 year ago

The last commit in this repository, 7811b8f1f00ee9f195b035951749c57498105d52.

nfp0 commented 1 year ago

@SuperSamus Yes, I remember testing that. But those commits were more of a compromise than a proper fix. That change degraded the rumble quality considerably, if I remember correctly.

And @DanielOgorchock said he heavily suspects the real issue is in the Bluetooth stack. And I agree with him, because the disconnecting behavior seems to originate from the stack and not the controller itself.

Here's the email where I explained why I think it's the stack disconnecting, and not the controller:

Hi again Daniel,

I've followed your suggestion with testing with more than one controller and I've got curious results.

With one Pro Controller sometimes it took 30 minutes to 1 hour to get a disconnect. But after connecting a Joycon and having them play at the same time, I get a disconnect in about 5 minutes, and it's always the Pro Controller that disconnects, and never the Joycon. I've repeated the test 5 or 6 times. It's always the Pro Controller that disconnects.

I fail to understand how can an unrelated device affect the Pro Controller's hid-nintendo instance. I'm starting to agree with you in that this might be a problem external to hid-nintendo.

Another hint to it being an external problem is the fact that as soon as this problem happens and the controller turns off, the device disconnect event is received instantly on the OS. From my understanding, these Nintendo controllers never send disconnect events even when you turn them off manually on the sync button, they just time-out instead. If this issue were due to a crash on the controller's firmware, we would be getting time-outs as well, instead of the instantaneous disconnections we're getting now, am I right? It almost feels like the disconnection is coming from the Bluetooth stack.

Taking this into account, where should we open an issue? BlueZ?

psycho-driver commented 1 year ago

I'm curious if anyone has reached out to Valve regarding this to see if they can help shed light on the issue?  I've read recently that the Steam pro controller support now works with wireless and bluetooth + rumble without d/cs.  I'm 99% positive that in the earlier days of this driver (3+ years ago) their in-built support exhibited exactly the same behavior of not being able to stay reliably connected with rumble enabled.

On Wednesday, July 26, 2023 at 09:53:58 AM CDT, nfp0 ***@***.***> wrote:  

@SuperSamus Yes, I remember testing that. But those commits were more of a compromise than a proper fix. That change degraded the rumble quality considerably, if I remember correctly.

And @DanielOgorchock said he heavily suspects the real issue is in the Bluetooth stack. And I agree with him, because the disconnecting behavior seems to originate from the stack and not the controller itself.

Here's the email where I explained why I think it's the stack disconnecting, and not the controller:

Hi again Daniel,

I've followed your suggestion with testing with more than one controller and I've got curious results.

With one Pro Controller sometimes it took 30 minutes to 1 hour to get a disconnect. But after connecting a Joycon and having them play at the same time, I get a disconnect in about 5 minutes, and it's always the Pro Controller that disconnects, and never the Joycon. I've repeated the test 5 or 6 times. It's always the Pro Controller that disconnects.

I fail to understand how can an unrelated device affect the Pro Controller's hid-nintendo instance. I'm starting to agree with you in that this might be a problem external to hid-nintendo.

Another hint to it being an external problem is the fact that as soon as this problem happens and the controller turns off, the device disconnect event is received instantly on the OS. From my understanding, these Nintendo controllers never send disconnect events even when you turn them off manually on the sync button, they just time-out instead. If this issue were due to a crash on the controller's firmware, we would be getting time-outs as well, instead of the instantaneous disconnections we're getting now, am I right? It almost feels like the disconnection is coming from the Bluetooth stack.

Taking this into account, where should we open an issue? BlueZ?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

nfp0 commented 1 year ago

Steam pro controller support now works with wireless and bluetooth + rumble without d/cs.

@psycho-driver Are you talking about the Steam controller or the Switch Pro controller?

psycho-driver commented 1 year ago

The Switch Pro controller.

On Thursday, July 27, 2023 at 01:30:17 PM CDT, nfp0 ***@***.***> wrote:  

Steam pro controller support now works with wireless and bluetooth + rumble without d/cs.

@psycho-driver Are you talking about the Steam controller or the Switch Pro controller?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

nfp0 commented 1 year ago

@psycho-driver It definitely had problems before, yes. If you do a search online, there's lots of people complaining about the Pro Controller disconnecting on the Steam Deck.

You think it's fixed now?

I remember someone mentioning here that Steam uses SDL, so shouldn't the fix be visible here in the SDL repository? https://github.com/libsdl-org/SDL/blob/main/src/joystick/hidapi/SDL_hidapi_switch.c#L53

TriVoxel commented 1 year ago

Just going to add my experiences here.

I've observed my (nearly brand new) controller working perfectly on macOS and a real Switch without problems, so I know it is good hardware. On Linux, indeed it will disconnect within a few minutes usually, sometimes multiple times in a row. I am not sure of using multiple controllers, or especially Switch controllers, makes a difference, I only have the one Switch controller and often several Wii U controllers connected. I don't think I've noticed a difference when having Wii U controllers connected via BT, so perhaps it is the driver running two Switch protocols at once which is problematic?

I wouldn't entirely discount the Switch controller hw as problematic, though. I haven't had any problems with bluetooth controllers on Linux for years. I've had success with PlayStation 3-5 controllers, Wiimotes, Wii U Pro Controllers, Xbox Series, etc. Of all my BT controllers, the Switch is the only one which is problematic. And it isn't just Linux which suffers with supporting this device. Here is an issue from BlueRetro, an open source controller firmware which allows hardware to be built that facilitates using modern Bluetooth controllers on retro game consoles. I ran into this issue using a Power-A GameCube style controller for Switch, Bluetooth using the Switch protocol. Their software also has major issues with supporting this hardware, and it doesn't have rumble either. I suspect they have problems with rumble and so opted to disable it. I'm not entirely sure what software BlueRetro uses, but it's a much smaller program than the Linix kernel, and if they share some components with Linux, that would probably be a good place to start looking for this problem. Perhaps there is also something about the Switch's bt protocol that is obfuscated somehow? I would not put it past Nintendo to intentionally design an anti open software controller in this day and age...

nfp0 commented 1 year ago

@TriVoxel Interesting. I'll subscribe to that issue to see what they changed if it gets fixed.

andsouto commented 1 year ago

I have a Pro Controller (with original firmware as I don't have a switch to update it) and it also suffers of the same disconnection issues that are described here when using rumble. Later I bought a [GuliKit KingKong 2 Controller])https://www.gulikit.com/productinfo/828615.html) and although it exposed itself using the switch protocol and uses also this driver in Linux, no disconnection occurs. So I guess something "special" has to be in the controller itself...

DanielOgorchock commented 11 months ago

I've been digging into these bluetooth issues more, and I may have stumbled across a way to improve reliability without allowing rumble quality to suffer.

I'd appreciate if anyone else is able to give this a try to see if it improves things for them.

First, to properly test, it's required to modify the hid-nintendo driver slightly. These changes will revert the driver to a state where it attempts to match USB rumble performance for bluetooth controllers:

  1. Set JC_SUBCMD_VALID_DELTA_REQ equal to 0 (disables the primary disconnect workaround currently used by the driver).
  2. Set JC_SUBCMD_RATE_LIMITER_BT_MS to 20 (matching the USB rate limiter values).
  3. Search for the only msleep call in the driver, and comment it out.

Now I have been testing 2 bluetooth-related tweaks.

The first one I'm not so sure if it actually matters, but it shouldn't hurt. I thought I saw more disconnects without it, but that may have been pure chance.

Edit the bluez main configuration file: /etc/bluetooth/main.conf You should see a line commented out with "LinkSupervisionTimeout". Uncomment it, and set it to:

LinkSupervisionTimeout=3200

You'll see two lines related to min/max sniff intervals. Uncomment them, and set them to the below values:

MinSniffInterval=6
MaxSniffInterval=6

Frankly, I'm not sure if these make any real difference when factoring in the next step using hcitool...

Be sure to restart bluez (systemctl restart bluetooth) and then reconnect your usb dongle.

Now, after you connect your controller, and the hid-nintendo driver probes, check dmesg output to see your controller's MAC address.

Now for the step which I can tell definitely improves reliability. Make sure that you have hcitool installed. We're going to use it to disable BT sniff mode with the controller. I'm not sure how drastically this will impact battery life, since from what I understand this will basically keep bluetooth constantly in active mode.

Observe the current link policy used with the connected controller:

hcitool lp <your_controller_mac_string>

You should see this:

Link policy settings: RSWITCH HOLD SNIFF PARK

Now, disable SNIFF functionality like so:

hcitool lp <your_controller_mac_string> RSWITCH,HOLD,PARK

Now, running hcitool lp <your_controller_mac_string> should yield:

Link policy settings: RSWITCH HOLD PARK

Note that the link policy needs to be set again each time the controller is reconnected. In my stress testing (mario kart on yuzu is my go-to), I'm no longer seeing pro controller disconnects, and the rumble performance is FAR better than the in-kernel workaround (not as good as USB due to apparent packet drops, but pretty close).

I do still get disconnects when using both joycons. I think a single usb bt adapter just isn't good enough typically to handle multiple connected controllers while using rumble.

I think a good compromise may be to expose those in-kernel driver rate limit definitions as module params. That way they can default to something conservative, but someone using a single controller per BT adapter can tweak them to be more performant.

Please let me know if anyone else is able to reproduce my results. If it's consistent, we can figure out a way to try applying the link policy tweak automatically (maybe udev rules, as part of joycond, or maybe even a bluez plugin). I suppose we also would need to figure out the battery life impact.

EDIT: Honestly, I'm not sure anymore. Sometimes the controller just really wants to disconnect anyway, even with these tweaks. The BT connection just isn't stable. I'm pretty sure this is an improvement in performance though, so it'd be good for others to try validating still.

EDIT 2: Added one more thing to experiment with in the bluez conf (might just be random chance that I saw improvement with it though)

benjamimgois commented 11 months ago

@DanielOgorchock since i don't know how to modify the driver, i tried the change in bluez maind config file. And i still got disconects. Some observations that might be usefull to you:

1- I'm using the original joycons 2- It's much more common that the disconection occurs on the righ joycon, it's very rare to have a disconection on the left one. 3- The right joycon seems to drain a lot more battery, since it alway dryout first. 4- This isn't a hardware issue, since i replaced the unit that i bought from amazon the first time i noticed the disconections (also the righ one had a worse time). 5- Here is the dmesg since i connect the joycons on yuzu until the right one disconects https://pastecode.dev/s/SvARPSLO

Let me know if there's any other thing i can do.

nfp0 commented 11 months ago

@DanielOgorchock Good to see you back on this issue! :slightly_smiling_face: I'll give this a try as soon as I can.

@benjamimgois If the disconnections occur much more frequently on the right joycon, could this be related to the joycon's NFC or IR features? The Pro Controller also has NFC functionality.