linuxbashshellgamepad

Handling gamepad button clicks in tty, in Linux


I have a Linux device with an EmulationStation on board (keyboard is connected to it via USB). I want to process gamepad keystrokes in the terminal so that I don't have to plug in a keyboard for that.

Test script to detect gamepad key codes:

#!/bin/bash

echo 'Press button "L1":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "L1":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "L2":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "L2":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "Up":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "Up":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "Down":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "Down":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "Left":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "Left":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "Right":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "Right":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "Select":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "Select":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "L3":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "L3":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "Start":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "Start":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "X":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "X":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "Y":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "Y":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "B":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "B":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "A":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "A":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "R3":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "R3":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "R2":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "R2":' >> keycode.txt
echo "$key" >> keycode.txt

echo 'Press button "R1":'
key=`jstest --event /dev/input/js0 | grep -m 1 "type 1, time .*, number .*, value 1" | awk -F ',' '{print $3}' | awk '{print $2}'`
echo 'Button "R1":' >> keycode.txt
echo "$key" >> keycode.txt

When you connect via SSH or quit EmulationStation and start tty, the script works correctly, when you press a gamepad key, the key code is detected, it is written to the file successfully, and the process completes.

Problems begin if the script is run directly from the EmulationStation, apparently jstest --event /dev/input/js0 is looping.

The process of running the script from the EmulationStation looks like this:

Press button "L1":

The script doesn't respond to gamepad key presses, or we don't see it. At the same time, the gamepad is connected, and using the second script we can see the difference from the keystrokes:

#!/bin/bash

jstest --event /dev/input/js0

Output of the second script:

Event: type 1, time -195236, number 9, value 1
Event: type 1, time -195128, number 9, value 0
Event: type 1, time -194840, number 8, value 1
Event: type 1, time -194744, number 8, value 0
Event: type 1, time -194492, number 10, value 1
Event: type 1, time -194360, number 10, value 0
Event: type 1, time -194096, number 9, value 1
Event: type 1, time -194096, number 11, value 1
Event: type 1, time -194000, number 9, value 0
Event: type 1, time -193988, number 11, value 0

Apparently, the problem has something to do with the fact that the loop runs indefinitely, and using grep -m 1 "type 1, time .*, number .*, value 1" does not end it.

When the script does not work, ps aux shows the following processes:

user        635  0.0  0.0   2048   508 ?        S    03:58   0:00 sh -c sudo chmod 666 /dev/tty1; /opt/system/Scripts/Keycode.sh > /dev/tty1; printf "\033c" >> /dev/tty1
user        645  0.0  0.3   6464  2916 ?        S    03:58   0:00 /bin/bash /opt/system/Scripts/Keycode.sh
user        646  0.0  0.1   6464  1572 ?        S    03:58   0:00 /bin/bash /opt/system/Scripts/Keycode.sh
user        647  0.0  0.0   1924   464 ?        S    03:58   0:00 jstest --event /dev/input/js0
user        651  0.0  0.2   8416  2728 pts/0    R+   03:59   0:00 ps aux

I want to run a script from the EmulationStation so that it reacts to gamepad button presses. If there is some other way to do this without using the GUI, please write it.


Solution

  • I solved the problem with gamepad input in the terminal by using this perl module.