-
Notifications
You must be signed in to change notification settings - Fork 22
feat(cli): Add support for USB CDC to cli component, for use on ESP32-S2 for example
#564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…32-S2 for example
|
✅Static analysis result - no issues found! ✅ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds USB CDC support to the cli component to enable its use on ESP32-S2 and other chips with native USB support.
Key Changes:
- Added
configure_stdin_stdout_usb_cdc()method for USB CDC console configuration - Removed the error directive that prevented compilation with
CONFIG_ESP_CONSOLE_USB_CDC - Added
esp_vfs_consolecomponent dependency for USB CDC functionality
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| components/cli/src/cli.cpp | Initializes the static console_ member variable for storing file handles |
| components/cli/include/cli.hpp | Adds new USB CDC configuration method and removes incompatibility error |
| components/cli/example/sdkconfig.defaults.esp32s2 | Configures ESP32-S2 example to use USB CDC console |
| components/cli/CMakeLists.txt | Adds required esp_vfs_console component dependency |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // _IONBF = no buffering | ||
| // disable buffering on stdin | ||
| setvbuf(stdin, nullptr, _IONBF, 0); | ||
|
|
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Missing a final fflush/fsync sequence before setting configured_ = true. The configure_stdin_stdout_uart() (lines 146-147) and configure_stdin_stdout_usb_serial_jtag() (lines 180-181) functions both call fflush(stdout) and fsync(fileno(stdout)) at the end to ensure all output is written before completing configuration. Consider adding this for consistency:
fflush(stdout);
fsync(fileno(stdout));
configured_ = true;| fflush(stdout); | |
| fsync(fileno(stdout)); |
| // redirect stdin, stdout, stderr to the USB CDC interface | ||
| console_.in = freopen(dev_name.data(), "r", stdin); | ||
| console_.out = freopen(dev_name.data(), "w", stdout); | ||
| console_.err = freopen(dev_name.data(), "w", stderr); | ||
|
|
||
| esp_vfs_dev_cdcacm_register(); | ||
|
|
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The VFS device should be registered before calling freopen on it. Currently, freopen is called on lines 204-206 before esp_vfs_dev_cdcacm_register() on line 208. This is inconsistent with the configure_stdin_stdout_vfs() function (lines 261 then 264-266) which registers the VFS first, then calls freopen. The order should be:
- Register the VFS device with
esp_vfs_dev_cdcacm_register() - Then call
freopento redirect stdin/stdout/stderr
| // redirect stdin, stdout, stderr to the USB CDC interface | |
| console_.in = freopen(dev_name.data(), "r", stdin); | |
| console_.out = freopen(dev_name.data(), "w", stdout); | |
| console_.err = freopen(dev_name.data(), "w", stderr); | |
| esp_vfs_dev_cdcacm_register(); | |
| // Register the VFS device before redirecting streams | |
| esp_vfs_dev_cdcacm_register(); | |
| // redirect stdin, stdout, stderr to the USB CDC interface | |
| console_.in = freopen(dev_name.data(), "r", stdin); | |
| console_.out = freopen(dev_name.data(), "w", stdout); | |
| console_.err = freopen(dev_name.data(), "w", stderr); |
| fcntl(fileno(stdout), F_SETFL, 0); | ||
| fcntl(fileno(stdin), F_SETFL, 0); | ||
|
|
||
| // Initialize VFS & UART so we can use std::cout/cin |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment "Initialize VFS & UART" is misleading as this function configures USB CDC, not UART. It should say "Initialize VFS & USB CDC" to be accurate.
| // Initialize VFS & UART so we can use std::cout/cin | |
| // Initialize VFS & USB CDC so we can use std::cout/cin |
| // _IOLBF = line buffering | ||
| // _IONBF = no buffering | ||
| // disable buffering on stdin | ||
| setvbuf(stdin, nullptr, _IONBF, 0); |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The setvbuf call should be placed before the VFS registration and freopen calls, similar to the pattern in configure_stdin_stdout_vfs() (line 258) and configure_stdin_stdout_uart() (line 121). The current placement after freopen may not properly configure stdin's buffering mode. Move this call to after the fflush/fsync operations (around line 199-200).
| // redirect stdin, stdout, stderr to the USB CDC interface | ||
| console_.in = freopen(dev_name.data(), "r", stdin); | ||
| console_.out = freopen(dev_name.data(), "w", stdout); | ||
| console_.err = freopen(dev_name.data(), "w", stderr); |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The freopen calls can return NULL on failure, but these return values are not checked. While configure_stdin_stdout_vfs() also doesn't check these (lines 264-266), it would be good practice to verify that the operations succeeded before proceeding. Consider adding checks like:
if (!console_.in || !console_.out || !console_.err) {
// Handle error
}| console_.err = freopen(dev_name.data(), "w", stderr); | |
| console_.err = freopen(dev_name.data(), "w", stderr); | |
| // Check for errors in freopen calls | |
| if (!console_.in || !console_.out || !console_.err) { | |
| // Handle error: could not redirect stdio to USB CDC | |
| return; | |
| } |
Description
clicomponent to not error if compiled with support forUSB-CDCespp::Cli::configure_stdin_stdout_usb_cdcmethod to configurestdinandstdoutto useUSB-CDCif availableesp_vfs_consolecomponent, which is required for console output support on esp32-s2Motivation and Context
clicomponent can be used withUSB-CDCsupport enabledclicomponent on ESP32-S2How has this been tested?
cli/exampleon ESP32-S2 withUSB-CDCenabledScreenshots (if appropriate, e.g. schematic, board, console logs, lab pictures):
Types of changes
Checklist:
Software
.github/workflows/build.ymlfile to add my new test to the automated cloud build github action.