From 1d5bade6a90e2a87207d269df8c7bc3f945a9369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= Date: Sun, 4 Jun 2017 22:57:34 +0100 Subject: Add a ne support class for HID-based devices. I'm currently implementing a separate HID-based driver that does not use the Abbott protocol, so this makes my life easier. --- glucometerutils/support/hiddevice.py | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 glucometerutils/support/hiddevice.py (limited to 'glucometerutils/support/hiddevice.py') diff --git a/glucometerutils/support/hiddevice.py b/glucometerutils/support/hiddevice.py new file mode 100644 index 0000000..a3f2776 --- /dev/null +++ b/glucometerutils/support/hiddevice.py @@ -0,0 +1,79 @@ +"""Common routines and base driver class for HID-based meters. +""" + +__author__ = 'Diego Elio Pettenò' +__email__ = 'flameeyes@flameeyes.eu' +__copyright__ = 'Copyright © 2017, Diego Elio Pettenò' +__license__ = 'MIT' + +import logging +import os + +from glucometerutils import exceptions + + +class HidDevice(object): + """A device speaking USB HID protocol driver base. + + This class does not implement an actual driver by itself, but provides an + easier access to the boilerplate code required for speaking USB HID. + + This helper wraps around an optional dependency on hidapi library: if + present the driver will auto-detect the device, if not the device path needs + to be provided and should point to a device implementing Linux's hidraw + interface. + + The following constants can be set by the actual drivers: + + USB_VENDOR_ID: (int) USB vendor ID for the device. + USB_PRODUCT_ID: (int) USB product ID for the device. + + If the VID/PID pair is not provided, the driver will require a device path + to be used. + """ + + USB_VENDOR_ID = None + USB_PRODUCT_ID = None + + def __init__(self, device): + if None in (self.USB_VENDOR_ID, self.USB_PRODUCT_ID) and not device: + raise exceptions.CommandLineError( + '--device parameter is required, should point to a /dev/hidraw ' + 'device node representing the meter.') + + # If the user passed a device path that does not exist, raise an + # error. This is to avoid writing to a file instead of to a device node. + if device and not os.path.exists(device): + raise exceptions.ConnectionFailed( + message='Path %s does not exist.' % device) + + # If the user passed a device, try opening it. + if device: + self.handle_ = open(device, 'w+b') + else: + logging.info( + 'No --device parameter provided, using hidapi library.') + try: + import hid + self.handle_ = hid.device() + self.handle_.open(self.USB_VENDOR_ID, self.USB_PRODUCT_ID) + except ImportError: + raise exceptions.ConnectionFailed( + message='Missing requied "hidapi" module.') + except OSError as e: + raise exceptions.ConnectionFailed( + message='Unable to connect to meter: %s.' % e) + + def _write(self, report): + """Writes a report to the HID handle.""" + + if self.handle_.write(report) < 0: + raise exceptions.CommandError() + + def _read(self, size=64): + """Read a report from the HID handle. + + This is important as it handles the one incompatible interface between + hidraw devices and hidapi handles. + """ + return bytes(self.handle_.read(size)) -- cgit v1.2.3