Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / usb_gadget / gadget.py
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 """Generic USB gadget functionality.
6 """
7
8 import struct
9
10 import usb_constants
11
12
13 class Gadget(object):
14   """Basic functionality for a USB device.
15
16   Implements standard control requests assuming that a subclass will handle
17   class- or vendor-specific requests.
18   """
19
20   def __init__(self, device_desc, fs_config_desc, hs_config_desc):
21     """Create a USB gadget device.
22
23     Args:
24       device_desc: USB device descriptor.
25       fs_config_desc: Low/full-speed device descriptor.
26       hs_config_desc: High-speed device descriptor.
27     """
28     self._speed = usb_constants.Speed.UNKNOWN
29     self._chip = None
30     self._device_desc = device_desc
31     self._fs_config_desc = fs_config_desc
32     self._hs_config_desc = hs_config_desc
33     # dict mapping language codes to a dict mapping indexes to strings
34     self._strings = {}
35     # dict mapping interface numbers to a set of endpoint addresses
36     self._active_endpoints = {}
37
38   def GetDeviceDescriptor(self):
39     return self._device_desc
40
41   def GetFullSpeedConfigurationDescriptor(self):
42     return self._fs_config_desc
43
44   def GetHighSpeedConfigurationDescriptor(self):
45     return self._hs_config_desc
46
47   def GetConfigurationDescriptor(self):
48     if self._speed == usb_constants.Speed.FULL:
49       return self._fs_config_desc
50     elif self._speed == usb_constants.Speed.HIGH:
51       return self._hs_config_desc
52     else:
53       raise RuntimeError('Device is not connected.')
54
55   def GetSpeed(self):
56     return self._speed
57
58   def AddStringDescriptor(self, index, value, lang=0x0409):
59     """Add a string descriptor to this device.
60
61     Args:
62       index: String descriptor index (matches 'i' fields in descriptors).
63       value: The string.
64       lang: Language code (default: English).
65
66     Raises:
67       ValueError: The index or language code is invalid.
68     """
69     if index < 1 or index > 255:
70       raise ValueError('String descriptor index out of range.')
71     if lang < 0 or lang > 0xffff:
72       raise ValueError('String descriptor language code out of range.')
73
74     lang_strings = self._strings.setdefault(lang, {})
75     lang_strings[index] = value
76
77   def Connected(self, chip, speed):
78     """The device has been connected to a USB host.
79
80     Args:
81       chip: USB controller.
82       speed: Connection speed.
83     """
84     self._speed = speed
85     self._chip = chip
86
87   def Disconnected(self):
88     """The device has been disconnected from the USB host."""
89     self._speed = usb_constants.Speed.UNKNOWN
90     self._chip = None
91     self._active_endpoints.clear()
92
93   def IsConnected(self):
94     return self._chip is not None
95
96   def ControlRead(self, request_type, request, value, index, length):
97     """Handle a read on the control pipe (endpoint zero).
98
99     Args:
100       request_type: bmRequestType field of the setup packet.
101       request: bRequest field of the setup packet.
102       value: wValue field of the setup packet.
103       index: wIndex field of the setup packet.
104       length: Maximum amount of data the host expects the device to return.
105
106     Returns:
107       A buffer to return to the USB host with len <= length on success or
108       None to stall the pipe.
109     """
110     assert request_type & usb_constants.Dir.IN
111     typ = request_type & usb_constants.Type.MASK
112     recipient = request_type & usb_constants.Recipient.MASK
113     if typ == usb_constants.Type.STANDARD:
114       return self.StandardControlRead(
115           recipient, request, value, index, length)
116     elif typ == usb_constants.Type.CLASS:
117       return self.ClassControlRead(
118           recipient, request, value, index, length)
119     elif typ == usb_constants.Type.VENDOR:
120       return self.VendorControlRead(
121           recipient, request, value, index, length)
122
123   def ControlWrite(self, request_type, request, value, index, data):
124     """Handle a write to the control pipe (endpoint zero).
125
126     Args:
127       request_type: bmRequestType field of the setup packet.
128       request: bRequest field of the setup packet.
129       value: wValue field of the setup packet.
130       index: wIndex field of the setup packet.
131       data: Data stage of the request.
132
133     Returns:
134       True on success, None to stall the pipe.
135     """
136     assert not request_type & usb_constants.Dir.IN
137     typ = request_type & usb_constants.Type.MASK
138     recipient = request_type & usb_constants.Recipient.MASK
139     if typ == usb_constants.Type.STANDARD:
140       return self.StandardControlWrite(
141           recipient, request, value, index, data)
142     elif typ == usb_constants.Type.CLASS:
143       return self.ClassControlWrite(
144           recipient, request, value, index, data)
145     elif typ == usb_constants.Type.VENDOR:
146       return self.VendorControlWrite(
147           recipient, request, value, index, data)
148
149   def SendPacket(self, endpoint, data):
150     """Send a data packet on the given endpoint.
151
152     Args:
153       endpoint: Endpoint address.
154       data: Data buffer.
155
156     Raises:
157       ValueError: If the endpoint address is not valid.
158       RuntimeError: If the device is not connected.
159     """
160     if self._chip is None:
161       raise RuntimeError('Device is not connected.')
162     if not endpoint & usb_constants.Dir.IN:
163       raise ValueError('Cannot write to non-input endpoint.')
164     self._chip.SendPacket(endpoint, data)
165
166   def ReceivePacket(self, endpoint, data):
167     """Handle an incoming data packet on one of the device's active endpoints.
168
169     This method should be overridden by a subclass implementing endpoint-based
170     data transfers.
171
172     Args:
173       endpoint: Endpoint address.
174       data: Data buffer.
175     """
176     pass
177
178   def HaltEndpoint(self, endpoint):
179     """Signals a STALL condition to the host on the given endpoint.
180
181     Args:
182       endpoint: Endpoint address.
183     """
184     self._chip.HaltEndpoint(endpoint)
185
186   def StandardControlRead(self, recipient, request, value, index, length):
187     """Handle standard control transfers.
188
189     Args:
190       recipient: Request recipient (device, interface, endpoint, etc.)
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       length: Maximum amount of data the host expects the device to return.
195
196     Returns:
197       A buffer to return to the USB host with len <= length on success or
198       None to stall the pipe.
199     """
200     if request == usb_constants.Request.GET_DESCRIPTOR:
201       desc_type = value >> 8
202       desc_index = value & 0xff
203       desc_lang = index
204
205       print 'GetDescriptor(recipient={}, type={}, index={}, lang={})'.format(
206           recipient, desc_type, desc_index, desc_lang)
207
208       return self.GetDescriptor(recipient, desc_type, desc_index, desc_lang,
209                                 length)
210
211   def GetDescriptor(self, recipient, typ, index, lang, length):
212     """Handle a standard GET_DESCRIPTOR request.
213
214     See Universal Serial Bus Specification Revision 2.0 section 9.4.3.
215
216     Args:
217       recipient: Request recipient (device, interface, endpoint, etc.)
218       typ: Descriptor type.
219       index: Descriptor index.
220       lang: Descriptor language code.
221       length: Maximum amount of data the host expects the device to return.
222
223     Returns:
224       The value of the descriptor or None to stall the pipe.
225     """
226     if recipient == usb_constants.Recipient.DEVICE:
227       if typ == usb_constants.DescriptorType.STRING:
228         return self.GetStringDescriptor(index, lang, length)
229
230   def ClassControlRead(self, recipient, request, value, index, length):
231     """Handle class-specific control transfers.
232
233     This function should be overridden by a subclass implementing a particular
234     device class.
235
236     Args:
237       recipient: Request recipient (device, interface, endpoint, etc.)
238       request: bRequest field of the setup packet.
239       value: wValue field of the setup packet.
240       index: wIndex field of the setup packet.
241       length: Maximum amount of data the host expects the device to return.
242
243     Returns:
244       A buffer to return to the USB host with len <= length on success or
245       None to stall the pipe.
246     """
247     _ = recipient, request, value, index, length
248     return None
249
250   def VendorControlRead(self, recipient, request, value, index, length):
251     """Handle vendor-specific control transfers.
252
253     This function should be overridden by a subclass if implementing a device
254     that responds to vendor-specific requests.
255
256     Args:
257       recipient: Request recipient (device, interface, endpoint, etc.)
258       request: bRequest field of the setup packet.
259       value: wValue field of the setup packet.
260       index: wIndex field of the setup packet.
261       length: Maximum amount of data the host expects the device to return.
262
263     Returns:
264       A buffer to return to the USB host with len <= length on success or
265       None to stall the pipe.
266     """
267     _ = recipient, request, value, index, length
268     return None
269
270   def StandardControlWrite(self, recipient, request, value, index, data):
271     """Handle standard control transfers.
272
273     Args:
274       recipient: Request recipient (device, interface, endpoint, etc.)
275       request: bRequest field of the setup packet.
276       value: wValue field of the setup packet.
277       index: wIndex field of the setup packet.
278       data: Data stage of the request.
279
280     Returns:
281       True on success, None to stall the pipe.
282     """
283     _ = data
284
285     if request == usb_constants.Request.SET_CONFIGURATION:
286       if recipient == usb_constants.Recipient.DEVICE:
287         return self.SetConfiguration(value)
288     elif request == usb_constants.Request.SET_INTERFACE:
289       if recipient == usb_constants.Recipient.INTERFACE:
290         return self.SetInterface(index, value)
291
292   def ClassControlWrite(self, recipient, request, value, index, data):
293     """Handle class-specific control transfers.
294
295     This function should be overridden by a subclass implementing a particular
296     device class.
297
298     Args:
299       recipient: Request recipient (device, interface, endpoint, etc.)
300       request: bRequest field of the setup packet.
301       value: wValue field of the setup packet.
302       index: wIndex field of the setup packet.
303       data: Data stage of the request.
304
305     Returns:
306       True on success, None to stall the pipe.
307     """
308     _ = recipient, request, value, index, data
309     return None
310
311   def VendorControlWrite(self, recipient, request, value, index, data):
312     """Handle vendor-specific control transfers.
313
314     This function should be overridden by a subclass if implementing a device
315     that responds to vendor-specific requests.
316
317     Args:
318       recipient: Request recipient (device, interface, endpoint, etc.)
319       request: bRequest field of the setup packet.
320       value: wValue field of the setup packet.
321       index: wIndex field of the setup packet.
322       data: Data stage of the request.
323
324     Returns:
325       True on success, None to stall the pipe.
326     """
327     _ = recipient, request, value, index, data
328     return None
329
330   def GetStringDescriptor(self, index, lang, length):
331     """Handle a GET_DESCRIPTOR(String) request from the host.
332
333     Descriptor index 0 returns the set of languages supported by the device.
334     All other indices return the string descriptors registered with those
335     indices.
336
337     See Universal Serial Bus Specification Revision 2.0 section 9.6.7.
338
339     Args:
340       index: Descriptor index.
341       lang: Descriptor language code.
342       length: Maximum amount of data the host expects the device to return.
343
344     Returns:
345       The string descriptor or None to stall the pipe if the descriptor is not
346       found.
347     """
348     if index == 0:
349       length = 2 + len(self._strings) * 2
350       header = struct.pack('<BB', length, usb_constants.DescriptorType.STRING)
351       lang_codes = [struct.pack('<H', lang)
352                     for lang in self._strings.iterkeys()]
353       buf = header + ''.join(lang_codes)
354       assert len(buf) == length
355       return buf[:length]
356     elif lang not in self._strings:
357       return None
358     elif index not in self._strings[lang]:
359       return None
360     else:
361       string = self._strings[lang][index].encode('UTF-16LE')
362       header = struct.pack(
363           '<BB', 2 + len(string), usb_constants.DescriptorType.STRING)
364       buf = header + string
365       return buf[:length]
366
367   def SetConfiguration(self, index):
368     """Handle a SET_CONFIGURATION request from the host.
369
370     See Universal Serial Bus Specification Revision 2.0 section 9.4.7.
371
372     Args:
373       index: Configuration index selected.
374
375     Returns:
376       True on success, None on error to stall the pipe.
377     """
378     print 'SetConfiguration({})'.format(index)
379
380     for endpoint_addrs in self._active_endpoints.values():
381       for endpoint_addr in endpoint_addrs:
382         self._chip.StopEndpoint(endpoint_addr)
383       endpoint_addrs.clear()
384
385     if index == 0:
386       # SET_CONFIGRATION(0) puts the device into the Address state which
387       # Windows does before suspending the port.
388       return True
389     elif index != 1:
390       return None
391
392     config_desc = self.GetConfigurationDescriptor()
393     for interface_desc in config_desc.GetInterfaces():
394       if interface_desc.bAlternateSetting != 0:
395         continue
396       endpoint_addrs = self._active_endpoints.setdefault(
397           interface_desc.bInterfaceNumber, set())
398       for endpoint_desc in interface_desc.GetEndpoints():
399         self._chip.StartEndpoint(endpoint_desc)
400         endpoint_addrs.add(endpoint_desc.bEndpointAddress)
401     return True
402
403   def SetInterface(self, interface, alt_setting):
404     """Handle a SET_INTERFACE request from the host.
405
406     See Universal Serial Bus Specification Revision 2.0 section 9.4.10.
407
408     Args:
409       interface: Interface number to configure.
410       alt_setting: Alternate setting to select.
411
412     Returns:
413       True on success, None on error to stall the pipe.
414     """
415     print 'SetInterface({}, {})'.format(interface, alt_setting)
416
417     config_desc = self.GetConfigurationDescriptor()
418     interface_desc = None
419     for interface_option in config_desc.GetInterfaces():
420       if (interface_option.bInterfaceNumber == interface and
421           interface_option.bAlternateSetting == alt_setting):
422         interface_desc = interface_option
423     if interface_desc is None:
424       return None
425
426     endpoint_addrs = self._active_endpoints.setdefault(interface, set())
427     for endpoint_addr in endpoint_addrs:
428       self._chip.StopEndpoint(endpoint_addr)
429     for endpoint_desc in interface_desc.GetEndpoints():
430       self._chip.StartEndpoint(endpoint_desc)
431       endpoint_addrs.add(endpoint_desc.bEndpointAddress)
432     return True