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.
5 """USB echo gadget module.
7 This gadget has pairs of IN/OUT endpoints that echo packets back to the host.
12 import composite_gadget
14 import usb_descriptors
17 class EchoCompositeFeature(composite_gadget
.CompositeFeature
):
18 """Composite device feature that echos data back to the host.
21 def __init__(self
, endpoints
):
22 """Create an echo gadget.
27 if len(endpoints
) >= 1:
28 iface_num
, iface_string
, in_endpoint
, out_endpoint
= endpoints
[0]
29 fs_intr_interface_desc
= usb_descriptors
.InterfaceDescriptor(
30 bInterfaceNumber
=iface_num
,
31 bInterfaceClass
=usb_constants
.DeviceClass
.VENDOR
,
34 iInterface
=iface_string
,
36 fs_intr_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
37 bEndpointAddress
=out_endpoint
,
38 bmAttributes
=usb_constants
.TransferType
.INTERRUPT
,
42 fs_intr_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
43 bEndpointAddress
=in_endpoint
,
44 bmAttributes
=usb_constants
.TransferType
.INTERRUPT
,
48 fs_interfaces
.append(fs_intr_interface_desc
)
50 hs_intr_interface_desc
= usb_descriptors
.InterfaceDescriptor(
51 bInterfaceNumber
=iface_num
,
52 bInterfaceClass
=usb_constants
.DeviceClass
.VENDOR
,
55 iInterface
=iface_string
57 hs_intr_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
58 bEndpointAddress
=out_endpoint
,
59 bmAttributes
=usb_constants
.TransferType
.INTERRUPT
,
63 hs_intr_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
64 bEndpointAddress
=in_endpoint
,
65 bmAttributes
=usb_constants
.TransferType
.INTERRUPT
,
69 hs_interfaces
.append(hs_intr_interface_desc
)
71 if len(endpoints
) >= 2:
72 iface_num
, iface_string
, in_endpoint
, out_endpoint
= endpoints
[1]
73 fs_bulk_interface_desc
= usb_descriptors
.InterfaceDescriptor(
74 bInterfaceNumber
=iface_num
,
75 bInterfaceClass
=usb_constants
.DeviceClass
.VENDOR
,
78 iInterface
=iface_string
80 fs_bulk_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
81 bEndpointAddress
=out_endpoint
,
82 bmAttributes
=usb_constants
.TransferType
.BULK
,
86 fs_bulk_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
87 bEndpointAddress
=in_endpoint
,
88 bmAttributes
=usb_constants
.TransferType
.BULK
,
92 fs_interfaces
.append(fs_bulk_interface_desc
)
94 hs_bulk_interface_desc
= usb_descriptors
.InterfaceDescriptor(
95 bInterfaceNumber
=iface_num
,
96 bInterfaceClass
=usb_constants
.DeviceClass
.VENDOR
,
99 iInterface
=iface_string
101 hs_bulk_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
102 bEndpointAddress
=out_endpoint
,
103 bmAttributes
=usb_constants
.TransferType
.BULK
,
107 hs_bulk_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
108 bEndpointAddress
=in_endpoint
,
109 bmAttributes
=usb_constants
.TransferType
.BULK
,
113 hs_interfaces
.append(hs_bulk_interface_desc
)
115 if len(endpoints
) >= 3:
116 iface_num
, iface_string
, in_endpoint
, out_endpoint
= endpoints
[2]
117 fs_interfaces
.append(usb_descriptors
.InterfaceDescriptor(
118 bInterfaceNumber
=iface_num
,
119 bInterfaceClass
=usb_constants
.DeviceClass
.VENDOR
,
120 bInterfaceSubClass
=0,
121 bInterfaceProtocol
=0,
122 iInterface
=iface_string
124 fs_isoc_interface_desc
= usb_descriptors
.InterfaceDescriptor(
125 bInterfaceNumber
=iface_num
,
127 bInterfaceClass
=usb_constants
.DeviceClass
.VENDOR
,
128 bInterfaceSubClass
=0,
129 bInterfaceProtocol
=0,
130 iInterface
=iface_string
132 fs_isoc_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
133 bEndpointAddress
=out_endpoint
,
134 bmAttributes
=usb_constants
.TransferType
.ISOCHRONOUS
,
138 fs_isoc_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
139 bEndpointAddress
=in_endpoint
,
140 bmAttributes
=usb_constants
.TransferType
.ISOCHRONOUS
,
144 fs_interfaces
.append(fs_isoc_interface_desc
)
146 hs_interfaces
.append(usb_descriptors
.InterfaceDescriptor(
147 bInterfaceNumber
=iface_num
,
148 bInterfaceClass
=usb_constants
.DeviceClass
.VENDOR
,
149 bInterfaceSubClass
=0,
150 bInterfaceProtocol
=0,
151 iInterface
=iface_string
153 hs_isoc_interface_desc
= usb_descriptors
.InterfaceDescriptor(
154 bInterfaceNumber
=iface_num
,
156 bInterfaceClass
=usb_constants
.DeviceClass
.VENDOR
,
157 bInterfaceSubClass
=0,
158 bInterfaceProtocol
=0,
159 iInterface
=iface_string
161 hs_isoc_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
162 bEndpointAddress
=out_endpoint
,
163 bmAttributes
=usb_constants
.TransferType
.ISOCHRONOUS
,
167 hs_isoc_interface_desc
.AddEndpoint(usb_descriptors
.EndpointDescriptor(
168 bEndpointAddress
=in_endpoint
,
169 bmAttributes
=usb_constants
.TransferType
.ISOCHRONOUS
,
173 hs_interfaces
.append(hs_isoc_interface_desc
)
175 super(EchoCompositeFeature
, self
).__init
__(fs_interfaces
, hs_interfaces
)
177 def ReceivePacket(self
, endpoint
, data
):
178 """Echo a packet back to the host.
181 endpoint: Incoming endpoint (must be an OUT pipe).
184 assert endpoint
& usb_constants
.Dir
.IN
== 0
186 self
.SendPacket(endpoint | usb_constants
.Dir
.IN
, data
)
189 class EchoGadget(composite_gadget
.CompositeGadget
):
194 """Create an echo gadget.
196 device_desc
= usb_descriptors
.DeviceDescriptor(
197 idVendor
=usb_constants
.VendorID
.GOOGLE
,
198 idProduct
=usb_constants
.ProductID
.GOOGLE_ECHO_GADGET
,
205 feature
= EchoCompositeFeature(
206 endpoints
=[(0, 4, 0x81, 0x01), (1, 5, 0x82, 0x02), (2, 6, 0x83, 0x03)])
208 super(EchoGadget
, self
).__init
__(device_desc
, [feature
])
209 self
.AddStringDescriptor(1, 'Google Inc.')
210 self
.AddStringDescriptor(2, 'Echo Gadget')
211 self
.AddStringDescriptor(3, '{:06X}'.format(uuid
.getnode()))
212 self
.AddStringDescriptor(4, 'Interrupt Echo')
213 self
.AddStringDescriptor(5, 'Bulk Echo')
214 self
.AddStringDescriptor(6, 'Isochronous Echo')
216 # Enable Microsoft OS Descriptors for Windows 8 and above.
217 self
.EnableMicrosoftOSDescriptorsV1(vendor_code
=0x01)
218 # These are used to force Windows to load WINUSB.SYS for the echo functions.
219 self
.SetMicrosoftCompatId(0, 'WINUSB')
220 self
.SetMicrosoftCompatId(1, 'WINUSB')
221 self
.SetMicrosoftCompatId(2, 'WINUSB')
223 self
.AddDeviceCapabilityDescriptor(usb_descriptors
.ContainerIdDescriptor(
224 ContainerID
=uuid
.uuid4().bytes_le
))
226 def RegisterHandlers():
227 """Registers web request handlers with the application server."""
230 from tornado
import web
232 class WebConfigureHandler(web
.RequestHandler
):
235 server
.SwitchGadget(EchoGadget())
237 server
.app
.add_handlers('.*$', [
238 (r
'/echo/configure', WebConfigureHandler
),