RADU: Adding a Custom Remote Game Controller

Connecting a Controller

USB Cable

[  159.187707] usb 1-1.1.2: new full-speed USB device number 5 using dwc_otg
[ 159.320782] usb 1-1.1.2: New USB device found, idVendor=054c, idProduct=05c4, bcdDevice= 1.00
[ 159.320799] usb 1-1.1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 159.320808] usb 1-1.1.2: Product: Wireless Controller
[ 159.320818] usb 1-1.1.2: Manufacturer: Sony Computer Entertainment
[ 159.415449] input: Sony Computer Entertainment Wireless Controller Touchpad as /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.2/1-1.1.2:1.0/0003:054C:05C4.0001/input/input1
[ 159.415913] input: Sony Computer Entertainment Wireless Controller Motion Sensors as /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.2/1-1.1.2:1.0/0003:054C:05C4.0001/input/input2
[ 159.478061] input: Sony Computer Entertainment Wireless Controller as /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.2/1-1.1.2:1.0/0003:054C:05C4.0001/input/input0
[ 159.478481] Sony 0003:054C:05C4.0001: input,hidraw0: USB HID v81.11 Gamepad [Sony Computer Entertainment Wireless Controller] on usb-3f980000.usb-1.1.2/input0
jstest /dev/input/js0
Driver version is 2.1.0.
Joystick (Sony Computer Entertainment Wireless Controller) has 8 axes (X, Y, Z, Rx, Ry, Rz, Hat0X, Hat0Y)
and 13 buttons (BtnA, BtnB, BtnX, BtnY, BtnTL, BtnTR, BtnTL2, BtnTR2, BtnSelect, BtnStart, BtnMode, BtnThumbL, BtnThumbR).
Testing ... (interrupt to exit)
Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:of
Axes:  0:     0  1:     0  2:     0  3:     0  4:     0  5:     0  6:     0  7:     0 Buttons:  0:off  1:on  2:off  3:off  4:on  5:off  6:of

Bluetooth Connection for a PS3 Pad

# wget http://www.pabr.org/sixlinux/sixpair.c
# gcc -o sixpair_connector sixpair.c -lusb
Current Bluetooth master: A0-25-73-A6-A8-E3
Setting master bd_addr to B2-F1-01-25-E9-49
hidd[8332]: Bluetooth HID daemon
hidd[8332]: New HID device AC-37-4A-E9-E8-50 (Sony Computer Entertainment Wireless Controller)

Raspberry Pi Built-in Programs

agent on
discoverable on
pairable on
default-agent
scan on
[NEW] Device AC-37-4A-E9-E8-50 Wireless Controller
connect PS4_PAD_MAC_ADDRESS
trust PS4_PAD_MAC_ADDRESS
[CHG] Device PS4_PAD_MAC_ADDRESS Connected: yes
[CHG] Device PS4_PAD_MAC_ADDRESS Paired: yes
Connection successful

Controller Software

Parsing raw HDI Input

import hidfor device in hid.enumerate():
print(f"0x{device['vendor_id']:04x}:0x{device['product_id']:04x} {device['product_string']}")
gamepad = hid.device()
gamepad.open(0x0f0d, 0x00c1)
gamepad.set_nonblocking(True)
while True:
report = gamepad.read(64)
if report:
print(report)
# No buttons pressed
[0, 0, 15, 128, 128, 128, 128, 0]
# A button pressed
[4, 0, 15, 128, 128, 128, 128, 0]

Python

import pygamepygame.init()if pygame.joystick.get_count() < 1:
print("No gamepad connected!","Exiting")
system.exit()
gamepad = pygame.joystick.Joystick(i)
gamepad.init()
print(f'Gamepad {gamepad.get_name()} detected')
for button in range(gamepad.get_numbuttons()):
print(button)
while True:
for event in pygame.event.get():
if event.type == pygame.JOYBUTTONDOW:
print(f'Gamepadd button {event.button} pressed')
from pyPS4Controller.controller import Controller
class MyController(Controller): def __init__(self, **kwargs):
Controller.__init__(self, **kwargs)
def on_x_press(self):
print("Hello world")
def on_x_release(self):
print("Goodbye world")
controller = MyController(interface="/dev/input/js0", connecting_using_ds4drv=False)
controller.listen(timeout=60)
import evdevdevice = evdev.InputDevice('/dev/input/event0')
print(device)
# device /dev/input/event0, name "Dell USB Optical Mouse", phys "usb-0000:00:12.0-2/input0"
device.capabilities()
# { 0: [0, 1, 2], 1: [272, 273, 274, 275], 2: [0, 1, 6, 8], 4: [4] }
device.capabilities(verbose=True)
# { ('EV_SYN', 0): [('SYN_REPORT', 0), ('SYN_CONFIG', 1), ('SYN_MT_REPORT', 2)],
# ('EV_KEY', 1): [('BTN_MOUSE', 272), ('BTN_RIGHT', 273), ('BTN_MIDDLE', 274), ('BTN_SIDE', 275)], ...
for event in device.read_loop():
if event.type == ecodes.EV_KEY:
print(categorize(event))
# key event at 1337016188.396030, 30 (KEY_A), down
# key event at 1337016188.492033, 30 (KEY_A), up
#!/usr/bin/env python
# coding: utf-8
# Load the gamepad and time libraries
import Gamepad
import time
gamepadType = Gamepad.PS4
buttonHappy = 'CROSS'
buttonBeep = 'CIRCLE'
buttonExit = 'PS'
joystickSpeed = 'LEFT-Y'
joystickSteering = 'RIGHT-X'
pollInterval = 0.1
if not Gamepad.available():
print('Please connect your gamepad...')
while not Gamepad.available():
time.sleep(1.0)
gamepad = gamepadType()
print('Gamepad connected')
# Set some initial state
speed = 0.0
steering = 0.0
# Start the background updating
gamepad.startBackgroundUpdates()
try:
while gamepad.isConnected():
if gamepad.beenPressed(buttonExit):
print('EXIT')
break
if gamepad.beenPressed(buttonHappy):
print(':)')
if gamepad.beenReleased(buttonHappy):
print(':(')
if gamepad.isPressed(buttonBeep):
print('BEEP')
speed = -gamepad.axis(joystickSpeed)
steering = gamepad.axis(joystickSteering)
print('%+.1f %% speed, %+.1f %% steering' % (speed * 100, steering * 100))
time.sleep(pollInterval)
finally:
gamepad.disconnect()

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Sebastian

Sebastian

IT Project Manager & Developer