Search code examples
linuxbluetoothraspberry-piudev

RetroPie and Bluetooth configuration


I have a Raspberry Pi 3B+ running RetroPie and am trying to set up my PS3 controller to always run in 'slave' mode to reduce latency issues. I got the idea from this post. I tested after running the command and it does indeed make a difference.

Problem is, it goes back to 'defaults' after the controller disconnects or rebooting the device. So I'm trying to make it always apply.

I have this shell script (yes, I know it's badly written - I plan to clean it up once I have it all working):

#!/bin/sh
concount=0
while [ ! "$(hcitool con | grep -o "[[:xdigit:]:]\{11,17\}")" ]; do
    sleep 0.1
    if [ $concount -eq 30 ]; then
        break
    else
        echo "Try $concount - Device not found, retrying."
    fi
    concount=$(($concount + 1))
done

if [ $concount -eq 30 ]; then
    echo "Device not found after $concount checks."
else
    sudo hcitool sr $(hcitool con | grep -o "[[:xdigit:]:]\{11,17\}") slave
    echo "Device found and set to slave"
fi

The delay part is because it would fire off before the controller was finished connecting and fail. This essentially gives it 3 seconds to work.

In any case, it works fine when I run it manually via command line and the latency is greatly reduced.

Connections:
        > ACL 00:26:43:CC:B0:FB handle 11 state 1 lm SLAVE
Ping: 00:26:43:CC:B0:FB from B8:27:EB:68:0E:9E (data size 44) ...
4 bytes from 00:26:43:CC:B0:FB id 0 time 14.97ms
4 bytes from 00:26:43:CC:B0:FB id 1 time 16.09ms
4 bytes from 00:26:43:CC:B0:FB id 2 time 9.78ms
4 bytes from 00:26:43:CC:B0:FB id 3 time 11.11ms
4 bytes from 00:26:43:CC:B0:FB id 4 time 13.58ms

I made a file /etc/udev/rules.d/50-btslave.rules containing:

ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="054C", ATTR{idProduct}=="0268", RUN+="/home/pi/btslave.sh"

(idvendor/idproduct came from reading the syslog)

and added this to 99-sixaxis.rules.

ACTION=="add", SUBSYSTEMS=="input", ATTRS{name}=="*PLAYSTATION(R)3 Controller", TAG+="systemd", RUN+="/home/pi/btslave.sh"

then did udevadm control --reload to apply the rules.

When I try to reconnect, the syslog doesn't seem to show anything different. It goes back to 'master' and I get the higher latency as well as spikes.

Feb 12 20:31:14 retropie kernel: [ 2121.796762] sony 0005:054C:0268.0005: unknown main item tag 0x0
Feb 12 20:31:15 retropie kernel: [ 2122.292506] input: Sony PLAYSTATION(R)3 Controller Motion Sensors as /devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:054C:0268.0005/input/input7
Feb 12 20:31:15 retropie kernel: [ 2122.293773] input: Sony PLAYSTATION(R)3 Controller as /devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:054C:0268.0005/input/input6
Feb 12 20:31:15 retropie kernel: [ 2122.294645] sony 0005:054C:0268.0005: input,hidraw2: BLUETOOTH HID v80.00 Joystick [Sony PLAYSTATION(R)3 Controller] on b8:27:eb:68:0e:9e
Feb 12 20:31:15 retropie systemd[1]: Started sixaxis helper (sys/devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:054C:0268.0005/input/input6).
Feb 12 20:31:15 retropie systemd[1]: Started sixaxis helper (/dev/input/event3).
Feb 12 20:31:15 retropie sixaxis-helper.sh[1403]: Calibrating: Sony PLAYSTATION(R)3 Controller (00:26:43:CC:B0:FB)
Feb 12 20:31:16 retropie sixaxis-helper.sh[1403]: Setting 600 second timeout on: Sony PLAYSTATION(R)3 Controller (00:26:43:CC:B0:FB)
Connections:
        > ACL 00:26:43:CC:B0:FB handle 11 state 1 lm MASTER
4 bytes from 00:26:43:CC:B0:FB id 0 time 36.31ms
4 bytes from 00:26:43:CC:B0:FB id 1 time 35.97ms
4 bytes from 00:26:43:CC:B0:FB id 2 time 36.07ms
4 bytes from 00:26:43:CC:B0:FB id 3 time 36.10ms
4 bytes from 00:26:43:CC:B0:FB id 4 time 34.82ms

When I move the script elsewhere and test again, it shows an error in syslog that the script couldn't be found:

Feb 12 20:40:36 retropie systemd-udevd[1579]: failed to execute '/home/pi/btslave.sh' '/home/pi/btslave.sh': No such file or directory
Feb 12 20:40:36 retropie systemd-udevd[1577]: Process '/home/pi/btslave.sh' failed with exit code 2.
Feb 12 20:40:36 retropie systemd-udevd[1591]: failed to execute '/home/pi/btslave.sh' '/home/pi/btslave.sh': No such file or directory
Feb 12 20:40:36 retropie systemd-udevd[1574]: Process '/home/pi/btslave.sh' failed with exit code 2.
Feb 12 20:40:36 retropie systemd-udevd[1592]: failed to execute '/home/pi/btslave.sh' '/home/pi/btslave.sh': No such file or directory
Feb 12 20:40:36 retropie systemd-udevd[1577]: Process '/home/pi/btslave.sh' failed with exit code 2.

So that tells me that the event does seem to fire. It's just... not actually doing it. I scoured Google for a while and went nowhere. Am I missing something here or is there an easier way to go about this?

Thank you.


Solution

  • So, a few hours later and I managed to figure it out after a whole lot of debugging (and some ideas from a reddit post). Apparently udev is fired way too early in the sequence and no amount of 'waiting' would actually be able to retrieve the controller's address. It needed to fire much later.

    So, I removed the udev rule and opted to just edit /usr/bin/sixaxis-helper.sh:

    Added

    hcitool sr "$SIXAXIS_MAC" slave
    

    after

    sixaxis_calibrate
    

    (way at the bottom) It's ugly but it works. :) Controller immediately pairs to 'slave' mode and latency is all sexy-like.

    Leaving it here for those who wish to implement the same solution. For now, I'm happy and can move on. Maybe I'll revisit later on and try to improve upon it so it doesn't require me to edit an existing script (or someone else takes up the challenge).