You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
4.5 KiB

  1. import unittest
  2. from contextlib import contextmanager
  3. from .. import emitter_for_format
  4. from ..descriptor import ComplexDescriptorEmitter
  5. from ...types.descriptors.hid import \
  6. HIDDescriptor as HIDDescriptorType
  7. from ...types.descriptors.hid import *
  8. ReportDescriptorItemEmitter = emitter_for_format(ReportDescriptorItem)
  9. from ...types.descriptors.hid import _hid_item_length, ItemFlags1, ItemFlags2
  10. class HIDDescriptor(ComplexDescriptorEmitter):
  11. DESCRIPTOR_FORMAT = HIDDescriptorType
  12. def add_report_raw(self, report_data):
  13. """Append raw report item or bytes to HID report
  14. Arguments:
  15. report_data -- bytes-like or ReportDescriptor to be appended to
  16. the HID report.
  17. """
  18. self._reports.append(report_data)
  19. def add_report_item(self, report_prefix, *report_data):
  20. """Convenience function to add formatted HID report item
  21. Arguments:
  22. report_prefix -- HIDPrefix enum representing report item type
  23. *report_data -- Additional bytes-like report item data.
  24. Valid lengths are 1, 2, or 4 bytes.
  25. """
  26. hid_report = ReportDescriptorItemEmitter()
  27. report_len = _hid_item_length.index(len(report_data))
  28. hid_report.bHeader = {
  29. "prefix": report_prefix,
  30. "bSize": report_len
  31. }
  32. hid_report.data = report_data
  33. self._reports.append(hid_report)
  34. def add_input_item(self, *args, **kwargs):
  35. """Convenience function to add HID input item with preformatted flags.
  36. See HID 1.11 section 6.2.2.5 for flag meanings.
  37. See add_inpout_item for argument names and defaults.
  38. """
  39. return self.add_inpout_item(HIDPrefix.INPUT, *args, **kwargs)
  40. def add_output_item(self, *args, **kwargs):
  41. """Convenience function to add HID output item with preformatted flags.
  42. See HID 1.11 section 6.2.2.5 for flag meanings.
  43. See add_inpout_item for argument names and defaults.
  44. """
  45. return self.add_inpout_item(HIDPrefix.OUTPUT, *args, **kwargs)
  46. def add_inpout_item(self, item,
  47. data_constant = False,
  48. array_variable = True,
  49. absolute_relative = False,
  50. wrap = False,
  51. linear = False,
  52. preferred = True,
  53. null = False,
  54. volatile = False,
  55. bitfield_bufferedbytes = False):
  56. if bitfield_bufferedbytes:
  57. itmf = ItemFlags2
  58. else:
  59. itmf = ItemFlags1
  60. item_flags = itmf.build({
  61. "data_constant": data_constant,
  62. "array_variable": array_variable,
  63. "absolute_relative": absolute_relative,
  64. "wrap": wrap,
  65. "nLinear": not linear,
  66. "nPreferred": not preferred,
  67. "null": null,
  68. "volatile": volatile,
  69. })
  70. self.add_report_item(item, item_flags)
  71. def __init__(self, parent_descriptor):
  72. super().__init__()
  73. # The HID Report Descriptor sits under a different USB Descriptor,
  74. # we need access to the descriptor root to create this.
  75. self._parent_descriptor = parent_descriptor
  76. self._reports = []
  77. def _pre_emit(self):
  78. report_descriptor = []
  79. for report in self._reports:
  80. if hasattr(report, "emit"):
  81. report_descriptor.append(report.emit())
  82. else:
  83. report_descriptor.append(report)
  84. report_descriptor = b"".join(report_descriptor)
  85. descriptor_len = len(report_descriptor)
  86. self.wDescriptorLength = descriptor_len
  87. self._parent_descriptor.add_descriptor(report_descriptor, descriptor_type=0x22)
  88. from ..descriptors import DeviceDescriptorCollection
  89. import unittest
  90. class TestHIDEmitter(unittest.TestCase):
  91. def test_hidemitter(self):
  92. collection = DeviceDescriptorCollection()
  93. hd = HIDDescriptor(collection)
  94. hd.add_report_item(HIDPrefix.USAGE_PAGE, 1)
  95. hd.add_report_item(HIDPrefix.USAGE, 6)
  96. hd.add_report_item(HIDPrefix.COLLECTION, 1)
  97. hd.add_report_item(HIDPrefix.USAGE_PAGE, 7)
  98. hd.add_report_item(HIDPrefix.USAGE_MIN, 224)
  99. hd.add_report_item(HIDPrefix.USAGE_MAX, 231)
  100. hd.add_report_item(HIDPrefix.LOGICAL_MIN, 0)
  101. hd.add_report_item(HIDPrefix.LOGICAL_MAX, 1)
  102. hd.add_report_item(HIDPrefix.REPORT_SIZE, 1)
  103. hd.add_report_item(HIDPrefix.REPORT_COUNT, 8)
  104. hd.add_input_item(data_constant=False, array_variable=True, absolute_relative=False)
  105. import codecs
  106. print(repr(codecs.encode(hd.emit(), 'hex')))