def _execute_ioctl(file_handle: typing.TextIO, nsm_message: NsmMessage) -> None: """Send an NsmMessage to /dev/nsm trough ioctl.""" # Calculate the IOWR operation. Should always result in 3223325184. operation = IOC( IOC_READ|IOC_WRITE, NSM_IOCTL_MAGIC, NSM_IOCTL_NUMBER, ctypes.sizeof(NsmMessage) ) # Execute the ioctl call. fcntl.ioctl(file_handle, operation, nsm_message)
def EVIOCGNAME(length): return IOC(IOC_READ, ord('E'), 0x06, length)
def read(fh: int, cmd: IOCTL, data: bytes) -> None: """Helper function for IOCTLs that read data from the driver""" fcntl.ioctl(fh, IOC(IOC_READ, ord(DEVICE_CHARACTER), cmd, len(data)), data)
def write(fh: int, cmd: IOCTL, data: bytes) -> None: """Helper function for IOCTLs that write data to the driver""" fcntl.ioctl(fh, IOC(IOC_WRITE, ord(DEVICE_CHARACTER), cmd, len(data)), data)
def call(fh: int, cmd: IOCTL) -> None: """Helper for IOCTLs that call driver functions (no arguments)""" fcntl.ioctl(fh, IOC(IOC_NONE, ord(DEVICE_CHARACTER), cmd, 0))
import ctypes, fcntl from ioctl_opt import IOR, IOC, IOC_READ, IOC_WRITE class hidraw_devinfo(ctypes.Structure): _fields_ = [ ('bustype', ctypes.c_uint), ('vendor', ctypes.c_short), ('product', ctypes.c_short), ] HIDIOCGRAWINFO = IOR(ord('H'), 0x03, hidraw_devinfo) HIDIOCGRAWNAME = lambda length: IOC(IOC_READ, ord('H'), 0x04, length) def get_device_name(fd, length=1024): name = (ctypes.c_char * length)() actual_length = fcntl.ioctl(fd, HIDIOCGRAWNAME(length), name, True) if actual_length < 0: raise OSError(-actual_length) if name[actual_length - 1] == b'\x00': actual_length -= 1 return name[:actual_length] def get_device_id(fd, length=1024): device_id = hidraw_devinfo() actual_length = fcntl.ioctl(fd, HIDIOCGRAWINFO, device_id, True) if actual_length < 0: raise OSError(-actual_length)
import fcntl import os from ioctl_opt import IOC, IOC_READ, IOC_WRITE HIDIOCSFEATURE = lambda length: IOC(IOC_WRITE|IOC_READ, ord('H'), 0x06, length) HIDIOCGFEATURE = lambda length: IOC(IOC_WRITE|IOC_READ, ord('H'), 0x07, length) class HIDRaw(): """Searches for a Linux hidraw device with the specifed VID/PID, and allows to send/get feature reports.""" def __init__(self, vid=0, pid=0, devname=None): if devname is not None: self.devname = devname else: with os.scandir('/sys/class/hidraw') as devices: for entry in devices: with open('/sys/class/hidraw/{}/device/modalias'.format(entry.name), 'r') as modalias: if modalias.read().rstrip().endswith('v{:08X}p{:08X}'.format(vid, pid)): self.devname = '/dev/' + entry.name break else: raise IOError('No device found') self._device = open(self.devname, 'r+b', buffering=0) def _ioctl(self, request, arg): result = fcntl.ioctl(self._device, request, arg) if result < 0: raise IOError(result) def send_feature_report(self, report, report_num=0): length = len(report) + 1