Files
ESPC3-wireless/app/drivers/data_port/usb-host/usbport.c

909 lines
29 KiB
C
Raw Normal View History

#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;
}