# 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.

"""Linux gadgetfs glue.

Exposes a USB gadget using a USB peripheral controller on Linux. The userspace
ABI is documented here:

https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/inode.c
"""

import errno
import multiprocessing
import os
import struct

from tornado import ioloop

import usb_constants
import usb_descriptors

GADGETFS_NOP = 0
GADGETFS_CONNECT = 1
GADGETFS_DISCONNECT = 2
GADGETFS_SETUP = 3
GADGETFS_SUSPEND = 4

BULK = 0x01
INTERRUPT = 0x02
ISOCHRONOUS = 0x04

USB_TRANSFER_TYPE_TO_MASK = {
    usb_constants.TransferType.BULK: BULK,
    usb_constants.TransferType.INTERRUPT: INTERRUPT,
    usb_constants.TransferType.ISOCHRONOUS: ISOCHRONOUS
}

IN = 0x01
OUT = 0x02

HARDWARE = {
    'beaglebone-black': (
        'musb-hdrc',  # Gadget controller name,
        {
            0x01: ('ep1out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x81: ('ep1in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x02: ('ep2out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x82: ('ep2in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x03: ('ep3out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x83: ('ep3in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x04: ('ep4out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x84: ('ep4in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x05: ('ep5out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x85: ('ep5in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x06: ('ep6out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x86: ('ep6in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x07: ('ep7out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x87: ('ep7in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x08: ('ep8out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x88: ('ep8in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x09: ('ep9out', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x89: ('ep9in', BULK | INTERRUPT | ISOCHRONOUS, 512),
            0x0A: ('ep10out', BULK | INTERRUPT | ISOCHRONOUS, 64),
            0x8A: ('ep10in', BULK | INTERRUPT | ISOCHRONOUS, 256),
            0x0B: ('ep11out', BULK | INTERRUPT | ISOCHRONOUS, 64),
            0x8B: ('ep11in', BULK | INTERRUPT | ISOCHRONOUS, 256),
            0x0C: ('ep12out', BULK | INTERRUPT | ISOCHRONOUS, 64),
            0x8C: ('ep12in', BULK | INTERRUPT | ISOCHRONOUS, 256),
            0x0D: ('ep13', BULK | INTERRUPT | ISOCHRONOUS, 4096),
            0x8D: ('ep13', BULK | INTERRUPT | ISOCHRONOUS, 4096),
            0x0E: ('ep14', BULK | INTERRUPT | ISOCHRONOUS, 1024),
            0x8E: ('ep14', BULK | INTERRUPT | ISOCHRONOUS, 1024),
            0x0F: ('ep15', BULK | INTERRUPT | ISOCHRONOUS, 1024),
            0x8F: ('ep15', BULK | INTERRUPT | ISOCHRONOUS, 1024),
        }
    )
}


class LinuxGadgetfs(object):
  """Linux gadgetfs-based gadget driver.
  """

  def __init__(self, hardware, mountpoint='/dev/gadget'):
    """Initialize bindings to the Linux gadgetfs interface.

    Args:
      hardware: Hardware type.
      mountpoint: Gadget filesystem mount point.
    """
    self._chip, self._hw_eps = HARDWARE[hardware]
    self._ep_dir = mountpoint
    self._gadget = None
    self._fd = None
    # map from bEndpointAddress to hardware ep name and open file descriptor
    self._ep_fds = {}
    self._io_loop = ioloop.IOLoop.current()

  def Create(self, gadget):
    """Bind a gadget to the USB peripheral controller."""
    self._gadget = gadget
    self._fd = os.open(os.path.join(self._ep_dir, self._chip), os.O_RDWR)
    buf = ''.join([struct.pack('=I', 0),
                   gadget.GetFullSpeedConfigurationDescriptor().Encode(),
                   gadget.GetHighSpeedConfigurationDescriptor().Encode(),
                   gadget.GetDeviceDescriptor().Encode()])
    os.write(self._fd, buf)
    self._io_loop.add_handler(self._fd, self.HandleEvent, self._io_loop.READ)

  def Destroy(self):
    """Unbind the gadget from the USB peripheral controller."""
    self.Disconnected()
    self._io_loop.remove_handler(self._fd)
    os.close(self._fd)
    self._gadget = None
    self._fd = None

  def IsConfigured(self):
    return self._gadget is not None

  def HandleEvent(self, unused_fd, unused_events):
    buf = os.read(self._fd, 12)
    event_type, = struct.unpack_from('=I', buf, 8)

    if event_type == GADGETFS_NOP:
      print 'NOP'
    elif event_type == GADGETFS_CONNECT:
      speed, = struct.unpack('=Ixxxxxxxx', buf)
      self.Connected(speed)
    elif event_type == GADGETFS_DISCONNECT:
      self.Disconnected()
    elif event_type == GADGETFS_SETUP:
      request_type, request, value, index, length = struct.unpack(
          '<BBHHHxxxx', buf)
      self.HandleSetup(request_type, request, value, index, length)
    elif event_type == GADGETFS_SUSPEND:
      print 'SUSPEND'
    else:
      print 'Unknown gadgetfs event type:', event_type

  def Connected(self, speed):
    print 'CONNECT speed={}'.format(speed)
    self._gadget.Connected(self, speed)

  def Disconnected(self):
    print 'DISCONNECT'
    for endpoint_addr in self._ep_fds.keys():
      self.StopEndpoint(endpoint_addr)
    self._ep_fds.clear()
    self._gadget.Disconnected()

  def HandleSetup(self, request_type, request, value, index, length):
    print ('SETUP bmRequestType=0x{:02X} bRequest=0x{:02X} wValue=0x{:04X} '
           'wIndex=0x{:04X} wLength={}'
           .format(request_type, request, value, index, length))

    if request_type & usb_constants.Dir.IN:
      data = self._gadget.ControlRead(
          request_type, request, value, index, length)
      if data is None:
        print 'SETUP STALL'
        try:
          os.read(self._fd, 0)  # Backwards I/O stalls the pipe.
        except OSError, e:
          # gadgetfs always returns EL2HLT which we should ignore.
          if e.errno != errno.EL2HLT:
            raise
      else:
        os.write(self._fd, data)
    else:
      data = ''
      if length:
        data = os.read(self._fd, length)
      result = self._gadget.ControlWrite(
          request_type, request, value, index, data)
      if result is None:
        print 'SETUP STALL'
        try:
          os.write(self._fd, '')  # Backwards I/O stalls the pipe.
        except OSError, e:
          # gadgetfs always returns EL2HLT which we should ignore.
          if e.errno != errno.EL2HLT:
            raise
      elif not length:
        # Only empty OUT transfers can be ACKed.
        os.read(self._fd, 0)

  def StartEndpoint(self, endpoint_desc):
    """Activate an endpoint.

    To enable a hardware endpoint the appropriate endpoint file must be opened
    and the endpoint descriptors written to it. Linux requires both full- and
    high-speed descriptors to be written for a high-speed device but since the
    endpoint is always reinitialized after disconnect only the high-speed
    endpoint will be valid in this case.

    Args:
      endpoint_desc: Endpoint descriptor.

    Raises:
      RuntimeError: If the hardware endpoint is in use or the configuration
          is not supported by the hardware.
    """
    endpoint_addr = endpoint_desc.bEndpointAddress
    name, hw_ep_type, hw_ep_size = self._hw_eps[endpoint_addr]

    if name in self._ep_fds:
      raise RuntimeError('Hardware endpoint {} already in use.'.format(name))

    ep_type = USB_TRANSFER_TYPE_TO_MASK[
        endpoint_desc.bmAttributes & usb_constants.TransferType.MASK]
    ep_size = endpoint_desc.wMaxPacketSize

    if not hw_ep_type & ep_type:
      raise RuntimeError('Hardware endpoint {} does not support this transfer '
                         'type.'.format(name))
    elif hw_ep_size < ep_size:
      raise RuntimeError('Hardware endpoint {} only supports a maximum packet '
                         'size of {}, {} requested.'
                         .format(name, hw_ep_size, ep_size))

    fd = os.open(os.path.join(self._ep_dir, name), os.O_RDWR)

    buf = struct.pack('=I', 1)
    if self._gadget.GetSpeed() == usb_constants.Speed.HIGH:
      # The full speed endpoint descriptor will not be used but Linux requires
      # one to be provided.
      full_speed_endpoint = usb_descriptors.EndpointDescriptor(
          bEndpointAddress=endpoint_desc.bEndpointAddress,
          bmAttributes=0,
          wMaxPacketSize=0,
          bInterval=0)
      buf = ''.join([buf, full_speed_endpoint.Encode(), endpoint_desc.Encode()])
    else:
      buf = ''.join([buf, endpoint_desc.Encode()])
    os.write(fd, buf)

    pipe_r, pipe_w = multiprocessing.Pipe(False)
    child = None

    # gadgetfs doesn't support polling on the endpoint file descriptors (why?)
    # so we have to start background threads for each.
    if endpoint_addr & usb_constants.Dir.IN:
      def WriterProcess():
        while True:
          data = pipe_r.recv()
          written = os.write(fd, data)
          print('IN bEndpointAddress=0x{:02X} length={}'
                .format(endpoint_addr, written))

      child = multiprocessing.Process(target=WriterProcess)
      self._ep_fds[endpoint_addr] = fd, child, pipe_w
    else:
      def ReceivePacket(unused_fd, unused_events):
        data = pipe_r.recv()
        print('OUT bEndpointAddress=0x{:02X} length={}'
              .format(endpoint_addr, len(data)))
        self._gadget.ReceivePacket(endpoint_addr, data)

      def ReaderProcess():
        while True:
          data = os.read(fd, ep_size)
          pipe_w.send(data)

      child = multiprocessing.Process(target=ReaderProcess)
      pipe_fd = pipe_r.fileno()
      self._io_loop.add_handler(pipe_fd, ReceivePacket, self._io_loop.READ)
      self._ep_fds[endpoint_addr] = fd, child, pipe_r

    child.start()
    print 'Started endpoint 0x{:02X}.'.format(endpoint_addr)

  def StopEndpoint(self, endpoint_addr):
    """Deactivate the given endpoint."""
    fd, child, pipe = self._ep_fds.pop(endpoint_addr)
    pipe_fd = pipe.fileno()
    child.terminate()
    child.join()
    if not endpoint_addr & usb_constants.Dir.IN:
      self._io_loop.remove_handler(pipe_fd)
    os.close(fd)
    print 'Stopped endpoint 0x{:02X}.'.format(endpoint_addr)

  def SendPacket(self, endpoint_addr, data):
    """Send a packet on the given endpoint."""
    _, _, pipe = self._ep_fds[endpoint_addr]
    pipe.send(data)

  def HaltEndpoint(self, endpoint_addr):
    """Signal a stall condition on the given endpoint."""
    fd, _ = self._ep_fds[endpoint_addr]
    # Reverse I/O direction sets the halt condition on the pipe.
    try:
      if endpoint_addr & usb_constants.Dir.IN:
        os.read(fd, 0)
      else:
        os.write(fd, '')
    except OSError, e:
      # gadgetfs always returns EBADMSG which we should ignore.
      if e.errno != errno.EBADMSG:
        raise
