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.

109 lines
3.9 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. ReportDescriptorEmitter = emitter_for_format(ReportDescriptor)
  9. _hid_item_length = [ 0, 1, 2, 4 ]
  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 = ReportDescriptorEmitter()
  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,
  35. data_constant = False,
  36. array_variable = True,
  37. absolute_relative = False,
  38. wrap = False,
  39. linear = False,
  40. preferred = True,
  41. null = False,
  42. volatile = False):
  43. """Convenience function to add HID input item with preformatted flags.
  44. See HID 1.11 section 6.2.2.5 for flag meanings.
  45. """
  46. item_flags = ItemFlags.build({
  47. "data_constant": data_constant,
  48. "array_variable": array_variable,
  49. "absolute_relative": absolute_relative,
  50. "wrap": wrap,
  51. "linear": linear,
  52. "nPreferred": ~preferred,
  53. "null": null,
  54. "volatile": volatile,
  55. })
  56. self.add_report_item(HIDPrefix.INPUT, ord(item_flags))
  57. def add_output_item(self,
  58. data_constant = False,
  59. array_variable = True,
  60. absolute_relative = False,
  61. wrap = False,
  62. linear = False,
  63. preferred = True,
  64. null = False,
  65. volatile = False):
  66. """Convenience function to add HID output item with preformatted flags.
  67. See HID 1.11 section 6.2.2.5 for flag meanings.
  68. """
  69. item_flags = ItemFlags.build({
  70. "data_constant": data_constant,
  71. "array_variable": array_variable,
  72. "absolute_relative": absolute_relative,
  73. "wrap": wrap,
  74. "linear": linear,
  75. "nPreferred": ~preferred,
  76. "null": null,
  77. "volatile": volatile,
  78. })
  79. self.add_report_item(HIDPrefix.OUTPUT, ord(item_flags))
  80. def __init__(self, parent_descriptor):
  81. super().__init__()
  82. # The HID Report Descriptor sits under a different USB Descriptor,
  83. # we need access to the descriptor root to create this.
  84. self._parent_descriptor = parent_descriptor
  85. self._reports = []
  86. def _pre_emit(self):
  87. report_descriptor = []
  88. for report in self._reports:
  89. if hasattr(report, "emit"):
  90. report_descriptor.append(report.emit())
  91. else:
  92. report_descriptor.append(report)
  93. report_descriptor = b"".join(report_descriptor)
  94. descriptor_len = len(report_descriptor)
  95. self.wDescriptorLength = descriptor_len
  96. self._parent_descriptor.add_descriptor(report_descriptor, descriptor_type=0x22)