From e2ccdd4818992159a0bc7e58265d1fe67700b642 Mon Sep 17 00:00:00 2001 From: Michiel van Leeuwen Date: Mon, 4 Nov 2024 10:40:12 +0100 Subject: [PATCH 1/3] Add HID classes --- usb_protocol/emitters/descriptors/hid.py | 39 ++++++++++++++++++++++++ usb_protocol/types/descriptors/hid.py | 33 ++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 usb_protocol/emitters/descriptors/hid.py create mode 100644 usb_protocol/types/descriptors/hid.py diff --git a/usb_protocol/emitters/descriptors/hid.py b/usb_protocol/emitters/descriptors/hid.py new file mode 100644 index 0000000..8b7b804 --- /dev/null +++ b/usb_protocol/emitters/descriptors/hid.py @@ -0,0 +1,39 @@ +import unittest + +from contextlib import contextmanager + +from .. import emitter_for_format +from ..descriptor import ComplexDescriptorEmitter +from ...types.descriptors.hid import * + +class HIDDescriptorEmitter(ComplexDescriptorEmitter): + + DESCRIPTOR_FORMAT = HIDDescriptor + + @contextmanager + def ReportDescriptor(self): + """ Context manager that allows addition of a subordinate report descriptor. + + It can be used with a `with` statement; and yields an HIDReportDescriptorEmitter + that can be populated: + + with hiddescriptor.ReportDescriptor() as r: + r.wDescriptorLength = 0x10 + + This adds the relevant descriptor, automatically. + """ + + descriptor = HIDReportDescriptorEmitter() + yield descriptor + + self.add_subordinate_descriptor(descriptor) + + def _pre_emit(self): + # Figure out the total length of our descriptor, including subordinates. + subordinate_length = sum(len(sub) for sub in self._subordinates) + self.bLength = subordinate_length + self.DESCRIPTOR_FORMAT.sizeof() + self.bNumDescriptors = len(self._subordinates) + pass + + +HIDReportDescriptorEmitter = emitter_for_format(HIDReportDescriptor) diff --git a/usb_protocol/types/descriptors/hid.py b/usb_protocol/types/descriptors/hid.py new file mode 100644 index 0000000..e05e557 --- /dev/null +++ b/usb_protocol/types/descriptors/hid.py @@ -0,0 +1,33 @@ +# +# This file is part of usb-protocol. +# +""" Structures describing Human Interface Device Class descriptors. """ + +import unittest +from enum import IntEnum + +from ..descriptor import \ + DescriptorField, DescriptorNumber, DescriptorFormat + +class HidClassSpecificDescriptorTypes(IntEnum): + CS_UNDEFINED = 0x20 + CS_HID = 0x21 + CS_REPORT = 0x22 + CS_PHYSICAL = 0x23 + + +HIDDescriptor = DescriptorFormat( + "bLength" / DescriptorField("Descriptor Length"), + "bDescriptorType" / DescriptorNumber(HidClassSpecificDescriptorTypes.CS_HID), + "bcdHID" / DescriptorField("HID Protocol Version", default=1.11), + "bCountryCode" / DescriptorField("Hardware target country", default=0), + "bNumDescriptors" / DescriptorField("Number of HID class descriptors to follow", default=0), +) + +# This is not reallyy a stand-alone descriptor, but it is part of the HIDDescriptor above. +# That descriptor can contain multiple ReportDescriptors. To support this, a seperate +# descriptor format is used. +HIDReportDescriptor = DescriptorFormat( + "bDescriptorType" / DescriptorField("HID Descriptor Type", default=HidClassSpecificDescriptorTypes.CS_REPORT), + "wDescriptorLength" / DescriptorField("HID Descriptor Length") +) From 2bc1a5d0083b68fe904a00fc82eaf63b0a5fc2ff Mon Sep 17 00:00:00 2001 From: Michiel van Leeuwen Date: Mon, 4 Nov 2024 14:25:14 +0100 Subject: [PATCH 2/3] Add HID class codes --- usb_protocol/types/descriptors/hid.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/usb_protocol/types/descriptors/hid.py b/usb_protocol/types/descriptors/hid.py index e05e557..e314d05 100644 --- a/usb_protocol/types/descriptors/hid.py +++ b/usb_protocol/types/descriptors/hid.py @@ -9,6 +9,18 @@ from ..descriptor import \ DescriptorField, DescriptorNumber, DescriptorFormat +class HidInterfaceClassCodes(IntEnum): + HID = 0x03 + +class HidInterfaceSubclassCodes(IntEnum): + NO_SUBCLASS = 0 + BOOT = 1 + +class HidInterfaceProtocols(IntEnum): + NONE = 0 + KEYBOARD = 1 + MOUSE = 2 + class HidClassSpecificDescriptorTypes(IntEnum): CS_UNDEFINED = 0x20 CS_HID = 0x21 From 72ac292b6968b5ef6f34941f0931f171a48f882b Mon Sep 17 00:00:00 2001 From: Michiel van Leeuwen Date: Mon, 4 Nov 2024 15:22:49 +0100 Subject: [PATCH 3/3] Rename ReportDescriptor to DescriptorReference --- usb_protocol/emitters/descriptors/hid.py | 10 +++++----- usb_protocol/types/descriptors/hid.py | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/usb_protocol/emitters/descriptors/hid.py b/usb_protocol/emitters/descriptors/hid.py index 8b7b804..031ec74 100644 --- a/usb_protocol/emitters/descriptors/hid.py +++ b/usb_protocol/emitters/descriptors/hid.py @@ -11,19 +11,19 @@ class HIDDescriptorEmitter(ComplexDescriptorEmitter): DESCRIPTOR_FORMAT = HIDDescriptor @contextmanager - def ReportDescriptor(self): + def DescriptorReference(self): """ Context manager that allows addition of a subordinate report descriptor. - It can be used with a `with` statement; and yields an HIDReportDescriptorEmitter + It can be used with a `with` statement; and yields an HIDDescriptorReferenceEmitter that can be populated: - with hiddescriptor.ReportDescriptor() as r: + with hiddescriptor.DescriptorReference() as r: r.wDescriptorLength = 0x10 This adds the relevant descriptor, automatically. """ - descriptor = HIDReportDescriptorEmitter() + descriptor = HIDDescriptorReferenceEmitter() yield descriptor self.add_subordinate_descriptor(descriptor) @@ -36,4 +36,4 @@ def _pre_emit(self): pass -HIDReportDescriptorEmitter = emitter_for_format(HIDReportDescriptor) +HIDDescriptorReferenceEmitter = emitter_for_format(HIDDescriptorReference) diff --git a/usb_protocol/types/descriptors/hid.py b/usb_protocol/types/descriptors/hid.py index e314d05..1d98933 100644 --- a/usb_protocol/types/descriptors/hid.py +++ b/usb_protocol/types/descriptors/hid.py @@ -36,10 +36,11 @@ class HidClassSpecificDescriptorTypes(IntEnum): "bNumDescriptors" / DescriptorField("Number of HID class descriptors to follow", default=0), ) -# This is not reallyy a stand-alone descriptor, but it is part of the HIDDescriptor above. -# That descriptor can contain multiple ReportDescriptors. To support this, a seperate +# This is not really a stand-alone descriptor, but it it is more a reference to a report +# descriptor that can retrieved seperately. It is part of the HIDDescriptor above. +# That descriptor can contain multiple descriptor references. To support this, a seperate # descriptor format is used. -HIDReportDescriptor = DescriptorFormat( +HIDDescriptorReference = DescriptorFormat( "bDescriptorType" / DescriptorField("HID Descriptor Type", default=HidClassSpecificDescriptorTypes.CS_REPORT), "wDescriptorLength" / DescriptorField("HID Descriptor Length") )