2#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32P4)
14#pragma GCC diagnostic ignored "-Wparentheses"
16using namespace bytebuffer;
18#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
19static void print_ep_desc(
const usb_ep_desc_t *ep_desc) {
20 const char *ep_type_str;
21 int type = ep_desc->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK;
24 case USB_BM_ATTRIBUTES_XFER_CONTROL:
27 case USB_BM_ATTRIBUTES_XFER_ISOC:
30 case USB_BM_ATTRIBUTES_XFER_BULK:
33 case USB_BM_ATTRIBUTES_XFER_INT:
41 ESP_LOGV(TAG,
"\t\t*** Endpoint descriptor ***");
42 ESP_LOGV(TAG,
"\t\tbLength %d", ep_desc->bLength);
43 ESP_LOGV(TAG,
"\t\tbDescriptorType %d", ep_desc->bDescriptorType);
44 ESP_LOGV(TAG,
"\t\tbEndpointAddress 0x%x\tEP %d %s", ep_desc->bEndpointAddress, USB_EP_DESC_GET_EP_NUM(ep_desc),
45 USB_EP_DESC_GET_EP_DIR(ep_desc) ?
"IN" :
"OUT");
46 ESP_LOGV(TAG,
"\t\tbmAttributes 0x%x\t%s", ep_desc->bmAttributes, ep_type_str);
47 ESP_LOGV(TAG,
"\t\twMaxPacketSize %d", ep_desc->wMaxPacketSize);
48 ESP_LOGV(TAG,
"\t\tbInterval %d", ep_desc->bInterval);
51static void usbh_print_intf_desc(
const usb_intf_desc_t *intf_desc) {
52 ESP_LOGV(TAG,
"\t*** Interface descriptor ***");
53 ESP_LOGV(TAG,
"\tbLength %d", intf_desc->bLength);
54 ESP_LOGV(TAG,
"\tbDescriptorType %d", intf_desc->bDescriptorType);
55 ESP_LOGV(TAG,
"\tbInterfaceNumber %d", intf_desc->bInterfaceNumber);
56 ESP_LOGV(TAG,
"\tbAlternateSetting %d", intf_desc->bAlternateSetting);
57 ESP_LOGV(TAG,
"\tbNumEndpoints %d", intf_desc->bNumEndpoints);
58 ESP_LOGV(TAG,
"\tbInterfaceClass 0x%x", intf_desc->bInterfaceProtocol);
59 ESP_LOGV(TAG,
"\tiInterface %d", intf_desc->iInterface);
62static void usbh_print_cfg_desc(
const usb_config_desc_t *cfg_desc) {
63 ESP_LOGV(TAG,
"*** Configuration descriptor ***");
64 ESP_LOGV(TAG,
"bLength %d", cfg_desc->bLength);
65 ESP_LOGV(TAG,
"bDescriptorType %d", cfg_desc->bDescriptorType);
66 ESP_LOGV(TAG,
"wTotalLength %d", cfg_desc->wTotalLength);
67 ESP_LOGV(TAG,
"bNumInterfaces %d", cfg_desc->bNumInterfaces);
68 ESP_LOGV(TAG,
"bConfigurationValue %d", cfg_desc->bConfigurationValue);
69 ESP_LOGV(TAG,
"iConfiguration %d", cfg_desc->iConfiguration);
70 ESP_LOGV(TAG,
"bmAttributes 0x%x", cfg_desc->bmAttributes);
71 ESP_LOGV(TAG,
"bMaxPower %dmA", cfg_desc->bMaxPower * 2);
74static void usb_client_print_device_descriptor(
const usb_device_desc_t *devc_desc) {
75 if (devc_desc == NULL) {
79 ESP_LOGV(TAG,
"*** Device descriptor ***");
80 ESP_LOGV(TAG,
"bLength %d", devc_desc->bLength);
81 ESP_LOGV(TAG,
"bDescriptorType %d", devc_desc->bDescriptorType);
82 ESP_LOGV(TAG,
"bcdUSB %d.%d0", ((devc_desc->bcdUSB >> 8) & 0xF), ((devc_desc->bcdUSB >> 4) & 0xF));
83 ESP_LOGV(TAG,
"bDeviceClass 0x%x", devc_desc->bDeviceClass);
84 ESP_LOGV(TAG,
"bDeviceSubClass 0x%x", devc_desc->bDeviceSubClass);
85 ESP_LOGV(TAG,
"bDeviceProtocol 0x%x", devc_desc->bDeviceProtocol);
86 ESP_LOGV(TAG,
"bMaxPacketSize0 %d", devc_desc->bMaxPacketSize0);
87 ESP_LOGV(TAG,
"idVendor 0x%x", devc_desc->idVendor);
88 ESP_LOGV(TAG,
"idProduct 0x%x", devc_desc->idProduct);
89 ESP_LOGV(TAG,
"bcdDevice %d.%d0", ((devc_desc->bcdDevice >> 8) & 0xF), ((devc_desc->bcdDevice >> 4) & 0xF));
90 ESP_LOGV(TAG,
"iManufacturer %d", devc_desc->iManufacturer);
91 ESP_LOGV(TAG,
"iProduct %d", devc_desc->iProduct);
92 ESP_LOGV(TAG,
"iSerialNumber %d", devc_desc->iSerialNumber);
93 ESP_LOGV(TAG,
"bNumConfigurations %d", devc_desc->bNumConfigurations);
96static void usb_client_print_config_descriptor(
const usb_config_desc_t *cfg_desc,
97 print_class_descriptor_cb class_specific_cb) {
98 if (cfg_desc ==
nullptr) {
103 uint16_t w_total_length = cfg_desc->wTotalLength;
104 const usb_standard_desc_t *next_desc = (
const usb_standard_desc_t *) cfg_desc;
107 switch (next_desc->bDescriptorType) {
108 case USB_W_VALUE_DT_CONFIG:
109 usbh_print_cfg_desc((
const usb_config_desc_t *) next_desc);
111 case USB_W_VALUE_DT_INTERFACE:
112 usbh_print_intf_desc((
const usb_intf_desc_t *) next_desc);
114 case USB_W_VALUE_DT_ENDPOINT:
115 print_ep_desc((
const usb_ep_desc_t *) next_desc);
118 if (class_specific_cb) {
119 class_specific_cb(next_desc);
124 next_desc = usb_parse_next_descriptor(next_desc, w_total_length, &offset);
126 }
while (next_desc != NULL);
129static std::string get_descriptor_string(
const usb_str_desc_t *desc) {
132 return "(unspecified)";
134 for (
int i = 0; i != desc->bLength / 2; i++) {
135 auto c = desc->wData[i];
137 *p++ =
static_cast<char>(c);
144static void client_event_cb(
const usb_host_client_event_msg_t *event_msg,
void *ptr) {
145 auto *client =
static_cast<USBClient *
>(ptr);
148 UsbEvent *
event = client->event_pool.allocate();
149 if (event ==
nullptr) {
151 client->event_queue.increment_dropped_count();
156 switch (event_msg->event) {
157 case USB_HOST_CLIENT_EVENT_NEW_DEV: {
158 ESP_LOGD(TAG,
"New device %d", event_msg->new_dev.address);
160 event->data.device_new.address = event_msg->new_dev.address;
163 case USB_HOST_CLIENT_EVENT_DEV_GONE: {
164 ESP_LOGD(TAG,
"Device gone");
166 event->data.device_gone.handle = event_msg->dev_gone.dev_hdl;
170 ESP_LOGD(TAG,
"Unknown event %d", event_msg->event);
171 client->event_pool.release(event);
176 client->event_queue.push(event);
179 usb_host_client_config_t config{.is_synchronous =
false,
180 .max_num_event_msg = 5,
181 .async = {.client_event_callback = client_event_cb, .callback_arg =
this}};
182 auto err = usb_host_client_register(&config, &this->
handle_);
184 ESP_LOGE(TAG,
"client register failed: %s", esp_err_to_name(err));
191 for (
size_t i = 0; i < MAX_REQUESTS; i++) {
192 usb_host_transfer_alloc(64, 0, &this->
requests_[i].transfer);
204 ESP_LOGE(TAG,
"Failed to create USB task");
210 auto *client =
static_cast<USBClient *
>(arg);
216 usb_host_client_handle_events(this->
handle_, portMAX_DELAY);
223 while ((event = this->
event_queue.pop()) !=
nullptr) {
224 switch (event->
type) {
233 auto *trq =
event->data.transfer.trq;
243 uint16_t dropped = this->
event_queue.get_and_reset_dropped_count();
245 ESP_LOGW(TAG,
"Dropped %u USB events due to queue overflow", dropped);
254 ESP_LOGW(TAG,
"Device open failed: %s", esp_err_to_name(err));
258 ESP_LOGD(TAG,
"Get descriptor device %d", this->
device_addr_);
259 const usb_device_desc_t *desc;
260 err = usb_host_get_device_descriptor(this->
device_handle_, &desc);
262 ESP_LOGW(TAG,
"Device get_desc failed: %s", esp_err_to_name(err));
265 ESP_LOGD(TAG,
"Device descriptor: vid %X pid %X", desc->idVendor, desc->idProduct);
266 if (desc->idVendor == this->vid_ && desc->idProduct == this->pid_ || this->vid_ == 0 && this->pid_ == 0) {
267 usb_device_info_t dev_info;
270 ESP_LOGW(TAG,
"Device info failed: %s", esp_err_to_name(err));
275 ESP_LOGD(TAG,
"Device connected: Manuf: %s; Prod: %s; Serial: %s",
276 get_descriptor_string(dev_info.str_desc_manufacturer).c_str(),
277 get_descriptor_string(dev_info.str_desc_product).c_str(),
278 get_descriptor_string(dev_info.str_desc_serial_num).c_str());
280#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
281 const usb_device_desc_t *device_desc;
282 err = usb_host_get_device_descriptor(this->
device_handle_, &device_desc);
284 usb_client_print_device_descriptor(device_desc);
285 const usb_config_desc_t *config_desc;
286 err = usb_host_get_active_config_descriptor(this->
device_handle_, &config_desc);
288 usb_client_print_config_descriptor(config_desc,
nullptr);
292 ESP_LOGD(TAG,
"Not our device, closing");
318 auto *client = trq->
client;
321 UsbEvent *
event = client->event_pool.allocate();
322 if (event ==
nullptr) {
324 client->event_queue.increment_dropped_count();
329 event->data.transfer.trq = trq;
332 client->event_queue.push(event);
336static void control_callback(
const usb_transfer_t *xfer) {
337 auto *trq =
static_cast<TransferRequest *
>(xfer->context);
339 trq->
status.
success = xfer->status == USB_TRANSFER_STATUS_COMPLETED;
361 uint16_t mask = this->
trq_in_use_.load(std::memory_order_relaxed);
366 while (i != MAX_REQUESTS) {
367 if (mask & (1U << i)) {
374 uint16_t desired = mask | (1U << i);
376 if (this->
trq_in_use_.compare_exchange_weak(mask, desired, std::memory_order_acquire, std::memory_order_relaxed)) {
389 ESP_LOGE(TAG,
"All %d transfer slots in use", MAX_REQUESTS);
396 ESP_LOGE(TAG,
"Device close failed: %s", esp_err_to_name(err));
406 const transfer_cb_t &callback,
const std::vector<uint8_t> &data) {
410 auto length = data.size();
411 if (
length >
sizeof(trq->
transfer->data_buffer_size) - SETUP_PACKET_SIZE) {
412 ESP_LOGE(TAG,
"Control transfer data size too large: %u > %u",
length,
413 sizeof(trq->
transfer->data_buffer_size) -
sizeof(usb_setup_packet_t));
418 control_packet.put_uint8(
type);
419 control_packet.put_uint8(request);
420 control_packet.put_uint16(value);
421 control_packet.put_uint16(index);
422 control_packet.put_uint16(
length);
423 memcpy(trq->
transfer->data_buffer, control_packet.get_data().data(), SETUP_PACKET_SIZE);
425 memcpy(trq->
transfer->data_buffer + SETUP_PACKET_SIZE, data.data(),
length);
429 trq->
transfer->num_bytes =
static_cast<int>(
length + SETUP_PACKET_SIZE);
430 trq->
transfer->callback =
reinterpret_cast<usb_transfer_cb_t
>(control_callback);
431 auto err = usb_host_transfer_submit_control(this->
handle_, trq->
transfer);
433 ESP_LOGE(TAG,
"Failed to submit control transfer, err=%s", esp_err_to_name(err));
441static void transfer_callback(usb_transfer_t *xfer) {
444 trq->
status.
success = xfer->status == USB_TRANSFER_STATUS_COMPLETED;
472 if (trq ==
nullptr) {
473 ESP_LOGE(TAG,
"Too many requests queued");
477 trq->
transfer->callback = transfer_callback;
478 trq->
transfer->bEndpointAddress = ep_address | USB_DIR_IN;
480 auto err = usb_host_transfer_submit(trq->
transfer);
482 ESP_LOGE(TAG,
"Failed to submit transfer, address=%x, length=%d, err=%x", ep_address,
length, err);
502 if (trq ==
nullptr) {
503 ESP_LOGE(TAG,
"Too many requests queued");
507 trq->
transfer->callback = transfer_callback;
508 trq->
transfer->bEndpointAddress = ep_address | USB_DIR_OUT;
511 auto err = usb_host_transfer_submit(trq->
transfer);
513 ESP_LOGE(TAG,
"Failed to submit transfer, address=%x, length=%d, err=%x", ep_address,
length, err);
536 if (index >= MAX_REQUESTS) {
537 ESP_LOGE(TAG,
"Invalid TransferRequest pointer");
543 uint16_t bit = 1U << index;
544 this->
trq_in_use_.fetch_and(
static_cast<uint16_t
>(~bit), std::memory_order_release);
virtual void mark_failed()
Mark this component as failed.
void status_set_error(const char *message=nullptr)
A class modelled on the Java ByteBuffer class.
TransferRequest * get_trq_()
usb_host_client_handle_t handle_
void on_opened(uint8_t addr)
TransferRequest requests_[MAX_REQUESTS]
void transfer_in(uint8_t ep_address, const transfer_cb_t &callback, uint16_t length)
Performs a transfer input operation.
void transfer_out(uint8_t ep_address, const transfer_cb_t &callback, const uint8_t *data, uint16_t length)
Performs an output transfer operation.
void dump_config() override
void release_trq(TransferRequest *trq)
std::atomic< uint16_t > trq_in_use_
static void usb_task_fn(void *arg)
virtual void on_connected()
virtual void disconnect()
TaskHandle_t usb_task_handle_
EventPool< UsbEvent, USB_EVENT_QUEUE_SIZE > event_pool
virtual void on_disconnected()
bool control_transfer(uint8_t type, uint8_t request, uint16_t value, uint16_t index, const transfer_cb_t &callback, const std::vector< uint8_t > &data={})
void on_removed(usb_device_handle_t handle)
usb_device_handle_t device_handle_
LockFreeQueue< UsbEvent, USB_EVENT_QUEUE_SIZE > event_queue
@ EVENT_TRANSFER_COMPLETE
std::function< void(const TransferStatus &)> transfer_cb_t
Providing packet encoding functions for exchanging data with a remote host.
usb_transfer_t * transfer
usb_device_handle_t handle
struct esphome::usb_host::UsbEvent::@152::@153 device_new
union esphome::usb_host::UsbEvent::@152 data
struct esphome::usb_host::UsbEvent::@152::@154 device_gone