USB Panic Button with Linux and Python

This article describes how to use a USB Panic Button with Python. The panic button is a pushbutton that can be read over USB. Unfortunately, it only comes with drivers for Windows, so using it with Linux is a bit of a challenge. I found a Perl library that can read the Panic Button using low-level USB operations, so I ported that simple library to Python.

First, download and install PyUSB. (You may also need to install python-devel.)

Next, dowwnload my PanicButton library.

Finally, use the library. The API is very simple: create a button object with PanicButton(), and then call read() on the button to see if the button is pressed. For example, the following code will print "Pressed" when the button is pressed. (I know, a button like this should be more dramatic...)

import PanicButton
import time

button = PanicButton.PanicButton()

while 1:
  if button.read():
    print "Pressed"
  time.sleep(.5)
A couple caveats. First, you need to run the Python code as root in order to access the device. (Maybe you can get around this with udev magic, but I couldn't.) Second, the button actually triggers when it is released, not when it is pressed.

How the library works

By running lsusb, you can see that the Panic Button's USB id is 1130:0202. We use the PyUSB library to get a device object:
class PanicButton:
  def __init__(self):
    # Device is: ID 1130:0202 Tenx Technology, Inc. 
    self.dev = usb.core.find(idVendor=0x1130, idProduct=0x0202)
The Linux kernel grabs the device and makes it into a hidraw device, so we need to detach that kernel driver before using the device:
    try:
      self.dev.detach_kernel_driver(0)
    except Exception, e:
      pass # already unregistered
Reading the status of the device is done through a USB control transfer. All the magic numbers come from the PanicButton Perl library. See details (translated from German).
  def read(self):
    return self.dev.ctrl_transfer(bmRequestType=0xA1, bRequest=1, wValue=0x300, data_or_wLength=8, timeout=500)[0]
Hopefully this will be of help to anyone trying to interface the USB Panic Button through Python.

2 comments:

Unknown said...

thank you! you're syntax on how to call the detach_ was what I was missing. got my own project working straight afterwards :)

Anonymous said...

It may be years later but this was exactly what I was looking for. Thank You.