From 8586bee48ef823d5c3c152156de83c72b043336a Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 16 Aug 2019 07:07:50 -0400 Subject: [PATCH 1/2] Allow devices to be passed in, instead of always using usb_hid --- adafruit_hid/consumer_control.py | 32 +++++++++++++----------- adafruit_hid/gamepad.py | 33 +++++++++++++------------ adafruit_hid/keyboard.py | 42 ++++++++++++++++++-------------- adafruit_hid/mouse.py | 30 ++++++++++++++--------- 4 files changed, 77 insertions(+), 60 deletions(-) diff --git a/adafruit_hid/consumer_control.py b/adafruit_hid/consumer_control.py index 76d3fa0..099b82b 100644 --- a/adafruit_hid/consumer_control.py +++ b/adafruit_hid/consumer_control.py @@ -35,23 +35,27 @@ # pylint: disable=wrong-import-position import struct import time -import usb_hid class ConsumerControl: """Send ConsumerControl code reports, used by multimedia keyboards, remote controls, etc. - - *New in CircuitPython 3.0.* """ - def __init__(self): - """Create a ConsumerControl object that will send Consumer Control Device HID reports.""" - self.hid_consumer = None - for device in usb_hid.devices: - if device.usage_page == 0x0C and device.usage == 0x01: - self.hid_consumer = device - break - if not self.hid_consumer: - raise IOError("Could not find an HID Consumer device.") + def __init__(self, consumer_device=None): + """Create a ConsumerControl object that will send Consumer Control Device HID reports. + If consumer_device is None (the default), find a usb_hid device to use. + But an equivalent device can be supplied instead for other kinds of consumer devices, + such as BLE. + It only needs to implement ``send_report()``. + """ + self._consumer_device = consumer_device + if not self._consumer_device: + import usb_hid + for device in usb_hid.devices: + if device.usage_page == 0x0C and device.usage == 0x01: + self._consumer_device = device + break + if not self._consumer_device: + raise IOError("Could not find an HID Consumer device.") # Reuse this bytearray to send consumer reports. self._report = bytearray(2) @@ -81,6 +85,6 @@ def send(self, consumer_code): consumer_control.send(ConsumerControlCode.SCAN_NEXT_TRACK) """ struct.pack_into(" Date: Wed, 18 Dec 2019 12:14:00 -0800 Subject: [PATCH 2/2] Require devices to be passed in so that they can be from USB or BLE. --- adafruit_hid/__init__.py | 12 ++++++++++++ adafruit_hid/consumer_control.py | 21 +++++++-------------- adafruit_hid/gamepad.py | 22 ++++++++-------------- adafruit_hid/keyboard.py | 22 ++++++++-------------- adafruit_hid/mouse.py | 22 ++++++++-------------- examples/hid_joywing_gamepad.py | 3 ++- examples/hid_keyboard_shortcuts.py | 3 ++- examples/hid_simple_gamepad.py | 3 ++- examples/hid_simpletest.py | 3 ++- 9 files changed, 51 insertions(+), 60 deletions(-) diff --git a/adafruit_hid/__init__.py b/adafruit_hid/__init__.py index d30fb32..65e459b 100644 --- a/adafruit_hid/__init__.py +++ b/adafruit_hid/__init__.py @@ -39,3 +39,15 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_HID.git" + +def find_device(devices, *, usage_page, usage): + """Search through the provided list of devices to find the one with the matching usage_page and + usage.""" + if hasattr(devices, "send_report"): + devices = [devices] + for device in devices: + if (device.usage_page == usage_page and + device.usage == usage and + hasattr(device, "send_report")): + return device + raise ValueError("Could not find matching HID device.") diff --git a/adafruit_hid/consumer_control.py b/adafruit_hid/consumer_control.py index 099b82b..b22da45 100644 --- a/adafruit_hid/consumer_control.py +++ b/adafruit_hid/consumer_control.py @@ -35,27 +35,20 @@ # pylint: disable=wrong-import-position import struct import time +from . import find_device class ConsumerControl: """Send ConsumerControl code reports, used by multimedia keyboards, remote controls, etc. """ - def __init__(self, consumer_device=None): + def __init__(self, devices): """Create a ConsumerControl object that will send Consumer Control Device HID reports. - If consumer_device is None (the default), find a usb_hid device to use. - But an equivalent device can be supplied instead for other kinds of consumer devices, - such as BLE. - It only needs to implement ``send_report()``. + + Devices can be a list of devices that includes a Consumer Control device or a CC device + itself. A device is any object that implements ``send_report()``, ``usage_page`` and + ``usage``. """ - self._consumer_device = consumer_device - if not self._consumer_device: - import usb_hid - for device in usb_hid.devices: - if device.usage_page == 0x0C and device.usage == 0x01: - self._consumer_device = device - break - if not self._consumer_device: - raise IOError("Could not find an HID Consumer device.") + self._consumer_device = find_device(devices, usage_page=0x0C, usage=0x01) # Reuse this bytearray to send consumer reports. self._report = bytearray(2) diff --git a/adafruit_hid/gamepad.py b/adafruit_hid/gamepad.py index 0aa0fa7..109a38b 100644 --- a/adafruit_hid/gamepad.py +++ b/adafruit_hid/gamepad.py @@ -31,6 +31,8 @@ import struct import time +from . import find_device + class Gamepad: """Emulate a generic gamepad controller with 16 buttons, numbered 1-16, and two joysticks, one controlling @@ -42,22 +44,14 @@ class Gamepad: The joystick values are in the range -127 to 127. """ - def __init__(self, gamepad_device=None): + def __init__(self, devices): """Create a Gamepad object that will send USB gamepad HID reports. - If gamepad_device is None (the default), find a usb_hid device to use. - But an equivalent device can be supplied instead for other kinds of gamepads, - such as BLE. - It only needs to implement ``send_report()``. + + Devices can be a list of devices that includes a gamepad device or a gamepad device + itself. A device is any object that implements ``send_report()``, ``usage_page`` and + ``usage``. """ - self._gamepad_device = gamepad_device - if self._gamepad_device is None: - import usb_hid - for device in usb_hid.devices: - if device.usage_page == 0x1 and device.usage == 0x05: - self._gamepad_device = device - break - if not self._gamepad_device: - raise IOError("Could not find an HID gamepad device.") + self._gamepad_device = find_device(devices, usage_page=0x1, usage=0x05) # Reuse this bytearray to send mouse reports. # Typically controllers start numbering buttons at 1 rather than 0. diff --git a/adafruit_hid/keyboard.py b/adafruit_hid/keyboard.py index c2938cd..197b93a 100644 --- a/adafruit_hid/keyboard.py +++ b/adafruit_hid/keyboard.py @@ -33,6 +33,8 @@ from .keycode import Keycode +from . import find_device + _MAX_KEYPRESSES = const(6) class Keyboard: @@ -40,22 +42,14 @@ class Keyboard: # No more than _MAX_KEYPRESSES regular keys may be pressed at once. - def __init__(self, keyboard_device=None): + def __init__(self, devices): """Create a Keyboard object that will send keyboard HID reports. - If keyboard_device is None (the default), find a usb_hid device to use. - But an equivalent device can be supplied instead for other kinds of keyboards, - such as BLE. - It only needs to implement `send_report()`. + + Devices can be a list of devices that includes a keyboard device or a keyboard device + itself. A device is any object that implements ``send_report()``, ``usage_page`` and + ``usage``. """ - self._keyboard_device = keyboard_device - if not self._keyboard_device: - import usb_hid - for device in usb_hid.devices: - if device.usage_page == 0x1 and device.usage == 0x06: - self._keyboard_device = device - break - if not self._keyboard_device: - raise IOError("Could not find an HID keyboard device.") + self._keyboard_device = find_device(devices, usage_page=0x1, usage=0x06) # Reuse this bytearray to send keyboard reports. self.report = bytearray(8) diff --git a/adafruit_hid/mouse.py b/adafruit_hid/mouse.py index 3aaa01f..b871f0f 100644 --- a/adafruit_hid/mouse.py +++ b/adafruit_hid/mouse.py @@ -29,6 +29,8 @@ """ import time +from . import find_device + class Mouse: """Send USB HID mouse reports.""" @@ -39,22 +41,14 @@ class Mouse: MIDDLE_BUTTON = 4 """Middle mouse button.""" - def __init__(self, mouse_device=None): + def __init__(self, devices): """Create a Mouse object that will send USB mouse HID reports. - If mouse_device is None (the default), find a usb_hid device to use. - But an equivalent device can be supplied instead for other kinds of nice, - such as BLE. - It only needs to implement ``send_report()``. + + Devices can be a list of devices that includes a keyboard device or a keyboard device + itself. A device is any object that implements ``send_report()``, ``usage_page`` and + ``usage``. """ - self._mouse_device = mouse_device - if not self._mouse_device: - import usb_hid - for device in usb_hid.devices: - if device.usage_page == 0x1 and device.usage == 0x02: - self._mouse_device = device - break - if not self._mouse_device: - raise IOError("Could not find an HID mouse device.") + self._mouse_device = find_device(devices, usage_page=0x1, usage=0x02) # Reuse this bytearray to send mouse reports. # report[0] buttons pressed (LEFT, MIDDLE, RIGHT) diff --git a/examples/hid_joywing_gamepad.py b/examples/hid_joywing_gamepad.py index 92cee5c..b1f652d 100644 --- a/examples/hid_joywing_gamepad.py +++ b/examples/hid_joywing_gamepad.py @@ -7,6 +7,7 @@ from micropython import const import adafruit_seesaw from adafruit_hid.gamepad import Gamepad +import usb_hid def range_map(value, in_min, in_max, out_min, out_max): return (value - in_min) * (out_max - out_min) // (in_max - in_min) + out_min @@ -31,7 +32,7 @@ def range_map(value, in_min, in_max, out_min, out_max): last_game_x = 0 last_game_y = 0 -g = Gamepad() +g = Gamepad(usb_hid.devices) while True: x = ss.analog_read(2) diff --git a/examples/hid_keyboard_shortcuts.py b/examples/hid_keyboard_shortcuts.py index f922bed..e93e4b9 100644 --- a/examples/hid_keyboard_shortcuts.py +++ b/examples/hid_keyboard_shortcuts.py @@ -3,8 +3,9 @@ import digitalio from adafruit_hid.keyboard import Keyboard from adafruit_hid.keycode import Keycode +import usb_hid -kbd = Keyboard() +kbd = Keyboard(usb_hid.devices) # define buttons. these can be any physical switches/buttons, but the values # here work out-of-the-box with a CircuitPlayground Express' A and B buttons. diff --git a/examples/hid_simple_gamepad.py b/examples/hid_simple_gamepad.py index 881ad4b..474354c 100644 --- a/examples/hid_simple_gamepad.py +++ b/examples/hid_simple_gamepad.py @@ -1,10 +1,11 @@ import board import digitalio import analogio +import usb_hid from adafruit_hid.gamepad import Gamepad -gp = Gamepad() +gp = Gamepad(usb_hid.devices) # Create some buttons. The physical buttons are connected # to ground on one side and these and these pins on the other. diff --git a/examples/hid_simpletest.py b/examples/hid_simpletest.py index fc7817a..124a1e4 100644 --- a/examples/hid_simpletest.py +++ b/examples/hid_simpletest.py @@ -1,9 +1,10 @@ import time import board import digitalio +import usb_hid from adafruit_hid.mouse import Mouse -mouse = Mouse() +mouse = Mouse(usb_hid.devices) # define buttons. these can be any physical switches/buttons, but the values # here work out-of-the-box with a CircuitPlayground Express' A and B buttons.