-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add HID descriptors #6
Closed
Closed
Changes from 7 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
cef2b8b
Add HID descriptors
TiltMeSenpai 2e7f95f
Rename to clarify HIDDescriptor report item methods
TiltMeSenpai 2db2205
Change HIDPrefixes -> HIDPrefix
TiltMeSenpai cbe13dd
Change report_enum -> report_prefix to clarify purpose
TiltMeSenpai 8417f36
Add add_report_raw method to append raw items/bytes-likes to HID desc…
TiltMeSenpai 9e10dbd
Add documentation to HID descriptor emitter
TiltMeSenpai bbc5f67
Fix some missed refactoring
TiltMeSenpai f292dc9
Fix typo in `add_report_raw`
TiltMeSenpai 45b7a89
Move descriptor_type argument to avoid API breakage
TiltMeSenpai 4a660f8
Change descriptor_type default check
TiltMeSenpai File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import unittest | ||
|
||
from contextlib import contextmanager | ||
|
||
from .. import emitter_for_format | ||
from ..descriptor import ComplexDescriptorEmitter | ||
from ...types.descriptors.hid import \ | ||
HIDDescriptor as HIDDescriptorType | ||
from ...types.descriptors.hid import * | ||
|
||
ReportDescriptorEmitter = emitter_for_format(ReportDescriptor) | ||
|
||
_hid_item_length = [ 0, 1, 2, 4 ] | ||
|
||
class HIDDescriptor(ComplexDescriptorEmitter): | ||
DESCRIPTOR_FORMAT = HIDDescriptorType | ||
|
||
def add_report_raw(self, report_data): | ||
"""Append raw report item or bytes to HID report | ||
|
||
Arguments: | ||
report_data -- bytes-like or ReportDescriptor to be appended to | ||
the HID report. | ||
""" | ||
self._reports.append(hid_data) | ||
TiltMeSenpai marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def add_report_item(self, report_prefix, *report_data): | ||
"""Convenience function to add formatted HID report item | ||
|
||
Arguments: | ||
report_prefix -- HIDPrefix enum representing report item type | ||
*report_data -- Additional bytes-like report item data. | ||
Valid lengths are 1, 2, or 4 bytes. | ||
""" | ||
hid_report = ReportDescriptorEmitter() | ||
report_len = _hid_item_length.index(len(report_data)) | ||
hid_report.bHeader = { | ||
"prefix": report_prefix, | ||
"bSize": report_len | ||
} | ||
hid_report.data = report_data | ||
self._reports.append(hid_report) | ||
|
||
def add_input_item(self, | ||
data_constant = False, | ||
array_variable = True, | ||
absolute_relative = False, | ||
wrap = False, | ||
linear = False, | ||
preferred = True, | ||
null = False, | ||
volatile = False): | ||
"""Convenience function to add HID input item with preformatted flags. | ||
See HID 1.11 section 6.2.2.5 for flag meanings. | ||
""" | ||
item_flags = ItemFlags.build({ | ||
"data_constant": data_constant, | ||
"array_variable": array_variable, | ||
"absolute_relative": absolute_relative, | ||
"wrap": wrap, | ||
"linear": linear, | ||
"nPreferred": ~preferred, | ||
"null": null, | ||
"volatile": volatile, | ||
}) | ||
self.add_report_item(HIDPrefix.INPUT, ord(item_flags)) | ||
|
||
def add_output_item(self, | ||
data_constant = False, | ||
array_variable = True, | ||
absolute_relative = False, | ||
wrap = False, | ||
linear = False, | ||
preferred = True, | ||
null = False, | ||
volatile = False): | ||
"""Convenience function to add HID output item with preformatted flags. | ||
See HID 1.11 section 6.2.2.5 for flag meanings. | ||
""" | ||
item_flags = ItemFlags.build({ | ||
"data_constant": data_constant, | ||
"array_variable": array_variable, | ||
"absolute_relative": absolute_relative, | ||
"wrap": wrap, | ||
"linear": linear, | ||
"nPreferred": ~preferred, | ||
"null": null, | ||
"volatile": volatile, | ||
}) | ||
self.add_report_item(HIDPrefix.OUTPUT, ord(item_flags)) | ||
|
||
def __init__(self, parent_descriptor): | ||
super().__init__() | ||
# The HID Report Descriptor sits under a different USB Descriptor, | ||
# we need access to the descriptor root to create this. | ||
self._parent_descriptor = parent_descriptor | ||
self._reports = [] | ||
|
||
def _pre_emit(self): | ||
report_descriptor = [] | ||
for report in self._reports: | ||
if hasattr(report, "emit"): | ||
report_descriptor.append(report.emit()) | ||
else: | ||
report_descriptor.append(report) | ||
report_descriptor = b"".join(report_descriptor) | ||
descriptor_len = len(report_descriptor) | ||
self.wDescriptorLength = descriptor_len | ||
self._parent_descriptor.add_descriptor(report_descriptor, 0x22) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# | ||
# This file is part of usb-protocol. | ||
# | ||
""" Structures describing Communications Device Class descriptors. """ | ||
|
||
import unittest | ||
from enum import IntEnum, unique | ||
|
||
import construct | ||
from construct import this, Default | ||
|
||
from .. import LanguageIDs | ||
from ..descriptor import \ | ||
DescriptorField, DescriptorNumber, DescriptorFormat, \ | ||
BCDFieldAdapter, DescriptorLength | ||
|
||
@unique | ||
class HIDPrefix(IntEnum): | ||
# Main items | ||
INPUT = 0b1000_00 | ||
OUTPUT = 0b1001_00 | ||
FEATURE = 0b1011_00 | ||
COLLECTION = 0b1010_00 | ||
END_COLLECTION = 0b1100_00 | ||
# Global items | ||
USAGE_PAGE = 0b0000_01 | ||
LOGICAL_MIN = 0b0001_01 | ||
LOGICAL_MAX = 0b0010_01 | ||
PHYSICAL_MIN = 0b0011_01 | ||
PHYSICAL_MAX = 0b0100_01 | ||
UNIT_EXPONENT = 0b0101_01 | ||
UNIT = 0b0110_01 | ||
REPORT_SIZE = 0b0111_01 | ||
REPORT_ID = 0b1000_01 | ||
REPORT_COUNT = 0b1001_01 | ||
PUSH = 0b1010_01 | ||
POP = 0b1011_01 | ||
# Local Items | ||
USAGE = 0b0000_10 | ||
USAGE_MIN = 0b0001_10 | ||
USAGE_MAX = 0b0010_10 | ||
DESIGNATOR_IDX = 0b0011_10 | ||
DESIGNATOR_MIN = 0b0100_10 | ||
DESIGNATOR_MAX = 0b0101_10 | ||
STRING_IDX = 0b0111_10 | ||
STRING_MIN = 0b1000_10 | ||
STRING_MAX = 0b1001_10 | ||
DELIMITER = 0b1010_10 | ||
|
||
HIDDescriptor = DescriptorFormat( | ||
"bLength" / construct.Const(0x09, construct.Int8ul), | ||
"bDescriptorType" / DescriptorNumber(33), | ||
"bcdHID" / DescriptorField("HID Protocol Version", default=1.11), | ||
"bCountryCode" / DescriptorField("HID Device Language", default=0), | ||
"bNumDescriptors" / DescriptorField("Number of HID Descriptors", default=1), | ||
"bDescriptorType" / DescriptorField("HID Descriptor Type", default=34), | ||
"wDescriptorLength" / DescriptorField("HID Descriptor Length") | ||
# bDescriptorType and wDescriptorLength repeat bNumDescriptors times | ||
) | ||
|
||
_hid_item_length = [ 0, 1, 2, 4 ] | ||
ReportDescriptor = DescriptorFormat( | ||
"bHeader" / construct.BitStruct( | ||
# prefix technically consists of a 4 byte tag and a 2 byte type, | ||
# however, they're all listed together in the HID spec | ||
"prefix" / construct.Enum(construct.BitsInteger(6), HIDPrefix), | ||
"bSize" / construct.BitsInteger(2), | ||
), | ||
"data" / construct.Byte[lambda ctx: _hid_item_length[ctx.bHeader.bSize]] | ||
) | ||
|
||
# Flags for INPUT/OUTPUT/FEATURE items. Named under one of the following conventions: | ||
# valA_valB: valA when 0, valB when 1 | ||
# flag: Flag disabled when 0, flag enabled when 1 | ||
# nFlag: Flag enabled when 0, flag disabled when 1 | ||
ItemFlags = construct.BitStruct( | ||
"volatile" / construct.Flag, | ||
"null" / construct.Flag, | ||
"nPreferred" / construct.Flag, | ||
"linear" / construct.Flag, | ||
"wrap" / construct.Flag, | ||
"absolute_relative" / construct.Flag, | ||
"array_variable" / construct.Flag, | ||
"data_constant" / construct.Flag, | ||
) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seem to be a bunch of naming inconsistencies, here.
For example, this looks like it produces more than a HID descriptor (it also builds report descriptors), so perhaps this would be better called e.g. a
HIDDescriptorCollection
?