/**
 * @file usbport.h
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2023-09-04
 *
 * @copyright Copyright (c) 2023
 *
 */

#pragma once

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

#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "os/os.h"

#include "config/hardware_define.h"
#include "drivers/data_port/sb_data_port.h"

#include "usb/usb_types_stack.h"

#include "os/os.h"

#define MAX_FILE_COUNT 255
#define MAX_EXCLUDING_FILE_COUNT 20
#define MAX_FILE_PATH 50

typedef enum
{
    USBPORT_STATUS_NO_CONNECTION = 0, // 没有外设
    USBPORT_STATUS_CDC = 1,           // 外设处于cdc状态
    USBPORT_STATUS_DFU = 2,           // 外设处于dfu状态
    USBPORT_STATUS_MSC = 3,           // 外设处于msc状态
} usbport_status_e;

typedef enum
{
    EXCLUDING_FILE_COMPARE_ALL = 0,    // 比较整个文名名，任意部分与指定字符串不同，则认为不相同
    EXCLUDING_FILE_COMPARE_PREFIX = 1, // 只比较文件名的前面部分是否与指定的字符串相同
} excluding_file_compare_type;

typedef struct
{
    const char filename[MAX_FILE_PATH];
    uint8_t is_dir;
    uint8_t compare_type;
} excluding_file_item_t;

#pragma pack(push, 1)
typedef struct
{
    char file_path[MAX_FILE_PATH];
    uint32_t file_size;
} msc_file_info;
#pragma pack(pop)

int usbport_init(void);
void usbport_deinit(void);
sb_data_port_t *usbport_bind(os_work_t *rx_resume_work);
void usbport_unbind(sb_data_port_t *port);

usbport_status_e usbport_get_state(void);

// 读取flash layout信息
void usbh_stm32_get_chipinfo(char *descriptors, uint8_t count, uint8_t *actual_desc_count);
// 读取传输块大小
// uint16_t usbh_stm32_get_transfer_block_size();
// clear status
esp_err_t usbh_stm32_clear_status(void);
// get status
esp_err_t usbh_stm32_get_status(uint8_t *out_result_data /*[6]*/);
esp_err_t usbh_stm32_get_status_ex(uint8_t *out_result_data /*[6]*/, uint16_t timeout);
// 设置当前地址
esp_err_t _usbh_stm32_load_address(uint32_t address);
// 控制指令传输
esp_err_t _usbh_stm32_control_transfer(uint8_t direction,
                                       uint8_t request,
                                       uint16_t value,
                                       uint16_t interface,
                                       uint16_t length,
                                       uint8_t *packet_data,
                                       uint8_t *out_buffer,
                                       uint16_t out_buffer_size,
                                       uint16_t *actual_result_size);

esp_err_t _usbh_stm32_control_transfer_ex(uint8_t direction,
                                          uint8_t request,
                                          uint16_t value,
                                          uint16_t interface,
                                          uint16_t length,
                                          uint8_t *packet_data,
                                          uint8_t *out_buffer,
                                          uint16_t out_buffer_size,
                                          uint16_t *actual_result_size,
                                          uint16_t timeout);
// 解除读保护
esp_err_t _usbh_stm32_unprotect(void);

// 读取option byte区别
esp_err_t _usbh_stm32_try_read_ob(uint16_t ob_data_size);

// 退出dfu状态
esp_err_t _usbh_stm32_leave_dfu(void);

// 断开usb设备的连接
void _usbh_pre_disconnect_deivce(void);

msc_file_info *msc_get_file_list(uint16_t *out_file_count, const excluding_file_item_t *excluding_files, uint8_t excluding_file_count);
msc_file_info *msc_get_cached_file_list(uint16_t *out_file_count);
typedef enum
{
    USB_CONNECTED_CDC = 0,
    USB_CONNECTED_DFU = 1,
    USB_CONNECTED_MSC = 2,
    USB_CONNECTED_UNKNOWN = 3,
} usb_connect_type_t;

usb_connect_type_t usbport_get_usb_type(void);
