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 """USB echo gadget module. 6 7 This gadget has pairs of IN/OUT endpoints that echo packets back to the host. 8 """ 9 10 import math 11 import struct 12 import uuid 13 14 import gadget 15 import usb_constants 16 import usb_descriptors 17 18 19 class EchoGadget(gadget.Gadget): 20 """Echo gadget. 21 """ 22 23 def __init__(self): 24 """Create an echo gadget. 25 """ 26 device_desc = usb_descriptors.DeviceDescriptor( 27 idVendor=usb_constants.VendorID.GOOGLE, 28 idProduct=usb_constants.ProductID.GOOGLE_ECHO_GADGET, 29 bcdUSB=0x0200, 30 iManufacturer=1, 31 iProduct=2, 32 iSerialNumber=3, 33 bcdDevice=0x0100) 34 35 fs_config_desc = usb_descriptors.ConfigurationDescriptor( 36 bmAttributes=0x80, 37 MaxPower=50) 38 fs_intr_interface_desc = usb_descriptors.InterfaceDescriptor( 39 bInterfaceNumber=0, 40 bInterfaceClass=usb_constants.DeviceClass.VENDOR, 41 bInterfaceSubClass=0, 42 bInterfaceProtocol=0, 43 iInterface=4, 44 ) 45 fs_intr_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 46 bEndpointAddress=0x01, 47 bmAttributes=usb_constants.TransferType.INTERRUPT, 48 wMaxPacketSize=64, 49 bInterval=1 # 1ms 50 )) 51 fs_intr_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 52 bEndpointAddress=0x81, 53 bmAttributes=usb_constants.TransferType.INTERRUPT, 54 wMaxPacketSize=64, 55 bInterval=1 # 1ms 56 )) 57 fs_config_desc.AddInterface(fs_intr_interface_desc) 58 59 fs_bulk_interface_desc = usb_descriptors.InterfaceDescriptor( 60 bInterfaceNumber=1, 61 bInterfaceClass=usb_constants.DeviceClass.VENDOR, 62 bInterfaceSubClass=0, 63 bInterfaceProtocol=0, 64 iInterface=5 65 ) 66 fs_bulk_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 67 bEndpointAddress=0x02, 68 bmAttributes=usb_constants.TransferType.BULK, 69 wMaxPacketSize=64, 70 bInterval=0 71 )) 72 fs_bulk_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 73 bEndpointAddress=0x82, 74 bmAttributes=usb_constants.TransferType.BULK, 75 wMaxPacketSize=64, 76 bInterval=0 77 )) 78 fs_config_desc.AddInterface(fs_bulk_interface_desc) 79 80 fs_config_desc.AddInterface(usb_descriptors.InterfaceDescriptor( 81 bInterfaceNumber=2, 82 bInterfaceClass=usb_constants.DeviceClass.VENDOR, 83 bInterfaceSubClass=0, 84 bInterfaceProtocol=0, 85 iInterface=6 86 )) 87 fs_isoc_interface_desc = usb_descriptors.InterfaceDescriptor( 88 bInterfaceNumber=2, 89 bAlternateSetting=1, 90 bInterfaceClass=usb_constants.DeviceClass.VENDOR, 91 bInterfaceSubClass=0, 92 bInterfaceProtocol=0, 93 iInterface=6 94 ) 95 fs_isoc_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 96 bEndpointAddress=0x03, 97 bmAttributes=usb_constants.TransferType.ISOCHRONOUS, 98 wMaxPacketSize=1023, 99 bInterval=1 # 1ms 100 )) 101 fs_isoc_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 102 bEndpointAddress=0x83, 103 bmAttributes=usb_constants.TransferType.ISOCHRONOUS, 104 wMaxPacketSize=1023, 105 bInterval=1 # 1ms 106 )) 107 fs_config_desc.AddInterface(fs_isoc_interface_desc) 108 109 hs_config_desc = usb_descriptors.ConfigurationDescriptor( 110 bmAttributes=0x80, 111 MaxPower=50) 112 113 hs_intr_interface_desc = usb_descriptors.InterfaceDescriptor( 114 bInterfaceNumber=0, 115 bInterfaceClass=usb_constants.DeviceClass.VENDOR, 116 bInterfaceSubClass=0, 117 bInterfaceProtocol=0, 118 iInterface=4 119 ) 120 hs_intr_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 121 bEndpointAddress=0x01, 122 bmAttributes=usb_constants.TransferType.INTERRUPT, 123 wMaxPacketSize=64, 124 bInterval=4 # 1ms 125 )) 126 hs_intr_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 127 bEndpointAddress=0x81, 128 bmAttributes=usb_constants.TransferType.INTERRUPT, 129 wMaxPacketSize=64, 130 bInterval=4 # 1ms 131 )) 132 hs_config_desc.AddInterface(hs_intr_interface_desc) 133 134 hs_bulk_interface_desc = usb_descriptors.InterfaceDescriptor( 135 bInterfaceNumber=1, 136 bInterfaceClass=usb_constants.DeviceClass.VENDOR, 137 bInterfaceSubClass=0, 138 bInterfaceProtocol=0, 139 iInterface=5 140 ) 141 hs_bulk_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 142 bEndpointAddress=0x02, 143 bmAttributes=usb_constants.TransferType.BULK, 144 wMaxPacketSize=512, 145 bInterval=0 146 )) 147 hs_bulk_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 148 bEndpointAddress=0x82, 149 bmAttributes=usb_constants.TransferType.BULK, 150 wMaxPacketSize=512, 151 bInterval=0 152 )) 153 hs_config_desc.AddInterface(hs_bulk_interface_desc) 154 155 hs_config_desc.AddInterface(usb_descriptors.InterfaceDescriptor( 156 bInterfaceNumber=2, 157 bInterfaceClass=usb_constants.DeviceClass.VENDOR, 158 bInterfaceSubClass=0, 159 bInterfaceProtocol=0, 160 iInterface=6 161 )) 162 hs_isoc_interface_desc = usb_descriptors.InterfaceDescriptor( 163 bInterfaceNumber=2, 164 bAlternateSetting=1, 165 bInterfaceClass=usb_constants.DeviceClass.VENDOR, 166 bInterfaceSubClass=0, 167 bInterfaceProtocol=0, 168 iInterface=6 169 ) 170 hs_isoc_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 171 bEndpointAddress=0x03, 172 bmAttributes=usb_constants.TransferType.ISOCHRONOUS, 173 wMaxPacketSize=1024, 174 bInterval=4 # 1ms 175 )) 176 hs_isoc_interface_desc.AddEndpoint(usb_descriptors.EndpointDescriptor( 177 bEndpointAddress=0x83, 178 bmAttributes=usb_constants.TransferType.ISOCHRONOUS, 179 wMaxPacketSize=1024, 180 bInterval=4 # 1ms 181 )) 182 hs_config_desc.AddInterface(hs_isoc_interface_desc) 183 184 super(EchoGadget, self).__init__( 185 device_desc, fs_config_desc, hs_config_desc) 186 self.AddStringDescriptor(1, 'Google Inc.') 187 self.AddStringDescriptor(2, 'Echo Gadget') 188 self.AddStringDescriptor(3, '{:06X}'.format(uuid.getnode())) 189 self.AddStringDescriptor(4, 'Interrupt Echo') 190 self.AddStringDescriptor(5, 'Bulk Echo') 191 self.AddStringDescriptor(6, 'Isochronous Echo') 192 193 def ReceivePacket(self, endpoint, data): 194 """Echo a packet back to the host. 195 196 Args: 197 endpoint: Incoming endpoint (must be an OUT pipe). 198 data: Packet data. 199 """ 200 assert endpoint & usb_constants.Dir.IN == 0 201 202 self.SendPacket(endpoint | usb_constants.Dir.IN, data) 203 204 def RegisterHandlers(): 205 """Registers web request handlers with the application server.""" 206 207 import server 208 from tornado import web 209 210 class WebConfigureHandler(web.RequestHandler): 211 212 def post(self): 213 server.SwitchGadget(EchoGadget()) 214 215 server.app.add_handlers('.*$', [ 216 (r'/echo/configure', WebConfigureHandler), 217 ]) 218