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.

69 lines
1.9 KiB

  1. #
  2. # This file is part of usb-protocol.
  3. #
  4. from . import ConstructEmitter
  5. from collections import defaultdict
  6. class ComplexDescriptorEmitter(ConstructEmitter):
  7. """ Base class for emitting complex descriptors, which contain nested subordinates. """
  8. # Base classes should override this.
  9. DESCRIPTOR_FORMAT = None
  10. def __init__(self):
  11. # Always create a basic ConstructEmitter from the given format.
  12. super().__init__(self.DESCRIPTOR_FORMAT)
  13. # Store a list of subordinate descriptors, and a count of
  14. # subordinate descriptor types.
  15. self._subordinates = []
  16. self._type_counts = {}
  17. def add_subordinate_descriptor(self, subordinate):
  18. """ Adds a subordinate descriptor to the relevant descriptor.
  19. Parameter:
  20. subordinate -- The subordinate descriptor to add; can be an emitter,
  21. or a bytes-like object.
  22. """
  23. if hasattr(subordinate, 'emit'):
  24. subordinate = subordinate.emit()
  25. else:
  26. subordinate = bytes(subordinate)
  27. # The second byte of a given descriptor is always its type number.
  28. # Count this descriptor type...
  29. subordinate_type = subordinate[1]
  30. try:
  31. self._type_counts[subordinate_type] += 1
  32. except KeyError:
  33. self._type_counts[subordinate_type] = 1
  34. # ... and add the relevant bytes to our list of subordinates.
  35. self._subordinates.append(subordinate)
  36. def emit(self, include_subordinates=True):
  37. """ Emit our descriptor.
  38. Parameters:
  39. include_subordinates -- If true or not provided, any subordinate descriptors will be included.
  40. """
  41. result = bytearray()
  42. # Add our basic descriptor...
  43. result.extend(super().emit())
  44. # ... and if descired, add our subordinates...
  45. for sub in self._subordinates:
  46. result.extend(sub)
  47. return bytes(result)