Files
ESPC3-wireless/app/drivers/data_port/usb-host/usbport.c
LokLiang 176b2c49f6 20250529 同步自原始工程:
优化 CMakeLists.txt,增加 lib-out 目录的包含;修改 app_config.c 中的 LED 灯带开关变量名;更新 app_config.h,增加新的灯效模式和方向控制;更新 SBDEMO.h 中的默认设备名称;在 msc_host.c 中添加 USB 设备连接类型的处理;在 usbport.c 中增加 USB 连接类型的状态管理;更新 Kconfig,增加 LED 灯带的最大图层数和竞速模式选项;新增 spbelib_interface.h 文件,定义无线调参功能接口;删除不再使用的 components/CMakeLists.txt 文件;更新 misc.h,添加读取 MCU 身份信息的 MD5 值的函数声明;修改 tim.h 中的 drv_pwm_init 函数参数;更新 kk.h,增加默认工作队列的创建宏;优化 sh.c 中的命令行插入字符串逻辑;更新 sdkconfig 默认配置文件,升级 ESP-IDF 版本和调整蓝牙默认发射功率。
2025-05-29 18:05:20 +08:00

909 lines
29 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/ringbuf.h"
#include "esp_err.h"
#include "esp_log.h"
#include "usb/usb_host.h"
#include "msc/include/msc_host.h"
#include "msc/include/msc_host_vfs.h"
#include "ffconf.h"
#include "ff.h"
#include "errno.h"
#include "esp_vfs.h"
#include "spbelib_interface.h"
#include "config/hardware_define.h"
// #include "usb/cdc_acm_host.h"
#include "usbport.h"
#define CONFIG_SYS_LOG_DUMP_ON 0
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_WRN
#define SYS_LOG_DOMAIN "USB"
#include "sys_log.h"
#define IN_RINGBUF_SIZE (1024 * 1)
#define OUT_RINGBUF_SIZE (1024 * 1)
#define CDC_CHECK(a, str, ret) \
do \
{ \
if (!(a)) \
{ \
SYS_LOG_ERR(str); \
return (ret); \
} \
} while (0)
#define CDC_CHECK_GOTO(a, str, lable) \
do \
{ \
if (!(a)) \
{ \
SYS_LOG_ERR(str); \
goto lable; \
} \
} while (0)
typedef struct
{
os_pipe_t pipe_obj;
os_work_t *rx_resume_work;
} __usb_data_t;
static QueueHandle_t app_queue;
// static SemaphoreHandle_t ready_to_uninstall_usb;
static msc_host_vfs_handle_t vfs_handle;
static usbport_status_e g_usb_status = USBPORT_STATUS_NO_CONNECTION;
static __usb_data_t s_usb_data;
static sb_data_port_t s_port;
static msc_host_device_handle_t g_connected_usb_device = NULL;
static cdc_acm_dev_hdl_t g_cdc_dev;
//////////// CDC 全局变量 ////////////
#define BULK_OUT_URB_NUM 2
#define BULK_IN_URB_NUM 2
#define BUFFER_SIZE_BULK_OUT 512
#define BUFFER_SIZE_BULK_IN 512
#define USB_TASK_KILL_BIT BIT1
#define CDC_DATA_TASK_KILL_BIT BIT4
#define CDC_DEVICE_READY_BIT BIT19
#define TIMEOUT_USB_RINGBUF_MS 200 // Timeout for Ring Buffer push
static EventGroupHandle_t s_usb_event_group = NULL;
// static RingbufHandle_t s_in_ringbuf_handle = NULL;
static RingbufHandle_t s_out_ringbuf_handle = NULL;
// static SemaphoreHandle_t s_usb_read_mux = NULL;
static SemaphoreHandle_t s_usb_write_mux = NULL;
// static TaskHandle_t s_usb_processing_task_hdl = NULL;
// static portMUX_TYPE s_in_ringbuf_mux = portMUX_INITIALIZER_UNLOCKED;
static portMUX_TYPE s_out_ringbuf_mux = portMUX_INITIALIZER_UNLOCKED;
volatile static int s_in_buffered_data_len = 0;
volatile static int s_out_buffered_data_len = 0;
volatile static usb_connect_type_t s_usb_connect_type = USB_CONNECTED_UNKNOWN;
//////////// End CDC 全局变量 ////////////
//////////// MSC 全局变量 ////////////////
static msc_file_info g_msc_file_lists[MAX_FILE_COUNT];
// static excluding_file_item_t msc_excluding_files[MAX_EXCLUDING_FILE_COUNT];
static uint16_t g_msc_file_count = 0;
//////////// End MSC 全局变量 ////////////
static TaskHandle_t s_usb_task_handle, s_device_task_handle; //, workthread_handle;
static void usb_device_event_cb(const msc_host_event_t *event, void *arg)
{
switch (event->event)
{
case MSC_DEVICE_CONNECTED:
s_usb_connect_type = USB_CONNECTED_MSC;
SYS_LOG_INF("MSC device connected");
sblib_send_event(LIB_EVENT_USBH_MSC, 0, NULL);
break;
case MSC_DEVICE_DISCONNECTED:
s_usb_connect_type = USB_CONNECTED_UNKNOWN;
SYS_LOG_INF("MSC device disconnected");
sblib_send_event(LIB_EVENT_USBH_UNKNOW_DEVICE, 0, NULL);
break;
case CDC_DEVICE_CONNECTED:
s_usb_connect_type = USB_CONNECTED_CDC;
SYS_LOG_INF("CDC device connected");
sblib_send_event(LIB_EVENT_USBH_CDC, 0, NULL);
break;
case CDC_DEVICE_DISCONNECTED:
s_usb_connect_type = USB_CONNECTED_UNKNOWN;
SYS_LOG_INF("CDC device disconnected");
sblib_send_event(LIB_EVENT_USBH_UNKNOW_DEVICE, 0, NULL);
break;
case DFU_DEVICE_CONNECTED:
s_usb_connect_type = USB_CONNECTED_DFU;
SYS_LOG_INF("DFU device connected");
sblib_send_event(LIB_EVENT_USBH_DFU, 0, NULL);
break;
case DFU_DEVICE_DISCONNECTED:
s_usb_connect_type = USB_CONNECTED_UNKNOWN;
SYS_LOG_INF("DFU device disconnected");
sblib_send_event(LIB_EVENT_USBH_UNKNOW_DEVICE, 0, NULL);
break;
}
xQueueSend(app_queue, event, 10);
}
// Handles common USB host library events
static void handle_usb_events(void *args)
{
while (1)
{
uint32_t event_flags;
SYS_LOG_INF("usb_host_lib_handle_events(portMAX_DELAY, &event_flags);");
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
// Release devices once all clients has deregistered
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS)
{
SYS_LOG_INF("usb_host_device_free_all();");
usb_host_device_free_all();
// SYS_LOG_INF("xSemaphoreGive(ready_to_uninstall_usb);");
// xSemaphoreGive(ready_to_uninstall_usb);
break;
}
// Give ready_to_uninstall_usb semaphore to indicate that USB Host library
// can be deinitialized, and terminate this task.
// if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE)
// {
// SYS_LOG_INF("xSemaphoreGive(ready_to_uninstall_usb);");
// xSemaphoreGive(ready_to_uninstall_usb);
// }
}
s_usb_task_handle = NULL;
vTaskDelete(NULL);
}
static void print_device_info(msc_host_device_info_t *info)
{
const size_t megabyte = 1024 * 1024;
uint64_t capacity = ((uint64_t)info->sector_size * info->sector_count) / megabyte;
printf("Device info:\n");
printf("\t Capacity: %llu MB\n", capacity);
printf("\t Sector size: %u\n", info->sector_size);
printf("\t Sector count: %u\n", info->sector_count);
printf("\t PID: 0x%4X \n", info->idProduct);
printf("\t VID: 0x%4X \n", info->idVendor);
wprintf(L"\t iProduct: %S \n", info->iProduct);
wprintf(L"\t iManufacturer: %S \n", info->iManufacturer);
wprintf(L"\t iSerialNumber: %S \n", info->iSerialNumber);
}
/* ------------------------------- Callbacks -------------------------------- */
static void handle_rx(uint8_t *data, size_t data_len, void *arg)
{
SYS_LOG_INF("Data received %d bytes", data_len);
// ESP_LOG_BUFFER_HEXDUMP(data, data_len, ESP_LOG_INFO);
int write_result = os_pipe_fifo_fill(&s_usb_data.pipe_obj, data, data_len);
if (write_result != data_len)
{
SYS_LOG_WRN("[ERROR]write data to pipe_obj failed, remain: %d bytes, data_len:%d!!",
write_result,
data_len);
}
if (os_pipe_get_empty_size(&s_usb_data.pipe_obj) >= BUFFER_SIZE_BULK_IN)
{
cdc_submit_transfer_in(g_cdc_dev);
}
}
static uint8_t check_file_is_in_excluding_list(const char *filename, uint8_t is_dir, const excluding_file_item_t *excluding_files, uint8_t excluding_file_count)
{
if (excluding_file_count == 0 || excluding_files == NULL)
{
SYS_LOG_INF("excluding file count is empty, break check");
return 0;
}
int source_str_len = strlen(filename);
int i = 0;
for (i = 0; i < excluding_file_count; i++)
{
const excluding_file_item_t *file_item = &(excluding_files[i]);
if (is_dir != file_item->is_dir)
{
SYS_LOG_INF("src is dir:%d, target is dir:%d", is_dir, file_item->is_dir);
continue;
}
uint8_t is_same = 0;
if (file_item->compare_type == EXCLUDING_FILE_COMPARE_ALL)
{
is_same = strcmp(filename, file_item->filename) == 0;
}
else if (file_item->compare_type == EXCLUDING_FILE_COMPARE_PREFIX)
{
int len = strlen(file_item->filename);
if (source_str_len < len)
{
// 如果文件名小于要比较的字符串,则忽略检查
SYS_LOG_INF("SOURCE LEN:%d, target len:%d", source_str_len, len);
continue;
}
SYS_LOG_INF("CHECKING, SRC:%s, target:%s, len:%d", filename, file_item->filename, len);
is_same = strncmp(filename, file_item->filename, len) == 0;
}
if (is_same)
{
SYS_LOG_INF("FOUND THE EXCLUD FILE:%s", filename);
return 1; // 这个文件是要排除的
}
}
return 0;
}
static void list_all_files(const char *dirpath, uint16_t *current_file_index, const excluding_file_item_t *excluding_files, uint8_t excluding_file_count)
{
// 递归枚举所有文件
struct dirent *entry;
struct stat entry_stat;
char entrypath[MAX_FILE_PATH];
char entrysize[16];
const char *entrytype;
size_t dirpath_len = strlen(dirpath);
DIR *dir = opendir(dirpath);
strlcpy(entrypath, dirpath, sizeof(entrypath));
if (entrypath[dirpath_len - 1] != '/')
{
entrypath[dirpath_len] = '/';
dirpath_len += 1;
}
uint16_t *file_index = current_file_index;
while ((entry = readdir(dir)) != NULL)
{
entrytype = (entry->d_type == DT_DIR ? "directory" : "file");
strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
if (entry->d_type != DT_DIR)
{
if (check_file_is_in_excluding_list(entry->d_name, 0, excluding_files, excluding_file_count))
{
continue;
}
SYS_LOG_INF("file path:%s", entrypath);
if (esp_vfs_stat(__getreent(), entrypath, &entry_stat) == -1)
{
SYS_LOG_ERR("Failed to stat %s : %s", entrytype, entry->d_name);
continue;
}
sprintf(entrysize, "%ld", entry_stat.st_size);
SYS_LOG_INF("Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);
msc_file_info *file_info = &(g_msc_file_lists[*file_index]);
strlcpy(file_info->file_path, entrypath, MAX_FILE_PATH);
file_info->file_size = entry_stat.st_size;
*file_index = *file_index + 1;
}
else
{
if (check_file_is_in_excluding_list(entry->d_name, 1, excluding_files, excluding_file_count))
{
continue;
}
// 检查文件名是否以.号开始,是的话则忽略这个文件夹
SYS_LOG_INF("ITEM NAME:%s", entry->d_name);
if (strncmp(entry->d_name, "SPOTLI~", 7) == 0)
{
// 这个文件夹是MAC系统自动生成的用于spotlight搜索的索引文件夹忽略它否则会导致opendir失败
continue;
}
else
{
SYS_LOG_INF("ENTER SUB DIR:%s", entrypath);
list_all_files(entrypath, file_index, excluding_files, excluding_file_count);
}
}
}
closedir(dir);
}
static void handle_device_events(void *args)
{
msc_host_event_t app_event;
while (1)
{
SYS_LOG_INF("xQueueReceive(app_queue, &app_event, portMAX_DELAY);");
xQueueReceive(app_queue, &app_event, portMAX_DELAY);
switch (app_event.event)
{
case MSC_DEVICE_CONNECTED:
{
uint8_t device_address = app_event.device.address;
ESP_ERROR_CHECK(msc_host_install_device(device_address, &g_connected_usb_device));
msc_host_print_descriptors(g_connected_usb_device);
msc_host_device_info_t info;
ESP_ERROR_CHECK(msc_host_get_device_info(g_connected_usb_device, &info));
print_device_info(&info);
const esp_vfs_fat_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 1,
.allocation_unit_size = 1024,
};
ESP_ERROR_CHECK(msc_host_vfs_register(g_connected_usb_device, "/usb", &mount_config, &vfs_handle));
for (int i = 0; i < g_msc_file_count; i++)
{
msc_file_info *file_info = &g_msc_file_lists[i];
SYS_LOG_INF("file path: %s, file_size:%d", file_info->file_path, file_info->file_size);
}
g_usb_status = USBPORT_STATUS_MSC;
}
break;
case MSC_DEVICE_DISCONNECTED:
ESP_ERROR_CHECK(msc_host_vfs_unregister(vfs_handle));
vfs_handle = NULL;
ESP_ERROR_CHECK(msc_host_uninstall_device(g_connected_usb_device));
g_connected_usb_device = NULL;
g_usb_status = USBPORT_STATUS_NO_CONNECTION;
break;
case CDC_DEVICE_CONNECTED:
{
SYS_LOG_INF("cdc device connected");
// SYS_LOG_INF("Installing CDC-ACM driver");
// ESP_ERROR_CHECK(cdc_acm_host_install(NULL));
// cdc_acm_dev_hdl_t cdc_dev;
const cdc_acm_host_device_config_t dev_config = {
.connection_timeout_ms = 5000,
.out_buffer_size = 64,
.user_arg = NULL,
.event_cb = NULL,
.data_cb = handle_rx};
cdc_host_open(app_event.vendor_id, app_event.product_id, 0, &dev_config, &g_cdc_dev);
assert(g_cdc_dev);
cdc_host_desc_print(g_cdc_dev);
g_usb_status = USBPORT_STATUS_CDC;
// g_connected_usb_device = cdc_dev;
}
break;
case CDC_DEVICE_DISCONNECTED:
SYS_LOG_INF("cdc device dconnected");
cdc_host_close(g_cdc_dev);
g_usb_status = USBPORT_STATUS_NO_CONNECTION;
break;
case DFU_DEVICE_CONNECTED:
SYS_LOG_INF("DFU DEVICE CONNECTED");
const cdc_acm_host_device_config_t dev_config = {
.connection_timeout_ms = 5000,
.out_buffer_size = 64,
.user_arg = NULL,
.event_cb = NULL,
.data_cb = handle_rx};
dfu_host_open(app_event.vendor_id, app_event.product_id, 0, &dev_config, &g_cdc_dev);
g_usb_status = USBPORT_STATUS_DFU;
break;
case DFU_DEVICE_DISCONNECTED:
SYS_LOG_INF("DFU DEVICE DISCONNECTED");
dfu_host_close(g_cdc_dev);
g_usb_status = USBPORT_STATUS_NO_CONNECTION;
break;
default:
assert(0);
break;
}
/* code */
}
vTaskDelete(NULL);
}
////////////////////////////////////////////////
//////////// CDC设备透传的相关的函数 //////////////
////////////////////////////////////////////////
static bool _if_device_ready()
{
if (!s_usb_event_group)
return false;
return xEventGroupGetBits(s_usb_event_group) & CDC_DEVICE_READY_BIT;
}
static bool _cdc_driver_is_init(void)
{
if (s_usb_event_group == NULL)
{
return false;
}
return true;
}
static esp_err_t usb_out_ringbuf_push(const uint8_t *buf, size_t write_bytes, TickType_t xTicksToWait)
{
int res =
xRingbufferSend(s_out_ringbuf_handle, buf, write_bytes, xTicksToWait);
if (res != pdTRUE)
{
SYS_LOG_WRN("The out buffer is too small, the data has been lost %u", write_bytes);
return ESP_FAIL;
}
portENTER_CRITICAL(&s_out_ringbuf_mux);
s_out_buffered_data_len += write_bytes;
#ifdef CONFIG_CDC_USE_TRACE_FACILITY
s_ringbuf_out_max = s_out_buffered_data_len > s_ringbuf_out_max ? s_out_buffered_data_len : s_ringbuf_out_max;
#endif
portEXIT_CRITICAL(&s_out_ringbuf_mux);
return ESP_OK;
}
int usbh_cdc_write_bytes(const uint8_t *buf, size_t length)
{
SYS_LOG_INF("write data to cdc devi11111");
CDC_CHECK(buf != NULL, "invalid args", -1);
int tx_data_size = 0;
if (_cdc_driver_is_init() == false)
{
SYS_LOG_INF("CDC Driver not installed");
return -1;
}
if (_if_device_ready() == false)
{
SYS_LOG_INF("Device not connected or not ready");
return -1;
}
SYS_LOG_INF("write data to cdc devie2222");
xSemaphoreTake(s_usb_write_mux, portMAX_DELAY);
esp_err_t ret = usb_out_ringbuf_push(buf, length, pdMS_TO_TICKS(TIMEOUT_USB_RINGBUF_MS));
if (ret != ESP_OK)
{
xSemaphoreGive(s_usb_write_mux);
SYS_LOG_DBG("Write pipe_obj failed");
return -1;
}
tx_data_size = length;
xSemaphoreGive(s_usb_write_mux);
return tx_data_size;
}
static int _usbhost_port_write(sb_data_port_t *port, const void *data, uint32_t size)
{
int result = cdc_write_bytes(data, size);
return result;
}
static int _usbhost_port_read(sb_data_port_t *port, void *buffer, uint32_t length)
{
if (os_pipe_is_valid(&s_usb_data.pipe_obj))
{
int ret = os_pipe_fifo_read(&s_usb_data.pipe_obj, buffer, length);
if (ret > 0 && os_pipe_get_empty_size(&s_usb_data.pipe_obj) >= BUFFER_SIZE_BULK_IN)
{
cdc_submit_transfer_in(g_cdc_dev);
}
SYS_LOG_INF("Data readed %d bytes", ret);
return ret;
}
else
{
return -1;
}
}
static bool s_is_started = false;
static int _usbhost_start(sb_data_port_t *port)
{
s_is_started = true;
return 0;
}
static int _usbhost_stop(sb_data_port_t *port)
{
s_is_started = false;
return 0;
}
static bool _usbhost_is_started(sb_data_port_t *port)
{
return s_is_started;
}
static uint32_t _usbhost_get_rx_length(sb_data_port_t *port)
{
return os_pipe_get_valid_size(&s_usb_data.pipe_obj);
}
static sb_data_port_vtable_t const usbhost_port_vtable = {
.start = _usbhost_start, // 由具体驱动实现的,以达到节省资源为主要目的,启动数据接口
.stop = _usbhost_stop, // 由具体驱动实现的,以达到节省资源为主要目的,关闭数据接口
.write = _usbhost_port_write, // 由具体驱动实现的,写数据到对应的接口。
.read = _usbhost_port_read, // 由具体驱动实现的,从数据接口中读取已缓存的数据。
.is_started = _usbhost_is_started, // 由具体驱动实现的,获取当前数据接口是否可用(是否已启动)
.get_rx_length = _usbhost_get_rx_length, // 由具体驱动实现的,获取当前数据接口的本次可读长度
};
//////////// CDC设备透传的相关的函数结束 ///////////
////////////////////////////////////////////////
//////////// STM32固件升级相关的函数 //////////////
////////////////////////////////////////////////
// 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)
// {
// // if (g_pipe_hdl_dflt != NULL) {
// // return _usb_control_transfer(g_pipe_hdl_dflt, direction, request, value, interface, length, packet_data, out_buffer, out_buffer_size, actual_result_size);
// // }
// return ESP_FAIL;
// }
// 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)
// {
// // if (g_pipe_hdl_dflt != NULL) {
// // return _usb_control_transfer_ex(g_pipe_hdl_dflt,
// // direction,
// // request,
// // value,
// // interface,
// // length,
// // packet_data,
// // out_buffer,
// // out_buffer_size,
// // actual_result_size,
// // timeout);
// // }
// return ESP_FAIL;
// }
// esp_err_t _usbh_stm32_try_read_ob(uint16_t ob_data_size)
// {
// // if (g_pipe_hdl_dflt != NULL) {
// // return _usb_try_read_ob(g_pipe_hdl_dflt, ob_data_size);
// // }
// return ESP_FAIL;
// }
// esp_err_t _usbh_stm32_unprotect()
// {
// // if (g_pipe_hdl_dflt != NULL) {
// // return _usb_unprotect(g_pipe_hdl_dflt);
// // }
// return ESP_FAIL;
// }
// esp_err_t _usbh_stm32_leave_dfu()
// {
// return ESP_OK;
// // if (g_pipe_hdl_dflt == NULL) {
// // return ESP_FAIL;
// // }
// // // _usb_control_transfer_ex(pipe_handle,
// // // USB_BM_REQUEST_TYPE_DIR_IN,
// // // STM32_DFU_REQUEST_GETSTATUS,
// // // 0,
// // // 0,
// // // 6,
// // // 0,
// // // out_result_data,
// // // 6,
// // // NULL,
// // // timeout);
// // uint8_t direction = USB_BM_REQUEST_TYPE_DIR_IN;
// // uint8_t request = STM32_DFU_REQUEST_GETSTATUS;
// // uint16_t value = 0;
// // uint16_t interface = 0;
// // uint16_t length = 6;
// // uint8_t *packet_data = NULL;
// // uint8_t *out_buffer = NULL;
// // uint16_t out_buffer_size = 0;
// // uint16_t *actual_result_size = NULL;
// // uint16_t timeout = 500;
// // CDC_CHECK(g_pipe_hdl_dflt != NULL, "g_pipe_hdl_dflt can't be NULL", ESP_ERR_INVALID_ARG);
// // // malloc URB for default control
// // uint16_t packet_data_size = ENUM_CTRL_TRANSFER_MAX_LEN;
// // if (length > packet_data_size) {
// // packet_data_size = length;
// // }
// // urb_t *urb_ctrl = _usb_urb_alloc(0, sizeof(usb_setup_packet_t) + packet_data_size, NULL);
// // CDC_CHECK(urb_ctrl != NULL, "alloc urb failed", ESP_ERR_NO_MEM);
// // usb_setup_packet_t *setup_packet = (usb_setup_packet_t *)urb_ctrl->transfer.data_buffer;
// // if (direction == USB_BM_REQUEST_TYPE_DIR_IN) {
// // setup_packet->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_CLASS | USB_BM_REQUEST_TYPE_RECIP_INTERFACE;
// // setup_packet->bRequest = request;
// // setup_packet->wValue = value;
// // setup_packet->wIndex = interface;
// // setup_packet->wLength = length;
// // urb_ctrl->transfer.num_bytes = sizeof(usb_setup_packet_t) + length;
// // } else if (direction == USB_BM_REQUEST_TYPE_DIR_OUT) {
// // setup_packet->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_CLASS | USB_BM_REQUEST_TYPE_RECIP_INTERFACE;
// // setup_packet->bRequest = request;
// // setup_packet->wValue = value;
// // setup_packet->wIndex = interface;
// // setup_packet->wLength = length;
// // memcpy(((uint8_t *)setup_packet) + sizeof(usb_setup_packet_t), packet_data, length);
// // urb_ctrl->transfer.num_bytes = sizeof(usb_setup_packet_t) + length;
// // }
// // // Enqueue it
// // esp_err_t ret = hcd_urb_enqueue(g_pipe_hdl_dflt, urb_ctrl);
// // CDC_CHECK_GOTO(ESP_OK == ret, "urb enqueue failed", free_urb_);
// // SYS_LOG_INF("urb request timeout:%d ms, and becuase it used for leave dfu, so dont wait response", timeout);
// // goto free_urb_;
// // free_urb_:
// // _usb_pipe_flush(g_pipe_hdl_dflt, 1);
// // _usb_urb_free(urb_ctrl);
// // return ret;
// }
// uint16_t usbh_stm32_get_transfer_block_size()
// {
// // if (g_pipe_hdl_dflt != NULL) {
// // usb_function_desc_packet_t function_desc_packet;
// // esp_err_t ret = _usb_get_function_descriptors(g_pipe_hdl_dflt, 0, &function_desc_packet);
// // if (ret != ESP_OK) {
// // return 2048;
// // } else {
// // return function_desc_packet.wTransferSize;
// // }
// // }
// return 0;
// }
// esp_err_t usbh_stm32_clear_status()
// {
// // // return _usbh_
// // if (g_pipe_hdl_dflt != NULL) {
// // return _usb_clear_status(g_pipe_hdl_dflt);
// // }
// return ESP_FAIL;
// }
// esp_err_t _usbh_stm32_load_address(uint32_t address)
// {
// // if (g_pipe_hdl_dflt != NULL) {
// // return _usb_load_address(g_pipe_hdl_dflt, address);
// // }
// return ESP_FAIL;
// }
//////////// STM32固件升级相关的函数结束 //////////////
// static TaskHandle_t s_usb_task_handle, s_device_task_handle; //, workthread_handle;
int usbport_init(void)
{
SYS_LOG_INF("usbport_init");
if (s_port.vtable)
{
SYS_LOG_WRN("repeated initialize");
return -1;
}
s_port.vtable = &usbhost_port_vtable;
s_port.data = &s_usb_data;
memset(&s_usb_data, 0, sizeof(__usb_data_t));
os_pipe_create(&s_usb_data.pipe_obj, 1024 * 2);
// if (ready_to_uninstall_usb == NULL)
// {
// ready_to_uninstall_usb = xSemaphoreCreateBinary();
// }
app_queue = xQueueCreate(3, sizeof(msc_host_event_t));
assert(app_queue);
static usb_host_config_t const host_config = {
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1,
};
ESP_ERROR_CHECK(usb_host_install(&host_config));
if (s_usb_task_handle == NULL)
{
xTaskCreatePinnedToCore(handle_usb_events, "usb_events", 4096, NULL, SBTASK_PRIORITY_USB_HOST, &s_usb_task_handle, SBTASK_CORE_INDEX_USB_HOST);
assert(s_usb_task_handle);
}
if (s_device_task_handle == NULL)
{
xTaskCreatePinnedToCore(handle_device_events, "device_events", 4096, NULL, SBTASK_PRIORITY_USB_DEVICE, &s_device_task_handle, SBTASK_CORE_INDEX_USB_DEVICE);
assert(s_device_task_handle);
}
const msc_host_driver_config_t msc_config = {
.create_backround_task = true,
.task_priority = SBTASK_PRIORITY_USB_MSC,
.stack_size = 2048 * 2,
.callback = usb_device_event_cb,
.core_id = 0};
ESP_ERROR_CHECK(msc_host_install(&msc_config));
return 0;
}
void usbport_deinit(void)
{
SYS_LOG_INF("usbport_deinit");
if (s_port.vtable == NULL)
{
SYS_LOG_WRN("usb host not initialized");
return;
}
if (g_connected_usb_device)
{
if (vfs_handle)
{
msc_host_vfs_unregister(vfs_handle);
vfs_handle = NULL;
}
msc_host_uninstall_device(g_connected_usb_device);
g_connected_usb_device = NULL;
}
if (g_cdc_dev)
{
cdc_host_close(g_cdc_dev);
g_cdc_dev = NULL;
}
ESP_ERROR_CHECK(msc_host_uninstall());
vTaskDelay(pdMS_TO_TICKS(100));
// if (s_device_task_handle)
// {
// vTaskDelete(s_device_task_handle);
// s_device_task_handle = NULL;
// }
// if (s_usb_task_handle)
// {
// vTaskDelete(s_usb_task_handle);
// s_usb_task_handle = NULL;
// }
ESP_ERROR_CHECK(usb_host_uninstall());
if (app_queue)
{
vQueueDelete(app_queue);
app_queue = NULL;
}
// if (ready_to_uninstall_usb)
// {
// vSemaphoreDelete(ready_to_uninstall_usb);
// ready_to_uninstall_usb = NULL;
// }
if (os_pipe_is_valid(&s_usb_data.pipe_obj))
{
os_pipe_delete(&s_usb_data.pipe_obj);
}
s_port.vtable = NULL;
}
sb_data_port_t *usbport_bind(os_work_t *rx_resume_work)
{
if (s_port.data == NULL)
{
SYS_LOG_WRN("usb host not initialized");
return NULL;
}
__usb_data_t *usb_data = s_port.data;
usb_data->rx_resume_work = rx_resume_work;
os_pipe_regist(&usb_data->pipe_obj, rx_resume_work, 0);
return &s_port;
}
void usbport_unbind(sb_data_port_t *port)
{
if (port == NULL)
{
SYS_LOG_WRN("usb host not initialized");
return;
}
__usb_data_t *usb_data = port->data;
os_pipe_unregist(&usb_data->pipe_obj);
usb_data->rx_resume_work = NULL;
}
usbport_status_e usbport_get_state(void)
{
return g_usb_status;
}
msc_file_info *msc_get_file_list(uint16_t *out_file_count, const excluding_file_item_t *excluding_files, uint8_t excluding_file_count)
{
g_msc_file_count = 0;
list_all_files("/usb/", &g_msc_file_count, excluding_files, excluding_file_count);
return msc_get_cached_file_list(out_file_count);
}
msc_file_info *msc_get_cached_file_list(uint16_t *out_file_count)
{
if (out_file_count)
{
*out_file_count = g_msc_file_count;
}
return g_msc_file_lists;
}
usb_connect_type_t usbport_get_usb_type(void)
{
return s_usb_connect_type;
}