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 """Generic USB gadget functionality.
10 import msos20_descriptors
12 import usb_descriptors
16 """Basic functionality for a USB device.
18 Implements standard control requests assuming that a subclass will handle
19 class- or vendor-specific requests.
22 def __init__(self
, device_desc
, fs_config_desc
, hs_config_desc
):
23 """Create a USB gadget device.
26 device_desc: USB device descriptor.
27 fs_config_desc: Low/full-speed device descriptor.
28 hs_config_desc: High-speed device descriptor.
30 self
._speed
= usb_constants
.Speed
.UNKNOWN
32 self
._device
_desc
= device_desc
33 self
._fs
_config
_desc
= fs_config_desc
34 self
._hs
_config
_desc
= hs_config_desc
35 # dict mapping language codes to a dict mapping indexes to strings
37 self
._bos
_descriptor
= None
38 # dict mapping interface numbers to a set of endpoint addresses
39 self
._active
_endpoints
= {}
40 # dict mapping endpoint addresses to interfaces
41 self
._endpoint
_interface
_map
= {}
42 self
._ms
_vendor
_code
_v
1 = None
43 self
._ms
_vendor
_code
_v
2 = None
44 self
._ms
_compat
_ids
= {}
45 self
._ms
_os
20_config
_subset
= None
47 def GetDeviceDescriptor(self
):
48 return self
._device
_desc
50 def GetFullSpeedConfigurationDescriptor(self
):
51 return self
._fs
_config
_desc
53 def GetHighSpeedConfigurationDescriptor(self
):
54 return self
._hs
_config
_desc
56 def GetConfigurationDescriptor(self
):
57 if self
._speed
== usb_constants
.Speed
.FULL
:
58 return self
._fs
_config
_desc
59 elif self
._speed
== usb_constants
.Speed
.HIGH
:
60 return self
._hs
_config
_desc
62 raise RuntimeError('Device is not connected.')
67 def AddStringDescriptor(self
, index
, value
, lang
=0x0409):
68 """Add a string descriptor to this device.
71 index: String descriptor index (matches 'i' fields in descriptors).
73 lang: Language code (default: English).
76 ValueError: The index or language code is invalid.
78 if index
< 1 or index
> 255:
79 raise ValueError('String descriptor index out of range.')
80 if lang
< 0 or lang
> 0xffff:
81 raise ValueError('String descriptor language code out of range.')
83 lang_strings
= self
._strings
.setdefault(lang
, {})
84 lang_strings
[index
] = value
86 def EnableMicrosoftOSDescriptorsV1(self
, vendor_code
=0x01):
87 if vendor_code
< 0 or vendor_code
> 255:
88 raise ValueError('Vendor code out of range.')
89 if vendor_code
== self
._ms
_vendor
_code
_v
1:
90 raise ValueError('OS Descriptor v1 vendor code conflicts with v2.')
92 self
._ms
_vendor
_code
_v
1 = vendor_code
94 def EnableMicrosoftOSDescriptorsV2(self
, vendor_code
=0x02):
95 if vendor_code
< 0 or vendor_code
> 255:
96 raise ValueError('Vendor code out of range.')
97 if vendor_code
== self
._ms
_vendor
_code
_v
1:
98 raise ValueError('OS Descriptor v2 vendor code conflicts with v1.')
100 self
._ms
_vendor
_code
_v
2 = vendor_code
101 self
._ms
_os
20_descriptor
_set
= \
102 msos20_descriptors
.DescriptorSetHeader(dwWindowsVersion
=0x06030000)
103 # Gadget devices currently only support one configuration. Contrary to
104 # Microsoft's documentation the bConfigurationValue field should be set to
105 # the index passed to GET_DESCRIPTOR that returned the configuration instead
106 # of the configuration's bConfigurationValue field. (i.e. 0 instead of 1).
108 # https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/ae64282c-3bc3-49af-8391-4d174479d9e7/microsoft-os-20-descriptors-not-working-on-an-interface-of-a-composite-usb-device
109 self
._ms
_os
20_config
_subset
= msos20_descriptors
.ConfigurationSubsetHeader(
110 bConfigurationValue
=0)
111 self
._ms
_os
20_descriptor
_set
.Add(self
._ms
_os
20_config
_subset
)
112 self
._ms
_os
20_platform
_descriptor
= \
113 msos20_descriptors
.PlatformCapabilityDescriptor(
114 dwWindowsVersion
=0x06030000,
115 bMS_VendorCode
=self
._ms
_vendor
_code
_v
2)
116 self
._ms
_os
20_platform
_descriptor
.SetDescriptorSet(
117 self
._ms
_os
20_descriptor
_set
)
118 self
.AddDeviceCapabilityDescriptor(self
._ms
_os
20_platform
_descriptor
)
120 def SetMicrosoftCompatId(self
, interface_number
, compat_id
, sub_compat_id
=''):
121 self
._ms
_compat
_ids
[interface_number
] = (compat_id
, sub_compat_id
)
122 if self
._ms
_os
20_config
_subset
is not None:
123 function_header
= msos20_descriptors
.FunctionSubsetHeader(
124 bFirstInterface
=interface_number
)
125 function_header
.Add(msos20_descriptors
.CompatibleId(
126 CompatibleID
=compat_id
, SubCompatibleID
=sub_compat_id
))
127 self
._ms
_os
20_config
_subset
.Add(function_header
)
129 def AddDeviceCapabilityDescriptor(self
, device_capability
):
130 """Add a device capability descriptor to this device.
133 device_capability: The Descriptor object.
135 if self
._bos
_descriptor
is None:
136 self
._bos
_descriptor
= usb_descriptors
.BosDescriptor()
137 self
._bos
_descriptor
.AddDeviceCapability(device_capability
)
139 def Connected(self
, chip
, speed
):
140 """The device has been connected to a USB host.
143 chip: USB controller.
144 speed: Connection speed.
149 def Disconnected(self
):
150 """The device has been disconnected from the USB host."""
151 self
._speed
= usb_constants
.Speed
.UNKNOWN
153 self
._active
_endpoints
.clear()
154 self
._endpoint
_interface
_map
.clear()
156 def IsConnected(self
):
157 return self
._chip
is not None
159 def ControlRead(self
, request_type
, request
, value
, index
, length
):
160 """Handle a read on the control pipe (endpoint zero).
163 request_type: bmRequestType field of the setup packet.
164 request: bRequest field of the setup packet.
165 value: wValue field of the setup packet.
166 index: wIndex field of the setup packet.
167 length: Maximum amount of data the host expects the device to return.
170 A buffer to return to the USB host with len <= length on success or
171 None to stall the pipe.
173 assert request_type
& usb_constants
.Dir
.IN
174 typ
= request_type
& usb_constants
.Type
.MASK
175 recipient
= request_type
& usb_constants
.Recipient
.MASK
176 if typ
== usb_constants
.Type
.STANDARD
:
177 return self
.StandardControlRead(
178 recipient
, request
, value
, index
, length
)
179 elif typ
== usb_constants
.Type
.CLASS
:
180 return self
.ClassControlRead(
181 recipient
, request
, value
, index
, length
)
182 elif typ
== usb_constants
.Type
.VENDOR
:
183 return self
.VendorControlRead(
184 recipient
, request
, value
, index
, length
)
186 def ControlWrite(self
, request_type
, request
, value
, index
, data
):
187 """Handle a write to the control pipe (endpoint zero).
190 request_type: bmRequestType field of the setup packet.
191 request: bRequest field of the setup packet.
192 value: wValue field of the setup packet.
193 index: wIndex field of the setup packet.
194 data: Data stage of the request.
197 True on success, None to stall the pipe.
199 assert not request_type
& usb_constants
.Dir
.IN
200 typ
= request_type
& usb_constants
.Type
.MASK
201 recipient
= request_type
& usb_constants
.Recipient
.MASK
202 if typ
== usb_constants
.Type
.STANDARD
:
203 return self
.StandardControlWrite(
204 recipient
, request
, value
, index
, data
)
205 elif typ
== usb_constants
.Type
.CLASS
:
206 return self
.ClassControlWrite(
207 recipient
, request
, value
, index
, data
)
208 elif typ
== usb_constants
.Type
.VENDOR
:
209 return self
.VendorControlWrite(
210 recipient
, request
, value
, index
, data
)
212 def SendPacket(self
, endpoint
, data
):
213 """Send a data packet on the given endpoint.
216 endpoint: Endpoint address.
220 ValueError: If the endpoint address is not valid.
221 RuntimeError: If the device is not connected.
223 if self
._chip
is None:
224 raise RuntimeError('Device is not connected.')
225 if not endpoint
& usb_constants
.Dir
.IN
:
226 raise ValueError('Cannot write to non-input endpoint.')
227 self
._chip
.SendPacket(endpoint
, data
)
229 def ReceivePacket(self
, endpoint
, data
):
230 """Handle an incoming data packet on one of the device's active endpoints.
232 This method should be overridden by a subclass implementing endpoint-based
236 endpoint: Endpoint address.
241 def HaltEndpoint(self
, endpoint
):
242 """Signals a STALL condition to the host on the given endpoint.
245 endpoint: Endpoint address.
247 self
._chip
.HaltEndpoint(endpoint
)
249 def StandardControlRead(self
, recipient
, request
, value
, index
, length
):
250 """Handle standard control transfers.
253 recipient: Request recipient (device, interface, endpoint, etc.)
254 request: bRequest field of the setup packet.
255 value: wValue field of the setup packet.
256 index: wIndex field of the setup packet.
257 length: Maximum amount of data the host expects the device to return.
260 A buffer to return to the USB host with len <= length on success or
261 None to stall the pipe.
263 if recipient
== usb_constants
.Recipient
.DEVICE
:
264 if request
== usb_constants
.Request
.GET_DESCRIPTOR
:
265 desc_type
= value
>> 8
266 desc_index
= value
& 0xff
269 print 'GetDescriptor(recipient={}, type={}, index={}, lang={})'.format(
270 recipient
, desc_type
, desc_index
, desc_lang
)
272 return self
.GetDescriptor(recipient
, desc_type
, desc_index
, desc_lang
,
275 def GetDescriptor(self
, recipient
, typ
, index
, lang
, length
):
276 """Handle a standard GET_DESCRIPTOR request.
278 See Universal Serial Bus Specification Revision 2.0 section 9.4.3.
281 recipient: Request recipient (device, interface, endpoint, etc.)
282 typ: Descriptor type.
283 index: Descriptor index.
284 lang: Descriptor language code.
285 length: Maximum amount of data the host expects the device to return.
288 The value of the descriptor or None to stall the pipe.
290 if typ
== usb_constants
.DescriptorType
.STRING
:
291 return self
.GetStringDescriptor(index
, lang
, length
)
292 elif typ
== usb_constants
.DescriptorType
.BOS
:
293 return self
.GetBosDescriptor(length
)
295 def ClassControlRead(self
, recipient
, request
, value
, index
, length
):
296 """Handle class-specific control transfers.
298 This function should be overridden by a subclass implementing a particular
302 recipient: Request recipient (device, interface, endpoint, etc.)
303 request: bRequest field of the setup packet.
304 value: wValue field of the setup packet.
305 index: wIndex field of the setup packet.
306 length: Maximum amount of data the host expects the device to return.
309 A buffer to return to the USB host with len <= length on success or
310 None to stall the pipe.
312 _
= recipient
, request
, value
, index
, length
315 def VendorControlRead(self
, recipient
, request
, value
, index
, length
):
316 """Handle vendor-specific control transfers.
318 This function should be overridden by a subclass if implementing a device
319 that responds to vendor-specific requests.
322 recipient: Request recipient (device, interface, endpoint, etc.)
323 request: bRequest field of the setup packet.
324 value: wValue field of the setup packet.
325 index: wIndex field of the setup packet.
326 length: Maximum amount of data the host expects the device to return.
329 A buffer to return to the USB host with len <= length on success or
330 None to stall the pipe.
332 if (self
._ms
_vendor
_code
_v
1 is not None and
333 request
== self
._ms
_vendor
_code
_v
1 and
334 (recipient
== usb_constants
.Recipient
.DEVICE
or
335 recipient
== usb_constants
.Recipient
.INTERFACE
)):
336 return self
.GetMicrosoftOSDescriptorV1(recipient
, value
, index
, length
)
337 if (self
._ms
_vendor
_code
_v
2 is not None and
338 request
== self
._ms
_vendor
_code
_v
2 and
339 recipient
== usb_constants
.Recipient
.DEVICE
and
342 return self
.GetMicrosoftOSDescriptorV2(length
)
346 def StandardControlWrite(self
, recipient
, request
, value
, index
, data
):
347 """Handle standard control transfers.
350 recipient: Request recipient (device, interface, endpoint, etc.)
351 request: bRequest field of the setup packet.
352 value: wValue field of the setup packet.
353 index: wIndex field of the setup packet.
354 data: Data stage of the request.
357 True on success, None to stall the pipe.
361 if request
== usb_constants
.Request
.SET_CONFIGURATION
:
362 if recipient
== usb_constants
.Recipient
.DEVICE
:
363 return self
.SetConfiguration(value
)
364 elif request
== usb_constants
.Request
.SET_INTERFACE
:
365 if recipient
== usb_constants
.Recipient
.INTERFACE
:
366 return self
.SetInterface(index
, value
)
368 def ClassControlWrite(self
, recipient
, request
, value
, index
, data
):
369 """Handle class-specific control transfers.
371 This function should be overridden by a subclass implementing a particular
375 recipient: Request recipient (device, interface, endpoint, etc.)
376 request: bRequest field of the setup packet.
377 value: wValue field of the setup packet.
378 index: wIndex field of the setup packet.
379 data: Data stage of the request.
382 True on success, None to stall the pipe.
384 _
= recipient
, request
, value
, index
, data
387 def VendorControlWrite(self
, recipient
, request
, value
, index
, data
):
388 """Handle vendor-specific control transfers.
390 This function should be overridden by a subclass if implementing a device
391 that responds to vendor-specific requests.
394 recipient: Request recipient (device, interface, endpoint, etc.)
395 request: bRequest field of the setup packet.
396 value: wValue field of the setup packet.
397 index: wIndex field of the setup packet.
398 data: Data stage of the request.
401 True on success, None to stall the pipe.
403 _
= recipient
, request
, value
, index
, data
406 def GetStringDescriptor(self
, index
, lang
, length
):
407 """Handle a GET_DESCRIPTOR(String) request from the host.
409 Descriptor index 0 returns the set of languages supported by the device.
410 All other indices return the string descriptors registered with those
413 See Universal Serial Bus Specification Revision 2.0 section 9.6.7.
416 index: Descriptor index.
417 lang: Descriptor language code.
418 length: Maximum amount of data the host expects the device to return.
421 The string descriptor or None to stall the pipe if the descriptor is not
425 length
= 2 + len(self
._strings
) * 2
426 header
= struct
.pack('<BB', length
, usb_constants
.DescriptorType
.STRING
)
427 lang_codes
= [struct
.pack('<H', lang
)
428 for lang
in self
._strings
.iterkeys()]
429 buf
= header
+ ''.join(lang_codes
)
430 assert len(buf
) == length
432 if index
== 0xEE and lang
== 0 and self
._ms
_vendor
_code
_v
1 is not None:
433 # See https://msdn.microsoft.com/en-us/windows/hardware/gg463179 for the
434 # definition of this special string descriptor.
435 buf
= (struct
.pack('<BB', 18, usb_constants
.DescriptorType
.STRING
) +
436 'MSFT100'.encode('UTF-16LE') +
437 struct
.pack('<BB', self
._ms
_vendor
_code
_v
1, 0))
438 assert len(buf
) == 18
440 elif lang
not in self
._strings
:
442 elif index
not in self
._strings
[lang
]:
445 descriptor
= usb_descriptors
.StringDescriptor(
446 bString
=self
._strings
[lang
][index
])
447 return descriptor
.Encode()[:length
]
449 def GetMicrosoftOSDescriptorV1(self
, recipient
, value
, index
, length
):
450 """Handle a the Microsoft OS 1.0 Descriptor request from the host.
452 See https://msdn.microsoft.com/en-us/windows/hardware/gg463179 for the
453 format of these descriptors.
456 recipient: Request recipient (device or interface)
457 value: wValue field of the setup packet.
458 index: wIndex field of the setup packet.
459 length: Maximum amount of data the host expects the device to return.
462 The descriptor or None to stall the pipe if the descriptor is not
467 return self
.GetMicrosoftCompatIds(length
)
469 def GetMicrosoftCompatIds(self
, length
):
470 interfaces
= self
.GetConfigurationDescriptor().GetInterfaces()
471 max_interface
= max([iface
.bInterfaceNumber
for iface
in interfaces
])
473 header
= struct
.pack('<IHHBxxxxxxx',
474 16 + 24 * (max_interface
+ 1),
478 if length
<= len(header
):
479 return header
[:length
]
482 for interface
in xrange(max_interface
+ 1):
483 compat_id
, sub_compat_id
= self
._ms
_compat
_ids
.get(interface
, ('', ''))
484 buf
+= struct
.pack('<BB8s8sxxxxxx',
485 interface
, 0x01, compat_id
, sub_compat_id
)
488 def GetMicrosoftOSDescriptorV2(self
, length
):
489 return self
._ms
_os
20_descriptor
_set
.Encode()[:length
]
491 def GetBosDescriptor(self
, length
):
492 """Handle a GET_DESCRIPTOR(BOS) request from the host.
494 Device capability descriptors can be added to the Binary Device Object Store
495 returned by this method by calling AddDeviceCapabilityDescriptor.
497 See Universal Serial Bus 3.1 Specification, Revision 1.0 section 9.6.2.
500 length: Maximum amount of data the host expects the device to return.
503 The device's binary object store descriptor or None to stall the pipe if
504 no device capability descriptors have been configured.
506 if self
._bos
_descriptor
is None:
509 return self
._bos
_descriptor
.Encode()[:length
]
511 def SetConfiguration(self
, index
):
512 """Handle a SET_CONFIGURATION request from the host.
514 See Universal Serial Bus Specification Revision 2.0 section 9.4.7.
517 index: Configuration index selected.
520 True on success, None on error to stall the pipe.
522 print 'SetConfiguration({})'.format(index
)
524 for endpoint_addrs
in self
._active
_endpoints
.values():
525 for endpoint_addr
in endpoint_addrs
:
526 self
._chip
.StopEndpoint(endpoint_addr
)
527 endpoint_addrs
.clear()
528 self
._endpoint
_interface
_map
.clear();
531 # SET_CONFIGRATION(0) puts the device into the Address state which
532 # Windows does before suspending the port.
537 config_desc
= self
.GetConfigurationDescriptor()
538 for interface_desc
in config_desc
.GetInterfaces():
539 if interface_desc
.bAlternateSetting
!= 0:
541 endpoint_addrs
= self
._active
_endpoints
.setdefault(
542 interface_desc
.bInterfaceNumber
, set())
543 for endpoint_desc
in interface_desc
.GetEndpoints():
544 self
._chip
.StartEndpoint(endpoint_desc
)
545 endpoint_addrs
.add(endpoint_desc
.bEndpointAddress
)
546 self
._endpoint
_interface
_map
[endpoint_desc
.bEndpointAddress
] = \
547 interface_desc
.bInterfaceNumber
550 def SetInterface(self
, interface
, alt_setting
):
551 """Handle a SET_INTERFACE request from the host.
553 See Universal Serial Bus Specification Revision 2.0 section 9.4.10.
556 interface: Interface number to configure.
557 alt_setting: Alternate setting to select.
560 True on success, None on error to stall the pipe.
562 print 'SetInterface({}, {})'.format(interface
, alt_setting
)
564 config_desc
= self
.GetConfigurationDescriptor()
565 interface_desc
= None
566 for interface_option
in config_desc
.GetInterfaces():
567 if (interface_option
.bInterfaceNumber
== interface
and
568 interface_option
.bAlternateSetting
== alt_setting
):
569 interface_desc
= interface_option
570 if interface_desc
is None:
573 endpoint_addrs
= self
._active
_endpoints
.setdefault(interface
, set())
574 for endpoint_addr
in endpoint_addrs
:
575 self
._chip
.StopEndpoint(endpoint_addr
)
576 del self
._endpoint
_interface
_map
[endpoint_addr
]
577 for endpoint_desc
in interface_desc
.GetEndpoints():
578 self
._chip
.StartEndpoint(endpoint_desc
)
579 endpoint_addrs
.add(endpoint_desc
.bEndpointAddress
)
580 self
._endpoint
_interface
_map
[endpoint_desc
.bEndpointAddress
] = \
581 interface_desc
.bInterfaceNumber
584 def GetInterfaceForEndpoint(self
, endpoint_addr
):
585 return self
._endpoint
_interface
_map
.get(endpoint_addr
)