// 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 <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/metadata.h>
#include <ddk/phys-iter.h>
#include <ddk/protocol/usb/dci.h>
#include <ddk/protocol/usb/function.h>
#include <ddk/protocol/usb/modeswitch.h>
#include <usb/usb-request.h>
#include <zircon/listnode.h>
#include <zircon/device/usb-peripheral.h>
#include <zircon/usb/peripheral/c/fidl.h>
#include <zircon/hw/usb-cdc.h>
#include <zircon/hw/usb.h>

/*
    THEORY OF OPERATION

    This driver is responsible for USB in the peripheral role, that is,
    acting as a USB device to a USB host.
    It serves as the central point of coordination for the peripheral role.
    It is configured via ioctls in the ZX_PROTOCOL_USB_DEVICE protocol
    (which is used by the usbctl command line program).
    Based on this configuration, it creates one or more DDK devices with protocol
    ZX_PROTOCOL_USB_FUNCTION. These devices are bind points for USB function drivers,
    which implement USB interfaces for particular functions (like USB ethernet or mass storage).
    This driver also binds to a device with protocol ZX_PROTOCOL_USB_DCI
    (Device Controller Interface) which is implemented by a driver for the actual
    USB controller hardware for the peripheral role.

    There are several steps needed to initialize and start USB in the peripheral role.
    The first step is setting up the USB configuration via ioctls.
    ioctl_usb_peripheral_set_device_desc() sets the USB device descriptor to be presented
    to the host during enumeration.
    Next, ioctl_usb_peripheral_add_function() can be called one or more times to add
    descriptors for the USB functions to be included in the USB configuration.
    Finally after all the functions have been added, ioctl_usb_peripheral_bind_functions()
    tells this driver that configuration is complete and it is now possible to build
    the configuration descriptor. Once we get to this point, usb_device_t.functions_bound
    is set to true.

    Independent of this configuration process, ioctl_usb_peripheral_set_mode() can be used
    to configure the role of the USB controller. If the role is set to USB_MODE_PERIPHERAL
    and "functions_bound" is true, then we are ready to start USB in peripheral role.
    At this point, we create DDK devices for our list of functions.
    When the function drivers bind to these functions, they register an interface of type
    usb_function_interface_t with this driver via the usb_function_register() API.
    Once all of the function drivers have registered themselves this way,
    usb_device_t.functions_registered is set to true.

    if the usb mode is set to USB_MODE_PERIPHERAL and "functions_registered" is true,
    we are now finally ready to operate in the peripheral role.
    At this point we can inform the DCI driver to start running in peripheral role
    by calling usb_mode_switch_set_mode(USB_MODE_PERIPHERAL) on its ZX_PROTOCOL_USB_MODE_SWITCH
    interface. Now the USB controller hardware is up and running as a USB peripheral.

    Teardown of the peripheral role one of two ways:
    First, ioctl_usb_peripheral_clear_functions() will reset this device's list of USB functions.
    Second, the USB mode can be set to something other than USB_MODE_PERIPHERAL.
    In this second case, we will remove the DDK devices for the USB functions
    so the function drivers will unbind, but the USB configuration remains ready to go
    for when the USB mode is switched back to USB_MODE_PERIPHERAL.
*/

#define MAX_INTERFACES 32

typedef zircon_usb_peripheral_FunctionDescriptor usb_function_descriptor_t;

typedef struct {
    zx_device_t* zxdev;
    zx_device_t* dci_dev;
    struct usb_device* dev;
    list_node_t node;
    usb_function_interface_t interface;
    usb_function_descriptor_t desc;
    usb_descriptor_header_t* descriptors;
    size_t descriptors_length;
    unsigned num_interfaces;
} usb_function_t;

typedef struct usb_device {
    // the device we publish
    zx_device_t* zxdev;
    // our parent device
    zx_device_t* dci_dev;
    // our parent's DCI protocol
    usb_dci_protocol_t usb_dci;
    // our parent's USB switch protocol
    usb_mode_switch_protocol_t usb_mode_switch;
    // true if our parent implements usb_mode_switch_protocol_t
    bool has_usb_mode_switch;
    // USB device descriptor set via ioctl_usb_peripheral_set_device_desc()
    usb_device_descriptor_t device_desc;
    // USB configuration descriptor, synthesized from our functions' descriptors
    usb_configuration_descriptor_t* config_desc;
    // map from interface number to function
    usb_function_t* interface_map[MAX_INTERFACES];
    // map from endpoint index to function
    usb_function_t* endpoint_map[USB_MAX_EPS];
    // strings for USB string descriptors
    char* strings[256];
    // list of usb_function_t
    list_node_t functions;
    // mutex for protecting our state
    mtx_t lock;
    // current USB mode set via ioctl_usb_peripheral_set_mode()
    usb_mode_t usb_mode;
    // our parent's USB mode
     usb_mode_t dci_usb_mode;
    // set if ioctl_usb_peripheral_bind_functions() has been called
    // and we have a complete list of our function.
    bool functions_bound;
    // set if all our functions have registered their usb_function_interface_t
    bool functions_registered;
    // true if we have added child devices for our functions
    bool function_devs_added;
    // true if we are connected to a host
    bool connected;
    // current configuration number selected via USB_REQ_SET_CONFIGURATION
    // (will be 0 or 1 since we currently do not support multiple configurations)
    uint8_t configuration;
    // USB connection speed
    usb_speed_t speed;
    size_t parent_request_size;
} usb_device_t;

// for mapping bEndpointAddress value to/from index in range 0 - 31
// OUT endpoints are in range 1 - 15, IN endpoints are in range 17 - 31
#define ep_address_to_index(addr) (((addr) & 0xF) | (((addr) & 0x80) >> 3))
#define ep_index_to_address(index) (((index) & 0xF) | (((index) & 0x10) << 3))
#define OUT_EP_START    1
#define OUT_EP_END      15
#define IN_EP_START     17
#define IN_EP_END       31

static zx_status_t usb_dev_state_changed_locked(usb_device_t* dev);

static zx_status_t usb_device_alloc_string_desc(usb_device_t* dev, const char* string,
                                                uint8_t* out_index) {

    mtx_lock(&dev->lock);

    unsigned i;
    for (i = 1; i < countof(dev->strings); i++) {
        if (!dev->strings[i]) {
            break;
        }
    }
    if (i == countof(dev->strings)) {
        mtx_unlock(&dev->lock);
        return ZX_ERR_NO_RESOURCES;
    }

    dev->strings[i] = strdup(string);
    if (!dev->strings[i]) {
        mtx_unlock(&dev->lock);
        return ZX_ERR_NO_MEMORY;
    }

    mtx_unlock(&dev->lock);

    *out_index = i;
    return ZX_OK;
}

static zx_protocol_device_t function_proto = {
    .version = DEVICE_OPS_VERSION,
    // Note that we purposely do not have a release callback for USB functions.
    // The functions are kept on a list when not active so they can be re-added
    // when reentering device mode.
};

static zx_status_t usb_device_function_registered(usb_device_t* dev) {
    mtx_lock(&dev->lock);

    if (dev->config_desc) {
        zxlogf(ERROR, "usb_device_function_registered: already have configuration descriptor!\n");
        mtx_unlock(&dev->lock);
        return ZX_ERR_BAD_STATE;
    }

    // check to see if we have all our functions registered
    // if so, we can build our configuration descriptor and tell the DCI driver we are ready
    usb_function_t* function;
    size_t length = sizeof(usb_configuration_descriptor_t);
    list_for_every_entry(&dev->functions, function, usb_function_t, node) {
        if (function->descriptors) {
            length += function->descriptors_length;
        } else {
            // need to wait for more functions to register
            mtx_unlock(&dev->lock);
            return ZX_OK;
        }
    }

    // build our configuration descriptor
    usb_configuration_descriptor_t* config_desc = malloc(length);
    if (!config_desc) {
        mtx_unlock(&dev->lock);
        return ZX_ERR_NO_MEMORY;
    }

    config_desc->bLength = sizeof(*config_desc);
    config_desc->bDescriptorType = USB_DT_CONFIG;
    config_desc->wTotalLength = htole16(length);
    config_desc->bNumInterfaces = 0;
    config_desc->bConfigurationValue = 1;
    config_desc->iConfiguration = 0;
    // TODO(voydanoff) add a way to configure bmAttributes and bMaxPower
    config_desc->bmAttributes = USB_CONFIGURATION_SELF_POWERED | USB_CONFIGURATION_RESERVED_7;
    config_desc->bMaxPower = 0;

    void* dest = config_desc + 1;
    list_for_every_entry(&dev->functions, function, usb_function_t, node) {
        memcpy(dest, function->descriptors, function->descriptors_length);
        dest += function->descriptors_length;
        config_desc->bNumInterfaces += function->num_interfaces;
    }
    dev->config_desc = config_desc;

    zxlogf(TRACE, "usb_device_function_registered functions_registered = true\n");
    dev->functions_registered = true;

    zx_status_t status = usb_dev_state_changed_locked(dev);
    mtx_unlock(&dev->lock);
    return status;
}

static zx_status_t usb_func_set_interface(void* ctx, const usb_function_interface_t* interface) {
    usb_function_t* function = ctx;
    usb_device_t* dev = function->dev;
    usb_function_t** endpoint_map = dev->endpoint_map;

    size_t length = usb_function_interface_get_descriptors_size(interface);
    void* descriptors = malloc(length);
    if (!descriptors) {
        return ZX_ERR_NO_MEMORY;
    }
    size_t actual;
    usb_function_interface_get_descriptors(interface, descriptors, length, &actual);
    if (actual != length) {
        zxlogf(ERROR, "usb_function_interface_get_descriptors failed\n");
        return ZX_ERR_INTERNAL;
    }

    usb_interface_descriptor_t* intf_desc = (usb_interface_descriptor_t *)descriptors;
    if (intf_desc->bDescriptorType != USB_DT_INTERFACE ||
            intf_desc->bLength != sizeof(usb_interface_descriptor_t)) {
        zxlogf(ERROR, "usb_func_set_interface: first descriptor not an interface descriptor\n");
        return ZX_ERR_INVALID_ARGS;
    }

    const usb_descriptor_header_t* end = (void *)descriptors + length;
    const usb_descriptor_header_t* header = descriptors;

    while (header < end) {
        if (header->bDescriptorType == USB_DT_INTERFACE) {
            usb_interface_descriptor_t* desc = (usb_interface_descriptor_t *)header;
            if (desc->bInterfaceNumber >= countof(dev->interface_map) ||
                dev->interface_map[desc->bInterfaceNumber] != function) {
                zxlogf(ERROR, "usb_func_set_interface: bInterfaceNumber %u\n",
                       desc->bInterfaceNumber);
                return ZX_ERR_INVALID_ARGS;
            }
            if (desc->bAlternateSetting == 0) {
                function->num_interfaces++;
            }
        } else if (header->bDescriptorType == USB_DT_ENDPOINT) {
            usb_endpoint_descriptor_t* desc = (usb_endpoint_descriptor_t *)header;
            unsigned index = ep_address_to_index(desc->bEndpointAddress);
            if (index == 0 || index >= countof(dev->endpoint_map) ||
                endpoint_map[index] != function) {
                zxlogf(ERROR, "usb_func_set_interface: bad endpoint address 0x%X\n",
                       desc->bEndpointAddress);
                return ZX_ERR_INVALID_ARGS;
            }
        }

        if (header->bLength == 0) {
            zxlogf(ERROR, "usb_func_set_interface: zero length descriptor\n");
            return ZX_ERR_INVALID_ARGS;
        }
        header = (void *)header + header->bLength;
    }

    function->descriptors = malloc(length);
    if (!function->descriptors) {
        return ZX_ERR_NO_MEMORY;
    }
    memcpy(function->descriptors, descriptors, length);
    function->descriptors_length = length;
    memcpy(&function->interface, interface, sizeof(function->interface));

    return usb_device_function_registered(function->dev);
}

static zx_status_t usb_func_alloc_interface(void* ctx, uint8_t* out_intf_num) {
    usb_function_t* function = ctx;
    usb_device_t* dev = function->dev;

    mtx_lock(&dev->lock);

    for (unsigned i = 0; i < countof(dev->interface_map); i++) {
        if (dev->interface_map[i] == NULL) {
            dev->interface_map[i] = function;
            mtx_unlock(&dev->lock);
            *out_intf_num = i;
            return ZX_OK;
        }
    }

    mtx_unlock(&dev->lock);
    return ZX_ERR_NO_RESOURCES;
}

static zx_status_t usb_func_alloc_ep(void* ctx, uint8_t direction, uint8_t* out_address) {
    unsigned start, end;

    if (direction == USB_DIR_OUT) {
        start = OUT_EP_START;
        end = OUT_EP_END;
    } else if (direction == USB_DIR_IN) {
        start = IN_EP_START;
        end = IN_EP_END;
    } else {
        return ZX_ERR_INVALID_ARGS;
    }

    usb_function_t* function = ctx;
    usb_device_t* dev = function->dev;
    usb_function_t** endpoint_map = dev->endpoint_map;

    mtx_lock(&dev->lock);
    for (unsigned index = start; index <= end; index++) {
        if (endpoint_map[index] == NULL) {
            endpoint_map[index] = function;
            mtx_unlock(&dev->lock);
            *out_address = ep_index_to_address(index);
            return ZX_OK;
        }
    }

    mtx_unlock(&dev->lock);
    return ZX_ERR_NO_RESOURCES;
}

static zx_status_t usb_func_config_ep(void* ctx, const usb_endpoint_descriptor_t* ep_desc,
                                      const usb_ss_ep_comp_descriptor_t* ss_comp_desc) {
    usb_function_t* function = ctx;
    return usb_dci_config_ep(&function->dev->usb_dci, ep_desc, ss_comp_desc);
}

static zx_status_t usb_func_disable_ep(void* ctx, uint8_t ep_addr) {
    zxlogf(TRACE, "usb_func_disable_ep\n");
    usb_function_t* function = ctx;
    return usb_dci_disable_ep(&function->dev->usb_dci, ep_addr);
}

static zx_status_t usb_func_alloc_string_desc(void* ctx, const char* string, uint8_t* out_index) {
    usb_function_t* function = ctx;
    return usb_device_alloc_string_desc(function->dev, string, out_index);
}

static void usb_func_request_queue(void* ctx, usb_request_t* req, const usb_request_complete_t* cb) {
    usb_function_t* function = ctx;
    usb_dci_request_queue(&function->dev->usb_dci, req, cb);
}

static zx_status_t usb_func_ep_set_stall(void* ctx, uint8_t ep_address) {
    usb_function_t* function = ctx;
    return usb_dci_ep_set_stall(&function->dev->usb_dci, ep_address);
}

static zx_status_t usb_func_ep_clear_stall(void* ctx, uint8_t ep_address) {
    usb_function_t* function = ctx;
    return usb_dci_ep_clear_stall(&function->dev->usb_dci, ep_address);
}

static size_t usb_func_get_request_size(void* ctx) {
    usb_function_t* function = ctx;
    return function->dev->parent_request_size;
}

usb_function_protocol_ops_t usb_function_proto = {
    .set_interface = usb_func_set_interface,
    .alloc_interface = usb_func_alloc_interface,
    .alloc_ep = usb_func_alloc_ep,
    .config_ep = usb_func_config_ep,
    .disable_ep = usb_func_disable_ep,
    .alloc_string_desc = usb_func_alloc_string_desc,
    .request_queue = usb_func_request_queue,
    .ep_set_stall = usb_func_ep_set_stall,
    .ep_clear_stall = usb_func_ep_clear_stall,
    .get_request_size = usb_func_get_request_size,
};

static zx_status_t usb_dev_get_descriptor(usb_device_t* dev, uint8_t request_type,
                                          uint16_t value, uint16_t index, void* buffer,
                                          size_t length, size_t* out_actual) {
    uint8_t type = request_type & USB_TYPE_MASK;

    if (type == USB_TYPE_STANDARD) {
        uint8_t desc_type = value >> 8;
        if (desc_type == USB_DT_DEVICE && index == 0) {
            const usb_device_descriptor_t* desc = &dev->device_desc;
            if (desc->bLength == 0) {
                zxlogf(ERROR, "usb_dev_get_descriptor: device descriptor not set\n");
                return ZX_ERR_INTERNAL;
            }
            if (length > sizeof(*desc)) length = sizeof(*desc);
            memcpy(buffer, desc, length);
            *out_actual = length;
            return ZX_OK;
        } else if (desc_type == USB_DT_CONFIG && index == 0) {
            const usb_configuration_descriptor_t* desc = dev->config_desc;
            if (!desc) {
                zxlogf(ERROR, "usb_dev_get_descriptor: configuration descriptor not set\n");
                return ZX_ERR_INTERNAL;
            }
            uint16_t desc_length = letoh16(desc->wTotalLength);
            if (length > desc_length) length =desc_length;
            memcpy(buffer, desc, length);
            *out_actual = length;
            return ZX_OK;
        }
        else if (value >> 8 == USB_DT_STRING) {
            uint8_t desc[255];
            usb_descriptor_header_t* header = (usb_descriptor_header_t *)desc;
            header->bDescriptorType = USB_DT_STRING;

            uint8_t string_index = value & 0xFF;
            if (string_index == 0) {
                // special case - return language list
                header->bLength = 4;
                desc[2] = 0x09;     // language ID
                desc[3] = 0x04;
            } else {
                char* string = dev->strings[string_index];
                if (!string) {
                    return ZX_ERR_INVALID_ARGS;
                }
                unsigned index = 2;

                // convert ASCII to Unicode
                if (string) {
                    while (*string && index < sizeof(desc) - 2) {
                        desc[index++] = *string++;
                        desc[index++] = 0;
                    }
                }
                header->bLength = index;
            }

            if (header->bLength < length) length = header->bLength;
            memcpy(buffer, desc, length);
            *out_actual = length;
            return ZX_OK;
        }
    }

    zxlogf(ERROR, "usb_device_get_descriptor unsupported value: %d index: %d\n", value, index);
    return ZX_ERR_NOT_SUPPORTED;
}

static zx_status_t usb_dev_set_configuration(usb_device_t* dev, uint8_t configuration) {
    zx_status_t status = ZX_OK;
    bool configured = configuration > 0;

    mtx_lock(&dev->lock);

    usb_function_t* function;
    list_for_every_entry(&dev->functions, function, usb_function_t, node) {
        if (function->interface.ops) {
            status = usb_function_interface_set_configured(&function->interface, configured,
                                                           dev->speed);
            if (status != ZX_OK && configured) {
                goto fail;
            }
        }
    }

    dev->configuration = configuration;

fail:
    mtx_unlock(&dev->lock);
    return status;
}

static zx_status_t usb_dev_set_interface(usb_device_t* dev, unsigned interface,
                                         unsigned alt_setting) {
    usb_function_t* function = dev->interface_map[interface];
    if (function && function->interface.ops) {
        return usb_function_interface_set_interface(&function->interface, interface, alt_setting);
    }
    return ZX_ERR_NOT_SUPPORTED;
}

static zx_status_t usb_dev_control(void* ctx, const usb_setup_t* setup, const void* write_buffer,
                                   size_t write_size, void* read_buffer, size_t read_size,
                                   size_t* out_read_actual) {
    usb_device_t* dev = ctx;
    uint8_t request_type = setup->bmRequestType;
    uint8_t direction = request_type & USB_DIR_MASK;
    uint8_t request = setup->bRequest;
    uint16_t value = le16toh(setup->wValue);
    uint16_t index = le16toh(setup->wIndex);
    uint16_t length = le16toh(setup->wLength);

    if (direction == USB_DIR_IN && length > read_size) {
        return ZX_ERR_BUFFER_TOO_SMALL;
    } else if (direction == USB_DIR_OUT && length > write_size) {
        return ZX_ERR_BUFFER_TOO_SMALL;
    }
    if ((write_size > 0 && write_buffer == NULL) || (read_size > 0 && read_buffer == NULL)) {
        return ZX_ERR_INVALID_ARGS;
    }

    zxlogf(TRACE, "usb_dev_control type: 0x%02X req: %d value: %d index: %d length: %d\n",
            request_type, request, value, index, length);

    switch (request_type & USB_RECIP_MASK) {
    case USB_RECIP_DEVICE:
        // handle standard device requests
        if ((request_type & (USB_DIR_MASK | USB_TYPE_MASK)) == (USB_DIR_IN | USB_TYPE_STANDARD) &&
            request == USB_REQ_GET_DESCRIPTOR) {
            return usb_dev_get_descriptor(dev, request_type, value, index, read_buffer, length,
                                          out_read_actual);
        } else if (request_type == (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) &&
                   request == USB_REQ_SET_CONFIGURATION && length == 0) {
            return usb_dev_set_configuration(dev, value);
        } else if (request_type == (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) &&
                   request == USB_REQ_GET_CONFIGURATION && length > 0) {
            *((uint8_t *)read_buffer) = dev->configuration;
            *out_read_actual = sizeof(uint8_t);
            return ZX_OK;
        }
        break;
    case USB_RECIP_INTERFACE: {
        if (request_type == (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) &&
                   request == USB_REQ_SET_INTERFACE && length == 0) {
            return usb_dev_set_interface(dev, index, value);
        } else {
            // delegate to the function driver for the interface
            usb_function_t* function = dev->interface_map[index];
            if (function && function->interface.ops) {
                return usb_function_interface_control(&function->interface, setup, write_buffer,
                                                      write_size, read_buffer, read_size,
                                                      out_read_actual);
            }
        }
        break;
    }
    case USB_RECIP_ENDPOINT: {
        // delegate to the function driver for the endpoint
        index = ep_address_to_index(index);
        if (index == 0 || index >= USB_MAX_EPS) {
            return ZX_ERR_INVALID_ARGS;
        }
        usb_function_t* function = dev->endpoint_map[index];
        if (function && function->interface.ops) {
            return usb_function_interface_control(&function->interface, setup, write_buffer,
                                                   write_size, read_buffer, read_size,
                                                   out_read_actual);
        }
        break;
    }
    case USB_RECIP_OTHER:
        // TODO(voydanoff) - how to handle this?
    default:
        break;
    }

    return ZX_ERR_NOT_SUPPORTED;
}

static void usb_dev_set_connected(void* ctx, bool connected) {
    usb_device_t* dev = ctx;
    if (dev->connected != connected) {
        if (!connected) {
            usb_function_t* function;
            list_for_every_entry(&dev->functions, function, usb_function_t, node) {
                if (function->interface.ops) {
                    usb_function_interface_set_configured(&function->interface, false,
                                                          USB_SPEED_UNDEFINED);
                }
            }
        }

        dev->connected = connected;
    }
}

static void usb_dev_set_speed(void* ctx, usb_speed_t speed) {
    usb_device_t* dev = ctx;
    dev->speed = speed;
}

usb_dci_interface_ops_t dci_ops = {
    .control = usb_dev_control,
    .set_connected = usb_dev_set_connected,
    .set_speed = usb_dev_set_speed,
};

static zx_status_t usb_dev_set_device_desc(void* ctx,
                                           const zircon_usb_peripheral_DeviceDescriptor* desc,
                                           fidl_txn_t* txn) {
    usb_device_t* dev = ctx;

    zx_status_t status;
    if (desc->bNumConfigurations != 1) {
        zxlogf(ERROR, "usb_device_ioctl: bNumConfigurations: %u, only 1 supported\n",
                desc->bNumConfigurations);
        status = ZX_ERR_INVALID_ARGS;
    } else {
        dev->device_desc.bLength = sizeof(usb_device_descriptor_t);
        dev->device_desc.bDescriptorType = USB_DT_DEVICE;
        dev->device_desc.bcdUSB = desc->bcdUSB;
        dev->device_desc.bDeviceClass = desc->bDeviceClass;
        dev->device_desc.bDeviceSubClass = desc->bDeviceSubClass;
        dev->device_desc.bDeviceProtocol = desc->bDeviceProtocol;
        dev->device_desc.bMaxPacketSize0 = desc->bMaxPacketSize0;
        dev->device_desc.idVendor = desc->idVendor;
        dev->device_desc.idProduct = desc->idProduct;
        dev->device_desc.bcdDevice = desc->bcdDevice;
        dev->device_desc.iManufacturer = desc->iManufacturer;
        dev->device_desc.iProduct = desc->iProduct;
        dev->device_desc.iSerialNumber = desc->iSerialNumber;
        dev->device_desc.bNumConfigurations = desc->bNumConfigurations;
        status = ZX_OK;
    }

    return zircon_usb_peripheral_DeviceSetDeviceDescriptor_reply(txn, status);
}

static zx_status_t usb_dev_alloc_string_desc(void* ctx, const char* name_data, size_t name_size,
                                             fidl_txn_t* txn) {
    usb_device_t* dev = ctx;

    uint8_t index = 0;
    zx_status_t status = usb_device_alloc_string_desc(dev, name_data, &index);
    return zircon_usb_peripheral_DeviceAllocStringDesc_reply(txn, status, index);
}

static zx_status_t usb_dev_do_add_function(usb_device_t* dev,
                                           const usb_function_descriptor_t* desc) {
    if (dev->functions_bound) {
        return ZX_ERR_BAD_STATE;
    }

    usb_function_t* function = calloc(1, sizeof(usb_function_t));
    if (!function) {
        return ZX_ERR_NO_MEMORY;
    }
    function->dci_dev = dev->dci_dev;
    function->dev = dev;
    memcpy(&function->desc, desc, sizeof(function->desc));
    list_add_tail(&dev->functions, &function->node);

    return ZX_OK;
}

static zx_status_t usb_dev_add_function(void* ctx, const usb_function_descriptor_t* desc,
                                        fidl_txn_t* txn) {
    usb_device_t* dev = ctx;

    zx_status_t status = usb_dev_do_add_function(dev, desc);
    return zircon_usb_peripheral_DeviceAddFunction_reply(txn, status);
}

static void usb_dev_remove_function_devices_locked(usb_device_t* dev) {
    zxlogf(TRACE, "usb_dev_remove_function_devices_locked\n");

    usb_function_t* function;
    list_for_every_entry(&dev->functions, function, usb_function_t, node) {
        if (function->zxdev) {
            // here we remove the function from the DDK device tree,
            // but the storage for the function remains on our function list.
            device_remove(function->zxdev);
            function->zxdev = NULL;
        }
    }

    free(dev->config_desc);
    dev->config_desc = NULL;
    dev->functions_registered = false;
    dev->function_devs_added = false;
}

static zx_status_t usb_dev_add_function_devices_locked(usb_device_t* dev) {
    zxlogf(TRACE, "usb_dev_add_function_devices_locked\n");
    if (dev->function_devs_added) {
        return ZX_OK;
    }

    usb_device_descriptor_t* device_desc = &dev->device_desc;
    int index = 0;
    usb_function_t* function;
    list_for_every_entry(&dev->functions, function, usb_function_t, node) {
        char name[16];
        snprintf(name, sizeof(name), "function-%03d", index);

        usb_function_descriptor_t* desc = &function->desc;

        zx_device_prop_t props[] = {
            { BIND_PROTOCOL, 0, ZX_PROTOCOL_USB_FUNCTION },
            { BIND_USB_CLASS, 0, desc->interface_class },
            { BIND_USB_SUBCLASS, 0, desc->interface_subclass },
            { BIND_USB_PROTOCOL, 0, desc->interface_protocol },
            { BIND_USB_VID, 0, device_desc->idVendor },
            { BIND_USB_PID, 0, device_desc->idProduct },
        };

        device_add_args_t args = {
            .version = DEVICE_ADD_ARGS_VERSION,
            .name = name,
            .ctx = function,
            .ops = &function_proto,
            .proto_id = ZX_PROTOCOL_USB_FUNCTION,
            .proto_ops = &usb_function_proto,
            .props = props,
            .prop_count = countof(props),
        };

        zx_status_t status = device_add(dev->zxdev, &args, &function->zxdev);
        if (status != ZX_OK) {
            zxlogf(ERROR, "usb_dev_bind_functions add_device failed %d\n", status);
            return status;
        }

        index++;
    }

    dev->function_devs_added = true;
    return ZX_OK;
}

static zx_status_t usb_dev_state_changed_locked(usb_device_t* dev) {
    zxlogf(TRACE, "usb_dev_state_changed_locked usb_mode: %d dci_usb_mode: %d\n", dev->usb_mode,
            dev->dci_usb_mode);

    usb_mode_t new_dci_usb_mode = dev->dci_usb_mode;
    bool add_function_devs = (dev->usb_mode == USB_MODE_PERIPHERAL && dev->functions_bound);
    zx_status_t status = ZX_OK;

    if (dev->usb_mode == USB_MODE_PERIPHERAL) {
        if (dev->functions_registered) {
            // switch DCI to device mode
            new_dci_usb_mode = USB_MODE_PERIPHERAL;
        } else {
            new_dci_usb_mode = USB_MODE_NONE;
        }
    } else {
        new_dci_usb_mode = dev->usb_mode;
    }

    if (add_function_devs) {
        // publish child devices if necessary
        if (!dev->function_devs_added) {
            status = usb_dev_add_function_devices_locked(dev);
            if (status != ZX_OK) {
                return status;
            }
        }
    }

    if (dev->dci_usb_mode != new_dci_usb_mode) {
        zxlogf(TRACE, "usb_dev_state_changed_locked set DCI mode %d\n", new_dci_usb_mode);
        if (dev->has_usb_mode_switch) {
            status = usb_mode_switch_set_mode(&dev->usb_mode_switch, new_dci_usb_mode);
            if (status != ZX_OK) {
                usb_mode_switch_set_mode(&dev->usb_mode_switch, USB_MODE_NONE);
                new_dci_usb_mode = USB_MODE_NONE;
            }
        }
        dev->dci_usb_mode = new_dci_usb_mode;
    }

    if (!add_function_devs && dev->function_devs_added) {
        usb_dev_remove_function_devices_locked(dev);
    }

    return status;
}

static zx_status_t usb_dev_do_bind_functions(usb_device_t* dev) {
    mtx_lock(&dev->lock);

    if (dev->functions_bound) {
        zxlogf(ERROR, "usb_dev_bind_functions: already bound!\n");
        mtx_unlock(&dev->lock);
        return ZX_ERR_BAD_STATE;
    }

    usb_device_descriptor_t* device_desc = &dev->device_desc;
    if (device_desc->bLength == 0) {
        zxlogf(ERROR, "usb_dev_bind_functions: device descriptor not set\n");
        mtx_unlock(&dev->lock);
        return ZX_ERR_BAD_STATE;
    }
    if (list_is_empty(&dev->functions)) {
        zxlogf(ERROR, "usb_dev_bind_functions: no functions to bind\n");
        mtx_unlock(&dev->lock);
        return ZX_ERR_BAD_STATE;
    }

    zxlogf(TRACE, "usb_dev_bind_functions functions_bound = true\n");
    dev->functions_bound = true;
    zx_status_t status = usb_dev_state_changed_locked(dev);
    mtx_unlock(&dev->lock);

    return status;
}

static zx_status_t usb_dev_bind_functions(void* ctx, fidl_txn_t* txn) {
    usb_device_t* dev = ctx;

    zx_status_t status = usb_dev_do_bind_functions(dev);
    return zircon_usb_peripheral_DeviceBindFunctions_reply(txn, status);
}


static zx_status_t usb_dev_do_clear_functions(usb_device_t* dev) {
    mtx_lock(&dev->lock);

    usb_function_t* function;
    while ((function = list_remove_head_type(&dev->functions, usb_function_t, node)) != NULL) {
        if (function->zxdev) {
            device_remove(function->zxdev);
            // device_remove will not actually free the function, so we free it here
            free(function->descriptors);
            free(function);
        }
    }
    free(dev->config_desc);
    dev->config_desc = NULL;
    dev->functions_bound = false;
    dev->functions_registered = false;

    memset(dev->interface_map, 0, sizeof(dev->interface_map));
    memset(dev->endpoint_map, 0, sizeof(dev->endpoint_map));
    for (unsigned i = 0; i < countof(dev->strings); i++) {
        free(dev->strings[i]);
        dev->strings[i] = NULL;
    }

    zx_status_t status = usb_dev_state_changed_locked(dev);
    mtx_unlock(&dev->lock);

    return status;
}

static zx_status_t usb_dev_clear_functions(void* ctx, fidl_txn_t* txn) {
    usb_device_t* dev = ctx;

    zxlogf(TRACE, "usb_dev_clear_functions\n");

    zx_status_t status = usb_dev_do_clear_functions(dev);
    return zircon_usb_peripheral_DeviceClearFunctions_reply(txn, status);
}

static zx_status_t usb_dev_get_mode(void* ctx, fidl_txn_t* txn) {
    usb_device_t* dev = ctx;

    mtx_lock(&dev->lock);
    uint32_t mode = dev->usb_mode;
    mtx_unlock(&dev->lock);

    return zircon_usb_peripheral_DeviceGetMode_reply(txn, ZX_OK, mode);
}

static zx_status_t usb_dev_set_mode(void* ctx, uint32_t mode, fidl_txn_t* txn) {
    usb_device_t* dev = ctx;

    mtx_lock(&dev->lock);
    dev->usb_mode = mode;
    zx_status_t status = usb_dev_state_changed_locked(dev);
    mtx_unlock(&dev->lock);

    return zircon_usb_peripheral_DeviceSetMode_reply(txn, status);
}

static zircon_usb_peripheral_Device_ops_t fidl_ops = {
    .SetDeviceDescriptor = usb_dev_set_device_desc,
    .AllocStringDesc = usb_dev_alloc_string_desc,
    .AddFunction = usb_dev_add_function,
    .BindFunctions = usb_dev_bind_functions,
    .ClearFunctions = usb_dev_clear_functions,
    .GetMode = usb_dev_get_mode,
    .SetMode = usb_dev_set_mode,
};

zx_status_t usb_dev_message(void* ctx, fidl_msg_t* msg, fidl_txn_t* txn) {
    return zircon_usb_peripheral_Device_dispatch(ctx, txn, msg, &fidl_ops);
}

static void usb_dev_unbind(void* ctx) {
    zxlogf(TRACE, "usb_dev_unbind\n");
    usb_device_t* dev = ctx;
    usb_dev_do_clear_functions(dev);
    device_remove(dev->zxdev);
}

static void usb_dev_release(void* ctx) {
    zxlogf(TRACE, "usb_dev_release\n");
    usb_device_t* dev = ctx;
    free(dev->config_desc);
    for (unsigned i = 0; i < countof(dev->strings); i++) {
        free(dev->strings[i]);
    }
    free(dev);
}

static zx_protocol_device_t device_proto = {
    .version = DEVICE_OPS_VERSION,
    .message = usb_dev_message,
    .unbind = usb_dev_unbind,
    .release = usb_dev_release,
};

#if defined(USB_DEVICE_VID) && defined(USB_DEVICE_PID) && defined(USB_DEVICE_FUNCTIONS)
static zx_status_t usb_dev_set_default_config(usb_device_t* dev) {
    usb_device_descriptor_t device_desc = {
        .bLength = sizeof(usb_device_descriptor_t),
        .bDescriptorType = USB_DT_DEVICE,
        .bcdUSB = htole16(0x0200),
        .bDeviceClass = 0,
        .bDeviceSubClass = 0,
        .bDeviceProtocol = 0,
        .bMaxPacketSize0 = 64,
        .idVendor = htole16(USB_DEVICE_VID),
        .idProduct = htole16(USB_DEVICE_PID),
        .bcdDevice = htole16(0x0100),
        .bNumConfigurations = 1,
    };

    zx_status_t status = ZX_OK;

#ifdef USB_DEVICE_MANUFACTURER
    status = usb_device_alloc_string_desc(dev, USB_DEVICE_MANUFACTURER, &device_desc.iManufacturer);
    if (status != ZX_OK) return status;
#endif
#ifdef USB_DEVICE_PRODUCT
    usb_device_alloc_string_desc(dev, USB_DEVICE_PRODUCT, &device_desc.iProduct);
    if (status != ZX_OK) return status;
#endif
#ifdef USB_DEVICE_SERIAL
    usb_device_alloc_string_desc(dev, USB_DEVICE_SERIAL, &device_desc.iSerialNumber);
    if (status != ZX_OK) return status;
#endif

    memcpy(&dev->device_desc, &device_desc, sizeof(dev->device_desc));

    usb_function_descriptor_t function_desc;
    if (strcasecmp(USB_DEVICE_FUNCTIONS, "cdc") == 0) {
        function_desc.interface_class = USB_CLASS_COMM;
        function_desc.interface_subclass = USB_CDC_SUBCLASS_ETHERNET;
        function_desc.interface_protocol = 0;
    } else if (strcasecmp(USB_DEVICE_FUNCTIONS, "ums") == 0) {
        function_desc.interface_class = USB_CLASS_MSC;
        function_desc.interface_subclass = USB_SUBCLASS_MSC_SCSI;
        function_desc.interface_protocol = USB_PROTOCOL_MSC_BULK_ONLY;
    } else if (strcasecmp(USB_DEVICE_FUNCTIONS, "test") == 0) {
        function_desc.interface_class = USB_CLASS_VENDOR;
        function_desc.interface_subclass = 0;
        function_desc.interface_protocol = 0;
    } else {
        zxlogf(ERROR, "usb_dev_set_default_config: unknown function %s\n", USB_DEVICE_FUNCTIONS);
        return ZX_ERR_INVALID_ARGS;
    }

    status = usb_dev_do_add_function(dev, &function_desc);
    if (status != ZX_OK) return status;

    return usb_dev_do_bind_functions(dev);
}
#endif // defined(USB_DEVICE_VID) && defined(USB_DEVICE_PID) && defined(USB_DEVICE_FUNCTIONS)

zx_status_t usb_dev_bind(void* ctx, zx_device_t* parent) {
    zxlogf(INFO, "usb_dev_bind\n");

    usb_device_t* dev = calloc(1, sizeof(usb_device_t));
    if (!dev) {
        return ZX_ERR_NO_MEMORY;
    }
    list_initialize(&dev->functions);
    mtx_init(&dev->lock, mtx_plain);
    dev->dci_dev = parent;

    if (device_get_protocol(parent, ZX_PROTOCOL_USB_DCI, &dev->usb_dci)) {
        free(dev);
        return ZX_ERR_NOT_SUPPORTED;
    }

    if (device_get_protocol(parent, ZX_PROTOCOL_USB_MODE_SWITCH, &dev->usb_mode_switch) == ZX_OK) {
        dev->has_usb_mode_switch = true;
    }

    // Starting USB mode is determined from device metadata.
    // We read initial value and store it in dev->usb_mode, but do not actually
    // enable it until after all of our functions have bound.
    size_t actual;
    zx_status_t status = device_get_metadata(parent, DEVICE_METADATA_USB_MODE,
                                             &dev->usb_mode, sizeof(dev->usb_mode), &actual);
    if (status == ZX_ERR_NOT_FOUND) {
        // Assume peripheral mode by default.
        dev->usb_mode = USB_MODE_PERIPHERAL;
    } else if (status != ZX_OK || actual != sizeof(dev->usb_mode)) {
        zxlogf(ERROR, "usb_dev_bind: DEVICE_METADATA_USB_MODE not found\n");
        free(dev);
        return status;
    }
    // Set DCI mode to USB_MODE_NONE until we are ready
    if (dev->has_usb_mode_switch) {
        usb_mode_switch_set_mode(&dev->usb_mode_switch, USB_MODE_NONE);
    }
    dev->dci_usb_mode = USB_MODE_NONE;
    dev->parent_request_size = usb_dci_get_request_size(&dev->usb_dci);

    device_add_args_t args = {
        .version = DEVICE_ADD_ARGS_VERSION,
        .name = "usb-peripheral",
        .ctx = dev,
        .ops = &device_proto,
        .proto_id = ZX_PROTOCOL_USB_PERIPHERAL,
        .flags = DEVICE_ADD_NON_BINDABLE,
    };

    status = device_add(parent, &args, &dev->zxdev);
    if (status != ZX_OK) {
        zxlogf(ERROR, "usb_device_bind add_device failed %d\n", status);
        free(dev);
        return status;
    }

    usb_dci_interface_t intf = {
        .ops = &dci_ops,
        .ctx = dev,
    };
    usb_dci_set_interface(&dev->usb_dci, &intf);

#if defined(USB_DEVICE_VID) && defined(USB_DEVICE_PID) && defined(USB_DEVICE_FUNCTIONS)
    // set compile time configuration, if we have one
    usb_dev_set_default_config(dev);
#endif

    return ZX_OK;
}

static zx_driver_ops_t usb_device_ops = {
    .version = DRIVER_OPS_VERSION,
    .bind = usb_dev_bind,
};

// clang-format off
ZIRCON_DRIVER_BEGIN(usb_device, usb_device_ops, "zircon", "0.1", 1)
    BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_USB_DCI),
ZIRCON_DRIVER_END(usb_device)
