mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	[usb_uart] Be flexible about descriptor layout for CDC-ACM devices (#9425)
This commit is contained in:
		| @@ -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,8 +92,8 @@ 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) |  | ||||||
|         in_ep = nullptr; |  | ||||||
|     } |     } | ||||||
|     if (in_ep != nullptr && out_ep != nullptr && notify_ep != nullptr) |     if (eps.in_ep != nullptr && eps.out_ep != nullptr && eps.notify_ep != nullptr) | ||||||
|       break; |       return eps; | ||||||
|   } |   } | ||||||
|   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 { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user