# # ==================================================================== # Copyright 2013 Greg Stein # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ==================================================================== # import types import ctypes ### make this work on all platforms _hidapi = ctypes.cdll.LoadLibrary('libhidapi.dylib') # Define a pointer to the incomplete hid_device structure. def _make_DEV_P(): class DEV(ctypes.Structure): pass return ctypes.POINTER(DEV) DEV_P = _make_DEV_P() class DEVINFO(ctypes.Structure): pass DEVINFO_P = ctypes.POINTER(DEVINFO) DEVINFO._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', DEVINFO_P), ] def _define(name, restype, *argtypes): f = getattr(_hidapi, name) f.restype = restype f.argtypes = argtypes globals()[name] = f return f _define('hid_init', ctypes.c_int) _define('hid_exit', ctypes.c_int) _define('hid_enumerate', DEVINFO_P, ctypes.c_ushort, ctypes.c_ushort) _define('hid_free_enumeration', None, DEVINFO_P) _define('hid_open', DEV_P, ctypes.c_ushort, ctypes.c_ushort, ctypes.c_wchar_p) _define('hid_open_path', DEV_P, ctypes.c_char_p) _define('hid_set_nonblocking', ctypes.c_int, DEV_P, ctypes.c_int) _define('hid_close', None, DEV_P) _define('hid_error', ctypes.c_wchar_p, DEV_P) _hid_write = _define('hid_write', ctypes.c_int, DEV_P, ctypes.c_char_p, ctypes.c_size_t) def hid_write(dev, buf): ### map -1 to None or an exception? return _hid_write(dev, buf, len(buf)) _hid_read = _define('hid_read', ctypes.c_int, DEV_P, ctypes.c_char_p, ctypes.c_size_t) def hid_read(dev, amt): buf = ctypes.create_string_buffer(amt) result = _hid_read(dev, buf, amt) if result == -1: return None return buf.raw[:result] _hid_read_timeout = _define('hid_read_timeout', ctypes.c_int, DEV_P, ctypes.c_char_p, ctypes.c_size_t, ctypes.c_int) def hid_read_timeout(devinfo, amt, milliseconds): buf = ctypes.create_string_buffer(amt) result = _hid_read_timeout(dev, buf, amt, milliseconds) if result == -1: return None return buf.raw[:result] _hid_send_feature_report = _define('hid_send_feature_report', ctypes.c_int, DEV_P, ctypes.c_char_p, ctypes.c_size_t) def hid_send_feature_report(dev, data): ### map -1 to None or an exception? return _hid_send_feature_report(dev, data, len(data)) _hid_get_feature_report = _define('hid_get_feature_report', ctypes.c_int, DEV_P, ctypes.c_char_p, ctypes.c_size_t) def hid_get_feature_report(dev, report_id, amt): buf = ctypes.create_string_buffer(amt) buf[0] = report_id result = _hid_get_feature_report(dev, buf, amt) if result == -1: return None return buf.raw[:result] def _define_get_string(fname): f = getattr(_hidapi, fname) f.restype = ctypes.c_int f.argtypes = (DEV_P, ctypes.c_wchar_p, ctypes.c_size_t) def wrapper(dev, maxlen=200): buf = ctypes.create_unicode_buffer(maxlen) result = f(dev, buf, maxlen) if result == -1: return None return buf.value # Create a function, named properly, based on WRAPPER globals()[fname] = types.FunctionType(wrapper.func_code, wrapper.func_globals, fname, wrapper.func_defaults, wrapper.func_closure) _define_get_string('hid_get_manufacturer_string') _define_get_string('hid_get_product_string') _define_get_string('hid_get_serial_number_string') _hid_get_indexed_string = _define('hid_get_indexed_string', ctypes.c_int, DEV_P, ctypes.c_wchar_p, ctypes.c_size_t) def hid_get_indexed_string(dev, idx, maxlen=200): buf = ctypes.create_unicode_buffer(maxlen) result = _hid_get_indexed_string(dev, idx, buf, maxlen) if result == -1: return None return buf.value