Skip to content

Dualshock 4 High Latency over Bluetooth #274

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

Open
markubiak opened this issue Feb 8, 2015 · 9 comments
Open

Dualshock 4 High Latency over Bluetooth #274

markubiak opened this issue Feb 8, 2015 · 9 comments

Comments

@markubiak
Copy link

The Sony Dualshock 4 (DS4) controller has a very low polling rate when connected to any Linux system over bluetooth. This issue is highlighted by the userspace ds4drv DS4 driver. When connected to the system via USB, the controller performs excellently with no issue whatsoever. However, over bluetooth, the controller reports at 20-21 reports per second (accoding to the ds4drv program) when connected as a standard bluetooth controller through Bluez. An interesting note, however, is that when the controller is connected through the ds4drv driver using its native mode (not the --hidraw mode), the reports up to around 32-38 reports a second, varying between the two numbers. I have done some troubleshooting, and the issue persists whether or not ds4drv is installed at all. Here is a wiki of devices with this issue, it is unknown at this time what exactly causes it. I am reporting this to the SteamOS github because it is not entirely certain whether the issue arises from the hid_sony kernel module or the Bluez5 userspace kernel driver. I would normally assume it to be the Bluez5 stack, as it has historically been terribly buggy, but there was an interesting note by the author of the hid-sony module:

397 /*
398 * The default behavior of the Dualshock 4 is to send reports using report
399 * type 1 when running over Bluetooth. However, when feature report 2 is
400 * requested during the controller initialization it starts sending input
401 * reports in report 17. Since report 17 is undefined in the default HID
402 * descriptor the button and axis definitions must be moved to report 17 or
403 * the HID layer won't process the received input.
404 */

I am happy to provide any more information that may help track down the bug and solve it, as I am essentially tied to a USB cord while playing controller based SteamOS games.

uname -a: Linux mark-arch 3.18.5-1-ARCH #1 SMP PREEMPT Fri Jan 30 07:31:50 CET 2015 x86_64 GNU/Linux
bluez 5.28-1

@Kontrabant
Copy link

The Dualshock 4 has two modes under Bluetooth: a basic mode that is quite barebones (buttons and sticks only and a full mode that sends all of the controller data (tilt, battery, touch etc...). The trigger to go into full mode is basically any outgoing communication with the controller (ie. using rumble or setting the LEDs) so the HID descriptor had to be reworked so the underlying Linux HID system knows what to do with the incoming data once the controller reporting state changes (and add support for the gyros and accelerometers that isn't there by default). That's what that comment block is referring to.

The hid_sony module knows nothing about the USB or Bluetooth transport systems aside from which way the controller is currently connected for the purposes of initialization. It has no control over the latency or processing speed of the underlying protocol. Also note that in Bluetooth mode the controller itself won't actually send a data packet unless some state changed, probably to conserve the battery. If it's sitting perfectly still and no buttons are pressed then it just won't send any data.

@markubiak
Copy link
Author

I tried pairing the controller while spinning the sticks, in order to try and force the controller to send as much data as possible, but I'm still getting low signal errors. Do you think it's an issue with BlueZ?

@Kontrabant
Copy link

What kind of Bluetooth adapter are you using? If you are getting low signal warnings it may just be that you actually have a weak signal. In my own experience I found that those little thumbnail sized adapters just don't work well with the DS4, especially if you plug them into a port on the back of the case. I was getting a terrible connection with lots of dropped traffic from less than 1 meter away. Once I bought an Intel Wifi+Bluetooth card and a PCI-E adapter with actual antennas my connection became rock solid.

@markubiak
Copy link
Author

I'm using an Intel 7260 AC Mini PCIE Half card. I'm sitting under 2 feet away from the adapter, so I doubt that there's a signal strength issue.

@ghost
Copy link

ghost commented Jul 28, 2015

I believe I found the problem. The hid-sony module initialized the controller with some incorrect values.
Here's the patch to test for yourself before it gets merged:
http://www.mail-archive.com/[email protected]/msg941718.html

@Kontrabant
Copy link

On 7/28/2015 03:50, Rostislav Pehlivanov wrote:

I believe I found the problem. The hid-sony module initialized the
controller with some incorrect values.
Here's the patch to test for yourself before it gets merged:
http://www.mail-archive.com/[email protected]/msg941718.html


Reply to this email directly or view it on GitHub
#274 (comment).

Nice fix. The original value wasn't a mistake though. It either came
from a packet dump or an example program. The purpose of that value was
undocumented at the time the code was written and 0xB0 seemed to work so
it was used. Looking at other traffic dumps, it seems the PS4 uses 0xC0
as the rate value:

http://eleccelerator.com/wiki/index.php?title=DualShock_4#0x11_2

Out of curiosity, do you know how the reporting rate is calculated from
that value? Does the value represent some multiplier or divisor, or
does it just use the leading zero count to look up a value in a table?
Might be worth adding a comment in the driver code as a reference for
others.

Regards,
Frank

@ghost
Copy link

ghost commented Jul 28, 2015

@frank:
Here's what I got:
0x20 was sending at 20 Hz. Controller took a bit longer to discover host
and the LED remained white, though it did work.
0x70 was the same. It's probably an invalid value, same as 0x20 and the
rate is just used as default fallback value.
0x80 was what I submitted. It works fine, controller gets discovered fine
and the rate seems fine.
0x90 resulted in the same result as 0xD0 of 62ish Hz, normal operation as
well.
0xA0 was sending at 31 Hz average.
0xAF was sending at the same rate as 0xB0
0xB0 was as I said 20.83 Hz on average, measured by a resetting counter at
sony_raw_event()
0xC0 and 0x80 resulted in identical results. Maybe they both set the rate
to over 822 Hz (probably my hardware's limit) so I can't see a difference.
0xD0 resulted in a rate around 66 Hz.
0xE0 and it was sending reports at 31 Hz.
0xF0 was just as 0xB0 sending at around 20 Hz.

0xD0 and 0xE0 are the only values which hint that the values are probably
used as divisors, but are a minority. 0xC0 is an anomaly.
It doesn't look like it's using a LUT, maybe just some if {} else if {}
else {} since the only rates I was able to observe were 20, 31, 66 and 822
(my adapter's limit?). This would explain the weirdness at 0x20 and 0x70.

At best, I can only say that the 1st offset has something to do with the
response rate and I think just editing the eccerelator wiki should be
enough.

0xC0 and 0x80 seem identical for all intents and purposes though and the
repeating pattern suggests they both trigger the same codepath, so I figure
either value would work.

On 28 July 2015 at 15:41, Frank Praznik [email protected] wrote:

On 7/28/2015 03:50, Rostislav Pehlivanov wrote:

I believe I found the problem. The hid-sony module initialized the
controller with some incorrect values.
Here's the patch to test for yourself before it gets merged:
http://www.mail-archive.com/[email protected]/msg941718.html


Reply to this email directly or view it on GitHub
<
#274 (comment)
.

Nice fix. The original value wasn't a mistake though. It either came
from a packet dump or an example program. The purpose of that value was
undocumented at the time the code was written and 0xB0 seemed to work so
it was used. Looking at other traffic dumps, it seems the PS4 uses 0xC0
as the rate value:

http://eleccelerator.com/wiki/index.php?title=DualShock_4#0x11_2

Out of curiosity, do you know how the reporting rate is calculated from
that value? Does the value represent some multiplier or divisor, or
does it just use the leading zero count to look up a value in a table?
Might be worth adding a comment in the driver code as a reference for
others.

Regards,
Frank


Reply to this email directly or view it on GitHub
#274 (comment)
.

@mdeguzis
Copy link
Collaborator

Not to derail this nice technical discussion I am enjoying, but is the previous method I used, sixad/qtsixa, not applicable to using the Dual Shock 4 anymore?

@jusapunk
Copy link

jusapunk commented Nov 1, 2016

Hi there guys.
I have the exact same Issue, as soon as I check "Hide DS4 Controller" in the settings,
my latency goes over 100ms.

How do I apply that Patch/change that value to 0x80?

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

No branches or pull requests

4 participants