mirror of
https://github.com/esphome/esphome.git
synced 2025-07-27 21:56:34 +00:00
[usb_uart] Be flexible about descriptor layout for CDC-ACM devices (#9425)
This commit is contained in:
parent
bc7cfeb9cd
commit
01b4e214b9
@ -70,7 +70,7 @@ static void usbh_print_cfg_desc(const usb_config_desc_t *cfg_desc) {
|
|||||||
ESP_LOGV(TAG, "bMaxPower %dmA", cfg_desc->bMaxPower * 2);
|
ESP_LOGV(TAG, "bMaxPower %dmA", cfg_desc->bMaxPower * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_client_print_device_descriptor(const usb_device_desc_t *devc_desc) {
|
static void usb_client_print_device_descriptor(const usb_device_desc_t *devc_desc) {
|
||||||
if (devc_desc == NULL) {
|
if (devc_desc == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ void usb_client_print_device_descriptor(const usb_device_desc_t *devc_desc) {
|
|||||||
ESP_LOGV(TAG, "bNumConfigurations %d", devc_desc->bNumConfigurations);
|
ESP_LOGV(TAG, "bNumConfigurations %d", devc_desc->bNumConfigurations);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_client_print_config_descriptor(const usb_config_desc_t *cfg_desc,
|
static void usb_client_print_config_descriptor(const usb_config_desc_t *cfg_desc,
|
||||||
print_class_descriptor_cb class_specific_cb) {
|
print_class_descriptor_cb class_specific_cb) {
|
||||||
if (cfg_desc == nullptr) {
|
if (cfg_desc == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -128,9 +128,9 @@ void usb_client_print_config_descriptor(const usb_config_desc_t *cfg_desc,
|
|||||||
static std::string get_descriptor_string(const usb_str_desc_t *desc) {
|
static std::string get_descriptor_string(const usb_str_desc_t *desc) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
if (desc == nullptr)
|
if (desc == nullptr)
|
||||||
return "(unknown)";
|
return "(unspecified)";
|
||||||
char *p = buffer;
|
char *p = buffer;
|
||||||
for (size_t i = 0; i != desc->bLength / 2; i++) {
|
for (int i = 0; i != desc->bLength / 2; i++) {
|
||||||
auto c = desc->wData[i];
|
auto c = desc->wData[i];
|
||||||
if (c < 0x100)
|
if (c < 0x100)
|
||||||
*p++ = static_cast<char>(c);
|
*p++ = static_cast<char>(c);
|
||||||
@ -169,7 +169,7 @@ void USBClient::setup() {
|
|||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto trq : this->trq_pool_) {
|
for (auto *trq : this->trq_pool_) {
|
||||||
usb_host_transfer_alloc(64, 0, &trq->transfer);
|
usb_host_transfer_alloc(64, 0, &trq->transfer);
|
||||||
trq->client = this;
|
trq->client = this;
|
||||||
}
|
}
|
||||||
@ -197,7 +197,8 @@ void USBClient::loop() {
|
|||||||
ESP_LOGD(TAG, "Device descriptor: vid %X pid %X", desc->idVendor, desc->idProduct);
|
ESP_LOGD(TAG, "Device descriptor: vid %X pid %X", desc->idVendor, desc->idProduct);
|
||||||
if (desc->idVendor == this->vid_ && desc->idProduct == this->pid_ || this->vid_ == 0 && this->pid_ == 0) {
|
if (desc->idVendor == this->vid_ && desc->idProduct == this->pid_ || this->vid_ == 0 && this->pid_ == 0) {
|
||||||
usb_device_info_t dev_info;
|
usb_device_info_t dev_info;
|
||||||
if ((err = usb_host_device_info(this->device_handle_, &dev_info)) != ESP_OK) {
|
err = usb_host_device_info(this->device_handle_, &dev_info);
|
||||||
|
if (err != ESP_OK) {
|
||||||
ESP_LOGW(TAG, "Device info failed: %s", esp_err_to_name(err));
|
ESP_LOGW(TAG, "Device info failed: %s", esp_err_to_name(err));
|
||||||
this->disconnect();
|
this->disconnect();
|
||||||
break;
|
break;
|
||||||
@ -336,7 +337,7 @@ static void transfer_callback(usb_transfer_t *xfer) {
|
|||||||
* @throws None.
|
* @throws None.
|
||||||
*/
|
*/
|
||||||
void USBClient::transfer_in(uint8_t ep_address, const transfer_cb_t &callback, uint16_t length) {
|
void USBClient::transfer_in(uint8_t ep_address, const transfer_cb_t &callback, uint16_t length) {
|
||||||
auto trq = this->get_trq_();
|
auto *trq = this->get_trq_();
|
||||||
if (trq == nullptr) {
|
if (trq == nullptr) {
|
||||||
ESP_LOGE(TAG, "Too many requests queued");
|
ESP_LOGE(TAG, "Too many requests queued");
|
||||||
return;
|
return;
|
||||||
@ -349,7 +350,6 @@ void USBClient::transfer_in(uint8_t ep_address, const transfer_cb_t &callback, u
|
|||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to submit transfer, address=%x, length=%d, err=%x", ep_address, length, err);
|
ESP_LOGE(TAG, "Failed to submit transfer, address=%x, length=%d, err=%x", ep_address, length, err);
|
||||||
this->release_trq(trq);
|
this->release_trq(trq);
|
||||||
this->disconnect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +364,7 @@ void USBClient::transfer_in(uint8_t ep_address, const transfer_cb_t &callback, u
|
|||||||
* @throws None.
|
* @throws None.
|
||||||
*/
|
*/
|
||||||
void USBClient::transfer_out(uint8_t ep_address, const transfer_cb_t &callback, const uint8_t *data, uint16_t length) {
|
void USBClient::transfer_out(uint8_t ep_address, const transfer_cb_t &callback, const uint8_t *data, uint16_t length) {
|
||||||
auto trq = this->get_trq_();
|
auto *trq = this->get_trq_();
|
||||||
if (trq == nullptr) {
|
if (trq == nullptr) {
|
||||||
ESP_LOGE(TAG, "Too many requests queued");
|
ESP_LOGE(TAG, "Too many requests queued");
|
||||||
return;
|
return;
|
||||||
|
@ -43,7 +43,7 @@ static constexpr uint8_t SET_BAUDRATE = 0x1E; // Set the baud rate.
|
|||||||
static constexpr uint8_t SET_CHARS = 0x19; // Set special characters.
|
static constexpr uint8_t SET_CHARS = 0x19; // Set special characters.
|
||||||
static constexpr uint8_t VENDOR_SPECIFIC = 0xFF; // Vendor specific command.
|
static constexpr uint8_t VENDOR_SPECIFIC = 0xFF; // Vendor specific command.
|
||||||
|
|
||||||
std::vector<CdcEps> USBUartTypeCP210X::parse_descriptors_(usb_device_handle_t dev_hdl) {
|
std::vector<CdcEps> USBUartTypeCP210X::parse_descriptors(usb_device_handle_t dev_hdl) {
|
||||||
const usb_config_desc_t *config_desc;
|
const usb_config_desc_t *config_desc;
|
||||||
const usb_device_desc_t *device_desc;
|
const usb_device_desc_t *device_desc;
|
||||||
int conf_offset = 0, ep_offset;
|
int conf_offset = 0, ep_offset;
|
||||||
|
@ -18,52 +18,48 @@ namespace usb_uart {
|
|||||||
*/
|
*/
|
||||||
static optional<CdcEps> get_cdc(const usb_config_desc_t *config_desc, uint8_t intf_idx) {
|
static optional<CdcEps> get_cdc(const usb_config_desc_t *config_desc, uint8_t intf_idx) {
|
||||||
int conf_offset, ep_offset;
|
int conf_offset, ep_offset;
|
||||||
const usb_ep_desc_t *notify_ep{}, *in_ep{}, *out_ep{};
|
// look for an interface with an interrupt endpoint (notify), and one with two bulk endpoints (data in/out)
|
||||||
uint8_t interface_number = 0;
|
CdcEps eps{};
|
||||||
// look for an interface with one interrupt endpoint (notify), and an interface with two bulk endpoints (data in/out)
|
eps.bulk_interface_number = 0xFF;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto intf_desc = usb_parse_interface_descriptor(config_desc, intf_idx++, 0, &conf_offset);
|
const auto *intf_desc = usb_parse_interface_descriptor(config_desc, intf_idx++, 0, &conf_offset);
|
||||||
if (!intf_desc) {
|
if (!intf_desc) {
|
||||||
ESP_LOGE(TAG, "usb_parse_interface_descriptor failed");
|
ESP_LOGE(TAG, "usb_parse_interface_descriptor failed");
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
if (intf_desc->bNumEndpoints == 1) {
|
ESP_LOGD(TAG, "intf_desc: bInterfaceClass=%02X, bInterfaceSubClass=%02X, bInterfaceProtocol=%02X, bNumEndpoints=%d",
|
||||||
|
intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol,
|
||||||
|
intf_desc->bNumEndpoints);
|
||||||
|
for (uint8_t i = 0; i != intf_desc->bNumEndpoints; i++) {
|
||||||
ep_offset = conf_offset;
|
ep_offset = conf_offset;
|
||||||
notify_ep = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &ep_offset);
|
const auto *ep = usb_parse_endpoint_descriptor_by_index(intf_desc, i, config_desc->wTotalLength, &ep_offset);
|
||||||
if (!notify_ep) {
|
if (!ep) {
|
||||||
ESP_LOGE(TAG, "notify_ep: usb_parse_endpoint_descriptor_by_index failed");
|
ESP_LOGE(TAG, "Ran out of interfaces at %d before finding all endpoints", i);
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
if (notify_ep->bmAttributes != USB_BM_ATTRIBUTES_XFER_INT)
|
ESP_LOGD(TAG, "ep: bEndpointAddress=%02X, bmAttributes=%02X", ep->bEndpointAddress, ep->bmAttributes);
|
||||||
notify_ep = nullptr;
|
if (ep->bmAttributes == USB_BM_ATTRIBUTES_XFER_INT) {
|
||||||
} else if (USB_CLASS_CDC_DATA && intf_desc->bNumEndpoints == 2) {
|
eps.notify_ep = ep;
|
||||||
interface_number = intf_desc->bInterfaceNumber;
|
eps.interrupt_interface_number = intf_desc->bInterfaceNumber;
|
||||||
ep_offset = conf_offset;
|
} else if (ep->bmAttributes == USB_BM_ATTRIBUTES_XFER_BULK && ep->bEndpointAddress & usb_host::USB_DIR_IN &&
|
||||||
out_ep = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &ep_offset);
|
(eps.bulk_interface_number == 0xFF || eps.bulk_interface_number == intf_desc->bInterfaceNumber)) {
|
||||||
if (!out_ep) {
|
eps.in_ep = ep;
|
||||||
ESP_LOGE(TAG, "out_ep: usb_parse_endpoint_descriptor_by_index failed");
|
eps.bulk_interface_number = intf_desc->bInterfaceNumber;
|
||||||
return nullopt;
|
} else if (ep->bmAttributes == USB_BM_ATTRIBUTES_XFER_BULK && !(ep->bEndpointAddress & usb_host::USB_DIR_IN) &&
|
||||||
|
(eps.bulk_interface_number == 0xFF || eps.bulk_interface_number == intf_desc->bInterfaceNumber)) {
|
||||||
|
eps.out_ep = ep;
|
||||||
|
eps.bulk_interface_number = intf_desc->bInterfaceNumber;
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Unexpected endpoint attributes: %02X", ep->bmAttributes);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (out_ep->bmAttributes != USB_BM_ATTRIBUTES_XFER_BULK)
|
|
||||||
out_ep = nullptr;
|
|
||||||
ep_offset = conf_offset;
|
|
||||||
in_ep = usb_parse_endpoint_descriptor_by_index(intf_desc, 1, config_desc->wTotalLength, &ep_offset);
|
|
||||||
if (!in_ep) {
|
|
||||||
ESP_LOGE(TAG, "in_ep: usb_parse_endpoint_descriptor_by_index failed");
|
|
||||||
return nullopt;
|
|
||||||
}
|
}
|
||||||
if (in_ep->bmAttributes != USB_BM_ATTRIBUTES_XFER_BULK)
|
if (eps.in_ep != nullptr && eps.out_ep != nullptr && eps.notify_ep != nullptr)
|
||||||
in_ep = nullptr;
|
return eps;
|
||||||
}
|
}
|
||||||
if (in_ep != nullptr && out_ep != nullptr && notify_ep != nullptr)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (in_ep->bEndpointAddress & usb_host::USB_DIR_IN)
|
|
||||||
return CdcEps{notify_ep, in_ep, out_ep, interface_number};
|
|
||||||
return CdcEps{notify_ep, out_ep, in_ep, interface_number};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CdcEps> USBUartTypeCdcAcm::parse_descriptors_(usb_device_handle_t dev_hdl) {
|
std::vector<CdcEps> USBUartTypeCdcAcm::parse_descriptors(usb_device_handle_t dev_hdl) {
|
||||||
const usb_config_desc_t *config_desc;
|
const usb_config_desc_t *config_desc;
|
||||||
const usb_device_desc_t *device_desc;
|
const usb_device_desc_t *device_desc;
|
||||||
int desc_offset = 0;
|
int desc_offset = 0;
|
||||||
@ -78,7 +74,7 @@ std::vector<CdcEps> USBUartTypeCdcAcm::parse_descriptors_(usb_device_handle_t de
|
|||||||
ESP_LOGE(TAG, "get_active_config_descriptor failed");
|
ESP_LOGE(TAG, "get_active_config_descriptor failed");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (device_desc->bDeviceClass == USB_CLASS_COMM) {
|
if (device_desc->bDeviceClass == USB_CLASS_COMM || device_desc->bDeviceClass == USB_CLASS_VENDOR_SPEC) {
|
||||||
// single CDC-ACM device
|
// single CDC-ACM device
|
||||||
if (auto eps = get_cdc(config_desc, 0)) {
|
if (auto eps = get_cdc(config_desc, 0)) {
|
||||||
ESP_LOGV(TAG, "Found CDC-ACM device");
|
ESP_LOGV(TAG, "Found CDC-ACM device");
|
||||||
@ -194,7 +190,7 @@ void USBUartComponent::start_input(USBUartChannel *channel) {
|
|||||||
if (!channel->initialised_ || channel->input_started_ ||
|
if (!channel->initialised_ || channel->input_started_ ||
|
||||||
channel->input_buffer_.get_free_space() < channel->cdc_dev_.in_ep->wMaxPacketSize)
|
channel->input_buffer_.get_free_space() < channel->cdc_dev_.in_ep->wMaxPacketSize)
|
||||||
return;
|
return;
|
||||||
auto ep = channel->cdc_dev_.in_ep;
|
const auto *ep = channel->cdc_dev_.in_ep;
|
||||||
auto callback = [this, channel](const usb_host::TransferStatus &status) {
|
auto callback = [this, channel](const usb_host::TransferStatus &status) {
|
||||||
ESP_LOGV(TAG, "Transfer result: length: %u; status %X", status.data_len, status.error_code);
|
ESP_LOGV(TAG, "Transfer result: length: %u; status %X", status.data_len, status.error_code);
|
||||||
if (!status.success) {
|
if (!status.success) {
|
||||||
@ -227,7 +223,7 @@ void USBUartComponent::start_output(USBUartChannel *channel) {
|
|||||||
if (channel->output_buffer_.is_empty()) {
|
if (channel->output_buffer_.is_empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto ep = channel->cdc_dev_.out_ep;
|
const auto *ep = channel->cdc_dev_.out_ep;
|
||||||
auto callback = [this, channel](const usb_host::TransferStatus &status) {
|
auto callback = [this, channel](const usb_host::TransferStatus &status) {
|
||||||
ESP_LOGV(TAG, "Output Transfer result: length: %u; status %X", status.data_len, status.error_code);
|
ESP_LOGV(TAG, "Output Transfer result: length: %u; status %X", status.data_len, status.error_code);
|
||||||
channel->output_started_ = false;
|
channel->output_started_ = false;
|
||||||
@ -259,15 +255,15 @@ static void fix_mps(const usb_ep_desc_t *ep) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void USBUartTypeCdcAcm::on_connected() {
|
void USBUartTypeCdcAcm::on_connected() {
|
||||||
auto cdc_devs = this->parse_descriptors_(this->device_handle_);
|
auto cdc_devs = this->parse_descriptors(this->device_handle_);
|
||||||
if (cdc_devs.empty()) {
|
if (cdc_devs.empty()) {
|
||||||
this->status_set_error("No CDC-ACM device found");
|
this->status_set_error("No CDC-ACM device found");
|
||||||
this->disconnect();
|
this->disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ESP_LOGD(TAG, "Found %zu CDC-ACM devices", cdc_devs.size());
|
ESP_LOGD(TAG, "Found %zu CDC-ACM devices", cdc_devs.size());
|
||||||
auto i = 0;
|
size_t i = 0;
|
||||||
for (auto channel : this->channels_) {
|
for (auto *channel : this->channels_) {
|
||||||
if (i == cdc_devs.size()) {
|
if (i == cdc_devs.size()) {
|
||||||
ESP_LOGE(TAG, "No configuration found for channel %d", channel->index_);
|
ESP_LOGE(TAG, "No configuration found for channel %d", channel->index_);
|
||||||
this->status_set_warning("No configuration found for channel");
|
this->status_set_warning("No configuration found for channel");
|
||||||
@ -277,10 +273,11 @@ void USBUartTypeCdcAcm::on_connected() {
|
|||||||
fix_mps(channel->cdc_dev_.in_ep);
|
fix_mps(channel->cdc_dev_.in_ep);
|
||||||
fix_mps(channel->cdc_dev_.out_ep);
|
fix_mps(channel->cdc_dev_.out_ep);
|
||||||
channel->initialised_ = true;
|
channel->initialised_ = true;
|
||||||
auto err = usb_host_interface_claim(this->handle_, this->device_handle_, channel->cdc_dev_.interface_number, 0);
|
auto err =
|
||||||
|
usb_host_interface_claim(this->handle_, this->device_handle_, channel->cdc_dev_.bulk_interface_number, 0);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "usb_host_interface_claim failed: %s, channel=%d, intf=%d", esp_err_to_name(err), channel->index_,
|
ESP_LOGE(TAG, "usb_host_interface_claim failed: %s, channel=%d, intf=%d", esp_err_to_name(err), channel->index_,
|
||||||
channel->cdc_dev_.interface_number);
|
channel->cdc_dev_.bulk_interface_number);
|
||||||
this->status_set_error("usb_host_interface_claim failed");
|
this->status_set_error("usb_host_interface_claim failed");
|
||||||
this->disconnect();
|
this->disconnect();
|
||||||
return;
|
return;
|
||||||
@ -290,7 +287,7 @@ void USBUartTypeCdcAcm::on_connected() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void USBUartTypeCdcAcm::on_disconnected() {
|
void USBUartTypeCdcAcm::on_disconnected() {
|
||||||
for (auto channel : this->channels_) {
|
for (auto *channel : this->channels_) {
|
||||||
if (channel->cdc_dev_.in_ep != nullptr) {
|
if (channel->cdc_dev_.in_ep != nullptr) {
|
||||||
usb_host_endpoint_halt(this->device_handle_, channel->cdc_dev_.in_ep->bEndpointAddress);
|
usb_host_endpoint_halt(this->device_handle_, channel->cdc_dev_.in_ep->bEndpointAddress);
|
||||||
usb_host_endpoint_flush(this->device_handle_, channel->cdc_dev_.in_ep->bEndpointAddress);
|
usb_host_endpoint_flush(this->device_handle_, channel->cdc_dev_.in_ep->bEndpointAddress);
|
||||||
@ -303,7 +300,7 @@ void USBUartTypeCdcAcm::on_disconnected() {
|
|||||||
usb_host_endpoint_halt(this->device_handle_, channel->cdc_dev_.notify_ep->bEndpointAddress);
|
usb_host_endpoint_halt(this->device_handle_, channel->cdc_dev_.notify_ep->bEndpointAddress);
|
||||||
usb_host_endpoint_flush(this->device_handle_, channel->cdc_dev_.notify_ep->bEndpointAddress);
|
usb_host_endpoint_flush(this->device_handle_, channel->cdc_dev_.notify_ep->bEndpointAddress);
|
||||||
}
|
}
|
||||||
usb_host_interface_release(this->handle_, this->device_handle_, channel->cdc_dev_.interface_number);
|
usb_host_interface_release(this->handle_, this->device_handle_, channel->cdc_dev_.bulk_interface_number);
|
||||||
channel->initialised_ = false;
|
channel->initialised_ = false;
|
||||||
channel->input_started_ = false;
|
channel->input_started_ = false;
|
||||||
channel->output_started_ = false;
|
channel->output_started_ = false;
|
||||||
@ -314,7 +311,7 @@ void USBUartTypeCdcAcm::on_disconnected() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void USBUartTypeCdcAcm::enable_channels() {
|
void USBUartTypeCdcAcm::enable_channels() {
|
||||||
for (auto channel : this->channels_) {
|
for (auto *channel : this->channels_) {
|
||||||
if (!channel->initialised_)
|
if (!channel->initialised_)
|
||||||
continue;
|
continue;
|
||||||
channel->input_started_ = false;
|
channel->input_started_ = false;
|
||||||
|
@ -25,7 +25,8 @@ struct CdcEps {
|
|||||||
const usb_ep_desc_t *notify_ep;
|
const usb_ep_desc_t *notify_ep;
|
||||||
const usb_ep_desc_t *in_ep;
|
const usb_ep_desc_t *in_ep;
|
||||||
const usb_ep_desc_t *out_ep;
|
const usb_ep_desc_t *out_ep;
|
||||||
uint8_t interface_number;
|
uint8_t bulk_interface_number;
|
||||||
|
uint8_t interrupt_interface_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UARTParityOptions {
|
enum UARTParityOptions {
|
||||||
@ -123,7 +124,7 @@ class USBUartTypeCdcAcm : public USBUartComponent {
|
|||||||
USBUartTypeCdcAcm(uint16_t vid, uint16_t pid) : USBUartComponent(vid, pid) {}
|
USBUartTypeCdcAcm(uint16_t vid, uint16_t pid) : USBUartComponent(vid, pid) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual std::vector<CdcEps> parse_descriptors_(usb_device_handle_t dev_hdl);
|
virtual std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl);
|
||||||
void on_connected() override;
|
void on_connected() override;
|
||||||
virtual void enable_channels();
|
virtual void enable_channels();
|
||||||
void on_disconnected() override;
|
void on_disconnected() override;
|
||||||
@ -134,7 +135,7 @@ class USBUartTypeCP210X : public USBUartTypeCdcAcm {
|
|||||||
USBUartTypeCP210X(uint16_t vid, uint16_t pid) : USBUartTypeCdcAcm(vid, pid) {}
|
USBUartTypeCP210X(uint16_t vid, uint16_t pid) : USBUartTypeCdcAcm(vid, pid) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<CdcEps> parse_descriptors_(usb_device_handle_t dev_hdl) override;
|
std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl) override;
|
||||||
void enable_channels() override;
|
void enable_channels() override;
|
||||||
};
|
};
|
||||||
class USBUartTypeCH34X : public USBUartTypeCdcAcm {
|
class USBUartTypeCH34X : public USBUartTypeCdcAcm {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user