Python script stops working on new started applications (python-evdev)

258 views Asked by At

I have been scratching my head for a couple of weeks now, I'm not well diversed in Linux so it's certanly something easy I've overlooked.

In my system I got an arduino that sends data via I2C to my RaspberryPi. The PI looks at the data and then should simulate button presses in the system. I'm using a python script and evdev to acomplish this. The system first boots in Attract Mode (an game emulator front end) and from there boots the desired emulator + game.

I first start the python script in rc.local with sudo python myscript.py & and that makes it run. It can read the I2C without any problems but the evdev thingy aint working as expected.

The raspberry pi doesnt have an keyboard plugged. In my first tests I had an keyboard plugged in for testing purposes and everything worked fine, python-evdev sent button presses that was recongnized both in Attract Mode and then in the launched emulator. Great! I thought...

This was the working code: `

#!/usr/bin/env python
# -*- coding: utf-8 -*-

#DECLARATIONS
import smbus
import time
import subprocess
import alsaaudio

from evdev import UInput, ecodes as e

ui = UInput()

debug = True

bus = smbus.SMBus(1)
address = 0x18

keys =  [
 e.KEY_ESC,
 e.KEY_0,
 e.KEY_ENTER,
 e.KEY_LEFT,
 e.KEY_UP,
 e.KEY_RIGHT,
 e.KEY_DOWN,
 e.KEY_1,
 e.KEY_2,
 e.KEY_3,
 e.KEY_4,
 e.KEY_5,
 e.KEY_6]

state = []
oldState = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

backHold = False
backTime = 0

#FUNCTIONS
def readController():
 global state
 global oldState
 try:
  state = bus.read_i2c_block_data(address,0,15)
  backBtn(state[0])
  if oldState != state:
   DEBUG(state)
   return True
 except IOError:
  subprocess.call(["i2cdetect","-y","1"])
 return False

def updateButtons():
 i = 0
 global state
 global oldState
 while(i < len(state)):
  if state[i] != oldState[i] and state[i] == 0 or state[i] == 1:
   DEBUG("Button State: " + str(state[i]))
   oldState[i] = state[i]
   if i < 13 and i > 0:
    UInput(i,state[i])
   if i >= 13:
    volumeControl(i,state[i])
  i = i+1
 return

def UInput(btn,state):
 ui.write(e.EV_KEY,keys[btn],state)
 ui.syn()
 DEBUG("Button Pressed: " + str(keys[btn]))
 return 

def volumeControl(btn,state):
 m = alsaaudio.Mixer("PCM")
 vol = m.getvolume()
 vol = int(vol[0])
 DEBUG("Current Volume: " + str(vol))
 if state == 1:
  if btn == 13:
   #INCREASE
   newVol = vol + 5
   if newVol > 100:
    newVol = 100
  else:
   #DECREASE
   newVol = vol - 5
   if newVol < 0:
    newVol = 0
  DEBUG("New Volume: " + str(newVol))
  m.setvolume(newVol)
 return

def backBtn(state):
 global backHold
 global backTime
 if state == 1:
  backHold = True
 else:
  backHold = False
  backTime = 0
  UInput(0,0)
 if backHold:
  backTime = backTime + 1
  DEBUG ("Holding ESC Time: " + str(backTime))
  if backTime == 50:
   backTime = 0
   UInput(0,1)

def DEBUG(msg):
 if debug:
  print msg

#MAIN LOOP

    while True:

 if readController():
  updateButtons()
 time.sleep(0.10)

`

I then shut down the system and unplugged the keyboard and started up the system again and now my problem starts; without the keyboard plugged in both Attract Mode and started emulators wont recognize any button presses anymore. So I tried to do what was described here: http://python-evdev.readthedocs.io/en/latest/tutorial.html#specifying-uinput-device-options

and got somewhat a diffrent result.

Now my buttons works great in Attract Mode but stops working as soon as I start up an emulator. But if I rerun my script after an emulator has started the button works there aswell.

this is my change in the code:

cap = {e.EV_KEY : [ 
 e.KEY_ESC,
 e.KEY_0,
 e.KEY_ENTER,
 e.KEY_LEFT,
 e.KEY_UP,
 e.KEY_RIGHT,
 e.KEY_DOWN,
 e.KEY_1,
 e.KEY_2,
 e.KEY_3,
 e.KEY_4,
 e.KEY_5,
 e.KEY_6]
}

ui = UInput(cap, name='ArcadeController', version=0x1)

I dont really know how to fix this, if I overlooked something or is missing something.

I've tried: http://python-evdev.readthedocs.io/en/latest/tutorial.html#create-uinput-device-with-capabilities-of-another-device And tried to start my script as a service in init.d. I monitored keyboard presses so I saw that my script was running when an emulator started.

EDIT:

If I run cat /proc/bus/input/devices when I'm using the second version of the script (the one thats working in Attract Mode but not in started emulator unless I run the script again), this is what I get:

I: Bus=0003 Vendor=0001 Product=0001 Version=0001
N: Name="ArcadeController"
P: Phys=
S: Sysfs=/devices/virtual/input/input1
U: Uniq=
H: Handlers=kbd event1
B: PROP=0
B: EV=3
B: KEY=1680 0 0 100008fe

And I can see with cat /dev/input/event1 that it is recieving my inputs.

and if I run the first version that only works when I got an external keyboard in this is what I get:

I: Bus=0003 Vendor=0001 Product=0001 Version=0001
N: Name="py-evdev-uinput"
P: Phys=
S: Sysfs=/devices/virtual/input/input3
U: Uniq=
H: Handlers=sysrq kbd event3 rfkill
B: PROP=0
B: EV=3
B: KEY=ff ffffffff 0 0 3f 3007f 1000f 7fff0fff 7fe001f ffff000f 7ffffff ffffffff ffffffff 3fdff 7fff8fff ff03ff 1ffffff ffffff07 ffffffff ffffffff ffffffff ffefffff ffffffff fffffffe

and if I run the same version without the external keyboard:

I: Bus=0003 Vendor=0001 Product=0001 Version=0001
N: Name="py-evdev-uinput"
P: Phys=
S: Sysfs=/devices/virtual/input/input1
U: Uniq=
H: Handlers=sysrq kbd event1 rfkill
B: PROP=0
B: EV=3
B: KEY=ff ffffffff 0 0 3f 3007f 1000f 7fff0fff 7fe001f ffff000f 7ffffff ffffffff ffffffff 3fdff 7fff8fff ff03ff 1ffffff ffffff07 ffffffff ffffffff ffffffff ffefffff ffffffff fffffffe
0

There are 0 answers