# PlayStation 5 DualSense controller pairing



## FrostKiwi (Jun 6, 2021)

I would like to connect a DualShock 4 (and PS5 controller later on) with FreeBSD and my integrated (USB) Bluetooth 2.1 or 4.0 chip.
With the DualShock 4 connected via *USB*, *controllermap* successfully detects both the controller and every single controller button / analog stick.
Now I used *bluetooth_config scan* to pair the controller. When asked for a pin, I simply left it at the default *nopin*.

Now there is an alias in */etc/bluetooth/hosts*, an entry in *hcsecd.conf* with *nokey* and *nopin* and *bthidd.conf* lists the device with the *bdaddr*, some more info and the *hid_descriptor{ ... }*.

However, nothing really happens from here on out.
Every 10 seconds, the bluetooth lamp blinks and hccontrol read_connection_list reports:

```
Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
DualShock4          3902  ACL    0 MAST    NONE       0     0 W4_CONN_COMPLETE
```
This lasts roughly 3 seconds, before the entry disappears and the cycle starts anew. The DualShock4 never lights up, putting it into connection mode changes nothing, just the blue connection light flashing on the controller. *controllermap* never detects a joystick.

What can I do to get a connection? Is my pairing maybe incomplete,  because I set *nopin *and *nokey*? With Linux and DualShock *3* there appears to be the need to connect it via USB first to exchange pairing data. Maybe that's when the key is transfered? But this does not appear to be the case for DualShock *4*.


----------



## FrostKiwi (Jun 7, 2021)

I compared to Linux and here are the results:
Connection on Linux works automatically. The DualShock4 turns instantly blue and the controller inputs are read successfully.
I checked /var/lib/bluetooth for pairing information.
My Smartphone leaves behind a pairing key, the DualShock4 does not. The DualShock4's bluetooth info file shows no special information being left behind:


Spoiler: DualShock4 Bluetooth info file





```
[General]
Name=Wireless Controller
Class=0x002508
SupportedTechnologies=BR/EDR;
Trusted=false
Blocked=false
WakeAllowed=true
Services=00001124-0000-1000-8000-00805f9b34fb;00001200-0000-1000-8000-00805f9b34fb;

[DeviceID]
Source=2
Vendor=1356
Product=2508
Version=256
```



For comparison the SmartPhone Info file:


Spoiler: Smartphone Bluetooth info file





```
[LinkKey]
Key=4A210DB2D0D1CC87459184DFB6A7F601
Type=5
PINLength=0

[General]
Name=OnePlus One
Class=0x5a020c
SupportedTechnologies=BR/EDR;
Trusted=true
Blocked=false
Services=00001105-0000-1000-8000-00805f9b34fb;0000110a-0000-1000-8000-00805f9b34fb;0000110c-0000-1000-8000-00805f9b34fb;0000110d-0000-1000-8000-00805f9b34fb;0000110e-0000-1000-8000-00805f9b34fb;00001112-0000-1000-8000-00805f9b34fb;00001115-0000-1000-8000-00805f9b34fb;00001116-0000-1000-8000-00805f9b34fb;0000111f-0000-1000-8000-00805f9b34fb;0000112f-0000-1000-8000-00805f9b34fb;00001132-0000-1000-8000-00805f9b34fb;00001200-0000-1000-8000-00805f9b34fb;00001800-0000-1000-8000-00805f9b34fb;00001801-0000-1000-8000-00805f9b34fb;

[DeviceID]
Source=1
Vendor=224
Product=4608
Version=5174
```



Thus I conclude, that both *nopin* and *nokey* properties in FreeBSD are indeed correct. So something about the handling of the Controller is wrong. I don't even know whether the pairing succesds or not, and I have no idea how to understand what hccontrol means by "W4_CONN_COMPLETE". skimming the kernel code, ng_hci_ulpi.c states "_NG_HCI_CON_W4_CONN_COMPLETE means that upper layer already requested connection or we just accepted it. In any case all we need to do here is set appropriate notification bit and wait._"
I guess FreeBSD is waiting for the DualShock4 to answer, but I'm way over my head here. I have no idea how to proceed or where to look for answers.
halp


----------



## sidetone (Jun 8, 2021)

According to the Handbook, Bluetooth version 1.1 and some models of v2 work. Some have claimed up to Bluetooth 3.0, or Bluetooth LE works, while the documentation is years behind, but this is difficult to validate or confirm. They say Bluetooth audio works no matter the version, this is documented.








						bluetooth
					






					forums.freebsd.org


----------



## FrostKiwi (Jun 8, 2021)

sidetone said:


> According to the Handbook, Bluetooth version 1 and some manufacturers of 2.1 work. Some have said up to Bluetooth 3.0 or Bluetooth LE works, while the documentation is years behind, but this is difficult to validate or confirm. They say Bluetooth audio works no matter the version.
> 
> 
> 
> ...


Ohh... So I misunderstood what FBSD supports.
There is just no support for Bluetooth v4, no need to try and investigate anything. I specifically replaced the USB daughterboard in my Thinkpads to Bluetooth v4 ones. I can downgrade to Bluetooth 2.1 again. Since the DualShock 4 is BlueTooth v2.1 and the PS5's Dual Sense controller *propably* supports BlueTooth 2.0 via backwards compatibility, because you can use a PS5 controller on a PS3 (A BlueTooth 2.0 only device), I should get everything to work by downgrading to the BlueTooth 2.1 daughter board.

That seems like a good theory to try :]  Will test that tomorrow and report back.


----------



## sidetone (Jun 8, 2021)

After reading the section on the handbook, the supported versions were easy to miss. I actually missed it, and went and bought a higher version Bluetooth dongle.

Some Bluetooth peripherals have shown up, but not as a Bluetooth device. They didn't work.

In a thread, there was a claim of Bluetooth v4 working. Bluetooth LE may possibly include higher versions. These claims of higher versions working is difficult to validate.

There's the possibility that some Bluetooth code was temporarily in Stable or Current. It's also possible that there's some code in FreeBSD base that isn't complete or officially functional.


----------



## FrostKiwi (Jun 9, 2021)

Progress!
After changing from the BCM920702MD BlueTooth 4.0 board to the BCM92046MD BlueTooth 2.1 EDR2 Board, pairing can be successfully completed.
The Bluetooth driver responds when the DualShock4 is turned on and opens a connection. After a successful pairing, the bluetooth lamp starts blinking non-stop and the controller shines light-blue all the time.

```
bthidd[892]: Accepted control connection from a0:ab:51:43:ba:27
bthidd[892]: Accepted interrupt connection from a0:ab:51:43:ba:27
```
hccontrol read_connection_list now reports constantly:

```
Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
a0:ab:51:43:ba:27     11  ACL    0 MAST     P2P       0     0 OPEN
```
Setting everything up, this article really helped. "bluetooth_config scan" behaves a bid weird, throwing error after writing the hid descriptor even though it succeeds. Manully setting it up, no errors were encountered. Also, I do not understand when or how it is setup, but sometimes I got to a state, where the BlueTooth chip would scan every 10 seconds actively with the lamp blinking. This is not the case anymore. Now it simply remains neutral, until the DS4 requests a connection.
Now the DualShock4 constantly shines light-blue. The same light blue that blinks when it searches for a connection. However, it is not the DarkBlue I encountered in Linux, when it is working as a controller.
No joystick is detected by controllermap. How can I procced? Where can I look? I don't even know whether there was a device created in /dev/ or not...


----------



## FrostKiwi (Jun 14, 2021)

Highly annoyingly I cannot get it to pair again to research further >.<
Nothing changed, but now the DS4 just blinks, the Bluetooth lamp blinks for a single time but nothing happens, no "Accepted control connection" in /var/messages
Doing manually


> sudo hccontrol -n ubt0hci create_connection a0:ab:51:43:ba:27


results in


> Status: ACL connection already exists [0xb]


And hccontrol read_connection_list lists the following for a single second:

```
Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
a0:ab:51:43:ba:27     3848  ACL    0 MAST     P2P       0     0 W4_CONN_COMPLETE
```
Like with the non-working BlueTooth 4.0. So frustrating, I don't know how to coerce it into connecting again. Since these are the symptoms as with BlueTooth 4, maybe BlueTooth 4 did work after all?


----------



## sidetone (Jun 14, 2021)

After giving it a few more tries, my guess is that a Bluetooth application has to be ported. If Linux has support for it, it likely can be ported, by using the Porter's Handbook, https://docs.freebsd.org/en/books/porters-handbook/.


----------



## FrostKiwi (Jun 14, 2021)

There exists this user space driver for the DualShock4 on Linux: https://github.com/chrippa/ds4drv
Let's say, that through sheer power of will I actually get FreeBSD's bluetooth to stick to "Accepted control connection" again, like on that miracle of a day...
... where would that bluetooth device be created? Is there a corresponding /dev/.... entry?


----------



## sidetone (Jun 14, 2021)

I believe so, that a device will be created in /dev/. A module may also be created in /boot/modules/. Use `dmesg` to see terminal output of a new connection.

* edit, a Bluetooth driver, if there is one. As for the gamepad driver, FreeBSD may already have it. Iichid is base of FreeBSD 13.0.


----------



## FrostKiwi (Jun 15, 2021)

sidetone said:


> I believe so, that a device will be created in /dev/. A module may also be created in /boot/modules/. Use `dmesg` to see terminal output of a new connection.
> 
> * edit, a Bluetooth driver, if there is one. As for the gamepad driver, FreeBSD may already have it. Iichid is base of FreeBSD 13.0.


A Bluetooth driver what for? What is it's purpose, for what device? To interface with the DualShock 4? To manage the BlueTooth Chip?

Also any idea how to solve
"sudo hccontrol -n ubt0hci create_connection a0:ab:51:43:ba:27" returning "Status: ACL connection already exists [0xb]"?


----------



## sidetone (Jun 15, 2021)

A Bluetooth driver simply for being of Bluetooth, if the version needed still doesn't work.
sysutils/btsixad, iichid(4) is in base of FreeBSD 13.0, and they say SDL takes care of gamepad/joystick drivers too. Try one of those. If it has both Bluetooth and a USB cable, test it over USB connection first.

Is there a command to list connected Bluetooth devices? There's `dmesg`, but there may be one more specific to Bluetooth. What about `kldstat`? I would say, ask on the mailing list (https://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth) too, but it hardly has anything. It wouldn't hurt to try, perhaps there can be a response.


----------



## FrostKiwi (Jun 16, 2021)

sidetone said:


> A Bluetooth driver simply for being of Bluetooth, if the version needed still doesn't work.
> sysutils/btsixad, iichid(4) is in base of FreeBSD 13.0, and they say SDL takes care of gamepad/joystick drivers too. Try one of those. If it has both Bluetooth and a USB cable, test it over USB connection first.
> 
> Is there a command to list connected Bluetooth devices? There's `dmesg`, but there may be one more specific to Bluetooth. What about `kldstat`? I would say, ask on the mailing list (https://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth) too, but it hardly has anything. It wouldn't hurt to try, perhaps there can be a response.


DualShock4 via USB works flawlessly and spawns /dev/uhid0, as described in the OP.
As for BlueTooth, I think this is once more progress...
...bthidd can interpret the HID descriptor and accept the DualShock4, as described in this post. However, this does not get us far no device is spawned in /dev.
Now on to btsixad - Many thanks for the reference! bthidd and btsixad listen on the same socket, so one thing or the other.
With bthidd gone, btsixad also detects the DS4, though not in name and disconnects:

```
btsixad 23379 - - connection from a0:ab:51:43:ba:27 on control channel
btsixad 23379 - - connection from a0:ab:51:43:ba:27 on interrupt channel
btsixad 23379 - - connection is from unknown device: vendor 0x054c (by 0x0002), product 0x09cc, release 0x0100
btsixad 23379 - - connection from a0:ab:51:43:ba:27 closed
```
The kernel module ng_l2cap_l2ca_receive also complains:

```
Jun 16 01:30:01 stripes kernel: ng_l2cap_l2ca_receive: ubt0l2cap - unexpected L2CAP data packet. Invalid channel state, cid=108, state=5
Jun 16 01:30:01 stripes syslogd: last message repeated 2 times
```
I presume the kernel complains, because btsixad killed the connection ungracefully, and not vice-versa (bluetooth kernel module creates an issue, that makes btsixad fail)

This is as far as I get. The btsixad package homepage mentions, that btsixad is aimed at the DualShock3. Maybe involve that package author to explain to us what would have to be done to revamp support for the PS4's DualShock 4 and the PS5's DualSense...


----------



## FrostKiwi (Jun 19, 2021)

I got my hands on a DualShock 3 and tried out the BlueTooth capability via sysutils/btsixad. It works!
It is successfully being detected as a controller and all inputs are being proccessed.

As mentioned in the previous post this does not extended to the DualShock 4. I do wonder what could be done about btsixad to get support going... The btsixad codebase is only 1000 SLOC. So I'll try to go through it to get a grip on the proccess of all of this...


----------



## FrostKiwi (Sep 10, 2021)

I got myself a PlayStation5 DualSense controller.
On Linux pairing via BlueTooth 2.1 works flawlessly and all buttons and axis work <3
The Situtation with FreeBSD is unfortunately the same as with the DualShock4 controller: Connecting via USB works, but with bluetooth: After exchanging Pairing and hid data, which works flawlessly, a connection cannot be establised.
hccontrol reports:

```
Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
a0:ab:51:c4:af:bb     13  ACL    0 MAST    NONE       1     0 OPEN

Followed by
Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
a0:ab:51:c4:af:bb   3884  ACL    0 MAST    NONE       0     0 W4_CONN_COMPLETE
```
And the connection terminates. btsixad does not pick up anything at all.
So I guess the only hope is adapting btsixad?


----------



## aaz (Sep 10, 2021)

btsixad author here. So btsixad has three functions:

1. Pairing. The PS3 gamepad uses a non-standard pairing procedure: it sets the host's Bluetooth address in the gamepad over USB. PS4 and PS5 gamepads use standard Bluetooth pairing.

2. Talking to the gamepad over Bluetooth L2CAP on HID control and interrupt channels and querying metadata over SDP. I think this is pretty normal for Bluetooth HID devices because bthidd and bthidcontrol do something similar. The PS3 controller either has a broken HID descriptor or none at all (seems pretty normal too) and needs a special message to initialize it. Other than that I think bthidd would be able to do this part.

3. Fakes a local /dev/uhid device via cuse(3). All the game engines (SDL etc.) understand this. The input reports received over Bluetooth are remapped a bit according to my preferences before being reported there. For example the D-pad is presented as a hat switch rather than buttons 4-7. I think the proper way to do this nowadays is evdev, which is mentioned on bthidd(8).

Only the PS3 gamepad is supported and you can see that a lot of this is relevant to the PS3 gamepad only. The immediate disconnect when it detects a different device is intentional.

As for the PS4 and PS5 gamepads - they are more well-behaved Bluetooth HID devices, and it sounds like you almost have bthidd working with them. Maybe the HID descriptor is broken and doesn't match the actual reports (bthidd.conf can provide a custom one), maybe some HID control message to initialize it is missing. The standard Linux driver (drivers/hid/hid-sony.c) or the userspace driver you mentioned (ds4drv) might have hints about this.

Adapting btsixad should only be needed if you want extra functions like changing the LED color, changing the default button map, or to do any initialization automatically. Since pairing already works, this would only involve detecting the new gamepad's model and creating a new device-specific file similar to sixaxis.c to send any required initialization messages, and to either provide a hardcoded HID descriptor as is done for the PS3 gamepad or to query the real HID descriptor over SDP. Unfortunately I don't have time to try this.


----------



## FrostKiwi (Sep 24, 2021)

Had E-Mail notifications off for such an important post >.<
aaz Many thanks for your input!


aaz said:


> I think bthidd would be able to do this part [...] and it sounds like you almost have bthidd working with them.


That sounds very good!


aaz said:


> Adapting btsixad should only be needed if you want extra functions like changing the LED color, changing the default button map, or to do any initialization automatically.


This is settled then, there is no need to dig through btsixad for the DualShock 4 and the DualSense. These extra functions are not support by Linux's kernel driver either and modern features like adaptive trigger and new haptic feedback probably won't ever be even with user space drivers. I care only about the basic stuff, like analog sticks and buttons. I really enjoy demoing my work by giving clients a modern controller with a certain elegance, no cables and a comfortable design.


aaz said:


> Maybe the HID descriptor is broken and doesn't match the actual reports (bthidd.conf can provide a custom one), maybe some HID control message to initialize it is missing. The standard Linux driver (drivers/hid/hid-sony.c) or the userspace driver you mentioned (ds4drv) might have hints about this.


This sounds like a lead <3 The HID descriptor is successfully provided by `bthidcontrol -a ${BDADDR} query`, but you say something with how bthidd handles things is going wrong with the symptoms being, that the connection is dropped and no device is spawned in /dev/. This is a very nice direction to dig in.


----------

