Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Access joysticks/game controllers from Python in Linux via the joystick driver. See https://www.panda3d.org/forums/viewtopic.php?f=8&t=16767
# Released by rdb under the Unlicense (unlicense.org)
# Based on information from:
# https://www.kernel.org/doc/Documentation/input/joystick-api.txt
import os, struct, array
from fcntl import ioctl
# Iterate over the joystick devices.
print('Available devices:')
for fn in os.listdir('/dev/input'):
if fn.startswith('js'):
print(' /dev/input/%s' % (fn))
# We'll store the states here.
axis_states = {}
button_states = {}
# These constants were borrowed from linux/input.h
axis_names = {
0x00 : 'x',
0x01 : 'y',
0x02 : 'z',
0x03 : 'rx',
0x04 : 'ry',
0x05 : 'rz',
0x06 : 'trottle',
0x07 : 'rudder',
0x08 : 'wheel',
0x09 : 'gas',
0x0a : 'brake',
0x10 : 'hat0x',
0x11 : 'hat0y',
0x12 : 'hat1x',
0x13 : 'hat1y',
0x14 : 'hat2x',
0x15 : 'hat2y',
0x16 : 'hat3x',
0x17 : 'hat3y',
0x18 : 'pressure',
0x19 : 'distance',
0x1a : 'tilt_x',
0x1b : 'tilt_y',
0x1c : 'tool_width',
0x20 : 'volume',
0x28 : 'misc',
}
button_names = {
0x120 : 'trigger',
0x121 : 'thumb',
0x122 : 'thumb2',
0x123 : 'top',
0x124 : 'top2',
0x125 : 'pinkie',
0x126 : 'base',
0x127 : 'base2',
0x128 : 'base3',
0x129 : 'base4',
0x12a : 'base5',
0x12b : 'base6',
0x12f : 'dead',
0x130 : 'a',
0x131 : 'b',
0x132 : 'c',
0x133 : 'x',
0x134 : 'y',
0x135 : 'z',
0x136 : 'tl',
0x137 : 'tr',
0x138 : 'tl2',
0x139 : 'tr2',
0x13a : 'select',
0x13b : 'start',
0x13c : 'mode',
0x13d : 'thumbl',
0x13e : 'thumbr',
0x220 : 'dpad_up',
0x221 : 'dpad_down',
0x222 : 'dpad_left',
0x223 : 'dpad_right',
# XBox 360 controller uses these codes.
0x2c0 : 'dpad_left',
0x2c1 : 'dpad_right',
0x2c2 : 'dpad_up',
0x2c3 : 'dpad_down',
}
axis_map = []
button_map = []
# Open the joystick device.
fn = '/dev/input/js0'
print('Opening %s...' % fn)
jsdev = open(fn, 'rb')
# Get the device name.
#buf = bytearray(63)
buf = array.array('c', ['\0'] * 64)
ioctl(jsdev, 0x80006a13 + (0x10000 * len(buf)), buf) # JSIOCGNAME(len)
js_name = buf.tostring()
print('Device name: %s' % js_name)
# Get number of axes and buttons.
buf = array.array('B', [0])
ioctl(jsdev, 0x80016a11, buf) # JSIOCGAXES
num_axes = buf[0]
buf = array.array('B', [0])
ioctl(jsdev, 0x80016a12, buf) # JSIOCGBUTTONS
num_buttons = buf[0]
# Get the axis map.
buf = array.array('B', [0] * 0x40)
ioctl(jsdev, 0x80406a32, buf) # JSIOCGAXMAP
for axis in buf[:num_axes]:
axis_name = axis_names.get(axis, 'unknown(0x%02x)' % axis)
axis_map.append(axis_name)
axis_states[axis_name] = 0.0
# Get the button map.
buf = array.array('H', [0] * 200)
ioctl(jsdev, 0x80406a34, buf) # JSIOCGBTNMAP
for btn in buf[:num_buttons]:
btn_name = button_names.get(btn, 'unknown(0x%03x)' % btn)
button_map.append(btn_name)
button_states[btn_name] = 0
print '%d axes found: %s' % (num_axes, ', '.join(axis_map))
print '%d buttons found: %s' % (num_buttons, ', '.join(button_map))
# Main event loop
while True:
evbuf = jsdev.read(8)
if evbuf:
time, value, type, number = struct.unpack('IhBB', evbuf)
if type & 0x80:
print "(initial)",
if type & 0x01:
button = button_map[number]
if button:
button_states[button] = value
if value:
print "%s pressed" % (button)
else:
print "%s released" % (button)
if type & 0x02:
axis = axis_map[number]
if axis:
fvalue = value / 32767.0
axis_states[axis] = fvalue
print "%s: %.3f" % (axis, fvalue)
@kharlashkin

This comment has been minimized.

Copy link

commented Jul 8, 2015

Hi, I want to create a python script vibration feedback for game in Wine. Part of your code is now used to emulate keyboard and mouse together with xaut. Can you explain how you got these strings, for example:

buf = array.array('H', [0] * 200)
ioctl(jsdev, 0x80406a34, buf) # JSIOCGBTNMAP

I am a beginner in python and I do not understand a lot.

@rdb

This comment has been minimized.

Copy link
Owner Author

commented Aug 18, 2015

You mean 0x80406a34? I got it from linux/joystick.h:
http://lxr.free-electrons.com/source/include/uapi/linux/joystick.h#L70
The _IOR and _IOW macros are a bit cryptic. I think I just wrote a small C program to include the file and print out the values.

@kharlashkin

This comment has been minimized.

Copy link

commented Sep 2, 2015

Okey, thanks. I'm try send vibration to xbox 360 controller under Linux. Find this code (http://dev.pyra-handheld.com/index.php/p/pyra-kernel/source/tree/0fdef2cdc32aabfb9408e558be25f0298f97958c/GTA04/root/vibra.py), but on x64system code don't work - IOError: [Errno 14] Bad address.
If you make help for me, please help :)

@zdavidmm

This comment has been minimized.

Copy link

commented Sep 23, 2015

Is there a way to get the state of joystick at time intervals, rather than getting it every time the state of the joystick changes?

@rdb

This comment has been minimized.

Copy link
Owner Author

commented Dec 9, 2015

Sorry, it seems GitHub does not notify me of comments on my own gist.

@kharlashkin: I haven't attempted to use force-feedback features yet, so I cannot advise you on the matter, sorry.

@zdavidmm: When you first connect with open(), the API will give you the current state of all the buttons. You can use this to your advantage by opening the device, reading out all "initial state" events, and then closing it again.

@raszga

This comment has been minimized.

Copy link

commented Jan 18, 2018

Thanks for your work, but I would like to go thru the
evbuf = jsdev.read(8)
not necessarily to wait in this instruction until joystick has an event , not sure if possible or if I'm correct in my view.
In other words I would like to read the current state and continue not to wait for an event. (Something similar with pygame joystick)
Thanks ,CR

@raszga

This comment has been minimized.

Copy link

commented Jan 18, 2018

OK I see a response above, I will try,, thanks.

@unregistrierterBenutzer

This comment has been minimized.

Copy link

commented Mar 29, 2018

Hi!
I use the script for a rc car, controlled by a ps4 controller. How can I use key combinations?

@PetNoire

This comment has been minimized.

Copy link

commented May 10, 2018

0x3b - 0x3e are for ps3 sixaxis but im not sure which is which

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.