diff --git a/lib/python/qmk/cli/xap/xap.py b/lib/python/qmk/cli/xap/xap.py index be86e0a6f0b..7757f8703a0 100644 --- a/lib/python/qmk/cli/xap/xap.py +++ b/lib/python/qmk/cli/xap/xap.py @@ -7,7 +7,7 @@ from milc import cli from qmk.keyboard import render_layout from qmk.xap.common import get_xap_keycodes -from .xap_client import XAPClient, XAPEventType, XAPSecureStatus +from xap_client import XAPClient, XAPEventType, XAPSecureStatus KEYCODE_MAP = get_xap_keycodes('latest') diff --git a/lib/python/xap_client/__init__.py b/lib/python/xap_client/__init__.py new file mode 100644 index 00000000000..e88170517e4 --- /dev/null +++ b/lib/python/xap_client/__init__.py @@ -0,0 +1,2 @@ +from .types import * # noqa: F403 +from .client import * # noqa: F403 diff --git a/lib/python/xap_client/client.py b/lib/python/xap_client/client.py new file mode 100644 index 00000000000..e3f032f4af9 --- /dev/null +++ b/lib/python/xap_client/client.py @@ -0,0 +1,29 @@ +"""XAP Client +""" +import hid + +from .device import XAPDevice + + +class XAPClient: + @staticmethod + def list(search=None): + """Find compatible XAP devices + """ + def _is_xap_usage(x): + return x['usage_page'] == 0xFF51 and x['usage'] == 0x0058 + + def _is_filtered_device(x): + name = '%04x:%04x' % (x['vendor_id'], x['product_id']) + return name.lower().startswith(search.lower()) + + devices = filter(_is_xap_usage, hid.enumerate()) + if search: + devices = filter(_is_filtered_device, devices) + + return list(devices) + + def connect(self, dev): + """Connect to a given XAP device + """ + return XAPDevice(dev) diff --git a/lib/python/qmk/cli/xap/xap_client.py b/lib/python/xap_client/device.py similarity index 79% rename from lib/python/qmk/cli/xap/xap_client.py rename to lib/python/xap_client/device.py index a12f54e35bc..5d00a1e317a 100644 --- a/lib/python/qmk/cli/xap/xap_client.py +++ b/lib/python/xap_client/device.py @@ -1,5 +1,6 @@ -"""Dummy XAP Client +"""XAP Device """ +import hid import json import random import gzip @@ -7,9 +8,11 @@ import threading import functools from struct import Struct, pack, unpack from collections import namedtuple -from enum import IntFlag, IntEnum from platform import platform +from .types import XAPSecureStatus, XAPFlags, XAPRouteError + + RequestPacket = namedtuple('RequestPacket', 'token length data') RequestStruct = Struct('>24}.{val>>16 & 0xFF}.{val & 0xFFFF}' -class XAPSecureStatus(IntEnum): - LOCKED = 0x00 - UNLOCKING = 0x01 - UNLOCKED = 0x02 - - -class XAPFlags(IntFlag): - FAILURE = 0 - SUCCESS = 1 << 0 - SECURE_FAILURE = 1 << 1 - - -class XAPEventType(IntEnum): - SECURE = 0x01 - KEYBOARD = 0x02 - USER = 0x03 - - -class XAPRouteError(Exception): - pass - - class XAPDevice: def __init__(self, dev): """Constructor opens hid device and starts dependent services @@ -191,37 +172,3 @@ class XAPDevice: def reset(self): status = int.from_bytes(self.transaction(b'\x01\x07') or bytes(0), 'little') return status == 1 - - -class XAPClient: - @staticmethod - def _lazy_imports(): - # Lazy load to avoid missing dependency issues - global hid - import hid - - @staticmethod - def list(search=None): - """Find compatible XAP devices - """ - XAPClient._lazy_imports() - - def _is_xap_usage(x): - return x['usage_page'] == 0xFF51 and x['usage'] == 0x0058 - - def _is_filtered_device(x): - name = '%04x:%04x' % (x['vendor_id'], x['product_id']) - return name.lower().startswith(search.lower()) - - devices = filter(_is_xap_usage, hid.enumerate()) - if search: - devices = filter(_is_filtered_device, devices) - - return list(devices) - - def connect(self, dev): - """Connect to a given XAP device - """ - XAPClient._lazy_imports() - - return XAPDevice(dev) diff --git a/lib/python/xap_client/types.py b/lib/python/xap_client/types.py new file mode 100644 index 00000000000..376849c8bb8 --- /dev/null +++ b/lib/python/xap_client/types.py @@ -0,0 +1,23 @@ +from enum import IntFlag, IntEnum + + +class XAPSecureStatus(IntEnum): + LOCKED = 0x00 + UNLOCKING = 0x01 + UNLOCKED = 0x02 + + +class XAPFlags(IntFlag): + FAILURE = 0 + SUCCESS = 1 << 0 + SECURE_FAILURE = 1 << 1 + + +class XAPEventType(IntEnum): + SECURE = 0x01 + KEYBOARD = 0x02 + USER = 0x03 + + +class XAPRouteError(Exception): + pass