// Copyright 2016 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/usb.h>
#include <zircon/compiler.h>
#include <stdlib.h>
#include <string.h>

// initializes a usb_desc_iter_t for iterating on descriptors past the
// interface's existing descriptors.
static zx_status_t usb_desc_iter_additional_init(usb_composite_protocol_t* comp,
                                                 usb_desc_iter_t* iter) {
    memset(iter, 0, sizeof(*iter));

    size_t length = usb_composite_get_additional_descriptor_length(comp);
    uint8_t* descriptors = malloc(length);
    if (!descriptors) {
        return ZX_ERR_NO_MEMORY;
    }
    size_t actual;
    zx_status_t status = usb_composite_get_additional_descriptor_list(comp, descriptors, length,
                                                                      &actual);
    if (status != ZX_OK) {
        return status;
    }

    iter->desc = descriptors;
    iter->desc_end = descriptors + length;
    iter->current = descriptors;
    return ZX_OK;
}

// helper function for claiming additional interfaces that satisfy the want_interface predicate,
// want_interface will be passed the supplied arg
__EXPORT zx_status_t usb_claim_additional_interfaces(usb_composite_protocol_t* comp,
    bool (*want_interface)(usb_interface_descriptor_t*, void*),
    void* arg) {
    usb_desc_iter_t iter;
    zx_status_t status = usb_desc_iter_additional_init(comp, &iter);
    if (status != ZX_OK) {
        return status;
    }

    usb_interface_descriptor_t* intf = usb_desc_iter_next_interface(&iter, true);
    while (intf != NULL && want_interface(intf, arg)) {
        // We need to find the start of the next interface to calculate the
        // total length of the current one.
        usb_interface_descriptor_t* next = usb_desc_iter_next_interface(&iter, true);
        // If we're currently on the last interface, next will be NULL.
        void* intf_end = next ? next : (void*)iter.desc_end;
        size_t length = intf_end - (void*)intf;

        status = usb_composite_claim_interface(comp, intf, length);
        if (status != ZX_OK) {
            break;
        }
        intf = next;
    }
    usb_desc_iter_release(&iter);
    return status;
}

// initializes a usb_desc_iter_t
__EXPORT zx_status_t usb_desc_iter_init(usb_protocol_t* usb, usb_desc_iter_t* iter) {
    memset(iter, 0, sizeof(*iter));

    size_t length = usb_get_descriptors_length(usb);
    void* descriptors = malloc(length);
    if (!descriptors) {
        return ZX_ERR_NO_MEMORY;
    }
    size_t actual;
    usb_get_descriptors(usb, descriptors, length, &actual);

    iter->desc = descriptors;
    iter->desc_end = descriptors + length;
    iter->current = descriptors;
    return ZX_OK;
}

// clones a usb_desc_iter_t
zx_status_t usb_desc_iter_clone(const usb_desc_iter_t* src, usb_desc_iter_t* dest) {
    size_t length = (size_t)(src->desc_end)-(size_t)(src->desc);
    size_t offset = (size_t)(src->current)-(size_t)(src->desc);
    void* descriptors = malloc(length);
    if(!descriptors) {
        return ZX_ERR_NO_MEMORY;
    }
    memcpy(descriptors, src->desc, length);
    dest->desc = descriptors;
    dest->current = ((unsigned char*)descriptors)+offset;
    dest->desc_end = ((unsigned char*)descriptors)+length;
    return ZX_OK;
}

// releases resources in a usb_desc_iter_t
__EXPORT void usb_desc_iter_release(usb_desc_iter_t* iter) {
    free(iter->desc);
    iter->desc = NULL;
}

// resets iterator to the beginning
__EXPORT void usb_desc_iter_reset(usb_desc_iter_t* iter) {
    iter->current = iter->desc;
}

// returns the next descriptor
__EXPORT usb_descriptor_header_t* usb_desc_iter_next(usb_desc_iter_t* iter) {
    usb_descriptor_header_t* header = usb_desc_iter_peek(iter);
    if (!header) return NULL;
    iter->current += header->bLength;
    return header;
}

// returns the next descriptor without incrementing the iterator
__EXPORT usb_descriptor_header_t* usb_desc_iter_peek(usb_desc_iter_t* iter) {
    if (iter->current + sizeof(usb_descriptor_header_t) > iter->desc_end) {
        return NULL;
    }
    usb_descriptor_header_t* header = (usb_descriptor_header_t *)iter->current;
    if (iter->current + header->bLength > iter->desc_end) {
        return NULL;
    }
    return header;
}

// returns the next interface descriptor, optionally skipping alternate interfaces
__EXPORT usb_interface_descriptor_t* usb_desc_iter_next_interface(usb_desc_iter_t* iter,
                                                                  bool skip_alt) {
    usb_descriptor_header_t* header = usb_desc_iter_next(iter);

    while (header) {
        if (header->bDescriptorType == USB_DT_INTERFACE) {
            usb_interface_descriptor_t* desc = (usb_interface_descriptor_t *)header;
            if (!skip_alt || desc->bAlternateSetting == 0) {
                return desc;
            }
        }
        header = usb_desc_iter_next(iter);
    }
    // not found
    return NULL;
}

// returns the next endpoint descriptor within the current interface
__EXPORT usb_endpoint_descriptor_t* usb_desc_iter_next_endpoint(usb_desc_iter_t* iter) {
    usb_descriptor_header_t* header = usb_desc_iter_peek(iter);
    while (header) {
        if (header->bDescriptorType == USB_DT_INTERFACE) {
            // we are at end of previous interface
            return NULL;
        }
        iter->current += header->bLength;
        if (header->bDescriptorType == USB_DT_ENDPOINT) {
            return (usb_endpoint_descriptor_t *)header;
        }
        header = usb_desc_iter_peek(iter);
    }
    // not found
    return NULL;
}
