class EchoFeature(hid_gadget.HidFeature): REPORT_DESC = hid_descriptors.ReportDescriptor( hid_descriptors.UsagePage(0xFF00), # Vendor Defined hid_descriptors.Usage(0), hid_descriptors.Collection( hid_constants.CollectionType.APPLICATION, hid_descriptors.LogicalMinimum(0, force_length=1), hid_descriptors.LogicalMaximum(255, force_length=2), hid_descriptors.ReportSize(8), hid_descriptors.ReportCount(8), hid_descriptors.Usage(0), hid_descriptors.Input(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute), hid_descriptors.Usage(0), hid_descriptors.Output(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute), hid_descriptors.Usage(0), hid_descriptors.Feature(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute) ) ) def __init__(self): super(EchoFeature, self).__init__() self._input_output_report = 0 self._feature_report = 0 def SetInputReport(self, data): self._input_output_report, = struct.unpack('<Q', data) self.SendReport(struct.pack('<Q', self._input_output_report)) return True def SetOutputReport(self, data): self._input_output_report, = struct.unpack('<Q', data) self.SendReport(struct.pack('<Q', self._input_output_report)) return True def SetFeatureReport(self, data): self._feature_report, = struct.unpack('<Q', data) return True def GetInputReport(self): return struct.pack('<Q', self._input_output_report) def GetOutputReport(self): return struct.pack('<Q', self._input_output_report) def GetFeatureReport(self): return struct.pack('<Q', self._feature_report)
import unittest import mock import hid_constants import hid_descriptors import hid_gadget import usb_constants report_desc = hid_descriptors.ReportDescriptor( hid_descriptors.UsagePage(0xFF00), # Vendor Defined hid_descriptors.Usage(0x00), hid_descriptors.Collection( hid_constants.CollectionType.APPLICATION, hid_descriptors.LogicalMinimum(0, force_length=1), hid_descriptors.LogicalMaximum(255, force_length=2), hid_descriptors.ReportSize(8), hid_descriptors.ReportCount(8), hid_descriptors.Input(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute, hid_descriptors.BufferedBytes), hid_descriptors.Output(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute, hid_descriptors.BufferedBytes), hid_descriptors.Feature(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute, hid_descriptors.BufferedBytes))) combo_report_desc = hid_descriptors.ReportDescriptor( hid_descriptors.ReportID(1), report_desc, hid_descriptors.ReportID(2), report_desc)
class MouseFeature(hid_gadget.HidFeature): """HID feature implementation for a mouse. REPORT_DESC provides an example HID report descriptor for a device including this functionality. """ REPORT_DESC = hid_descriptors.ReportDescriptor( hid_descriptors.UsagePage(0x01), # Generic Desktop hid_descriptors.Usage(0x02), # Mouse hid_descriptors.Collection( hid_constants.CollectionType.APPLICATION, hid_descriptors.Usage(0x01), # Pointer hid_descriptors.Collection( hid_constants.CollectionType.PHYSICAL, hid_descriptors.UsagePage(0x09), # Buttons hid_descriptors.UsageMinimum(1), hid_descriptors.UsageMaximum(3), hid_descriptors.LogicalMinimum(0, force_length=1), hid_descriptors.LogicalMaximum(1), hid_descriptors.ReportCount(3), hid_descriptors.ReportSize(1), hid_descriptors.Input(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute), hid_descriptors.ReportCount(1), hid_descriptors.ReportSize(5), hid_descriptors.Input(hid_descriptors.Constant), hid_descriptors.UsagePage(0x01), # Generic Desktop hid_descriptors.Usage(0x30), # X hid_descriptors.Usage(0x31), # Y hid_descriptors.LogicalMinimum(0x81), # -127 hid_descriptors.LogicalMaximum(127), hid_descriptors.ReportSize(8), hid_descriptors.ReportCount(2), hid_descriptors.Input(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Relative)))) def __init__(self): super(MouseFeature, self).__init__() self._buttons = 0 def ButtonDown(self, button): self._buttons |= button if self.IsConnected(): self.SendReport(self.EncodeInputReport()) def ButtonUp(self, button): self._buttons &= ~button if self.IsConnected(): self.SendReport(self.EncodeInputReport()) def Move(self, x_displacement, y_displacement): if self.IsConnected(): self.SendReport( self.EncodeInputReport(x_displacement, y_displacement)) def EncodeInputReport(self, x_displacement=0, y_displacement=0): return struct.pack('Bbb', self._buttons, x_displacement, y_displacement) def GetInputReport(self): """Construct an input report. See Device Class Definition for Human Interface Devices (HID) Version 1.11 Appendix B.2. Returns: A packed input report. """ return self.EncodeInputReport()
class KeyboardFeature(hid_gadget.HidFeature): """HID feature implementation for a keyboard. REPORT_DESC provides an example HID report descriptor for a device including this functionality. """ REPORT_DESC = hid_descriptors.ReportDescriptor( hid_descriptors.UsagePage(0x01), # Generic Desktop hid_descriptors.Usage(0x06), # Keyboard hid_descriptors.Collection( hid_constants.CollectionType.APPLICATION, hid_descriptors.UsagePage(0x07), # Key Codes hid_descriptors.UsageMinimum(224), hid_descriptors.UsageMaximum(231), hid_descriptors.LogicalMinimum(0, force_length=1), hid_descriptors.LogicalMaximum(1), hid_descriptors.ReportSize(1), hid_descriptors.ReportCount(8), hid_descriptors.Input(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute), hid_descriptors.ReportCount(1), hid_descriptors.ReportSize(8), hid_descriptors.Input(hid_descriptors.Constant), hid_descriptors.ReportCount(5), hid_descriptors.ReportSize(1), hid_descriptors.UsagePage(0x08), # LEDs hid_descriptors.UsageMinimum(1), hid_descriptors.UsageMaximum(5), hid_descriptors.Output(hid_descriptors.Data, hid_descriptors.Variable, hid_descriptors.Absolute), hid_descriptors.ReportCount(1), hid_descriptors.ReportSize(3), hid_descriptors.Output(hid_descriptors.Constant), hid_descriptors.ReportCount(6), hid_descriptors.ReportSize(8), hid_descriptors.LogicalMinimum(0, force_length=1), hid_descriptors.LogicalMaximum(101), hid_descriptors.UsagePage(0x07), # Key Codes hid_descriptors.UsageMinimum(0, force_length=1), hid_descriptors.UsageMaximum(101), hid_descriptors.Input(hid_descriptors.Data, hid_descriptors.Array))) def __init__(self): super(KeyboardFeature, self).__init__() self._modifiers = 0 self._keys = [0, 0, 0, 0, 0, 0] self._leds = 0 def ModifierDown(self, modifier): self._modifiers |= modifier if self.IsConnected(): self.SendReport(self.GetInputReport()) def ModifierUp(self, modifier): self._modifiers &= ~modifier if self.IsConnected(): self.SendReport(self.GetInputReport()) def KeyDown(self, keycode): free = self._keys.index(0) self._keys[free] = keycode if self.IsConnected(): self.SendReport(self.GetInputReport()) def KeyUp(self, keycode): free = self._keys.index(keycode) self._keys[free] = 0 if self.IsConnected(): self.SendReport(self.GetInputReport()) def GetInputReport(self): """Construct an input report. See Device Class Definition for Human Interface Devices (HID) Version 1.11 Appendix B.1. Returns: A packed input report. """ return struct.pack('BBBBBBBB', self._modifiers, 0, *self._keys) def GetOutputReport(self): """Construct an output report. See Device Class Definition for Human Interface Devices (HID) Version 1.11 Appendix B.1. Returns: A packed input report. """ return struct.pack('B', self._leds) def SetOutputReport(self, data): """Handle an output report. See Device Class Definition for Human Interface Devices (HID) Version 1.11 Appendix B.1. Args: data: Report data. Returns: True on success, None to stall the pipe. """ if len(data) >= 1: self._leds, = struct.unpack('B', data) return True