# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""USB descriptor generation utilities.

Classes to represent and generate USB descriptors.
"""

import struct

import hid_constants
import usb_constants


class Field(object):
  """USB descriptor field information."""

  def __init__(self, name, str_fmt, struct_fmt, required):
    """Define a new USB descriptor field.

    Args:
      name: Name of the field.
      str_fmt: Python 'string' module format string for this field.
      struct_fmt: Python 'struct' module format string for this field.
      required: Is this a required field?
    """
    self.name = name
    self.str_fmt = str_fmt
    self.struct_fmt = struct_fmt
    self.required = required

  def Format(self, value):
    return self.str_fmt.format(value)


class Descriptor(object):
  """Base class for USB descriptor types.

  This class provides general functionality for creating object types that
  represent USB descriptors. The AddField and related methods are used to
  define the fields of each structure. Fields can then be set using keyword
  arguments to the object constructor or by accessing properties on the object.
  """

  _fields = None

  @classmethod
  def AddField(cls, name, struct_fmt, str_fmt='{}', default=None):
    """Adds a user-specified field to this descriptor.

    Adds a field to the binary structure representing this descriptor. The field
    can be set by passing a keyword argument name=... to the object constructor
    will be accessible as foo.name on any instance.

    If no default value is provided then the constructor will through an
    exception if this field is not one of the provided keyword arguments.

    Args:
      name: String name of the field.
      struct_fmt: Python 'struct' module format string for this field.
      str_fmt: Python 'string' module format string for this field.
      default: Default value.
    """
    if cls._fields is None:
      cls._fields = []
    cls._fields.append(Field(name, str_fmt, struct_fmt, default is None))

    member_name = '_{}'.format(name)
    def Setter(self, value):
      setattr(self, member_name, value)
    def Getter(self):
      try:
        return getattr(self, member_name)
      except AttributeError:
        assert default is not None
        return default

    setattr(cls, name, property(Getter, Setter))

  @classmethod
  def AddFixedField(cls, name, struct_fmt, value, str_fmt='{}'):
    """Adds a constant field to this descriptor.

    Adds a constant field to the binary structure representing this descriptor.
    The field will be accessible as foo.name on any instance.

    The value of this field may not be given as a constructor parameter or
    set on an existing instance.

    Args:
      name: String name of the field.
      struct_fmt: Python 'struct' module format string for this field.
      value: Field value.
      str_fmt: Python 'string' module format string for this field.
    """
    if cls._fields is None:
      cls._fields = []
    cls._fields.append(Field(name, str_fmt, struct_fmt, False))

    def Setter(unused_self, unused_value):
      raise RuntimeError('{} is a fixed field.'.format(name))
    def Getter(unused_self):
      return value

    setattr(cls, name, property(Getter, Setter))

  @classmethod
  def AddComputedField(cls, name, struct_fmt, property_name, str_fmt='{}'):
    """Adds a constant field to this descriptor.

    Adds a field to the binary structure representing this descriptor whos value
    is equal to an object property. The field will be accessible as foo.name on
    any instance.

    The value of this field may not be given as a constructor parameter or
    set on an existing instance.

    Args:
      name: String name of the field.
      struct_fmt: Python 'struct' module format string for this field.
      property_name: Property to read.
      str_fmt: Python 'string' module format string for this field.
    """
    if cls._fields is None:
      cls._fields = []
    cls._fields.append(Field(name, str_fmt, struct_fmt, False))

    def Setter(unused_self, unused_value):
      raise RuntimeError('{} is a computed field.'.format(name))
    def Getter(self):
      return getattr(self, property_name)

    setattr(cls, name, property(Getter, Setter))

  def __init__(self, **kwargs):
    """Constructs a new instance of this descriptor.

    All fields which do not have a default value and are not fixed or computed
    from a property must be specified as keyword arguments.

    Args:
      **kwargs: Field values.

    Raises:
      TypeError: A required field was missing or an unexpected field was given.
    """
    fields = {field.name for field in self._fields}
    required_fields = {field.name for field in self._fields if field.required}

    for arg, value in kwargs.iteritems():
      if arg not in fields:
        raise TypeError('Unexpected field: {}'.format(arg))

      setattr(self, arg, value)
      required_fields.discard(arg)

    if required_fields:
      raise TypeError('Missing fields: {}'.format(', '.join(required_fields)))

  @property
  def fmt(self):
    """Returns the Python 'struct' module format string for this descriptor."""
    return '<{}'.format(''.join([field.struct_fmt for field in self._fields]))

  @property
  def struct_size(self):
    """Returns the size of the struct defined by fmt."""
    return struct.calcsize(self.fmt)

  @property
  def total_size(self):
    """Returns the total size of this descriptor."""
    return self.struct_size

  def Encode(self):
    """Returns the binary representation of this descriptor."""
    values = [getattr(self, field.name) for field in self._fields]
    return struct.pack(self.fmt, *values)

  def __str__(self):
    max_length = max(len(field.name) for field in self._fields)

    return '{}:\n  {}'.format(
        self.__class__.__name__,
        '\n  '.join('{} {}'.format(
            '{}:'.format(field.name).ljust(max_length+1),
            field.Format(getattr(self, field.name))
        ) for field in self._fields)
    )


class DeviceDescriptor(Descriptor):
  """Standard Device Descriptor.

  See Universal Serial Bus Specification Revision 2.0 Table 9-8.
  """
  pass

DeviceDescriptor.AddComputedField('bLength', 'B', 'struct_size')
DeviceDescriptor.AddFixedField('bDescriptorType', 'B',
                               usb_constants.DescriptorType.DEVICE)
DeviceDescriptor.AddField('bcdUSB', 'H', default=0x0200, str_fmt='0x{:04X}')
DeviceDescriptor.AddField('bDeviceClass', 'B',
                          default=usb_constants.DeviceClass.PER_INTERFACE)
DeviceDescriptor.AddField('bDeviceSubClass', 'B',
                          default=usb_constants.DeviceSubClass.PER_INTERFACE)
DeviceDescriptor.AddField('bDeviceProtocol', 'B',
                          default=usb_constants.DeviceProtocol.PER_INTERFACE)
DeviceDescriptor.AddField('bMaxPacketSize0', 'B', default=64)
DeviceDescriptor.AddField('idVendor', 'H', str_fmt='0x{:04X}')
DeviceDescriptor.AddField('idProduct', 'H', str_fmt='0x{:04X}')
DeviceDescriptor.AddField('bcdDevice', 'H', str_fmt='0x{:04X}')
DeviceDescriptor.AddField('iManufacturer', 'B', default=0)
DeviceDescriptor.AddField('iProduct', 'B', default=0)
DeviceDescriptor.AddField('iSerialNumber', 'B', default=0)
DeviceDescriptor.AddField('bNumConfigurations', 'B', default=1)


class DescriptorContainer(Descriptor):
  """Super-class for descriptors which contain more descriptors.

  This class adds the ability for a descriptor to have an array of additional
  descriptors which follow it.
  """

  def __init__(self, **kwargs):
    super(DescriptorContainer, self).__init__(**kwargs)
    self._descriptors = []

  @property
  def total_size(self):
    return self.struct_size + sum([descriptor.total_size
                                   for descriptor in self._descriptors])

  def Add(self, descriptor):
    self._descriptors.append(descriptor)

  def Encode(self):
    bufs = [super(DescriptorContainer, self).Encode()]
    bufs.extend(descriptor.Encode() for descriptor in self._descriptors)
    return ''.join(bufs)

  def __str__(self):
    return '{}\n{}'.format(super(DescriptorContainer, self).__str__(),
                           '\n'.join(str(descriptor)
                                     for descriptor in self._descriptors))


class ConfigurationDescriptor(DescriptorContainer):
  """Standard Configuration Descriptor.

  See Universal Serial Bus Specification Revision 2.0 Table 9-10.
  """

  def __init__(self, **kwargs):
    super(ConfigurationDescriptor, self).__init__(**kwargs)
    self._interfaces = {}

  @property
  def num_interfaces(self):
    interface_numbers = {key[0] for key in self._interfaces.iterkeys()}
    return len(interface_numbers)

  def AddInterface(self, interface):
    key = (interface.bInterfaceNumber, interface.bAlternateSetting)
    if key in self._interfaces:
      raise RuntimeError('Interface {} (alternate {}) already defined.'
                         .format(key[0], key[1]))
    self._interfaces[key] = interface
    self.Add(interface)

  def GetInterfaces(self):
    return self._interfaces.values()

ConfigurationDescriptor.AddComputedField('bLength', 'B', 'struct_size')
ConfigurationDescriptor.AddFixedField(
    'bDescriptorType', 'B', usb_constants.DescriptorType.CONFIGURATION)
ConfigurationDescriptor.AddComputedField('wTotalLength', 'H', 'total_size')
ConfigurationDescriptor.AddComputedField('bNumInterfaces', 'B',
                                         'num_interfaces')
ConfigurationDescriptor.AddField('bConfigurationValue', 'B', default=1)
ConfigurationDescriptor.AddField('iConfiguration', 'B', default=0)
ConfigurationDescriptor.AddField('bmAttributes', 'B', str_fmt='0x{:02X}')
ConfigurationDescriptor.AddField('MaxPower', 'B')


class InterfaceDescriptor(DescriptorContainer):
  """Standard Interface Descriptor.

  See Universal Serial Bus Specification Revision 2.0 Table 9-12.
  """

  def __init__(self, **kwargs):
    super(InterfaceDescriptor, self).__init__(**kwargs)
    self._endpoints = {}

  @property
  def num_endpoints(self):
    return len(self._endpoints)

  def AddEndpoint(self, endpoint):
    if endpoint.bEndpointAddress in self._endpoints:
      raise RuntimeError('Endpoint 0x{:02X} already defined on this interface.'
                         .format(endpoint.bEndpointAddress))
    self._endpoints[endpoint.bEndpointAddress] = endpoint
    self.Add(endpoint)

  def GetEndpoints(self):
    return self._endpoints.values()

InterfaceDescriptor.AddComputedField('bLength', 'B', 'struct_size')
InterfaceDescriptor.AddFixedField('bDescriptorType', 'B',
                                  usb_constants.DescriptorType.INTERFACE)
InterfaceDescriptor.AddField('bInterfaceNumber', 'B')
InterfaceDescriptor.AddField('bAlternateSetting', 'B', default=0)
InterfaceDescriptor.AddComputedField('bNumEndpoints', 'B', 'num_endpoints')
InterfaceDescriptor.AddField('bInterfaceClass', 'B',
                             default=usb_constants.InterfaceClass.VENDOR)
InterfaceDescriptor.AddField('bInterfaceSubClass', 'B',
                             default=usb_constants.InterfaceSubClass.VENDOR)
InterfaceDescriptor.AddField('bInterfaceProtocol', 'B',
                             default=usb_constants.InterfaceProtocol.VENDOR)
InterfaceDescriptor.AddField('iInterface', 'B', default=0)


class EndpointDescriptor(Descriptor):
  """Standard Endpoint Descriptor.

  See Universal Serial Bus Specification Revision 2.0 Table 9-13.
  """
  pass

EndpointDescriptor.AddComputedField('bLength', 'B', 'struct_size')
EndpointDescriptor.AddFixedField('bDescriptorType', 'B',
                                 usb_constants.DescriptorType.ENDPOINT)
EndpointDescriptor.AddField('bEndpointAddress', 'B', str_fmt='0x{:02X}')
EndpointDescriptor.AddField('bmAttributes', 'B', str_fmt='0x{:02X}')
EndpointDescriptor.AddField('wMaxPacketSize', 'H')
EndpointDescriptor.AddField('bInterval', 'B')


class HidDescriptor(Descriptor):
  """HID Descriptor.

  See Device Class Definition for Human Interface Devices (HID) Version 1.11
  section 6.2.1.
  """

  def __init__(self, **kwargs):
    super(HidDescriptor, self).__init__(**kwargs)
    self._descriptors = []

  def AddDescriptor(self, typ, length):
    self._descriptors.append((typ, length))

  @property
  def struct_size(self):
    return super(HidDescriptor, self).struct_size + self.num_descriptors * 3

  @property
  def num_descriptors(self):
    return len(self._descriptors)

  def Encode(self):
    bufs = [super(HidDescriptor, self).Encode()]
    bufs.extend(struct.pack('<BH', typ, length)
                for typ, length in self._descriptors)
    return ''.join(bufs)

  def __str__(self):
    return '{}\n{}'.format(
        super(HidDescriptor, self).__str__(),
        '\n'.join('  bDescriptorType: 0x{:02X}\n  wDescriptorLength: {}'
                  .format(typ, length) for typ, length in self._descriptors))

HidDescriptor.AddComputedField('bLength', 'B', 'struct_size')
HidDescriptor.AddFixedField('bDescriptorType', 'B',
                            hid_constants.DescriptorType.HID)
HidDescriptor.AddField('bcdHID', 'H', default=0x0111, str_fmt='0x{:04X}')
HidDescriptor.AddField('bCountryCode', 'B', default=0)
HidDescriptor.AddComputedField('bNumDescriptors', 'B', 'num_descriptors')
