#ifndef VMF_NNM_USBD_HAL_H
#define VMF_NNM_USBD_HAL_H

#pragma once

#include <stdint.h>
#include <stdbool.h>

#include <linux/usb/functionfs.h>

typedef enum {
    VMF_NNM_USB_ENDPOINT_DATA_IN = 1,
    VMF_NNM_USB_ENDPOINT_DATA_OUT = 2,
#ifdef FIFIOQ_LOG_VIA_USB
    VMF_NNM_Usb_Endpoint_Log_In = 3,
#endif
    VMF_NNM_USB_ENDPOINT_TOTAL
} VMF_NNM_Usb_Endpoint;

/**
 * @brief USBD HAL link status
 */
typedef enum {
    VMF_NNM_USBD_HAL_STATUS_DISCONNECTED = 0x1,
    VMF_NNM_USBD_HAL_STATUS_CONFIGURED, // connected
} VMF_NNM_Usbd_Hal_Link_Status;

typedef enum
{
    VMF_NNM_USBD_HAL_STATUS_OK = 0,                       /**< driver status OK */
    VMF_NNM_USBD_HAL_STATUS_ERROR,                        /**< driver status error */
    VMF_NNM_USBD_HAL_STATUS_INVALID_PARAM,                /**< driver invalid parameters */
    VMF_NNM_USBD_HAL_STATUS_INVALID_ENDPOINT,        /**< USBD : invalid endpoint */
    VMF_NNM_USBD_HAL_STATUS_TRANSFER_TIMEOUT,        /**< USBD : transfer timeout */
    VMF_NNM_USBD_HAL_STATUS_INVALID_TRANSFER,        /**< USBD : invalid transfer operation */
    VMF_NNM_USBD_HAL_STATUS_TRANSFER_IN_PROGRESS,    /**< USBD : transfer is in progress */
} VMF_NNM_Usbd_Hal_Status;

typedef struct usb_ctrlrequest VMF_NNM_Usbd_Hal_Setup_Packet_T;

/**
 * @brief callback function for usb link status
 * @param link_status usb link status
 */
typedef void (*VMF_NNM_Usbd_Hal_User_Link_Status_Callback_T)(VMF_NNM_Usbd_Hal_Link_Status link_status);

/**
 * @brief callback function for control command handler
 * @param setup control command package
 */
typedef bool (*VMF_NNM_Usbd_Hal_User_Control_Callback_T)(VMF_NNM_Usbd_Hal_Setup_Packet_T *setup);

/**
 * @brief usbd hal initialize function
 *
 * @param serial_string device serial string (kn number)
 * @param bcdDevice Device firmware version
 * @param usr_link_isr_cb callback function for usb link status
 * @param usr_cx_isr_cb callback function for control command handler
 * @return VMF_NNM_Usbd_Hal_Status
 */
VMF_NNM_Usbd_Hal_Status VMF_NNM_Usbd_Hal_Initialize(uint8_t *serial_string, uint16_t bcdDevice,
                                          VMF_NNM_Usbd_Hal_User_Link_Status_Callback_T usr_link_isr_cb,
                                          VMF_NNM_Usbd_Hal_User_Control_Callback_T usr_cx_isr_cb);

/**
 * @brief set usbd hal enalbe
 *
 * @param enable enable/disable usbd hal
 * @return VMF_NNM_Usbd_Hal_Status
 */
VMF_NNM_Usbd_Hal_Status VMF_NNM_Usbd_Hal_Set_Enable(bool enable);

/**
 * @brief send data in bulk transfer
 *
 * @param endpoint the output endpoint for bulk transfer
 * @param buf data to be sent
 * @param txLen size of data to be sent
 * @param timeout_ms timeout in milliseconds
 * @return VMF_NNM_Usbd_Hal_Status
 */
VMF_NNM_Usbd_Hal_Status VMF_NNM_Usbd_Hal_Bulk_Send(VMF_NNM_Usb_Endpoint endpoint, uint32_t *buf, uint32_t txLen, uint32_t timeout_ms);

/**
 * @brief receive data in bulk transfer
 *
 * @param endpoint the input endpoint for bulk transfer
 * @param buf buffer to receive data
 * @param blen [in] size to be receive or max size of buffer
 *             [out] size of received data
 * @param timeout_ms timeout in milliseconds
 * @return VMF_NNM_Usbd_Hal_Status
 */
VMF_NNM_Usbd_Hal_Status VMF_NNM_Usbd_Hal_Bulk_Receive(VMF_NNM_Usb_Endpoint endpoint, uint32_t *buf, uint32_t *blen, uint32_t timeout_ms);

/**
 * @brief terminate all endpoints
 *
 * @return VMF_NNM_Usbd_Hal_Status
 */
VMF_NNM_Usbd_Hal_Status VMF_NNM_Usbd_Hal_Terminate_All_Endpoint(void);

/**
 * @brief terminate the endpoint
 *
 * @param endpoint the endpoint to be ternminated
 * @return VMF_NNM_Usbd_Hal_Status
 */
VMF_NNM_Usbd_Hal_Status VMF_NNM_Usbd_Hal_Terminate_Endpoint(VMF_NNM_Usb_Endpoint endpoint);

#endif
