summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2020-04-10 00:26:13 +0200
committerVegard Storheil Eriksen <zyp@jvnv.net>2020-04-10 00:26:13 +0200
commitdd3688040fcf08b7987722dc3e0deef40d46bf79 (patch)
tree2c561a27019e8c788d9a75d678202b318be0450a
Initial import.HEADmaster
-rw-r--r--.gitignore4
-rw-r--r--MANIFEST.in1
-rw-r--r--README0
-rw-r--r--pyhidapi/__init__.py134
-rwxr-xr-xsetup.py13
5 files changed, 152 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..37dca56
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.pyc
+MANIFEST
+build
+dist
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..eb762f3
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include COPYING
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
diff --git a/pyhidapi/__init__.py b/pyhidapi/__init__.py
new file mode 100644
index 0000000..819d476
--- /dev/null
+++ b/pyhidapi/__init__.py
@@ -0,0 +1,134 @@
+import ctypes, ctypes.util
+
+path = ctypes.util.find_library('hidapi')
+
+if not path:
+ path = ctypes.util.find_library('hidapi-libusb')
+
+if not path:
+ path = ctypes.util.find_library('hidapi-hidraw')
+
+if not path:
+ raise ImportError('Cannot find hidapi library')
+
+hidapi = ctypes.CDLL(path)
+
+class c_hid_device_info(ctypes.Structure):
+ def __iter__(self):
+ p = self
+ yield DeviceInfo(p)
+
+ while p.next:
+ p = p.next.contents
+ yield DeviceInfo(p)
+
+c_hid_device_info._fields_ = [
+ ('path', ctypes.c_char_p),
+ ('vendor_id', ctypes.c_ushort),
+ ('product_id', ctypes.c_ushort),
+ ('serial_number', ctypes.c_wchar_p),
+ ('release_number', ctypes.c_ushort),
+ ('manufacturer_string', ctypes.c_wchar_p),
+ ('product_string', ctypes.c_wchar_p),
+ ('usage_page', ctypes.c_ushort),
+ ('usage', ctypes.c_ushort),
+ ('interface_number', ctypes.c_int),
+ ('next', ctypes.POINTER(c_hid_device_info)),
+]
+
+hidapi.hid_open.argtypes = [ctypes.c_ushort, ctypes.c_ushort, ctypes.c_wchar_p]
+hidapi.hid_open.restype = ctypes.c_void_p
+
+hidapi.hid_open_path.argtypes = [ctypes.c_char_p]
+hidapi.hid_open_path.restype = ctypes.c_void_p
+
+hidapi.hid_close.argtypes = [ctypes.c_void_p]
+
+hidapi.hid_read_timeout.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t, ctypes.c_int]
+hidapi.hid_read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
+hidapi.hid_write.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
+hidapi.hid_send_feature_report.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
+hidapi.hid_get_feature_report.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
+
+hidapi.hid_enumerate.restype = ctypes.POINTER(c_hid_device_info)
+
+def enumerate(vid = 0, pid = 0):
+ info = hidapi.hid_enumerate(vid, pid)
+
+ if not info:
+ return []
+
+ l = list(info.contents)
+
+ hidapi.hid_free_enumeration(info)
+
+ return l
+
+class HIDError(Exception):
+ pass
+
+class DeviceInfo:
+ def __init__(self, cstruct):
+ self.path = cstruct.path
+ self.vendor_id = cstruct.vendor_id
+ self.product_id = cstruct.product_id
+ self.serial_number = cstruct.serial_number
+ self.release_number = cstruct.release_number
+ self.manufacturer_string = cstruct.manufacturer_string
+ self.product_string = cstruct.product_string
+ self.usage_page = cstruct.usage_page
+ self.usage = cstruct.usage
+ self.interface_number = cstruct.interface_number
+
+ def open(self):
+ return Device(path = self.path)
+
+class Device:
+ def __init__(self, vid = None, pid = None, serial = None, path = None):
+ if path is not None:
+ self._dev = hidapi.hid_open_path(path)
+
+ elif vid is not None and pid is not None:
+ self._dev = hidapi.hid_open(vid, pid, serial)
+
+ else:
+ raise TypeError('vid/pid or path is required')
+
+ if not self._dev:
+ raise HIDError('failed to open device')
+
+ def __del__(self):
+ self.close()
+
+ def close(self):
+ if self._dev:
+ hidapi.hid_close(self._dev)
+ self._dev = None
+
+ def set_output_report(self, data, id = 0):
+ if hidapi.hid_write(self._dev, ctypes.c_char_p(chr(id) + data), len(data) + 1) != len(data) + 1:
+ raise HIDError('failed to set output')
+
+ def get_input_report(self, timeout = -1):
+ buf = ctypes.create_string_buffer(64)
+
+ ret = hidapi.hid_read_timeout(self._dev, buf, 64, timeout)
+
+ if ret < 0:
+ raise HIDError('failed to get input')
+
+ return buf[:ret]
+
+ def set_feature_report(self, data, id = 0):
+ if hidapi.hid_send_feature_report(self._dev, ctypes.c_char_p(chr(id) + data), len(data) + 1) != len(data) + 1:
+ raise HIDError('failed to set feature')
+
+ def get_feature_report(self, id = 0):
+ buf = ctypes.create_string_buffer(chr(id), 64)
+
+ ret = hidapi.hid_get_feature_report(self._dev, buf, 64)
+
+ if ret < 0:
+ raise HIDError('failed to get feature')
+
+ return buf[1:ret]
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..b6f8be0
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+from distutils.core import setup
+
+setup(
+ name = 'pyhidapi',
+ version = '0.1',
+ description = 'ctypes wrapper for hidapi',
+ author = 'Vegard Storheil Eriksen',
+ author_email = 'zyp@jvnv.net',
+ url = 'http://cgit.jvnv.net/pyhidapi/',
+ packages = ['pyhidapi'],
+)