diff --git a/gamepads/padconfig.sh b/gamepads/configload similarity index 93% rename from gamepads/padconfig.sh rename to gamepads/configload index 6a7da40..6f516f7 100755 --- a/gamepads/padconfig.sh +++ b/gamepads/configload @@ -19,12 +19,6 @@ was written for this script. DISCLAIMER -# script control variables - -FORCE=$1 -GAMEPAD="picadehat-default" - -# function define confirm() { if [ "$FORCE" == '-y' ]; then @@ -115,11 +109,13 @@ above this section for clarity, thanks! MAINSTART -# copying gamepad configuration file +if [ "$#" -eq 0 ]; then + warning "a pad config is required as argument" && exit 1 +fi sudo service picadehatd stop -sudo rm /usr/bin/picadehatd -sudo cp $GAMEPAD /usr/bin/picadehatd +sudo rm /usr/bin/picadehatd &> /dev/null +sudo cp "$1" /usr/bin/picadehatd sudo chmod +x /usr/bin/picadehatd sudo service picadehatd start diff --git a/gamepads/pigrrl-default b/gamepads/pigrrl-default index 33db152..5edc33c 100644 --- a/gamepads/pigrrl-default +++ b/gamepads/pigrrl-default @@ -3,6 +3,7 @@ # Adafruit PiGRRL PCB default configuration # maps buttons to GPIO for connection to PiTFT # or mounting back to back to a Raspberry Pi Zero +# soft shutdown is not supported import time import signal diff --git a/gamepads/pigrrl-shutdown b/gamepads/pigrrl-shutdown new file mode 100644 index 0000000..f5b52aa --- /dev/null +++ b/gamepads/pigrrl-shutdown @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +# Adafruit PiGRRL PCB alternative configuration +# maps buttons to GPIO for connection to PiTFT +# or mounting back to back to a Raspberry Pi Zero +# soft shutdown is supported through L bumper + +import time +import signal +import os +import sys +from datetime import datetime +from threading import Timer + +try: + from evdev import uinput, UInput, ecodes as e +except ImportError: + exit("This library requires the evdev module\nInstall with: sudo pip install evdev") + +try: + import RPi.GPIO as gpio +except ImportError: + exit("This library requires the RPi.GPIO module\nInstall with: sudo pip install RPi.GPIO") + + +#time.sleep(30) + +os.system("sudo modprobe uinput") + +DEBUG = False + +PIDFILE = "/var/run/picadehatd.pid" +LOGFILE = "/var/log/picadehatd.log" + +BOUNCE_TIME = 0.01 # Debounce time in seconds +SHUTDOWN_HOLD_TIME = 3 # Time in seconds that power button must be held + +SHUTDOWN = 4 +BUTTON_POWER = 12 + +UP = 16 +DOWN = 26 +LEFT = 4 +RIGHT = 19 + +BUTTON1 = 14 +BUTTON2 = 15 +BUTTON3 = 20 +BUTTON4 = 18 + +ENTER = 5 +START= 6 + +BUTTONS = [ENTER,START,BUTTON1,BUTTON2,BUTTON3,BUTTON4,UP,DOWN,LEFT,RIGHT] + +KEYS = { + ENTER: e.KEY_ENTER, + START: e.KEY_S, + UP: e.KEY_UP, + DOWN: e.KEY_DOWN, + LEFT: e.KEY_LEFT, + RIGHT: e.KEY_RIGHT, + BUTTON1: e.KEY_LEFTCTRL, + BUTTON2: e.KEY_LEFTALT, + BUTTON3: e.KEY_SPACE, + BUTTON4: e.KEY_LEFTSHIFT, +} + +states = [False for b in BUTTONS] + +shutdown_timer = None + +try: + pid = os.fork() + if pid > 0: + sys.exit(0) + +except OSError, e: + print("Fork #1 failed: {} ({})".format(e.errno, e.strerror)) + sys.exit(1) + +os.chdir("/") +os.setsid() +os.umask(0) + +try: + pid = os.fork() + if pid > 0: + fpid = open(PIDFILE, 'w') + fpid.write(str(pid)) + fpid.close() + sys.exit(0) +except OSError, e: + print("Fork #2 failed: {} ({})".format(e.errno, e.strerror)) + sys.exit(1) + +si = file("/dev/null", 'r') +so = file(LOGFILE, 'a+') +se = file("/dev/null", 'a+', 0) + +os.dup2(si.fileno(), sys.stdin.fileno()) +os.dup2(so.fileno(), sys.stdout.fileno()) +os.dup2(se.fileno(), sys.stderr.fileno()) + +gpio.setmode(gpio.BCM) +gpio.setwarnings(False) +gpio.setup(BUTTONS, gpio.IN, pull_up_down=gpio.PUD_UP) +gpio.setup(BUTTON_POWER, gpio.IN, pull_up_down=gpio.PUD_UP) + +try: + ui = UInput({e.EV_KEY: KEYS.values()}, name="PiGRRL-PCB", bustype=e.BUS_USB) + +except uinput.UInputError as e: + sys.stdout.write(e.message) + sys.stdout.write("Have you tried running as root? sudo {}".format(sys.argv[0])) + sys.exit(0) + +def log(msg): + sys.stdout.write(str(datetime.now())) + sys.stdout.write(": ") + sys.stdout.write(msg) + sys.stdout.write("\n") + sys.stdout.flush() + +def handle_button(pin): + key = KEYS[pin] + time.sleep(BOUNCE_TIME) + state = 0 if gpio.input(pin) else 1 + ui.write(e.EV_KEY, key, state) + ui.syn() + if DEBUG: + log("Pin: {}, KeyCode: {}, Event: {}".format(pin, key, 'press' if state else 'release')) + +def perform_shutdown(): + log("Shutting down...") + os.system("sudo shutdown -h now") + +def handle_shutdown(pin): + global shutdown_timer + + time.sleep(BOUNCE_TIME) + state = 0 if gpio.input(pin) else 1 + + if DEBUG: + log("Power button: {}".format('pressed' if state else 'released')) + + if state and shutdown_timer is None: + shutdown_timer = Timer(SHUTDOWN_HOLD_TIME, perform_shutdown) + shutdown_timer.start() + + elif not state and shutdown_timer is not None: + shutdown_timer.cancel() + shutdown_timer = None + +for button in BUTTONS: + gpio.add_event_detect(button, gpio.BOTH, callback=handle_button, bouncetime=1) + +gpio.add_event_detect(BUTTON_POWER, gpio.BOTH, callback=handle_shutdown, bouncetime=1) + +log("Picade HAT daemon running...") + +try: + signal.pause() +except KeyboardInterrupt: + pass + +log("daemon shutting down...") + +ui.close()