Re: divide_error in dualshock4_parse_report (drivers/hid/hid-sony.c) when using official sony ds4 dongle

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Diego,

Thanks for reporting the issue. I somewhat understand what the problem
is, but I'm not sure about the root cause.

The dongle is essentially a proxy DS4 device, which always emits HID
reports back to the kernel. The data in there is only valid when a
physical DS4 is connected. We have some logic to detect when a DS4 is
connected. For DS4 connected over USB/Bluetooth we do a calibration
when the device is connected to calibrate the sensors. For the dongle,
we defer this until there is an actual DS4.

For whatever reason, the calibration data is 0 in your case. Maybe our
hotplug logic isn't working properly in this case, but I'm not yet
sure how. We have tested this extensively however not with Steam.

To me it is interesting the issues don't happen without Steam. (The
fact that not all apps use the DS4 to its full potential shouldn't
matter in this case.) In regards to Steam I'm not sure how 'innocent'
it is as I'm not sure on what "data path" it is taking for DS4. They
have their own cross-platform HID implementation supporting DS4, which
they might be using here and they might support evdev as well. On
Linux this implementation uses hidraw, while on windows e.g. hid.dll.
If they are using this implementation on Linux then there are
essentially "2 drivers" fighting over the same DS4.

I would like to figure out the data path first. So IF Steam is using
their own HID, they are going through hidraw. I'm curious what happens
if you prevent it from using hidraw (e.g. temporarily change
/dev/hidraw* permissions).

How are you disconnecting the DS4? Are you doing the long-press on the
power button or some other method? We haven't implemented an official
disconnect way outside of that mechanism in hid-sony. I know the Steam
guys did something reverse engineered, but I recall we didn't like the
approach (the HID request they used is meant for something else if I
recall..).

Thanks,
Roderick

On Sun, Feb 10, 2019 at 1:07 AM Diego Veralli <diego@xxxxxxxxxxxxxxxx> wrote:
>
> I don't think my previous email made it through majordomo's filters, so
> trying again.
>
> On 23/01/2019 13:05, Diego Veralli wrote:
> > Hello,
> >
> > I've been experiencing issues with a Sony Dualshock controller, which
> > causes a divide_error in dualshock4_parse_report, using the official
> > Sony dongle (USB 054c:0ba0).
> >
> > Kernel: Linux version 4.20.0+ (d@debian-desk2) (gcc version 8.2.0
> > (Debian 8.2.0-14)) #7 SMP Tue Jan 22 23:02:31 CET 2019. Attached
> > .config of kernel used under qemu to
> > debug the issue.
> > Same problem in the default Debian kernel: Linux version
> > 4.19.0-1-amd64 (debian-kernel@xxxxxxxxxxxxxxxx) (gcc version 8.2.0
> > (Debian 8.2.0-13)) #1 SMP Debian 4.19.12-1 (2018-12-22)
> >
> > I can confirm I've had this issue at least since 4.17, but probably
> > before that as well. I've been running Debian testing and following
> > along with the updates, no package upgrade has made any difference on
> > the issue.
> >
> > What happens is:
> > 1. I turn on the controller (all fine at this point, the controller works)
> > 2. I turn off the controller
> > 3. I turn on the controller again
> >
> > At this point the computer freezes completely. I've reproduced the
> > issue under qemu and I can see the freeze causes a panic:
> >
> > (gdb) bt
> > #0  delay_tsc (__loops=3696029) at arch/x86/lib/delay.c:79
> > #1  0xffffffff81060782 in panic (fmt=<optimized out>) at kernel/panic.c:305
> > #2  0xffffffff8101d8da in oops_end (flags=<optimized out>,
> > regs=<optimized out>, signr=<optimized out>)
> >      at arch/x86/kernel/dumpstack.c:352
> > #3  oops_end.cold () at arch/x86/kernel/dumpstack.c:331
> > #4  0xffffffff8101a4ac in do_trap_no_signal (error_code=<optimized
> > out>, regs=<optimized out>, str=<optimized out>,
> >      trapnr=<optimized out>, tsk=<optimized out>) at arch/x86/kernel/traps.c:211
> > #5  do_trap (trapnr=<optimized out>, signr=8, str=<optimized out>,
> > regs=0xffff88807da03c78, error_code=0, sicode=1,
> >      addr=0xffffffff8178f5a9 <dualshock4_parse_report+233>) at
> > arch/x86/kernel/traps.c:250
> > #6  0xffffffff8101a82b in do_error_trap (regs=<optimized out>,
> > error_code=<optimized out>, str=<optimized out>,
> >      trapnr=<optimized out>, signr=<optimized out>, sicode=<optimized
> > out>, addr=0xffffffff8178f5a9 <dualshock4_parse_report+233>)
> >      at arch/x86/kernel/traps.c:277
> > #7  0xffffffff8101ab7e in do_divide_error (regs=0xffff88807da03c78,
> > error_code=0) at arch/x86/kernel/traps.c:288
> > #8  0xffffffff81c00b84 in divide_error () at arch/x86/entry/entry_64.S:970
> > #9  0xffff88807c858000 in ?? ()
> > #10 0xffff88807ceb0e28 in ?? ()
> > #11 0x0000000000000015 in irq_stack_union ()
> > #12 0xffff88807ceb0fb0 in ?? ()
> > #13 0xffff88807ceb0fd0 in ?? ()
> > #14 0xffff88807c7f3000 in ?? ()
> > #15 0x000000000000004c in irq_stack_union ()
> > #16 0x00000000ffffdb84 in ?? ()
> > #17 0x0000000000000000 in ?? ()
> > (gdb)
> >
> > If I break on divide_error I see the following backtrace:
> >
> > (gdb) bt
> > #0  0xffffffff81c00b70 in divide_error () at
> > arch/x86/entry/entry_64.S:813
> > #1  0xffffffff8178f5a9 in dualshock4_parse_report
> > (sc=0xffff88807c772e28, rd=0xffff88807c8ac000 "\001\205{}\177\b",
> >      size=<optimized out>) at drivers/hid/hid-sony.c:1018
> > #2  0x0000000000000000 in ?? ()
> >
> > The issue *never* happens the first time I turn on the controller.
> > Only after turning it off and on again (ironic I suppose?)
> >
> > The code in question is the following:
> >
> > int calib_data = mult_frac(calib->sens_numer,
> >                 raw_data - calib->bias,
> >                 calib->sens_denom);
> >
> > It seems sens_denom is 0 some times after reconnecting. I've worked
> > around it with a small change to set calib_data to 0 when sens_denom
> > is 0, but I've no idea what side effects this change could have eg.
> > leave the controller in a badly calibrated state.
> >
> > The issue *only* occurs when I enable Dualshock support in the Steam
> > client (https://store.steampowered.com/). When this is set, Steam
> > enables additional features in the controller to set light bar
> > intensity, colour, etc... Connecting, disconnecting, and reconnecting
> > the controller without running Steam does *not* cause the issue.
> > There aren't many userspace applications using the full set of
> > features of the Sony ds4 dongle so this may be why only Steam triggers
> > it. I've submitted a bug report
> > (https://github.com/ValveSoftware/steam-for-linux/issues/6050) but the
> > Steam devs consider this a kernel issue.
> >
> > I've reproduced this on 3 physical machines and also qemu/kvm. I've
> > also tested two different Dualshock controllers. The only thing I've
> > not been able to test is a second Sony dongle, in case mine is
> > defective, but I did lend it to a friend who runs Windows and he
> > reported no issues using the dongle with Steam.
> >
> > Thanks
> > Diego



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux