summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipe Laíns <lains@archlinux.org>2020-08-07 02:43:26 +0100
committerFilipe Laíns <lains@archlinux.org>2020-08-07 02:45:39 +0100
commite472e588cd027f3058e5663fc8aedf22a01a20e3 (patch)
treecf2261602f9679b4117b07a2aee16ac8c7ecf477
parentac1fe9bc1a63def16f743693fb237301b3b0c349 (diff)
hidraw: add initial hidraw ioctl(s)
Signed-off-by: Filipe Laíns <lains@archlinux.org>
-rw-r--r--ioctl/hidraw.py118
1 files changed, 118 insertions, 0 deletions
diff --git a/ioctl/hidraw.py b/ioctl/hidraw.py
new file mode 100644
index 0000000..13b476c
--- /dev/null
+++ b/ioctl/hidraw.py
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: MIT
+
+import array
+import ctypes
+import fcntl
+import os
+
+from typing import BinaryIO, List, Tuple
+
+import ioctl
+
+
+class HidrawReportDescriptor(ctypes.Structure):
+ HID_MAX_DESCRIPTOR_SIZE = 4096
+ _fields_ = [
+ ('size', ctypes.c_uint),
+ ('value', ctypes.c_ubyte * HID_MAX_DESCRIPTOR_SIZE),
+ ]
+
+
+class HidrawDevinfo(ctypes.Structure):
+ _fields_ = [
+ ('bustype', ctypes.c_uint),
+ ('vendor', ctypes.c_ushort),
+ ('product', ctypes.c_ushort),
+ ]
+
+
+class Hidraw(object):
+ '''
+ Represents a hidraw node
+
+ See linux/hidraw.h
+ '''
+ HIDIOCGRDESCSIZE = 0x01
+ HIDIOCGRDESC = 0x02
+ HIDIOCGRAWINFO = 0x03
+ HIDIOCGRAWNAME = 0x04
+ HIDIOCGRAWPHYS = 0x05
+ HIDIOCSFEATURE = 0x06
+ HIDIOCGFEATURE = 0x07
+
+ HID_NAME_SIZE = 1024
+
+ def __init__(self, path: str) -> None:
+ self._path = path
+ self._fd = open(path, 'rb+')
+ fcntl.fcntl(self._fd, fcntl.F_SETFL, os.O_NONBLOCK)
+
+ def __str__(self) -> str:
+ return f'Hidraw({self.path})'
+
+ @property
+ def path(self) -> str:
+ '''
+ Node path
+ '''
+ return self._path
+
+ @property
+ def fd(self) -> BinaryIO:
+ '''
+ Node file descriptor
+ '''
+ return self._fd
+
+ @property
+ def report_descriptor_size(self) -> int:
+ '''
+ Size of the report descriptor of the hidraw node
+ '''
+ return ctypes.c_uint.from_buffer(
+ ioctl.IOCTL.IOR(
+ 'H', self.HIDIOCGRDESCSIZE, ctypes.sizeof(ctypes.c_uint)
+ ).perform(self._fd)
+ ).value
+
+ @property
+ def report_descriptor(self) -> List[int]:
+ '''
+ Report descriptor of the hidraw node
+ '''
+ # fcntl.ioctl does not support such big buffer sizes when using the default buffer so we need to provide our own buffer
+ buf = array.array(
+ 'B', self.report_descriptor_size.to_bytes(4, 'little') +
+ HidrawReportDescriptor.HID_MAX_DESCRIPTOR_SIZE * b'\x00'
+ )
+
+ ioctl.IOCTL.IOR(
+ 'H', self.HIDIOCGRDESC, ctypes.sizeof(HidrawReportDescriptor)
+ ).perform(self._fd, buf=buf)
+
+ ret = HidrawReportDescriptor.from_buffer(buf)
+ return list(ret.value)[:ret.size]
+
+ @property
+ def info(self) -> Tuple[int, int, int]:
+ '''
+ Device info of the hidraw node
+ '''
+ dev_info = HidrawDevinfo.from_buffer(
+ ioctl.IOCTL.IOR(
+ 'H', self.HIDIOCGRAWINFO, ctypes.sizeof(HidrawDevinfo)
+ ).perform(self._fd)
+ )
+
+ return dev_info.bustype, dev_info.vendor, dev_info.product
+
+ @property
+ def name(self) -> str:
+ '''
+ HID name of the hidraw node
+ '''
+ return ioctl.IOCTL.IOR(
+ 'H', self.HIDIOCGRAWNAME, self.HID_NAME_SIZE
+ ).perform(self._fd).decode('utf-8').strip('\x00')
+
+ # TODO: HIDIOCGRAWPHYS, HIDIOCSFEATURE, HIDIOCGFEATURE, HIDIOCGRAWUNIQ