#!/usr/bin/python
import struct, array, fcntl
class struxx:
_fields = None
_format = None
_buffer = None
def __init__(self):
self.reset()
def __len__(self):
"""binary represntation length, for fields, use __dict__ or something"""
return struct.calcsize(self._format)
def __iter__(self):
return [getattr(self, field) for field in self._fields.split(";")].__iter__()
def reset(self):
for field in self._fields.split(";"):
setattr(self, field, 0)
self._buffer = array.array('B', [0]*len(self))
def pack(self):
self._buffer = array.array('B', struct.pack(self._format, *self))
def unpack(self):
rv = struct.unpack(self._format, self._buffer)
for i in range(len(rv)):
setattr(self, self._fields.split(";")[i], rv[i])
def ioctl(self, fd, ioctlno):
self.pack()
rv = fcntl.ioctl(fd, ioctlno, self._buffer, True)
self.unpack()
return rv
class uint(struxx):
_fields = "uint"
_format = "I"
def get_version(self, fd): return self.ioctl(fd, HIDIOCGVERSION)
def get_flags(self, fd): return self.ioctl(fd, HIDIOCGFLAG)
def set_flags(self, fd): return self.ioctl(fd, HIDIOCSFLAG)
class hiddev_devinfo(struxx):
_fields = "bustype;busnum;devnum;ifnum;vendor;product;version;num_applications"
_format = "IIIIhhhI"
def get(self, fd): return self.ioctl(fd, HIDIOCGDEVINFO)
class hiddev_string_descriptor(struxx):
_fields = "index;value"
_format = "i256c"
def reset(self):
self.index = 0
self.value = '\0'*256
def pack(self):
tmp = struct.pack("i", self.index) + self.value[:256].ljust(256, '\0')
self._buffer = array.array('B', tmp)
def unpack(self):
self.index = struct.unpack("i", self._buffer[:4])
self.value = self._buffer[4:].tostring()
def get_string(self, fd, idx):
self.index = idx
return self.ioctl(fd, HIDIOCGSTRING)
class hiddev_report_info(struxx):
_fields = "report_type;report_id;num_fields"
_format = "III"
def get_info(self, fd): return self.ioctl(fd, HIDIOCGREPORTINFO)
class hiddev_field_info(struxx):
_fields = "report_type;report_id;field_index;maxusage;flags;physical;logical;application;logical_minimum;logical_maximum;physical_minimum;physical_maximum;unit_exponent;unit"
_format = "I"*8+"i"*4+"II"
def get_info(self, fd): return self.ioctl(fd, HIDIOCGFIELDINFO)
class hiddev_usage_ref(struxx):
_fields = "report_type;report_id;field_index;usage_index;usage_code;value"
_format = "I"*5+"i"
class hiddev_collection_info(struxx):
_fields = "index;type;usage;level"
_format = "I"*4
def get_info(self, fd, index):
self.index = index
return self.ioctl(fd, HIDIOCGCOLLECTIONINFO)
class hiddev_event(struxx):
_fields = "hid;value"
_format = "Hi"
IOCPARM_MASK = 0x7f
IOC_NONE = 0x20000000
IOC_WRITE = 0x40000000
IOC_READ = 0x80000000
def FIX(x): return struct.unpack("i", struct.pack("I", x))[0]
def _IO(x,y): return FIX(IOC_NONE|(ord(x)<<8)|y)
def _IOR(x,y,t): return FIX(IOC_READ|((t&IOCPARM_MASK)<<16)|(ord(x)<<8)|y)
def _IOW(x,y,t): return FIX(IOC_WRITE|((t&IOCPARM_MASK)<<16)|(ord(x)<<8)|y)
def _IOWR(x,y,t): return FIX(IOC_READ|IOC_WRITE|((t&IOCPARM_MASK)<<16)|(ord(x)<<8)|y)
HIDIOCGVERSION =_IOR('H', 0x01, struct.calcsize("I"))
HIDIOCAPPLICATION =_IO('H', 0x02)
HIDIOCGDEVINFO =_IOR('H', 0x03, len(hiddev_devinfo()))
HIDIOCGSTRING =_IOR('H', 0x04, len(hiddev_string_descriptor()))
HIDIOCINITREPORT =_IO('H', 0x05)
def HIDIOCGNAME(buflen): return _IOR('H', 0x06, buflen)
HIDIOCGREPORT =_IOW('H', 0x07, len(hiddev_report_info()))
HIDIOCSREPORT =_IOW('H', 0x08, len(hiddev_report_info()))
HIDIOCGREPORTINFO =_IOWR('H', 0x09, len(hiddev_report_info()))
HIDIOCGFIELDINFO =_IOWR('H', 0x0A, len(hiddev_field_info()))
HIDIOCGUSAGE =_IOWR('H', 0x0B, len(hiddev_usage_ref()))
HIDIOCSUSAGE =_IOW('H', 0x0C, len(hiddev_usage_ref()))
HIDIOCGUCODE =_IOWR('H', 0x0D, len(hiddev_usage_ref()))
HIDIOCGFLAG =_IOR('H', 0x0E, struct.calcsize("I"))
HIDIOCSFLAG =_IOW('H', 0x0F, struct.calcsize("I"))
HIDIOCGCOLLECTIONINDEX =_IOW('H', 0x10, len(hiddev_usage_ref()))
HIDIOCGCOLLECTIONINFO =_IOWR('H', 0x11, len(hiddev_collection_info()))
def HIDIOCGPHYS(buflen): return _IOR('H', 0x12, buflen)
HID_REPORT_TYPE_INPUT =1
HID_REPORT_TYPE_OUTPUT =2
HID_REPORT_TYPE_FEATURE =3
HID_REPORT_TYPE_MIN =1
HID_REPORT_TYPE_MAX =3
HID_REPORT_ID_UNKNOWN =0xffffffff
HID_REPORT_ID_FIRST =0x00000100
HID_REPORT_ID_NEXT =0x00000200
HID_REPORT_ID_MASK =0x000000ff
HID_REPORT_ID_MAX =0x000000ff
def enum_reports(fd):
for report_type in (HID_REPORT_TYPE_INPUT,
HID_REPORT_TYPE_OUTPUT,
HID_REPORT_TYPE_FEATURE):
for i in range(HID_REPORT_ID_MAX+1):
try:
ri = hiddev_report_info()
ri.report_type = report_type
ri.report_id = i
#print "trying", ri.__dict__
ri.get_info(fd)
print "%s(%s): %s fields" % ({1: 'input', 2:'output', 3:'feature'}.get(ri.report_type), ri.report_id, ri.num_fields)
for field in range(ri.num_fields):
fi = hiddev_field_info()
fi.report_type = ri.report_type
fi.report_id = ri.report_id
fi.field_index = field
fi.get_info(fd)
print ", ".join(["%s:%s" % (key, fi.__dict__[key]) for key in fi.__dict__ if key not in ("report_type", "report_id", "_buffer") and fi.__dict__[key] ])
#print report_info.__dict__
print
except IOError:
pass
if __name__=="__main__":
# name = ""
# for name in globals():
# if name.startswith("HID"):
# if type(globals()[name]) == int:
# print name, "\t%x" % globals()[name]
f = open("/dev/usb/hiddev0", "r")
tmp = uint()
tmp.get_version(f)
print "version 0x%x" % tmp.uint
tmp.get_flags(f)
print "flags 0x%x" % tmp.uint
tmp.uint = 3
tmp.set_flags(f)
tmp.get_flags(f)
print "flags 0x%x" % tmp.uint
devinfo = hiddev_devinfo()
devinfo.get(f)
print "devinfo", devinfo.__dict__
enum_reports(f)
def get_device_name(f):
a = array.array('B', [0]*1024)
fcntl.ioctl(f, HIDIOCGNAME(1024), a, True)
print a
def get_some_strings(f):
for i in range(-10000, 10000):
try:
string = hiddev_string_descriptor()
string.get_string(f, i)
print "string %s: %s", string.index, repr(string.value)
except IOError:
pass
def show_all_collections(f):
for i in range(256):
try:
collection_info = hiddev_collection_info()
collection_info.get_info(f, i)
print "coll %s" % i, collection_info.__dict__
print """
idnex: %(index)s
type: %(type)s
level: %(level)s
usage: 0x%(usage)x""" % collection_info.__dict__
except IOError:
pass