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

#pragma once

#include <ddk/protocol/usb.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <zircon/hw/usb.h>

__BEGIN_CDECLS;

// This protocol is used for USB peripheral function functions

// callbacks implemented by the function driver
typedef struct {

    // return the descriptor list for the function
    // TODO(voydanoff) - descriptors will likely vary (different max packet sizes, etc)
    // depending on whether we are in low/full, high or super speed mode.
    // We will need to add a usb_speed_t argument to this callback.
    const usb_descriptor_header_t* (*get_descriptors)(void* ctx, size_t* out_length);

    // callback for handling ep0 control requests
    zx_status_t (*control)(void* ctx, const usb_setup_t* setup, void* buffer, size_t buffer_length,
                           size_t* out_actual);

    // Called to inform the function driver when the USB device configured state changes.
    // Called with configured == true in response to a SET_CONFIGURATION control request
    // that selects a configuration that contains this function. In this case, the function driver
    // should call usb_function_config_ep() to configure its endpoints.
    // Called with configured == false when configuration is disabled or USB is disconnected.
    // The function driver should then call usb_function_disable_ep() to disable its endpoints.
    zx_status_t (*set_configured)(void* ctx, bool configured, usb_speed_t speed);

    // Called to set an alternate setting for an interface due to a SET_INTERFACE control request.
    // The function driver should call usb_function_config_ep() and/or usb_function_config_ep()
    // to configure or disable the interface's endpoints as appropriate.
    zx_status_t (*set_interface)(void* ctx, unsigned interface, unsigned alt_setting);
} usb_function_interface_ops_t;

typedef struct {
    usb_function_interface_ops_t* ops;
    void* ctx;
} usb_function_interface_t;

static inline const usb_descriptor_header_t* usb_function_get_descriptors(
                                        usb_function_interface_t* intf, size_t* out_length) {
    return intf->ops->get_descriptors(intf->ctx, out_length);
}

static inline zx_status_t usb_function_control(usb_function_interface_t* intf,
                                               const usb_setup_t* setup, void* buffer,
                                               size_t buffer_length, size_t* out_actual) {
    return intf->ops->control(intf->ctx, setup, buffer, buffer_length, out_actual);
}

static inline zx_status_t usb_function_set_configured(usb_function_interface_t* intf,
                                                      bool configured, usb_speed_t speed) {
    return intf->ops->set_configured(intf->ctx, configured, speed);
}

static inline zx_status_t usb_function_set_interface(usb_function_interface_t* intf,
                                                     unsigned interface, unsigned alt_setting) {
    return intf->ops->set_interface(intf->ctx, interface, alt_setting);
}

typedef struct {
    zx_status_t (*register_func)(void* ctx, usb_function_interface_t* intf);
    zx_status_t (*alloc_interface)(void* ctx, uint8_t* out_intf_num);
    zx_status_t (*alloc_ep)(void* ctx, uint8_t direction, uint8_t* out_address);
    zx_status_t (*config_ep)(void* ctx, usb_endpoint_descriptor_t* ep_desc,
                             usb_ss_ep_comp_descriptor_t* ss_comp_desc);
    zx_status_t (*disable_ep)(void* ctx, uint8_t ep_addr);
    zx_status_t (*alloc_string_desc)(void* ctx, const char* string, uint8_t* out_index);
    void (*queue)(void* ctx, usb_request_t* req, const usb_request_complete_t* complete_cb);
    zx_status_t (*ep_set_stall)(void* ctx, uint8_t ep_address);
    zx_status_t (*ep_clear_stall)(void* ctx, uint8_t ep_address);
    size_t (*get_request_size)(void* ctx);
} usb_function_protocol_ops_t;

typedef struct {
    usb_function_protocol_ops_t* ops;
    void* ctx;
} usb_function_protocol_t;

// registers the function driver's callback interface
static inline void usb_function_register(usb_function_protocol_t* func,
                                         usb_function_interface_t* intf) {
    func->ops->register_func(func->ctx, intf);
}

// allocates a unique interface descriptor number
static inline zx_status_t usb_function_alloc_interface(usb_function_protocol_t* func,
                                                       uint8_t* out_intf_num) {
    return func->ops->alloc_interface(func->ctx, out_intf_num);
}

// allocates a unique endpoint descriptor number
// direction should be either USB_DIR_OUT or USB_DIR_IN
static inline zx_status_t usb_function_alloc_ep(usb_function_protocol_t* func, uint8_t direction,
                                                uint8_t* out_address) {
    return func->ops->alloc_ep(func->ctx, direction, out_address);
}

// configures an endpoint based on the provided usb_endpoint_descriptor_t and
// usb_ss_ep_comp_descriptor_t descriptors.
static inline zx_status_t usb_function_config_ep(usb_function_protocol_t* func,
                                                 usb_endpoint_descriptor_t* ep_desc,
                                                 usb_ss_ep_comp_descriptor_t* ss_comp_desc) {
    return func->ops->config_ep(func->ctx, ep_desc, ss_comp_desc);
}

// disables an endpoint. called when the device is no longer configured or an alternate interface
// is selected.
static inline zx_status_t usb_function_disable_ep(usb_function_protocol_t* func, uint8_t ep_addr) {
    return func->ops->disable_ep(func->ctx, ep_addr);
}

// adds a string descriptor to the device configuration.
static inline zx_status_t usb_function_alloc_string_desc(usb_function_protocol_t* func,
                                                         const char* string, uint8_t* out_index) {
    return func->ops->alloc_string_desc(func->ctx, string, out_index);
}

// helper for queueing a usb request on an endpoint.
static inline void usb_function_queue(usb_function_protocol_t* func, usb_request_t* req,
                                      const usb_request_complete_t* complete_cb) {
    return func->ops->queue(func->ctx, req, complete_cb);
}

// stalls an endpoint
static zx_status_t usb_function_ep_set_stall(usb_function_protocol_t* func, uint8_t ep_address) {
    return func->ops->ep_set_stall(func->ctx, ep_address);
}

// clears endpoint stall state
static zx_status_t usb_function_ep_clear_stall(usb_function_protocol_t* func, uint8_t ep_address) {
    return func->ops->ep_clear_stall(func->ctx, ep_address);
}

// returns the total request size including any internal context size at this
// layer per usb_request
static size_t usb_function_get_request_size(usb_function_protocol_t* func) {
    return func->ops->get_request_size(func->ctx);
}
__END_CDECLS;
