1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""A HID-class echo device. 6 7This module provides a HID feature and HID device that can be used as an 8echo test for HID drivers. The device exposes vendor-specific input, output 9and feature usages that transmit 8 bytes of data. Data written sent as an 10output report is echoed as an input report. The value of the feature report 11can be written and read with control transfers. 12""" 13 14import struct 15 16import hid_constants 17import hid_descriptors 18import hid_gadget 19import usb_constants 20 21 22class EchoFeature(hid_gadget.HidFeature): 23 24 REPORT_DESC = hid_descriptors.ReportDescriptor( 25 hid_descriptors.UsagePage(0xFF00), # Vendor Defined 26 hid_descriptors.Usage(0), 27 hid_descriptors.Collection( 28 hid_constants.CollectionType.APPLICATION, 29 hid_descriptors.LogicalMinimum(0, force_length=1), 30 hid_descriptors.LogicalMaximum(255, force_length=2), 31 hid_descriptors.ReportSize(8), 32 hid_descriptors.ReportCount(8), 33 hid_descriptors.Usage(0), 34 hid_descriptors.Input(hid_descriptors.Data, 35 hid_descriptors.Variable, 36 hid_descriptors.Absolute), 37 hid_descriptors.Usage(0), 38 hid_descriptors.Output(hid_descriptors.Data, 39 hid_descriptors.Variable, 40 hid_descriptors.Absolute), 41 hid_descriptors.Usage(0), 42 hid_descriptors.Feature(hid_descriptors.Data, 43 hid_descriptors.Variable, 44 hid_descriptors.Absolute) 45 ) 46 ) 47 48 def __init__(self): 49 super(EchoFeature, self).__init__() 50 self._input_output_report = 0 51 self._feature_report = 0 52 53 def SetInputReport(self, data): 54 self._input_output_report, = struct.unpack('<Q', data) 55 self.SendReport(struct.pack('<Q', self._input_output_report)) 56 return True 57 58 def SetOutputReport(self, data): 59 self._input_output_report, = struct.unpack('<Q', data) 60 self.SendReport(struct.pack('<Q', self._input_output_report)) 61 return True 62 63 def SetFeatureReport(self, data): 64 self._feature_report, = struct.unpack('<Q', data) 65 return True 66 67 def GetInputReport(self): 68 return struct.pack('<Q', self._input_output_report) 69 70 def GetOutputReport(self): 71 return struct.pack('<Q', self._input_output_report) 72 73 def GetFeatureReport(self): 74 return struct.pack('<Q', self._feature_report) 75 76 77class EchoGadget(hid_gadget.HidGadget): 78 79 def __init__(self): 80 self._feature = EchoFeature() 81 super(EchoGadget, self).__init__( 82 report_desc=EchoFeature.REPORT_DESC, 83 features={0: self._feature}, 84 packet_size=8, 85 interval_ms=1, 86 out_endpoint=True, 87 vendor_id=usb_constants.VendorID.GOOGLE, 88 product_id=usb_constants.ProductID.GOOGLE_HID_ECHO_GADGET, 89 device_version=0x0100) 90 self.AddStringDescriptor(1, 'Google Inc.') 91 self.AddStringDescriptor(2, 'HID Echo Gadget') 92 93 94def RegisterHandlers(): 95 from tornado import web 96 97 class WebConfigureHandler(web.RequestHandler): 98 99 def post(self): 100 server.SwitchGadget(EchoGadget()) 101 102 import server 103 server.app.add_handlers('.*$', [ 104 (r'/hid_echo/configure', WebConfigureHandler), 105 ]) 106