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

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/usb.h>
#include <usb/usb.h>
#include <fbl/vector.h>
#include <stdlib.h>
#include <zircon/hw/usb/video.h>

#include "garnet/drivers/usb_video/usb-video-stream.h"
#include "garnet/drivers/usb_video/usb-video.h"
#include "garnet/drivers/usb_video/uvc_format.h"

namespace {
// The biggest size we are allowing USB descriptor strings to be.
// Technically, the bLength field for strings is one byte, so the
// max size for any string should be 255.
static constexpr size_t kUsbDescriptorStringSize = 512;

// Extract strings from the device description.
// Strings in the usb device description are represented as indices
// into the 'strings' section at the end.  This function unpacks a specific
// string, given its index.
std::string FetchString(const usb_protocol_t& usb_proto,
                        uint8_t description_index) {
  uint8_t str_buf[kUsbDescriptorStringSize];
  size_t buflen = sizeof(str_buf);
  uint16_t language_id = 0;
  zx_status_t res = usb_get_string_descriptor(&usb_proto, description_index,
                                              language_id,  &language_id,
                                              str_buf, buflen, &buflen);
  if (res != ZX_OK) {
    return std::string();
  }

  buflen = std::min(buflen, sizeof(str_buf));
  return std::string(reinterpret_cast<char*>(str_buf), buflen);
}

// Extract vendor and product information from the USB device description.
video::usb::UsbDeviceInfo GetDeviceInfo(const usb_protocol_t& usb_proto) {
  usb_device_descriptor_t usb_dev_desc;
  video::usb::UsbDeviceInfo device_info;
  // Fetch our top level device descriptor, so we know stuff like the values
  // of our VID/PID.
  usb_get_device_descriptor(&usb_proto, &usb_dev_desc);
  device_info.vendor_id = usb_dev_desc.idVendor;
  device_info.product_id = usb_dev_desc.idProduct;
  // Attempt to fetch the string descriptors for our manufacturer name,
  // product name, and serial number.
  if (usb_dev_desc.iManufacturer) {
    device_info.manufacturer =
        FetchString(usb_proto, usb_dev_desc.iManufacturer);
  }

  if (usb_dev_desc.iProduct) {
    device_info.product_name = FetchString(usb_proto, usb_dev_desc.iProduct);
  }

  if (usb_dev_desc.iSerialNumber) {
    device_info.serial_number =
        FetchString(usb_proto, usb_dev_desc.iSerialNumber);
  }
  return device_info;
}

zx_status_t usb_video_parse_descriptors(void* ctx, zx_device_t* device,
                                        void** cookie) {
  usb_protocol_t usb;
  zx_status_t status = device_get_protocol(device, ZX_PROTOCOL_USB, &usb);
  if (status != ZX_OK) {
    return status;
  }

  size_t parent_req_size = usb_get_request_size(&usb);
  ZX_DEBUG_ASSERT(parent_req_size != 0);

  // Grab the device information, so we can use it when creating the
  // UsbVideoStream.
  auto device_info = GetDeviceInfo(usb);

  usb_desc_iter_t iter;
  status = usb_desc_iter_init(&usb, &iter);
  if (status != ZX_OK) {
    return status;
  }

  int video_source_index = 0;
  video::usb::UvcFormatList formats;
  fbl::Vector<video::usb::UsbVideoStreamingSetting> streaming_settings;
  fbl::AllocChecker ac;

  usb_descriptor_header_t* header;
  // Most recent USB interface descriptor.
  usb_interface_descriptor_t* intf = NULL;
  // Most recent video control header.
  usb_video_vc_header_desc* control_header = NULL;
  // Most recent video streaming input header.
  usb_video_vs_input_header_desc* input_header = NULL;

  while ((header = usb_desc_iter_next(&iter)) != NULL) {
    switch (header->bDescriptorType) {
      case USB_DT_INTERFACE_ASSOCIATION: {
        usb_interface_assoc_descriptor_t* assoc_desc =
            (usb_interface_assoc_descriptor_t*)header;
        zxlogf(TRACE,
               "USB_DT_INTERFACE_ASSOCIATION bInterfaceCount: %u "
               "bFirstInterface: %u\n",
               assoc_desc->bInterfaceCount, assoc_desc->bFirstInterface);
        break;
      }
      case USB_DT_INTERFACE: {
        intf = (usb_interface_descriptor_t*)header;

        if (intf->bInterfaceClass == USB_CLASS_VIDEO) {
          if (intf->bInterfaceSubClass == USB_SUBCLASS_VIDEO_CONTROL) {
            zxlogf(TRACE, "interface USB_SUBCLASS_VIDEO_CONTROL\n");
            break;
          } else if (intf->bInterfaceSubClass == USB_SUBCLASS_VIDEO_STREAMING) {
            zxlogf(TRACE,
                   "interface USB_SUBCLASS_VIDEO_STREAMING bAlternateSetting: "
                   "%d\n",
                   intf->bAlternateSetting);
            // Encountered a new video streaming interface.
            if (intf->bAlternateSetting == 0) {
              // Create a video source if we've successfully parsed a VS
              // interface.
              if (formats.Size() > 0) {
                status = video::usb::UsbVideoStream::Create(
                    device, &usb, video_source_index++, intf, control_header,
                    input_header, std::move(formats), &streaming_settings,
                    std::move(device_info), parent_req_size);
                if (status != ZX_OK) {
                  zxlogf(ERROR, "UsbVideoStream::Create failed: %d\n", status);
                  goto error_return;
                }
              }
              // formats.reset();  //TODO(garratt): what to do here?
              streaming_settings.reset();
              input_header = NULL;
            }
            break;
          } else if (intf->bInterfaceSubClass ==
                     USB_SUBCLASS_VIDEO_INTERFACE_COLLECTION) {
            zxlogf(TRACE,
                   "interface USB_SUBCLASS_VIDEO_INTERFACE_COLLECTION "
                   "bAlternateSetting: %d\n",
                   intf->bAlternateSetting);
            break;
          }
        }
        zxlogf(TRACE, "USB_DT_INTERFACE %d %d %d\n", intf->bInterfaceClass,
               intf->bInterfaceSubClass, intf->bInterfaceProtocol);
        break;
      }
      case USB_VIDEO_CS_INTERFACE: {
        usb_video_vc_desc_header* vc_header = (usb_video_vc_desc_header*)header;
        if (intf->bInterfaceSubClass == USB_SUBCLASS_VIDEO_CONTROL) {
          switch (vc_header->bDescriptorSubtype) {
            case USB_VIDEO_VC_HEADER: {
              control_header = (usb_video_vc_header_desc*)header;
              zxlogf(TRACE, "USB_VIDEO_VC_HEADER dwClockFrequency: %u\n",
                     control_header->dwClockFrequency);
              break;
            }
            case USB_VIDEO_VC_INPUT_TERMINAL: {
              usb_video_vc_input_terminal_desc* desc =
                  (usb_video_vc_input_terminal_desc*)header;
              zxlogf(TRACE, "USB_VIDEO_VC_INPUT_TERMINAL wTerminalType: %04X\n",
                     le16toh(desc->wTerminalType));
              break;
            }
            case USB_VIDEO_VC_OUTPUT_TERMINAL: {
              usb_video_vc_output_terminal_desc* desc =
                  (usb_video_vc_output_terminal_desc*)header;
              zxlogf(TRACE,
                     "USB_VIDEO_VC_OUTPUT_TERMINAL wTerminalType: %04X\n",
                     le16toh(desc->wTerminalType));
              break;
            }
            case USB_VIDEO_VC_SELECTOR_UNIT:
              zxlogf(TRACE, "USB_VIDEO_VC_SELECTOR_UNIT\n");
              break;
            case USB_VIDEO_VC_PROCESSING_UNIT:
              zxlogf(TRACE, "USB_VIDEO_VC_PROCESSING_UNIT\n");
              break;
            case USB_VIDEO_VC_EXTENSION_UNIT:
              zxlogf(TRACE, "USB_VIDEO_VS_EXTENSION_TYPE\n");
              break;
            case USB_VIDEO_VC_ENCODING_UNIT:
              zxlogf(TRACE, "USB_VIDEO_VS_ENCODING_TYPE\n");
              break;
          }
        } else if (intf->bInterfaceSubClass == USB_SUBCLASS_VIDEO_STREAMING) {
          switch (vc_header->bDescriptorSubtype) {
            case USB_VIDEO_VS_INPUT_HEADER: {
              input_header = (usb_video_vs_input_header_desc*)header;
              zxlogf(TRACE,
                     "USB_VIDEO_VS_INPUT_HEADER bNumFormats: %u "
                     "bEndpointAddress 0x%x\n",
                     input_header->bNumFormats, input_header->bEndpointAddress);
              break;
            }
            case USB_VIDEO_VS_OUTPUT_HEADER:
              zxlogf(TRACE, "USB_VIDEO_VS_OUTPUT_HEADER\n");
              break;
            case USB_VIDEO_VS_FORMAT_UNCOMPRESSED:
            case USB_VIDEO_VS_FORMAT_MJPEG:
            case USB_VIDEO_VS_FORMAT_MPEG2TS:
            case USB_VIDEO_VS_FORMAT_DV:
            case USB_VIDEO_VS_FORMAT_FRAME_BASED:
            case USB_VIDEO_VS_FORMAT_STREAM_BASED:
            case USB_VIDEO_VS_FORMAT_H264:
            case USB_VIDEO_VS_FORMAT_H264_SIMULCAST:
            case USB_VIDEO_VS_FORMAT_VP8:
            case USB_VIDEO_VS_FORMAT_VP8_SIMULCAST:
              if (formats.number_of_formats() >= input_header->bNumFormats) {
                // More formats than expected, this should never happen.
                zxlogf(
                    ERROR,
                    "skipping unexpected format %u, already have %d formats\n",
                    vc_header->bDescriptorSubtype, input_header->bNumFormats);
                break;
              }
              status = formats.ParseUsbDescriptor(vc_header, &iter);
              if (status == ZX_ERR_NO_MEMORY) {
                goto error_return;
              }
              // ParseUsbDescriptor will return an error if it's an unsupported
              // format, but we shouldn't return early in case the device has
              // other formats we support.
              break;
          }
        } else if (intf->bInterfaceSubClass ==
                   USB_SUBCLASS_VIDEO_INTERFACE_COLLECTION) {
          zxlogf(TRACE, "USB_SUBCLASS_VIDEO_INTERFACE_COLLECTION\n");
        }
        break;
      }
      case USB_DT_ENDPOINT: {
        usb_endpoint_descriptor_t* endp = (usb_endpoint_descriptor_t*)header;
        const char* direction =
            (endp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN
                ? "IN"
                : "OUT";
        uint16_t max_packet_size = usb_ep_max_packet(endp);
        // The additional transactions per microframe value is extracted
        // from bits 12..11 of wMaxPacketSize, so it fits in a uint8_t.
        uint8_t per_mf =
            static_cast<uint8_t>(usb_ep_add_mf_transactions(endp) + 1);
        zxlogf(TRACE,
               "USB_DT_ENDPOINT %s bEndpointAddress 0x%x packet size %d, %d / "
               "mf\n",
               direction, endp->bEndpointAddress, max_packet_size, per_mf);

        // There may be another still image endpoint, so check the address
        // matches the input header.
        if (input_header &&
            endp->bEndpointAddress == input_header->bEndpointAddress) {
          video::usb::UsbVideoStreamingSetting setting = {
              .alt_setting = intf->bAlternateSetting,
              .transactions_per_microframe = per_mf,
              .max_packet_size = max_packet_size,
              .ep_type = usb_ep_type(endp)};
          streaming_settings.push_back(setting, &ac);
          if (!ac.check()) {
            status = ZX_ERR_NO_MEMORY;
            goto error_return;
          }
        }
        break;
      }
      case USB_VIDEO_CS_ENDPOINT: {
        usb_video_vc_interrupt_endpoint_desc* desc =
            (usb_video_vc_interrupt_endpoint_desc*)header;
        zxlogf(TRACE, "USB_VIDEO_CS_ENDPOINT wMaxTransferSize %u\n",
               desc->wMaxTransferSize);
        break;
      }
      case USB_DT_SS_EP_COMPANION: {
        if (streaming_settings.is_empty()) {
          status = ZX_ERR_BAD_STATE;
          goto error_return;
        }
        auto& settings = streaming_settings[streaming_settings.size() - 1];

        if (settings.ep_type == USB_ENDPOINT_ISOCHRONOUS) {
          usb_ss_ep_comp_descriptor_t* desc =
              (usb_ss_ep_comp_descriptor_t*)header;
          if (usb_ss_ep_comp_isoc_comp(desc)) {
            auto next = usb_desc_iter_next(&iter);
            if (next == nullptr ||
                next->bDescriptorType != USB_DT_SS_ISOCH_EP_COMPANION) {
              status = ZX_ERR_BAD_STATE;
              goto error_return;
            }
            usb_ss_isoch_ep_comp_descriptor_t* next_desc =
                (usb_ss_isoch_ep_comp_descriptor_t*)next;
            uint32_t denom = (desc->bMaxBurst + 1) * settings.max_packet_size;
            settings.transactions_per_microframe =
                (uint8_t)((next_desc->dwBytesPerInterval + denom - 1) / denom);
          } else {
            settings.transactions_per_microframe = (uint8_t)(
                (desc->bMaxBurst + 1) * (usb_ss_ep_comp_isoc_mult(desc) + 1));
          }
          break;
        }
        // fall through for unhandled superspeed bulk endpoint
      }
      default:
        zxlogf(TRACE, "unknown DT %d\n", header->bDescriptorType);
        break;
    }
  }
  if (formats.Size() > 0) {
    status = video::usb::UsbVideoStream::Create(
        device, &usb, video_source_index++, intf, control_header, input_header,
        std::move(formats), &streaming_settings, std::move(device_info), parent_req_size);
    if (status != ZX_OK) {
      zxlogf(ERROR, "UsbVideoStream::Create failed: %d\n", status);
    }
  }
error_return:
  usb_desc_iter_release(&iter);
  return status;
}

}  // namespace

extern "C" zx_status_t usb_video_bind(void* ctx, zx_device_t* device,
                                      void** cookie) {
  return usb_video_parse_descriptors(ctx, device, cookie);
}
