Skip to content

Commit

Permalink
hid watchdog
Browse files Browse the repository at this point in the history
  • Loading branch information
regicidalplutophage committed Dec 18, 2024
1 parent 936ff70 commit 8e8dccf
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 55 deletions.
119 changes: 64 additions & 55 deletions kmk/hid.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from storage import getmount

from kmk.keys import ConsumerKey, KeyboardKey, ModifierKey, MouseKey

# from kmk.scheduler import create_task
from kmk.utils import Debug, clamp

try:
Expand Down Expand Up @@ -55,13 +57,47 @@ class HIDUsagePage:


class AbstractHID:
REPORT_BYTES = 8
report_bytes_default = 8
REPORT_BYTES = report_bytes_default
hid_devices = {}

def __init__(self, **kwargs):
self._nkro = False
self._mouse = True
self._pan = False
self.make_device_list()

self._cc_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.CONSUMER] + 1)
self._cc_report[0] = HIDReportTypes.CONSUMER
self._cc_pending = False

self.test_nkro()
self.test_mouse()

def make_device_list(self):
self.devices = {}

for device in self.hid_devices:
if not hasattr(device, 'send_report'):
continue
us = device.usage
up = device.usage_page

if up == HIDUsagePage.CONSUMER and us == HIDUsage.CONSUMER:
self.devices[HIDReportTypes.CONSUMER] = device
elif up == HIDUsagePage.KEYBOARD and us == HIDUsage.KEYBOARD:
self.devices[HIDReportTypes.KEYBOARD] = device
elif up == HIDUsagePage.MOUSE and us == HIDUsage.MOUSE:
self.devices[HIDReportTypes.MOUSE] = device
elif up == HIDUsagePage.SYSCONTROL and us == HIDUsage.SYSCONTROL:
self.devices[HIDReportTypes.SYSCONTROL] = device

def test_nkro(self):
if self._nkro:
return

self._evt = bytearray(self.REPORT_BYTES)
self._evt[0] = HIDReportTypes.KEYBOARD
self._nkro = False

# bodgy NKRO autodetect
try:
Expand All @@ -87,9 +123,9 @@ def __init__(self, **kwargs):
self.report_mods = memoryview(self._evt)[1:2]
self.report_non_mods = memoryview(self._evt)[3:]

self._cc_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.CONSUMER] + 1)
self._cc_report[0] = HIDReportTypes.CONSUMER
self._cc_pending = False
def test_mouse(self):
if not self._mouse or self._pan:
return

self._pd_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.MOUSE] + 1)
self._pd_report[0] = HIDReportTypes.MOUSE
Expand All @@ -103,12 +139,17 @@ def __init__(self, **kwargs):
except ValueError:
self._pd_report = bytearray(6)
self._pd_report[0] = HIDReportTypes.MOUSE
self._pan = True
if debug.enabled:
debug('use pan')
except KeyError:
self._mouse = False
if debug.enabled:
debug('mouse disabled')

def watchdog(self):
return

def __repr__(self):
return f'{self.__class__.__name__}(REPORT_BYTES={self.REPORT_BYTES})'

Expand Down Expand Up @@ -254,27 +295,22 @@ def has_key(self, key):


class USBHID(AbstractHID):
REPORT_BYTES = 9
report_bytes_default = 9
REPORT_BYTES = report_bytes_default

def __init__(self, **kwargs):

self.devices = {}

for device in usb_hid.devices:
us = device.usage
up = device.usage_page

if up == HIDUsagePage.CONSUMER and us == HIDUsage.CONSUMER:
self.devices[HIDReportTypes.CONSUMER] = device
elif up == HIDUsagePage.KEYBOARD and us == HIDUsage.KEYBOARD:
self.devices[HIDReportTypes.KEYBOARD] = device
elif up == HIDUsagePage.MOUSE and us == HIDUsage.MOUSE:
self.devices[HIDReportTypes.MOUSE] = device
elif up == HIDUsagePage.SYSCONTROL and us == HIDUsage.SYSCONTROL:
self.devices[HIDReportTypes.SYSCONTROL] = device

self.hid = usb_hid
self.hid_devices = self.hid.devices
self.usb_status = None
super().__init__(**kwargs)

def watchdog(self):
if self.usb_status != supervisor.runtime.usb_connected:
self.usb_status = supervisor.runtime.usb_connected
self.make_device_list()
self.test_nkro()
self.test_mouse()

def hid_send(self, evt):
if not supervisor.runtime.usb_connected:
return
Expand All @@ -291,11 +327,12 @@ class BLEHID(AbstractHID):
MAX_CONNECTIONS = const(2)

def __init__(self, ble_name=str(getmount('/').label), **kwargs):

self.ble_status = None
self.ble_name = ble_name
self.ble = BLERadio()
self.ble.name = self.ble_name
self.hid = HIDService()
self.hid_devices = self.hid.devices
self.hid.protocol_mode = 0 # Boot protocol
super().__init__(**kwargs)

Expand All @@ -307,38 +344,10 @@ def __init__(self, ble_name=str(getmount('/').label), **kwargs):
if not self.ble.connected or not self.hid.devices:
self.start_advertising()

@property
def devices(self):
'''Search through the provided list of devices to find the ones with the
send_report attribute.'''
if not self.ble.connected:
return {}

result = {}

for device in self.hid.devices:
if not hasattr(device, 'send_report'):
continue
us = device.usage
up = device.usage_page

if up == HIDUsagePage.CONSUMER and us == HIDUsage.CONSUMER:
result[HIDReportTypes.CONSUMER] = device
continue

if up == HIDUsagePage.KEYBOARD and us == HIDUsage.KEYBOARD:
result[HIDReportTypes.KEYBOARD] = device
continue

if up == HIDUsagePage.MOUSE and us == HIDUsage.MOUSE:
result[HIDReportTypes.MOUSE] = device
continue

if up == HIDUsagePage.SYSCONTROL and us == HIDUsage.SYSCONTROL:
result[HIDReportTypes.SYSCONTROL] = device
continue

return result
def watchdog(self):
if self.ble_status != self.ble.connected:
self.ble_status = self.ble.connected
self.make_device_list()

def hid_send(self, evt):
if not self.ble.connected:
Expand Down
23 changes: 23 additions & 0 deletions kmk/kmk_keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ class Sandbox:


class KMKKeyboard:
def __init__(
self,
keymap=[],
coord_mapping=None,
matrix=None,
modules=[],
extensions=[],
):
self.keymap = keymap
self.coord_mapping = coord_mapping
self.matrix = matrix
self.modules = modules
self.extensions = extensions

#####
# User-configurable
keymap = []
Expand Down Expand Up @@ -185,6 +199,14 @@ def _process_resume_buffer(self):

self._resume_buffer_x = buffer

@property
def debug_enabled(self) -> bool:
return debug.enabled

@debug_enabled.setter
def debug_enabled(self, enabled: bool):
debug.enabled = enabled

def pre_process_key(
self,
key: Key,
Expand Down Expand Up @@ -286,6 +308,7 @@ def _init_hid(self) -> None:
else:
self._hid_helper = AbstractHID
self._hid_helper = self._hid_helper(**self._go_args)
self._watchdog = create_task(self._hid_helper.watchdog, period_ms=200)
self._hid_send_enabled = True

if debug.enabled:
Expand Down

0 comments on commit 8e8dccf

Please sign in to comment.