2014-01-17 05:09:35

by Simon Wood

[permalink] [raw]
Subject: Dualshock4 - 'HIDP: Handshake: Unsupported request' after 'unplug virtual cable'.

Hi all,
Frank and I have been working on a kernel driver for the Dualshock 4 and
we're having problems with the BT connection (USB is OK).

When powered on the DS4 will initiate a connection to the PC once it knows
it's Bdaddr (via pairing), but will power off shortly there after. This
seems to be related to incorrect (??) data sent from Bluez, or if no hid
connection is made within a short window.

On the two systems I have tried:
1) Debian with bluez 4.99, I can 'hidd --connect xxx' to hold the
connection. I get joystick data but can't send data to DS4 to drive
ff/leds. (I am told that 'hidd' is deprated)

2) Fedora LiveCD with bluez 5.13. Connection is immediately terminated by
the controller. HCI log attached.

It appears that the controller is insisting on a encrypted link ('noenc'
and 'noauth' make no difference) and does not like the 'unplug virtual
cable' which is sent (presumably as the link is being brought down to
re-start encrypted).

In the BT HID 1.1 spec (page 48) it says
--
If the HIDVirtualCable SDP attribute is set to TRUE, then a Virtual Cable
is considered to be established after both the HID Control and HID
Interrupt L2CAP channels have been opened.
--

However the Fedora system does not have a copy of the SDP records for the
controller, it never pulled them and I have never managed to make a
connection long enough to read them.

My theory is that the controller is rejecting the 'Unplug Virtual Cable'
command as it shouldn't have been established, but I'm not really sure.



I managed use my Debian system to read SDP records but that barfs on
what's sent.... files also attached.

Does anyone have any suggestions on what I should try next?
Thanks, Simon





Attachments:
hcidump_records.txt.gz (15.76 kB)
records.txt (673.00 B)
records_raw.txt (2.78 kB)
connect_ds4_fedora_4.txt (9.79 kB)
info (157.00 B)
Download all attachments

2014-01-17 20:17:36

by Simon Wood

[permalink] [raw]
Subject: Re: Dualshock4 - 'HIDP: Handshake: Unsupported request' after 'unplug virtual cable'.


> So the problem is, your host refuses the HIDP connection from the
> device. This is intentional, as we don't want *any* remote Bluetooth
> device to be allowed to provide HID services. This could be used for
> very subtle attacks. The code responsible for that is
> ./profiles/input/server.c in bluez.

I note that there is now some DS3/SixAxis specfic stuff in there:
http://git.kernel.org/cgit/bluetooth/bluez.git/tree/profiles/input/server.c#n167

> Now, there are two ways to go on:
> - try to initiate the HIDP connection from the host instead of the
> device. Simply use "bluetoothctl" and then "connect <bdaddr>"
> - add the remote device to the list of known devices so incoming
> connections are not blocked. You can do this by triggering the
> ->device_probe() callback of the input device. I'm not sure how this
> is done, but I think a simple "connect <bdaddr>" should trigger it on
> *all* available services.

Thanks for your suggestions, I'll try to get some logs early next week.

Cheers,
Simon


2014-01-17 10:16:29

by David Herrmann

[permalink] [raw]
Subject: Re: Dualshock4 - 'HIDP: Handshake: Unsupported request' after 'unplug virtual cable'.

Hi

On Fri, Jan 17, 2014 at 6:09 AM, <[email protected]> wrote:
> Hi all,
> Frank and I have been working on a kernel driver for the Dualshock 4 and
> we're having problems with the BT connection (USB is OK).
>
> When powered on the DS4 will initiate a connection to the PC once it knows
> it's Bdaddr (via pairing), but will power off shortly there after. This
> seems to be related to incorrect (??) data sent from Bluez, or if no hid
> connection is made within a short window.
>
> On the two systems I have tried:
> 1) Debian with bluez 4.99, I can 'hidd --connect xxx' to hold the
> connection. I get joystick data but can't send data to DS4 to drive
> ff/leds. (I am told that 'hidd' is deprated)
>
> 2) Fedora LiveCD with bluez 5.13. Connection is immediately terminated by
> the controller. HCI log attached.
>
> It appears that the controller is insisting on a encrypted link ('noenc'
> and 'noauth' make no difference) and does not like the 'unplug virtual
> cable' which is sent (presumably as the link is being brought down to
> re-start encrypted).

Could you provide a bluetoothd log, too? I suspect it contains a
message along the line:
"Refusing input device connect: %s (%d)"

"connect_ds4_fedora_4.txt" contains all the important information.
I'll just summarize what it does:
1. The remote device initiates a base-band connection to your host
2. Your host fetches all SDP records from the device (L2CAP PSM: 1)
3. The SDP connection is closed
4. Link-key negotiation is successful (=> you already were connected
to the device before)
5. encryption-mode is changed successfully (not sure whether it's
turned ON or OFF, but I guess "encrypt 0x01" means ON)
6. device initiates L2CAP on PSM 0x17 (HIDP control channel)
7. Host sends "HIDP: Control: Virtual cable unplug" on the HIDP control channel
8. host closes L2CAP PSM 0x17
9. device initiates L2CAP on PSM 0x19 (HIDP intr channel)
10. host refuses connection on PSM 0x19
11. device closes baseband connection

So the problem is, your host refuses the HIDP connection from the
device. This is intentional, as we don't want *any* remote Bluetooth
device to be allowed to provide HID services. This could be used for
very subtle attacks. The code responsible for that is
./profiles/input/server.c in bluez.

Now, there are two ways to go on:
- try to initiate the HIDP connection from the host instead of the
device. Simply use "bluetoothctl" and then "connect <bdaddr>"
- add the remote device to the list of known devices so incoming
connections are not blocked. You can do this by triggering the
->device_probe() callback of the input device. I'm not sure how this
is done, but I think a simple "connect <bdaddr>" should trigger it on
*all* available services.

I hope that helps. If not, we can try to add the device manually.
Cheers
David

> In the BT HID 1.1 spec (page 48) it says
> --
> If the HIDVirtualCable SDP attribute is set to TRUE, then a Virtual Cable
> is considered to be established after both the HID Control and HID
> Interrupt L2CAP channels have been opened.
> --
>
> However the Fedora system does not have a copy of the SDP records for the
> controller, it never pulled them and I have never managed to make a
> connection long enough to read them.
>
> My theory is that the controller is rejecting the 'Unplug Virtual Cable'
> command as it shouldn't have been established, but I'm not really sure.
>
>
>
> I managed use my Debian system to read SDP records but that barfs on
> what's sent.... files also attached.
>
> Does anyone have any suggestions on what I should try next?
> Thanks, Simon
>
>
>
>