mirror of
https://github.com/esphome/esphome.git
synced 2025-10-31 23:21:54 +00:00
readable
This commit is contained in:
@@ -184,48 +184,56 @@ void USBUartComponent::restart_input_(USBUartChannel *channel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void USBUartComponent::do_start_input_(USBUartChannel *channel) {
|
void USBUartComponent::input_transfer_callback_(USBUartChannel *channel, const usb_host::TransferStatus &status) {
|
||||||
// This function does the actual work of starting input
|
// CALLBACK CONTEXT: This function is executed in USB task via transfer_callback
|
||||||
// Caller must ensure input_started_ is already set to true
|
ESP_LOGV(TAG, "Transfer result: length: %u; status %X", status.data_len, status.error_code);
|
||||||
const auto *ep = channel->cdc_dev_.in_ep;
|
|
||||||
// CALLBACK CONTEXT: This lambda is executed in USB task via transfer_callback
|
if (!status.success) {
|
||||||
auto callback = [this, channel](const usb_host::TransferStatus &status) {
|
ESP_LOGE(TAG, "Control transfer failed, status=%s", esp_err_to_name(status.error_code));
|
||||||
ESP_LOGV(TAG, "Transfer result: length: %u; status %X", status.data_len, status.error_code);
|
// Transfer failed, slot already released
|
||||||
if (!status.success) {
|
// Reset state so normal operations can restart later
|
||||||
ESP_LOGE(TAG, "Control transfer failed, status=%s", esp_err_to_name(status.error_code));
|
this->reset_input_state_(channel);
|
||||||
// Transfer failed, slot already released
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!channel->dummy_receiver_ && status.data_len > 0) {
|
||||||
|
// Allocate a chunk from the pool
|
||||||
|
UsbDataChunk *chunk = this->chunk_pool_.allocate();
|
||||||
|
if (chunk == nullptr) {
|
||||||
|
// No chunks available - queue is full, data dropped, slot already released
|
||||||
|
this->usb_data_queue_.increment_dropped_count();
|
||||||
// Reset state so normal operations can restart later
|
// Reset state so normal operations can restart later
|
||||||
this->reset_input_state_(channel);
|
this->reset_input_state_(channel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!channel->dummy_receiver_ && status.data_len > 0) {
|
// Copy data to chunk (this is fast, happens in USB task)
|
||||||
// Allocate a chunk from the pool
|
memcpy(chunk->data, status.data, status.data_len);
|
||||||
UsbDataChunk *chunk = this->chunk_pool_.allocate();
|
chunk->length = status.data_len;
|
||||||
if (chunk == nullptr) {
|
chunk->channel = channel;
|
||||||
// No chunks available - queue is full, data dropped, slot already released
|
|
||||||
this->usb_data_queue_.increment_dropped_count();
|
|
||||||
// Reset state so normal operations can restart later
|
|
||||||
this->reset_input_state_(channel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy data to chunk (this is fast, happens in USB task)
|
// Push to lock-free queue for main loop processing
|
||||||
memcpy(chunk->data, status.data, status.data_len);
|
// Push always succeeds because pool size == queue size
|
||||||
chunk->length = status.data_len;
|
this->usb_data_queue_.push(chunk);
|
||||||
chunk->channel = channel;
|
}
|
||||||
|
|
||||||
// Push to lock-free queue for main loop processing
|
// On success, reset retry count and restart input immediately from USB task for performance
|
||||||
// Push always succeeds because pool size == queue size
|
// The lock-free queue will handle backpressure
|
||||||
this->usb_data_queue_.push(chunk);
|
channel->input_retry_count_.store(0);
|
||||||
}
|
channel->input_started_.store(false);
|
||||||
|
this->start_input(channel);
|
||||||
|
}
|
||||||
|
|
||||||
// On success, reset retry count and restart input immediately from USB task for performance
|
void USBUartComponent::do_start_input_(USBUartChannel *channel) {
|
||||||
// The lock-free queue will handle backpressure
|
// This function does the actual work of starting input
|
||||||
channel->input_retry_count_.store(0);
|
// Caller must ensure input_started_ is already set to true
|
||||||
channel->input_started_.store(false);
|
const auto *ep = channel->cdc_dev_.in_ep;
|
||||||
this->start_input(channel);
|
|
||||||
|
// Set up callback using a lambda that captures channel and forwards to the named function
|
||||||
|
auto callback = [this, channel](const usb_host::TransferStatus &status) {
|
||||||
|
this->input_transfer_callback_(channel, status);
|
||||||
};
|
};
|
||||||
|
|
||||||
// input_started_ already set to true by caller
|
// input_started_ already set to true by caller
|
||||||
auto result = this->transfer_in(ep->bEndpointAddress, callback, ep->wMaxPacketSize);
|
auto result = this->transfer_in(ep->bEndpointAddress, callback, ep->wMaxPacketSize);
|
||||||
if (result == usb_host::TRANSFER_ERROR_NO_SLOTS) {
|
if (result == usb_host::TRANSFER_ERROR_NO_SLOTS) {
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ class USBUartComponent : public usb_host::USBClient {
|
|||||||
void reset_input_state_(USBUartChannel *channel);
|
void reset_input_state_(USBUartChannel *channel);
|
||||||
void restart_input_(USBUartChannel *channel);
|
void restart_input_(USBUartChannel *channel);
|
||||||
void do_start_input_(USBUartChannel *channel);
|
void do_start_input_(USBUartChannel *channel);
|
||||||
|
void input_transfer_callback_(USBUartChannel *channel, const usb_host::TransferStatus &status);
|
||||||
std::vector<USBUartChannel *> channels_{};
|
std::vector<USBUartChannel *> channels_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user