Home | History | Annotate | Download | only in usb_gadget
      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
    433