// Copyright 2020 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 "usb-cdc-ecm-lib.h"

#include <usb/usb.h>

const char* module_name = "usb-cdc-ecm";

static bool parse_cdc_header(usb_cs_header_interface_descriptor_t* header_desc) {
  // Check for supported CDC version
  zxlogf(DEBUG, "%s: device reports CDC version as 0x%x", module_name, header_desc->bcdCDC);
  return header_desc->bcdCDC >= CDC_SUPPORTED_VERSION;
}

static bool parse_cdc_ethernet_descriptor(ecm_ctx_t* ctx,
                                          usb_cs_ethernet_interface_descriptor_t* desc) {
  ctx->mtu = desc->wMaxSegmentSize;

  // MAC address is stored in a string descriptor in UTF-16 format, so we get one byte of
  // address for each 32 bits of text.
  const size_t expected_str_size = sizeof(usb_string_descriptor_t) + ETH_MAC_SIZE * 4;
  char str_desc_buf[expected_str_size];

  // Read string descriptor for MAC address (string index is in iMACAddress field)
  size_t out_length;
  zx_status_t result =
      usb_get_descriptor(&ctx->usb, 0, USB_DT_STRING, desc->iMACAddress, (uint8_t*)str_desc_buf,
                         sizeof(str_desc_buf), ZX_TIME_INFINITE, &out_length);
  if (result < 0) {
    zxlogf(ERROR, "%s: error reading MAC address", module_name);
    return false;
  }
  if (out_length != expected_str_size) {
    zxlogf(ERROR, "%s: MAC address string incorrect length (saw %zd, expected %zd)", module_name,
           out_length, expected_str_size);
    return false;
  }

  // Convert MAC address to something more machine-friendly
  usb_string_descriptor_t* str_desc = (usb_string_descriptor_t*)str_desc_buf;
  uint8_t* str = str_desc->bString;
  size_t ndx;
  for (ndx = 0; ndx < ETH_MAC_SIZE * 4; ndx++) {
    if (ndx % 2 == 1) {
      if (str[ndx] != 0) {
        zxlogf(ERROR, "%s: MAC address contains invalid characters", module_name);
        return false;
      }
      continue;
    }
    uint8_t value;
    if (str[ndx] >= '0' && str[ndx] <= '9') {
      value = str[ndx] - '0';
    } else if (str[ndx] >= 'A' && str[ndx] <= 'F') {
      value = (str[ndx] - 'A') + 0xa;
    } else {
      zxlogf(ERROR, "%s: MAC address contains invalid characters", module_name);
      return false;
    }
    if (ndx % 4 == 0) {
      ctx->mac_addr[ndx / 4] = (uint8_t)(value << 4);
    } else {
      ctx->mac_addr[ndx / 4] |= value;
    }
  }

  zxlogf(INFO, "%s: MAC address is %02X:%02X:%02X:%02X:%02X:%02X", module_name, ctx->mac_addr[0],
         ctx->mac_addr[1], ctx->mac_addr[2], ctx->mac_addr[3], ctx->mac_addr[4], ctx->mac_addr[5]);
  return true;
}

zx_status_t parse_usb_descriptor(usb_desc_iter_t* iter, usb_endpoint_descriptor_t** int_ep,
                                 usb_endpoint_descriptor_t** tx_ep,
                                 usb_endpoint_descriptor_t** rx_ep,
                                 usb_interface_descriptor_t** default_ifc,
                                 usb_interface_descriptor_t** data_ifc, ecm_ctx_t* ecm_ctx) {
  zx_status_t result = ZX_ERR_NOT_SUPPORTED;
  usb_descriptor_header_t* desc;
  usb_cs_header_interface_descriptor_t* cdc_header_desc = NULL;
  usb_cs_ethernet_interface_descriptor_t* cdc_eth_desc = NULL;
  *int_ep = NULL;
  *tx_ep = NULL;
  *rx_ep = NULL;
  *default_ifc = NULL;
  *data_ifc = NULL;
  while ((desc = usb_desc_iter_peek(iter)) != NULL) {
    if (desc->bDescriptorType == USB_DT_INTERFACE) {
      usb_interface_descriptor_t* ifc_desc =
          usb_desc_iter_get_structure(iter, sizeof(usb_interface_descriptor_t));
      if (ifc_desc == NULL) {
        goto fail;
      }
      if (ifc_desc->b_interface_class == USB_CLASS_CDC) {
        if (ifc_desc->b_num_endpoints == 0) {
          if (*default_ifc) {
            zxlogf(ERROR, "%s: multiple default interfaces found", module_name);
            goto fail;
          }
          *default_ifc = ifc_desc;
        } else if (ifc_desc->b_num_endpoints == 2) {
          if (*data_ifc) {
            zxlogf(ERROR, "%s: multiple data interfaces found", module_name);
            goto fail;
          }
          *data_ifc = ifc_desc;
        }
      }
    } else if (desc->bDescriptorType == USB_DT_CS_INTERFACE) {
      usb_cs_interface_descriptor_t* cs_ifc_desc =
          usb_desc_iter_get_structure(iter, sizeof(usb_cs_interface_descriptor_t));
      if (cs_ifc_desc == NULL) {
        goto fail;
      }
      if (cs_ifc_desc->bDescriptorSubType == USB_CDC_DST_HEADER) {
        if (cdc_header_desc != NULL) {
          zxlogf(ERROR, "%s: multiple CDC headers", module_name);
          goto fail;
        }
        cdc_header_desc =
            usb_desc_iter_get_structure(iter, sizeof(usb_cs_header_interface_descriptor_t));
      } else if (cs_ifc_desc->bDescriptorSubType == USB_CDC_DST_ETHERNET) {
        if (cdc_eth_desc != NULL) {
          zxlogf(ERROR, "%s: multiple CDC ethernet descriptors", module_name);
          goto fail;
        }
        cdc_eth_desc =
            usb_desc_iter_get_structure(iter, sizeof(usb_cs_ethernet_interface_descriptor_t));
      }
    } else if (desc->bDescriptorType == USB_DT_ENDPOINT) {
      usb_endpoint_descriptor_t* endpoint_desc =
          usb_desc_iter_get_structure(iter, sizeof(usb_endpoint_descriptor_t));
      if (endpoint_desc == NULL) {
        goto fail;
      }
      if (usb_ep_direction(endpoint_desc) == USB_ENDPOINT_IN &&
          usb_ep_type(endpoint_desc) == USB_ENDPOINT_INTERRUPT) {
        if (*int_ep != NULL) {
          zxlogf(ERROR, "%s: multiple interrupt endpoint descriptors", module_name);
          goto fail;
        }
        *int_ep = endpoint_desc;
      } else if (usb_ep_direction(endpoint_desc) == USB_ENDPOINT_OUT &&
                 usb_ep_type(endpoint_desc) == USB_ENDPOINT_BULK) {
        if (*tx_ep != NULL) {
          zxlogf(ERROR, "%s: multiple tx endpoint descriptors", module_name);
          goto fail;
        }
        *tx_ep = endpoint_desc;
      } else if (usb_ep_direction(endpoint_desc) == USB_ENDPOINT_IN &&
                 usb_ep_type(endpoint_desc) == USB_ENDPOINT_BULK) {
        if (*rx_ep != NULL) {
          zxlogf(ERROR, "%s: multiple rx endpoint descriptors", module_name);
          goto fail;
        }
        *rx_ep = endpoint_desc;
      } else {
        zxlogf(ERROR, "%s: unrecognized endpoint", module_name);
        goto fail;
      }
    }
    usb_desc_iter_advance(iter);
  }
  if (cdc_header_desc == NULL || cdc_eth_desc == NULL) {
    zxlogf(ERROR, "%s: CDC %s descriptor(s) not found", module_name,
           cdc_header_desc ? "ethernet"
           : cdc_eth_desc  ? "header"
                           : "ethernet and header");
    goto fail;
  }
  if (*int_ep == NULL || *tx_ep == NULL || *rx_ep == NULL) {
    zxlogf(ERROR, "%s: missing one or more required endpoints", module_name);
    goto fail;
  }
  if (*default_ifc == NULL) {
    zxlogf(ERROR, "%s: unable to find CDC default interface", module_name);
    goto fail;
  }
  if (*data_ifc == NULL) {
    zxlogf(ERROR, "%s: unable to find CDC data interface", module_name);
    goto fail;
  }

  // Parse the information in the CDC descriptors
  if (!parse_cdc_header(cdc_header_desc)) {
    zxlogf(ERROR, "%s: unable to parse cdc header", module_name);
    goto fail;
  }
  if (!parse_cdc_ethernet_descriptor(ecm_ctx, cdc_eth_desc)) {
    zxlogf(ERROR, "%s: unable to parse cdc ethernet descriptor", module_name);
    goto fail;
  }
  result = ZX_OK;
fail:
  return result;
}
