first commit

This commit is contained in:
2026-07-13 17:14:27 +08:00
commit 8a05bb238b
106 changed files with 24459 additions and 0 deletions

109
src/cam.cpp Normal file
View File

@ -0,0 +1,109 @@
#include "cam.h"
//////////////////ov5640//////////////////////////////////
// #define CAM_PIN_PWDN 21 //power down is not used
// #define CAM_PIN_RESET -1 //software reset will be performed
// #define CAM_PIN_XCLK 12
// #define CAM_PIN_SIOD 45
// #define CAM_PIN_SIOC 48
// #define CAM_PIN_D7 13
// #define CAM_PIN_D6 11
// #define CAM_PIN_D5 10
// #define CAM_PIN_D4 46
// #define CAM_PIN_D3 17
// #define CAM_PIN_D2 15
// #define CAM_PIN_D1 16
// #define CAM_PIN_D0 3
// #define CAM_PIN_VSYNC 47
// #define CAM_PIN_HREF 14
// #define CAM_PIN_PCLK 9
////////////////ov2640//////////////////////////////////
#define CAM_PIN_PWDN 21 //power down is not used
#define CAM_PIN_RESET -1 //software reset will be performed
#define CAM_PIN_XCLK 12
#define CAM_PIN_SIOD 45
#define CAM_PIN_SIOC 48
#define CAM_PIN_D7 13
#define CAM_PIN_D6 11
#define CAM_PIN_D5 10
#define CAM_PIN_D4 46
#define CAM_PIN_D3 17
#define CAM_PIN_D2 15
#define CAM_PIN_D1 16
#define CAM_PIN_D0 3
#define CAM_PIN_VSYNC 47
#define CAM_PIN_HREF 14
#define CAM_PIN_PCLK 18
static const char *TAG = "example:take_picture";
#if ESP_CAMERA_SUPPORTED
static camera_config_t camera_config = {
.pin_pwdn = CAM_PIN_PWDN,
.pin_reset = CAM_PIN_RESET,
.pin_xclk = CAM_PIN_XCLK,
.pin_sccb_sda = CAM_PIN_SIOD,
.pin_sccb_scl = CAM_PIN_SIOC,
.pin_d7 = CAM_PIN_D7,
.pin_d6 = CAM_PIN_D6,
.pin_d5 = CAM_PIN_D5,
.pin_d4 = CAM_PIN_D4,
.pin_d3 = CAM_PIN_D3,
.pin_d2 = CAM_PIN_D2,
.pin_d1 = CAM_PIN_D1,
.pin_d0 = CAM_PIN_D0,
.pin_vsync = CAM_PIN_VSYNC,
.pin_href = CAM_PIN_HREF,
.pin_pclk = CAM_PIN_PCLK,
//XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
.xclk_freq_hz = 8 * 1000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG
.frame_size = FRAMESIZE_HVGA, //QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates.
.jpeg_quality = 10, //0-63, for OV series camera sensors, lower number means higher quality
.fb_count = 2, //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode.
.fb_location = CAMERA_FB_IN_DRAM,
.grab_mode = CAMERA_GRAB_LATEST,
};
esp_err_t cam_init(void)
{
//initialize the camera
esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK)
{
Serial0.println("Camera Init Failed");
return err;
}
Serial0.println("Camera Init OK ");
sensor_t *s = esp_camera_sensor_get();
// s->set_exposure_ctrl(s, 0);
// s->set_gain_ctrl(s, 0);
// s->set_gainceiling(s, GAINCEILING_2X);
// s->set_whitebal(s, 0);
// s->set_agc_gain(s, 0); // 限制增益
// s->set_aec_value(s, 300); // 固定或半固定曝光
s->set_exposure_ctrl(s, 0); // 关闭AE
s->set_gain_ctrl(s, 0); // 关闭AGC
s->set_agc_gain(s, 0); // 设置固定增益
s->set_aec_value(s, 300); // 设置曝光时间
return ESP_OK;
}
#endif

8
src/cam.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef __CAM_H
#define __CAM_H
#include "Arduino.h"
#include "esp_camera.h"
// void cam_init();
esp_err_t cam_init(void);
#endif

55
src/main.cpp Normal file
View File

@ -0,0 +1,55 @@
#include <Arduino.h>
#include "cam.h"
// #include "sd_card.h"
#include "myusb_host.h"
#include "WiFi.h"
void setup()
{
// setCpuFrequencyMhz(80);
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
Serial0.begin(115200);
Serial0.println("start");
pinMode(0, INPUT_PULLUP);
cam_init();
hoststart();
}
void loop() {
while (1)
{
// uint32_t start = millis();
if(digitalRead(0) == LOW)
{
esp_restart();
}
camera_fb_t *pic = esp_camera_fb_get();
if(pic != NULL)
{
host_send_data(pic->buf, pic->len);
}
else
{
Serial0.println("pic is null");
}
esp_camera_fb_return(pic);
// uint32_t end = millis();
// Serial0.printf("send pic time: %d ms\n", millis() - start);
// vTaskDelay(500 / portTICK_RATE_MS);
// String msg = "hello world";
// host_send_message(msg.c_str());
vTaskDelay(20 / portTICK_RATE_MS);
}
}
// multi_heap_free multi_heap_poisoning.c:279 (head != NULL)

838
src/myusb_host.cpp Normal file
View File

@ -0,0 +1,838 @@
// //////////主机//////////////////////
// #include "myusb_host.h"
// static usb_host_client_handle_t usb_host_client = NULL;
// static usb_device_handle_t usb_host_dev = NULL;
// static uint8_t usb_host_interface_number = 0xFF;
// static uint8_t usb_host_in_endpoint = 0;
// static usb_transfer_t *usb_host_transfer = NULL;
// static bool usb_host_new_device = false;
// static uint8_t usb_host_new_address = 0;
// static bool usb_host_device_gone = false;
// static usb_device_handle_t usb_host_gone_handle = NULL;
// static void usb_host_cleanup_device(void)
// {
// if (usb_host_transfer) {
// usb_host_transfer_free(usb_host_transfer);
// usb_host_transfer = NULL;
// }
// if (usb_host_interface_number != 0xFF && usb_host_dev != NULL) {
// esp_err_t err = usb_host_interface_release(usb_host_client, usb_host_dev, usb_host_interface_number);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_interface_release error=%d\r\n", err);
// }
// usb_host_interface_number = 0xFF;
// }
// if (usb_host_dev != NULL) {
// esp_err_t err = usb_host_device_close(usb_host_client, usb_host_dev);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_device_close error=%d\r\n", err);
// }
// usb_host_dev = NULL;
// }
// usb_host_in_endpoint = 0;
// }
// static void usb_host_transfer_callback(usb_transfer_t *transfer)
// {
// if (transfer->status == USB_TRANSFER_STATUS_COMPLETED)
// {
// int len = transfer->actual_num_bytes;
// if (len > 0) {
// Serial0.write(transfer->data_buffer, len);
// }
// transfer->num_bytes = transfer->data_buffer_size;
// transfer->actual_num_bytes = 0;
// esp_err_t err = usb_host_transfer_submit(transfer);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_transfer_submit retry failed=%d\r\n", err);
// }
// }
// else if (transfer->status == USB_TRANSFER_STATUS_STALL)
// {
// Serial0.println("USB IN transfer stalled");
// }
// else
// {
// Serial0.printf("USB IN transfer error status=%d\r\n", transfer->status);
// transfer->num_bytes = transfer->data_buffer_size;
// transfer->actual_num_bytes = 0;
// usb_host_transfer_submit(transfer);
// }
// }
// static bool usb_host_find_in_endpoint(const usb_config_desc_t *config_desc, uint8_t *in_interface, uint8_t *in_endpoint)
// {
// const uint8_t *buf = (const uint8_t *)config_desc;
// size_t total_len = config_desc->wTotalLength;
// size_t idx = 0;
// uint8_t current_bInterfaceNumber = 0xFF;
// uint8_t current_interface_idx = 0xFF;
// uint8_t interface_counter = 0; // interface descriptor order index
// Serial0.printf("total_len=%d\r\n", total_len);
// while (idx + 2u <= total_len)
// {
// uint8_t desc_len = buf[idx];
// uint8_t desc_type = buf[idx + 1];
// Serial0.printf("idx=%d\r\n", idx);
// Serial0.printf(" desc_len=%u desc_type=0x%02x\r\n", desc_len, desc_type);
// if (desc_len < 2 || idx + desc_len > total_len) break;
// if (desc_type == USB_B_DESCRIPTOR_TYPE_INTERFACE && desc_len >= USB_INTF_DESC_SIZE)
// {
// const usb_intf_desc_t *intf_desc = (const usb_intf_desc_t *)(buf + idx);
// current_bInterfaceNumber = intf_desc->bInterfaceNumber;
// current_interface_idx = interface_counter;
// interface_counter++;
// Serial0.printf(" found interface idx=%u bInterfaceNumber=%u class=0x%02x subclass=0x%02x proto=0x%02x eps=%u\r\n",
// current_interface_idx,
// current_bInterfaceNumber,
// intf_desc->bInterfaceClass,
// intf_desc->bInterfaceSubClass,
// intf_desc->bInterfaceProtocol,
// intf_desc->bNumEndpoints);
// if (intf_desc->bInterfaceClass == 0x02) {
// Serial0.printf(" (CDC control)\r\n");
// } else if (intf_desc->bInterfaceClass == 0x0A) {
// Serial0.printf(" (CDC data)\r\n");
// }
// }
// else if (desc_type == USB_B_DESCRIPTOR_TYPE_ENDPOINT && desc_len >= USB_EP_DESC_SIZE)
// {
// const usb_ep_desc_t *ep_desc = (const usb_ep_desc_t *)(buf + idx);
// uint8_t ep_dir = ep_desc->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK;
// uint8_t ep_type = ep_desc->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK;
// if (ep_dir && ep_type == USB_BM_ATTRIBUTES_XFER_BULK)
// {
// *in_interface = current_bInterfaceNumber; // use bInterfaceNumber, not interface_idx
// *in_endpoint = ep_desc->bEndpointAddress;
// Serial0.printf(" selected bulk IN endpoint 0x%02x interface_idx=%u bInterfaceNumber=%u mps=%u\r\n",
// *in_endpoint,
// current_interface_idx,
// current_bInterfaceNumber,
// USB_EP_DESC_GET_MPS(ep_desc));
// return true;
// }
// }
// idx += desc_len;
// }
// return false;
// }
// static void usb_host_start_reading(usb_device_handle_t dev_hdl, uint8_t interface_number, uint8_t endpoint_address)
// {
// Serial0.printf("Starting USB IN read on interface_number=%u endpoint_address=%d \r\n", interface_number, endpoint_address);
// if (usb_host_transfer) {
// usb_host_transfer_free(usb_host_transfer);
// usb_host_transfer = NULL;
// }
// // // 先 claim CDC control interface (0)
// // esp_err_t err_ctrl = usb_host_interface_claim(usb_host_client, dev_hdl, 0, 0);
// // if (err_ctrl == ESP_OK) {
// // Serial0.println("Claimed CDC control interface 0");
// // } else {
// // Serial0.printf("Claim control interface 0 failed=%d (continuing)\r\n", err_ctrl);
// // }
// // 再 claim CDC data interface (interface_number,即 1)
// Serial0.println("Claiming CDC data interface...");
// esp_err_t err = usb_host_interface_claim(usb_host_client, dev_hdl, interface_number, 0);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_interface_claim intf=%u failed=%d\r\n", interface_number, err);
// return;
// }
// usb_host_interface_number = interface_number;
// err = usb_host_transfer_alloc(256, 0, &usb_host_transfer);
// if (err != ESP_OK || usb_host_transfer == NULL) {
// Serial0.printf("usb_host_transfer_alloc failed=%d\r\n", err);
// return;
// }
// // // 现在释放配置描述符(claim 完成后)
// // usb_host_free_config_desc(config_desc);
// usb_host_transfer->num_bytes = usb_host_transfer->data_buffer_size;
// usb_host_transfer->device_handle = dev_hdl;
// usb_host_transfer->bEndpointAddress = endpoint_address;
// usb_host_transfer->timeout_ms = 1000;
// usb_host_transfer->callback = usb_host_transfer_callback;
// usb_host_transfer->context = NULL;
// usb_host_transfer->flags = 0;
// err = usb_host_transfer_submit(usb_host_transfer);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_transfer_submit failed=%d\r\n", err);
// } else {
// Serial0.printf("USB IN read started on endpoint 0x%02x\r\n", endpoint_address);
// }
// }
// // const usb_config_desc_t *config_desc = NULL;
// static void usb_host_open_device(uint8_t dev_addr)
// {
// Serial0.printf("Opening USB device addr=%u\r\n", dev_addr);
// if (usb_host_dev != NULL) {
// Serial0.println("USB device already open, skipping open_device");
// return;
// }
// usb_device_handle_t dev_hdl = NULL;
// esp_err_t err = usb_host_device_open(usb_host_client, dev_addr, &dev_hdl);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_device_open addr=%u failed=%d\r\n", dev_addr, err);
// return;
// }
// usb_device_info_t device_info;
// err = usb_host_device_info(dev_hdl, &device_info);
// if (err == ESP_OK) {
// Serial0.printf("opened device addr=%u speed=%d maxpkt=%u config=%u\r\n",
// dev_addr,
// device_info.speed,
// device_info.bMaxPacketSize0,
// device_info.bConfigurationValue);
// // tuh_cdc_write(dev_addr, "hello", 5);
// } else {
// Serial0.printf("usb_host_device_info error=%d\r\n", err);
// }
// const usb_config_desc_t *config_desc = NULL;
// err = usb_host_get_active_config_descriptor(dev_hdl, &config_desc);
// if (err != ESP_OK || config_desc == NULL) {
// Serial0.printf("usb_host_get_active_config_descriptor failed=%d\r\n", err);
// usb_host_device_close(usb_host_client, dev_hdl);
// return;
// }
// Serial0.printf("config_desc size=%u\r\n", config_desc->bLength);
// Serial0.printf("config_desc bLength=%u wTotalLength=%u\r\n", config_desc->bLength, config_desc->wTotalLength);
// // const uint8_t *p = (const uint8_t*)config_desc;
// // for (size_t i = 0; i < config_desc->wTotalLength && i < 128; ++i) {
// // Serial0.printf("%02X ", p[i]);
// // if ((i & 0x0F) == 0x0F) Serial0.println();
// // }
// // Serial0.println();
// uint8_t interface_number = 0xFF;
// uint8_t endpoint_address = 0;
// if (!usb_host_find_in_endpoint(config_desc, &interface_number, &endpoint_address)) {
// Serial0.println("No bulk IN endpoint found in active config");
// usb_host_free_config_desc(config_desc);
// usb_host_device_close(usb_host_client, dev_hdl);
// return;
// }
// Serial0.printf("Found bulk IN endpoint 0x%02x on interface %u\r\n", endpoint_address, interface_number);
// usb_host_dev = dev_hdl;
// usb_host_in_endpoint = endpoint_address;
// usb_host_start_reading(dev_hdl, interface_number, endpoint_address);
// usb_host_free_config_desc(config_desc);
// }
// static void usb_host_event_callback(const usb_host_client_event_msg_t *event_msg, void *arg)
// {
// if (event_msg->event == USB_HOST_CLIENT_EVENT_NEW_DEV) {
// usb_host_new_device = true;
// usb_host_new_address = event_msg->new_dev.address;
// Serial0.printf("USB host event: new device address=%u\r\n", usb_host_new_address);
// } else if (event_msg->event == USB_HOST_CLIENT_EVENT_DEV_GONE) {
// Serial0.println("USB host event: device gone");
// usb_host_device_gone = true;
// usb_host_gone_handle = event_msg->dev_gone.dev_hdl;
// }
// }
// static void usb_host_print_device_list()
// {
// uint8_t dev_addrs[8];
// int num_dev = 0;
// esp_err_t err = usb_host_device_addr_list_fill(sizeof(dev_addrs), dev_addrs, &num_dev);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_device_addr_list_fill error=%d\r\n", err);
// return;
// }
// Serial0.printf("USB host connected devices: %d\r\n", num_dev);
// for (int i = 0; i < num_dev; ++i) {
// Serial0.printf(" device addr=%u\r\n", dev_addrs[i]);
// }
// }
// void hoststart()
// {
// usb_host_config_t usb_host_config;
// usb_host_config.skip_phy_setup = false;
// usb_host_config.root_port_unpowered = false;
// usb_host_config.intr_flags = 0;
// usb_host_config.enum_filter_cb = NULL;
// esp_err_t err = usb_host_install(&usb_host_config);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_install failed=%d\r\n", err);
// return;
// }
// usb_host_client_config_t client_cfg;
// client_cfg.is_synchronous = false;
// client_cfg.max_num_event_msg = 4;
// client_cfg.async.client_event_callback = usb_host_event_callback;
// client_cfg.async.callback_arg = NULL;
// err = usb_host_client_register(&client_cfg, &usb_host_client);
// if (err != ESP_OK) {
// Serial0.printf("usb_host_client_register failed=%d\r\n", err);
// return;
// }
// }
// void hostloop()
// {
// uint32_t event_flags = 0;
// usb_host_lib_handle_events(pdMS_TO_TICKS(10), &event_flags);
// if (usb_host_client != NULL) {
// usb_host_client_handle_events(usb_host_client, pdMS_TO_TICKS(10));
// }
// if (usb_host_device_gone && usb_host_gone_handle == usb_host_dev) {
// usb_host_device_gone = false;
// usb_host_gone_handle = NULL;
// usb_host_cleanup_device();
// Serial0.println("Active USB device disconnected");
// }
// // Serial0.printf("usb_host_new_device=%d\r\n", usb_host_new_device);
// if (usb_host_new_device) {
// usb_host_new_device = false;
// Serial0.printf("New USB Reading Device");
// usb_host_print_device_list();
// usb_host_open_device(usb_host_new_address);
// }
// // Serial0.println("loop");
// // vTaskDelay(pdMS_TO_TICKS(100));
// }
#include "myusb_host.h"
#define USB_TX_BLOCK_SIZE 1024 * 50
static usb_host_client_handle_t usb_host_client = NULL;
static usb_device_handle_t usb_host_dev = NULL;
static uint8_t usb_host_interface_number = 0xFF;
static uint8_t usb_host_out_interface_number = 0xFF;
static uint8_t usb_host_in_endpoint = 0; // 0x81
static uint8_t usb_host_out_endpoint = 0; // 0x01
static usb_transfer_t *usb_host_transfer = NULL;
static usb_transfer_t *usb_host_out_transfer = NULL;
volatile static bool usb_host_new_device = false;
static uint8_t usb_host_new_address = 0;
static bool usb_host_device_gone = false;
static usb_device_handle_t usb_host_gone_handle = NULL;
static void usb_host_cleanup_device(void)
{
if (usb_host_transfer) {
usb_host_transfer_free(usb_host_transfer);
usb_host_transfer = NULL;
}
if (usb_host_out_transfer) {
usb_host_transfer_free(usb_host_out_transfer);
usb_host_out_transfer = NULL;
}
if (usb_host_interface_number != 0xFF && usb_host_dev != NULL) {
esp_err_t err = usb_host_interface_release(usb_host_client, usb_host_dev, usb_host_interface_number);
if (err != ESP_OK) {
Serial0.printf("usb_host_interface_release error=%d\r\n", err);
}
usb_host_interface_number = 0xFF;
}
if (usb_host_out_interface_number != 0xFF && usb_host_dev != NULL && usb_host_out_interface_number != usb_host_interface_number) {
esp_err_t err = usb_host_interface_release(usb_host_client, usb_host_dev, usb_host_out_interface_number);
if (err != ESP_OK) {
Serial0.printf("usb_host_interface_release out error=%d\r\n", err);
}
usb_host_out_interface_number = 0xFF;
}
if (usb_host_dev != NULL) {
esp_err_t err = usb_host_device_close(usb_host_client, usb_host_dev);
if (err != ESP_OK) {
Serial0.printf("usb_host_device_close error=%d\r\n", err);
}
usb_host_dev = NULL;
}
usb_host_in_endpoint = 0;
usb_host_out_endpoint = 0;
}
// char *msg = "I am host\r\n";
// // host_send_data(msg, strlen(msg));
// host_send_message(msg);
static void usb_host_transfer_callback(usb_transfer_t *transfer)
{
if (transfer->status == USB_TRANSFER_STATUS_COMPLETED)
{
int len = transfer->actual_num_bytes;
if (len > 0) {
Serial0.write(transfer->data_buffer, len);
Serial0.println("\r\n");
}
transfer->num_bytes = transfer->data_buffer_size;
transfer->actual_num_bytes = 0;
esp_err_t err = usb_host_transfer_submit(transfer);
if (err != ESP_OK) {
Serial0.printf("usb_host_transfer_submit retry failed=%d\r\n", err);
}
}
else if (transfer->status == USB_TRANSFER_STATUS_STALL)
{
Serial0.println("USB IN transfer stalled");
}
else
{
Serial0.printf("USB IN transfer error status=%d\r\n", transfer->status);
transfer->num_bytes = transfer->data_buffer_size;
transfer->actual_num_bytes = 0;
usb_host_transfer_submit(transfer);
}
}
static void usb_host_out_transfer_callback(usb_transfer_t *transfer)
{
if (transfer->status == USB_TRANSFER_STATUS_COMPLETED) {
Serial0.printf("USB OUT transfer completed len=%d\r\n", transfer->actual_num_bytes);
} else if (transfer->status == USB_TRANSFER_STATUS_STALL) {
Serial0.println("USB OUT transfer stalled");
} else {
Serial0.printf("USB OUT transfer error status=%d\r\n", transfer->status);
}
}
static bool usb_host_start_writing(usb_device_handle_t dev_hdl, uint8_t interface_number, uint8_t endpoint_address)
{
if (endpoint_address == 0) {
Serial0.println("No bulk OUT endpoint configured");
return false;
}
if (interface_number != usb_host_interface_number) {
Serial0.println("Claiming USB OUT interface...");
esp_err_t err = usb_host_interface_claim(usb_host_client, dev_hdl, interface_number, 0);
if (err != ESP_OK) {
Serial0.printf("usb_host_interface_claim OUT intf=%u failed=%d\r\n", interface_number, err);
return false;
}
usb_host_out_interface_number = interface_number;
} else {
usb_host_out_interface_number = interface_number;
}
if (usb_host_out_transfer) {
usb_host_transfer_free(usb_host_out_transfer);
usb_host_out_transfer = NULL;
}
esp_err_t err = usb_host_transfer_alloc(USB_TX_BLOCK_SIZE, 0, &usb_host_out_transfer);
if (err != ESP_OK || usb_host_out_transfer == NULL) {
Serial0.printf("usb_host_transfer_alloc OUT failed=%d\r\n", err);
return false;
}
usb_host_out_transfer->num_bytes = 0;
usb_host_out_transfer->actual_num_bytes = 0;
usb_host_out_transfer->device_handle = dev_hdl;
usb_host_out_transfer->bEndpointAddress = endpoint_address;
usb_host_out_transfer->timeout_ms = 1000;
usb_host_out_transfer->callback = usb_host_out_transfer_callback;
usb_host_out_transfer->context = NULL;
usb_host_out_transfer->flags = 0;
Serial0.printf("USB OUT ready on endpoint 0x%02x interface=%u\r\n", endpoint_address, interface_number);
return true;
}
static bool usb_host_write_data(const uint8_t *data, int len)
{
if (!usb_host_out_transfer) {
Serial0.println("USB OUT transfer not initialized");
return false;
}
if (len <= 0 || len > (int)usb_host_out_transfer->data_buffer_size) {
Serial0.printf("USB OUT invalid len=%d\r\n", len);
return false;
}
memcpy(usb_host_out_transfer->data_buffer, data, len);
usb_host_out_transfer->num_bytes = len;
usb_host_out_transfer->actual_num_bytes = 0;
esp_err_t err = usb_host_transfer_submit(usb_host_out_transfer);
if (err != ESP_OK) {
Serial0.printf("usb_host_transfer_submit OUT failed=%d\r\n", err);
return false;
}
// while(usb_host_out_transfer->status != USB_TRANSFER_STATUS_COMPLETED)
// {
// vTaskDelay(1);
// }
return true;
}
static bool usb_host_find_in_endpoint(const usb_config_desc_t *config_desc, uint8_t *in_interface, uint8_t *in_endpoint, uint8_t *out_interface, uint8_t *out_endpoint)
{
const uint8_t *buf = (const uint8_t *)config_desc;
size_t total_len = config_desc->wTotalLength;
size_t idx = 0;
uint8_t current_bInterfaceNumber = 0xFF;
uint8_t current_interface_idx = 0xFF;
uint8_t interface_counter = 0; // interface descriptor order index
bool found_in = false;
bool found_out = false;
*in_interface = 0xFF;
*out_interface = 0xFF;
*in_endpoint = 0;
*out_endpoint = 0;
Serial0.printf("total_len=%d\r\n", total_len);
while (idx + 2u <= total_len)
{
uint8_t desc_len = buf[idx];
uint8_t desc_type = buf[idx + 1];
if (desc_len < 2 || idx + desc_len > total_len) break;
if (desc_type == USB_B_DESCRIPTOR_TYPE_INTERFACE && desc_len >= USB_INTF_DESC_SIZE)
{
const usb_intf_desc_t *intf_desc = (const usb_intf_desc_t *)(buf + idx);
current_bInterfaceNumber = intf_desc->bInterfaceNumber;
current_interface_idx = interface_counter;
interface_counter++;
Serial0.printf(" found interface idx=%u bInterfaceNumber=%u class=0x%02x subclass=0x%02x proto=0x%02x eps=%u\r\n",
current_interface_idx,
current_bInterfaceNumber,
intf_desc->bInterfaceClass,
intf_desc->bInterfaceSubClass,
intf_desc->bInterfaceProtocol,
intf_desc->bNumEndpoints);
// if (intf_desc->bInterfaceClass == 0x02) {
// Serial0.printf(" (CDC control)\r\n");
// } else if (intf_desc->bInterfaceClass == 0x0A) {
// Serial0.printf(" (CDC data)\r\n");
// }
}
else if (desc_type == USB_B_DESCRIPTOR_TYPE_ENDPOINT && desc_len >= USB_EP_DESC_SIZE)
{
const usb_ep_desc_t *ep_desc = (const usb_ep_desc_t *)(buf + idx);
uint8_t ep_dir = ep_desc->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK;
uint8_t ep_type = ep_desc->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK;
if (ep_type == USB_BM_ATTRIBUTES_XFER_BULK)
{
if (ep_dir) {
*in_interface = current_bInterfaceNumber; // use bInterfaceNumber, not interface_idx
*in_endpoint = ep_desc->bEndpointAddress;
found_in = true;
Serial0.printf(" selected bulk IN endpoint 0x%02x interface_idx=%u bInterfaceNumber=%u mps=%u\r\n",
*in_endpoint,
current_interface_idx,
current_bInterfaceNumber,
USB_EP_DESC_GET_MPS(ep_desc));
} else {
*out_interface = current_bInterfaceNumber;
*out_endpoint = ep_desc->bEndpointAddress;
found_out = true;
Serial0.printf(" selected bulk OUT endpoint 0x%02x interface_idx=%u bInterfaceNumber=%u mps=%u\r\n",
*out_endpoint,
current_interface_idx,
current_bInterfaceNumber,
USB_EP_DESC_GET_MPS(ep_desc));
}
if (found_in && found_out) {
return true;
}
}
}
idx += desc_len;
}
return found_in;
}
static void usb_host_start_reading(usb_device_handle_t dev_hdl, uint8_t interface_number, uint8_t endpoint_address)
{
Serial0.printf("Starting USB IN read on interface_number=%u endpoint_address=%d \r\n", interface_number, endpoint_address);
if (usb_host_transfer) {
usb_host_transfer_free(usb_host_transfer);
usb_host_transfer = NULL;
}
// // 先 claim CDC control interface (0)
// esp_err_t err_ctrl = usb_host_interface_claim(usb_host_client, dev_hdl, 0, 0);
// if (err_ctrl == ESP_OK) {
// Serial0.println("Claimed CDC control interface 0");
// } else {
// Serial0.printf("Claim control interface 0 failed=%d (continuing)\r\n", err_ctrl);
// }
// 再 claim CDC data interface (interface_number,即 1)
Serial0.println("Claiming CDC data interface...");
esp_err_t err = usb_host_interface_claim(usb_host_client, dev_hdl, interface_number, 0);
if (err != ESP_OK) {
Serial0.printf("usb_host_interface_claim intf=%u failed=%d\r\n", interface_number, err);
return;
}
usb_host_interface_number = interface_number;
err = usb_host_transfer_alloc(256, 0, &usb_host_transfer);
if (err != ESP_OK || usb_host_transfer == NULL) {
Serial0.printf("usb_host_transfer_alloc failed=%d\r\n", err);
return;
}
usb_host_transfer->num_bytes = usb_host_transfer->data_buffer_size;
usb_host_transfer->device_handle = dev_hdl;
usb_host_transfer->bEndpointAddress = endpoint_address;
usb_host_transfer->timeout_ms = 1000;
usb_host_transfer->callback = usb_host_transfer_callback;
usb_host_transfer->context = NULL;
usb_host_transfer->flags = 0;
err = usb_host_transfer_submit(usb_host_transfer);
if (err != ESP_OK) {
Serial0.printf("usb_host_transfer_submit failed=%d\r\n", err);
} else {
Serial0.printf("USB IN read started on endpoint 0x%02x\r\n", endpoint_address);
}
}
// const usb_config_desc_t *config_desc = NULL;
static void usb_host_open_device(uint8_t dev_addr)
{
Serial0.printf("Opening USB device addr=%u\r\n", dev_addr);
if (usb_host_dev != NULL) {
Serial0.println("USB device already open, skipping open_device");
return;
}
usb_device_handle_t dev_hdl = NULL;
esp_err_t err = usb_host_device_open(usb_host_client, dev_addr, &dev_hdl);
if (err != ESP_OK) {
Serial0.printf("usb_host_device_open addr=%u failed=%d\r\n", dev_addr, err);
return;
}
usb_device_info_t device_info;
err = usb_host_device_info(dev_hdl, &device_info);
if (err == ESP_OK) {
Serial0.printf("opened device addr=%u speed=%d maxpkt=%u config=%u\r\n",
dev_addr,
device_info.speed,
device_info.bMaxPacketSize0,
device_info.bConfigurationValue);
// tuh_cdc_write(dev_addr, "hello", 5);
} else {
Serial0.printf("usb_host_device_info error=%d\r\n", err);
}
const usb_config_desc_t *config_desc = NULL;
err = usb_host_get_active_config_descriptor(dev_hdl, &config_desc);
if (err != ESP_OK || config_desc == NULL) {
Serial0.printf("usb_host_get_active_config_descriptor failed=%d\r\n", err);
usb_host_device_close(usb_host_client, dev_hdl);
return;
}
Serial0.printf("config_desc size=%u\r\n", config_desc->bLength);
Serial0.printf("config_desc bLength=%u wTotalLength=%u\r\n", config_desc->bLength, config_desc->wTotalLength);
uint8_t in_interface_number = 0xFF;
uint8_t in_endpoint_address = 0;
uint8_t out_interface_number = 0xFF;
uint8_t out_endpoint_address = 0;
if (!usb_host_find_in_endpoint(config_desc, &in_interface_number, &in_endpoint_address, &out_interface_number, &out_endpoint_address)) {
Serial0.println("No bulk IN endpoint found in active config");
usb_host_free_config_desc(config_desc);
usb_host_device_close(usb_host_client, dev_hdl);
return;
}
// Serial0.printf("Found bulk IN endpoint 0x%02x on interface %u\r\n", endpoint_address, interface_number);
usb_host_dev = dev_hdl;
usb_host_in_endpoint = in_endpoint_address;
usb_host_out_endpoint = out_endpoint_address;
usb_host_start_reading(dev_hdl, in_interface_number, in_endpoint_address);
if (out_endpoint_address != 0) {
usb_host_start_writing(dev_hdl, out_interface_number, out_endpoint_address);
}
usb_host_free_config_desc(config_desc);
}
static void usb_host_event_callback(const usb_host_client_event_msg_t *event_msg, void *arg)
{
if (event_msg->event == USB_HOST_CLIENT_EVENT_NEW_DEV) {
usb_host_new_device = true;
usb_host_new_address = event_msg->new_dev.address;
Serial0.printf("USB host event: new device address=%u\r\n", usb_host_new_address);
} else if (event_msg->event == USB_HOST_CLIENT_EVENT_DEV_GONE) {
Serial0.println("USB host event: device gone");
usb_host_device_gone = true;
usb_host_gone_handle = event_msg->dev_gone.dev_hdl;
}
}
static void usb_host_print_device_list()
{
uint8_t dev_addrs[8];
int num_dev = 0;
esp_err_t err = usb_host_device_addr_list_fill(sizeof(dev_addrs), dev_addrs, &num_dev);
if (err != ESP_OK) {
Serial0.printf("usb_host_device_addr_list_fill error=%d\r\n", err);
return;
}
Serial0.printf("USB host connected devices: %d\r\n", num_dev);
for (int i = 0; i < num_dev; ++i) {
Serial0.printf(" device addr=%u\r\n", dev_addrs[i]);
}
}
void hostloop(void *pvParameters)
{
while(1)
{
uint32_t event_flags = 0;
usb_host_lib_handle_events(pdMS_TO_TICKS(10), &event_flags);
if (usb_host_client != NULL) {
usb_host_client_handle_events(usb_host_client, pdMS_TO_TICKS(10));
}
if (usb_host_device_gone && usb_host_gone_handle == usb_host_dev) {
usb_host_device_gone = false;
usb_host_gone_handle = NULL;
usb_host_cleanup_device();
Serial0.println("Active USB device disconnected");
}
// Serial0.printf("usb_host_new_device=%d\r\n", usb_host_new_device);
if (usb_host_new_device) {
usb_host_new_device = false;
Serial0.printf("New USB Reading Device");
usb_host_print_device_list();
usb_host_open_device(usb_host_new_address);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
// Serial0.println("loop");
// vTaskDelay(pdMS_TO_TICKS(100));
}
void hoststart()
{
usb_host_config_t usb_host_config;
usb_host_config.skip_phy_setup = false;
usb_host_config.root_port_unpowered = false;
usb_host_config.intr_flags = 0;
usb_host_config.enum_filter_cb = NULL;
esp_err_t err = usb_host_install(&usb_host_config);
if (err != ESP_OK) {
Serial0.printf("usb_host_install failed=%d\r\n", err);
return;
}
usb_host_client_config_t client_cfg;
client_cfg.is_synchronous = false;
client_cfg.max_num_event_msg = 4;
client_cfg.async.client_event_callback = usb_host_event_callback;
client_cfg.async.callback_arg = NULL;
err = usb_host_client_register(&client_cfg, &usb_host_client);
if (err != ESP_OK) {
Serial0.printf("usb_host_client_register failed=%d\r\n", err);
return;
}
xTaskCreate(hostloop, "hostloop", 4096, NULL, 5, NULL);
}
bool host_send_data(const uint8_t *data, int len)
{
if (usb_host_dev == NULL) {
Serial0.println("No USB device open");
return false;
}
if (usb_host_out_endpoint == 0) {
Serial0.println("No USB OUT endpoint available");
return false;
}
return usb_host_write_data(data, len);
}
bool host_send_message(const char *msg)
{
if (!msg) {
return false;
}
int len = strlen(msg);
return host_send_data((const uint8_t *)msg, len);
}
// bool host_send_large_data(const uint8_t *data, uint32_t total_len)
// {
// uint32_t offset = 0;
// while(offset < total_len)
// {
// uint32_t send_len =
// MIN(USB_TX_BLOCK_SIZE,
// total_len - offset);
// if(!host_send_data(
// data + offset,
// send_len))
// {
// return false;
// }
// offset += send_len;
// while(!tx_done)
// {
// vTaskDelay(1);
// }
// }
// return true;
// }

16
src/myusb_host.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef MYUSB_HOST_H
#define MYUSB_HOST_H
// #define sys_power_pin 48
#include <Arduino.h>
#include "usb/usb_host.h"
// #include "cdc_host.h"
// #include "cdc.h"
#include "Adafruit_TinyUSB.h"
void hoststart();
bool host_send_data(const uint8_t *data, int len);
bool host_send_message(const char *msg);
#endif