blob: a053a24f90a42539bb32cdcfb622f868dbf0bbb4 [file] [log] [blame]
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""This module includes the python hidraw libray
The hidraw interface is a straight forward translation of linux hidraw c
interface. Running this file directly, it will print all the hidraw device.
"""
from __future__ import print_function
import array
import ctypes
import fcntl
import glob
from input.linux_ioctl import IOC, IOC_READ, IOC_WRITE
HID_MAX_DESCRIPTOR_SIZE = 4096
class HIDRawReportDescriptor(ctypes.Structure):
"""A class for linux hidraw_report_descriptor
struct hidraw_report_descriptor {
__u32 size;
__u8 value[HID_MAX_DESCRIPTOR_SIZE];
}
"""
_fields_ = [
('size', ctypes.c_uint),
('value', ctypes.c_ubyte * HID_MAX_DESCRIPTOR_SIZE),
]
class HIDRawDevInfo(ctypes.Structure):
"""A class for linux hidraw_devinfo
struct hidraw_devinfo {
__u32 bustype;
__s16 vendor;
__s16 product;
}
"""
_fields_ = [
('bustype', ctypes.c_uint),
('vendor', ctypes.c_ushort),
('product', ctypes.c_ushort),
]
# The following code are from hidraw.h
HIDIOCGRDESCSIZE = IOC(IOC_READ, 'H', 0x01, ctypes.sizeof(ctypes.c_uint))
HIDIOCGRDESC = IOC(IOC_READ, 'H', 0x02,
ctypes.sizeof(HIDRawReportDescriptor))
HIDIOCGRAWINFO = IOC(IOC_READ, 'H', 0x03, ctypes.sizeof(HIDRawDevInfo))
def HIDIOCGRAWNAME(length):
return IOC(IOC_READ, 'H', 0x04, length)
def HIDIOCGRAWPHYS(length):
return IOC(IOC_READ, 'H', 0x05, length)
def HIDIOCSFEATURE(length):
return IOC(IOC_READ | IOC_WRITE, 'H', 0x06, length)
def HIDIOCGFEATURE(length):
return IOC(IOC_READ | IOC_WRITE, 'H', 0x07, length)
HIDRAW_FIRST_MINOR = 0
HIDRAW_MAX_DEVICES = 64
HIDRAW_BUFFER_SIZE = 64
class HIDRaw(object):
"""A class used to access hidraw interface."""
def __init__(self, path):
self.path = path
self.f = open(path, 'rb+', buffering=0)
self._ioctl_raw_report_descritpor()
self._ioctl_info()
self._ioctl_name()
self._ioctl_physical_addr()
def __exit__(self, *_):
if self.f and not self.f.closed:
self.f.close()
def send_feature_report(self, report_buffer):
fcntl.ioctl(self.f, HIDIOCSFEATURE(len(report_buffer)), report_buffer, 1)
def get_feature_report(self, report_num, length):
report_buffer = array.array('B', [0] * length)
report_buffer[0] = report_num
fcntl.ioctl(self.f, HIDIOCGFEATURE(length), report_buffer, 1)
return buffer
def read(self, size):
return self.f.read(size)
def _ioctl_raw_report_descritpor(self):
"""Queries device file for the report descriptor"""
descriptor_size = ctypes.c_uint()
fcntl.ioctl(self.f, HIDIOCGRDESCSIZE, descriptor_size, 1)
self.descriptor = HIDRawReportDescriptor()
self.descriptor.size = descriptor_size
fcntl.ioctl(self.f, HIDIOCGRDESC, self.descriptor, 1)
def _ioctl_info(self):
"""Queries device file for the dev info"""
self.devinfo = HIDRawDevInfo()
fcntl.ioctl(self.f, HIDIOCGRAWINFO, self.devinfo, 1)
def _ioctl_name(self):
"""Queries device file for the dev name"""
name_len = 255
name = array.array('B', [0] * name_len)
name_len = fcntl.ioctl(self.f, HIDIOCGRAWNAME(name_len), name, 1)
self.name = name[0:name_len-1].tostring()
def _ioctl_physical_addr(self):
"""Queries device file for the dev physical addr"""
addr_len = 255
addr = array.array('B', [0] * addr_len)
addr_len = fcntl.ioctl(self.f, HIDIOCGRAWPHYS(addr_len), addr, 1)
self.physic_addr = addr[0:addr_len-1].tostring()
def main():
"""Function to interactively select a hidraw device"""
for path in glob.glob('/dev/hidraw*'):
hid = HIDRaw(path)
print('Device at:', path)
print(' ', hid.physic_addr, ':', hid.name)
print(' ', "Vendor:", hex(hid.devinfo.vendor))
print(' ', 'Product:', hex(hid.devinfo.product))
if __name__ == '__main__':
main()