diff --git a/esphome/components/usb_host/usb_host.h b/esphome/components/usb_host/usb_host.h index 2eec0c9699..dcb76a3a3b 100644 --- a/esphome/components/usb_host/usb_host.h +++ b/esphome/components/usb_host/usb_host.h @@ -144,7 +144,10 @@ class USBClient : public Component { // Lock-free event queue and pool for USB task to main loop communication // Must be public for access from static callbacks LockFreeQueue event_queue; - EventPool event_pool; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing a pool slot leak. + EventPool event_pool; protected: // Process USB events from the queue. Returns true if any work was done. diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 2a460d1a07..18d938344c 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -193,7 +193,8 @@ static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void * return; } - // Push to lock-free queue (always succeeds since pool size == queue size) + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. client->event_queue.push(event); // Re-enable component loop to process the queued event