mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 13:09:38 +00:00 
			
		
		
		
	vfs_usb_serial: set secondary selection for making usb port can output under default menu
This commit is contained in:
		| @@ -57,7 +57,7 @@ TEST_CASE("can use std::vector", "[cxx]") | |||||||
| #elif CONFIG_IDF_TARGET_ESP32S2 | #elif CONFIG_IDF_TARGET_ESP32S2 | ||||||
| #define LEAKS "800" | #define LEAKS "800" | ||||||
| #elif CONFIG_IDF_TARGET_ESP32C3 | #elif CONFIG_IDF_TARGET_ESP32C3 | ||||||
| #define LEAKS "600" | #define LEAKS "700" | ||||||
| #else | #else | ||||||
| #error "unknown target in CXX tests, can't set leaks threshold" | #error "unknown target in CXX tests, can't set leaks threshold" | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -95,8 +95,30 @@ menu "Common ESP-related" | |||||||
|             bool "None" |             bool "None" | ||||||
|     endchoice |     endchoice | ||||||
|  |  | ||||||
|     # Internal option, indicates that console UART is used (and not USB, for example) |     choice ESP_CONSOLE_SECONDARY | ||||||
|  |         depends on IDF_TARGET_ESP32C3 | ||||||
|  |         prompt "Channel for console secondary output" | ||||||
|  |         default ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG | ||||||
|  |         help | ||||||
|  |             This secondary option supports output through other specific port like USB_SERIAL_JTAG | ||||||
|  |             when UART0 port as a primary is selected but not connected. This secondary output currently only supports | ||||||
|  |             non-blocking mode without using REPL. If you want to output in blocking mode with REPL or | ||||||
|  |             input through this secondary port, please change the primary config to this port | ||||||
|  |             in `Channel for console output` menu. | ||||||
|  |         config ESP_CONSOLE_SECONDARY_NONE | ||||||
|  |             bool "No secondary console" | ||||||
|  |         config ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG | ||||||
|  |             bool "USB_SERIAL_JTAG PORT" | ||||||
|  |             depends on !ESP_CONSOLE_USB_SERIAL_JTAG | ||||||
|  |             help | ||||||
|  |                 This option supports output through USB_SERIAL_JTAG port when the UART0 port is not connected. | ||||||
|  |                 The output currently only supports non-blocking mode without using the console. | ||||||
|  |                 If you want to output in blocking mode with REPL or input through USB_SERIAL_JTAG port, | ||||||
|  |                 please change the primary config to ESP_CONSOLE_USB_SERIAL_JTAG above. | ||||||
|  |     endchoice | ||||||
|  |  | ||||||
|     config ESP_CONSOLE_UART |     config ESP_CONSOLE_UART | ||||||
|  |         # Internal option, indicates that console UART is used (and not USB, for example) | ||||||
|         bool |         bool | ||||||
|         default y if ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_CUSTOM |         default y if ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_CUSTOM | ||||||
|  |  | ||||||
|   | |||||||
| @@ -53,9 +53,7 @@ | |||||||
| #include "esp_pm.h" | #include "esp_pm.h" | ||||||
| #include "esp_private/pm_impl.h" | #include "esp_private/pm_impl.h" | ||||||
| #include "esp_pthread.h" | #include "esp_pthread.h" | ||||||
| #include "esp_private/usb_console.h" | #include "esp_vfs_console.h" | ||||||
| #include "esp_vfs_cdcacm.h" |  | ||||||
| #include "esp_vfs_usb_serial_jtag.h" |  | ||||||
|  |  | ||||||
| #include "esp_rom_sys.h" | #include "esp_rom_sys.h" | ||||||
|  |  | ||||||
| @@ -86,9 +84,6 @@ | |||||||
|     #error "System has been configured to run on multiple cores, but target SoC only has a single core." |     #error "System has been configured to run on multiple cores, but target SoC only has a single core." | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define STRINGIFY(s) STRINGIFY2(s) |  | ||||||
| #define STRINGIFY2(s) #s |  | ||||||
|  |  | ||||||
| uint64_t g_startup_time = 0; | uint64_t g_startup_time = 0; | ||||||
|  |  | ||||||
| #if SOC_APB_BACKUP_DMA | #if SOC_APB_BACKUP_DMA | ||||||
| @@ -273,23 +268,14 @@ static void do_core_init(void) | |||||||
|     esp_timer_early_init(); |     esp_timer_early_init(); | ||||||
|     esp_newlib_time_init(); |     esp_newlib_time_init(); | ||||||
|  |  | ||||||
| #ifdef CONFIG_VFS_SUPPORT_IO | #if CONFIG_VFS_SUPPORT_IO | ||||||
| #ifdef CONFIG_ESP_CONSOLE_UART |     // VFS console register. | ||||||
|     esp_vfs_dev_uart_register(); |     esp_err_t vfs_err = esp_vfs_console_register(); | ||||||
|     const char *default_stdio_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM); |     assert(vfs_err == ESP_OK && "Failed to register vfs console"); | ||||||
| #endif // CONFIG_ESP_CONSOLE_UART | #endif | ||||||
| #ifdef CONFIG_ESP_CONSOLE_USB_CDC |  | ||||||
|     ESP_ERROR_CHECK(esp_usb_console_init()); |  | ||||||
|     ESP_ERROR_CHECK(esp_vfs_dev_cdcacm_register()); |  | ||||||
|     const char *default_stdio_dev = "/dev/cdcacm"; |  | ||||||
| #endif // CONFIG_ESP_CONSOLE_USB_CDC |  | ||||||
| #ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG |  | ||||||
|     ESP_ERROR_CHECK(esp_vfs_dev_usb_serial_jtag_register()); |  | ||||||
|     const char *default_stdio_dev = "/dev/usbserjtag"; |  | ||||||
| #endif // CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG |  | ||||||
| #endif // CONFIG_VFS_SUPPORT_IO |  | ||||||
|  |  | ||||||
| #if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE) | #if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE) | ||||||
|  |     const static char *default_stdio_dev = "/dev/console/"; | ||||||
|     esp_reent_init(_GLOBAL_REENT); |     esp_reent_init(_GLOBAL_REENT); | ||||||
|     _GLOBAL_REENT->_stdin  = fopen(default_stdio_dev, "r"); |     _GLOBAL_REENT->_stdin  = fopen(default_stdio_dev, "r"); | ||||||
|     _GLOBAL_REENT->_stdout = fopen(default_stdio_dev, "w"); |     _GLOBAL_REENT->_stdout = fopen(default_stdio_dev, "w"); | ||||||
|   | |||||||
| @@ -1,13 +1,15 @@ | |||||||
| idf_component_register(SRCS "vfs.c" | idf_component_register(SRCS "vfs.c" | ||||||
|                             "vfs_uart.c" |                             "vfs_uart.c" | ||||||
|                             "vfs_semihost.c" |                             "vfs_semihost.c" | ||||||
|  |                             "vfs_console.c" | ||||||
|  |                     PRIV_INCLUDE_DIRS private_include | ||||||
|                     INCLUDE_DIRS include) |                     INCLUDE_DIRS include) | ||||||
|  |  | ||||||
| if(CONFIG_ESP_CONSOLE_USB_CDC) | if(CONFIG_ESP_CONSOLE_USB_CDC) | ||||||
|     target_sources(${COMPONENT_LIB} PRIVATE "vfs_cdcacm.c") |     target_sources(${COMPONENT_LIB} PRIVATE "vfs_cdcacm.c") | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| if(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) | if(CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG OR CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) | ||||||
|     target_sources(${COMPONENT_LIB} PRIVATE "vfs_usb_serial_jtag.c") |     target_sources(${COMPONENT_LIB} PRIVATE "vfs_usb_serial_jtag.c") | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | COMPONENT_PRIV_INCLUDEDIRS := private_include | ||||||
| ifndef CONFIG_ESP_CONSOLE_USB_CDC | ifndef CONFIG_ESP_CONSOLE_USB_CDC | ||||||
|     COMPONENT_OBJEXCLUDE := vfs_cdcacm.o |     COMPONENT_OBJEXCLUDE := vfs_cdcacm.o | ||||||
| endif | endif | ||||||
|   | |||||||
| @@ -246,7 +246,6 @@ typedef struct | |||||||
| #endif // CONFIG_VFS_SUPPORT_SELECT | #endif // CONFIG_VFS_SUPPORT_SELECT | ||||||
| } esp_vfs_t; | } esp_vfs_t; | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Register a virtual filesystem for given path prefix. |  * Register a virtual filesystem for given path prefix. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -1,16 +1,8 @@ | |||||||
| // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD | /* | ||||||
| // |  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); |  * | ||||||
| // you may not use this file except in compliance with the License. |  * SPDX-License-Identifier: Apache-2.0 | ||||||
| // You may obtain a copy of the License at |  */ | ||||||
| // |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
| // |  | ||||||
| // Unless required by applicable law or agreed to in writing, software |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
| // See the License for the specific language governing permissions and |  | ||||||
| // limitations under the License. |  | ||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								components/vfs/include/esp_vfs_console.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								components/vfs/include/esp_vfs_console.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | /* | ||||||
|  |  * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD | ||||||
|  |  * | ||||||
|  |  * SPDX-License-Identifier: Apache-2.0 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esp_err.h" | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief add uart/usb_serial_jtag/usb_otg_acmcdc virtual filesystem driver | ||||||
|  |  * | ||||||
|  |  * This function is called from startup code to enable serial output | ||||||
|  |  */ | ||||||
|  | esp_err_t esp_vfs_console_register(void); | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
| @@ -1,16 +1,8 @@ | |||||||
| // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD | /* | ||||||
| // |  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); |  * | ||||||
| // you may not use this file except in compliance with the License. |  * SPDX-License-Identifier: Apache-2.0 | ||||||
| // You may obtain a copy of the License at |  */ | ||||||
| // |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
| // |  | ||||||
| // Unless required by applicable law or agreed to in writing, software |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
| // See the License for the specific language governing permissions and |  | ||||||
| // limitations under the License. |  | ||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,16 +1,8 @@ | |||||||
| // Copyright 2021 Espressif Systems (Shanghai) PTE LTD | /* | ||||||
| // |  * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); |  * | ||||||
| // you may not use this file except in compliance with the License. |  * SPDX-License-Identifier: Apache-2.0 | ||||||
| // You may obtain a copy of the License at |  */ | ||||||
| // |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
| // |  | ||||||
| // Unless required by applicable law or agreed to in writing, software |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
| // See the License for the specific language governing permissions and |  | ||||||
| // limitations under the License. |  | ||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										101
									
								
								components/vfs/private_include/esp_vfs_private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								components/vfs/private_include/esp_vfs_private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | /* | ||||||
|  |  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD | ||||||
|  |  * | ||||||
|  |  * SPDX-License-Identifier: Apache-2.0 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "esp_vfs.h" | ||||||
|  | #include "esp_vfs_common.h" | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | typedef struct vfs_entry_ { | ||||||
|  |     esp_vfs_t vfs;          // contains pointers to VFS functions | ||||||
|  |     char path_prefix[ESP_VFS_PATH_MAX]; // path prefix mapped to this VFS | ||||||
|  |     size_t path_prefix_len; // micro-optimization to avoid doing extra strlen | ||||||
|  |     void* ctx;              // optional pointer which can be passed to VFS | ||||||
|  |     int offset;             // index of this structure in s_vfs array | ||||||
|  | } vfs_entry_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief get pointer of uart vfs. | ||||||
|  |  * | ||||||
|  |  * This function is called in vfs_console in order to get the vfs implementation | ||||||
|  |  * of uart. | ||||||
|  |  * | ||||||
|  |  * @return pointer to structure esp_vfs_t | ||||||
|  |  */ | ||||||
|  | const esp_vfs_t *esp_vfs_uart_get_vfs(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief get pointer of cdcacm vfs. | ||||||
|  |  * | ||||||
|  |  * This function is called in vfs_console in order to get the vfs implementation | ||||||
|  |  * of cdcacm. | ||||||
|  |  * | ||||||
|  |  * @return pointer to structure esp_vfs_t | ||||||
|  |  */ | ||||||
|  | const esp_vfs_t *esp_vfs_cdcacm_get_vfs(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief get pointer of usb_serial_jtag vfs. | ||||||
|  |  * | ||||||
|  |  * This function is called in vfs_console in order to get the vfs implementation | ||||||
|  |  * of usb_serial_jtag. | ||||||
|  |  * | ||||||
|  |  * @return pointer to structure esp_vfs_nonblocking_console_t | ||||||
|  |  */ | ||||||
|  | const esp_vfs_t *esp_vfs_usb_serial_jtag_get_vfs(void); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Register a virtual filesystem. | ||||||
|  |  * | ||||||
|  |  * @param base_path  file path prefix associated with the filesystem. | ||||||
|  |  *                   Must be a zero-terminated C string, may be empty. | ||||||
|  |  *                   If not empty, must be up to ESP_VFS_PATH_MAX | ||||||
|  |  *                   characters long, and at least 2 characters long. | ||||||
|  |  *                   Name must start with a "/" and must not end with "/". | ||||||
|  |  *                   For example, "/data" or "/dev/spi" are valid. | ||||||
|  |  *                   These VFSes would then be called to handle file paths such as | ||||||
|  |  *                   "/data/myfile.txt" or "/dev/spi/0". | ||||||
|  |  *                   In the special case of an empty base_path, a "fallback" | ||||||
|  |  *                   VFS is registered. Such VFS will handle paths which are not | ||||||
|  |  *                   matched by any other registered VFS. | ||||||
|  |  * @param len  Length of the base_path. | ||||||
|  |  * @param vfs  Pointer to esp_vfs_t, a structure which maps syscalls to | ||||||
|  |  *             the filesystem driver functions. VFS component doesn't | ||||||
|  |  *             assume ownership of this pointer. | ||||||
|  |  * @param ctx  If vfs->flags has ESP_VFS_FLAG_CONTEXT_PTR set, a pointer | ||||||
|  |  *             which should be passed to VFS functions. Otherwise, NULL. | ||||||
|  |  * @param vfs_index Index for getting the vfs content. | ||||||
|  |  * | ||||||
|  |  * @return  ESP_OK if successful. | ||||||
|  |  *          ESP_ERR_NO_MEM if too many VFSes are registered. | ||||||
|  |  *          ESP_ERR_INVALID_ARG if given an invalid parameter. | ||||||
|  |  */ | ||||||
|  | esp_err_t esp_vfs_register_common(const char *base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get vfs fd with given path. | ||||||
|  |  * | ||||||
|  |  * @param path file path prefix associated with the filesystem. | ||||||
|  |  * | ||||||
|  |  * @return Pointer to the `vfs_entry_t` corresponding to the given path, which cannot be NULL. | ||||||
|  |  */ | ||||||
|  | const vfs_entry_t *get_vfs_for_path(const char *path); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get vfs fd with given vfs index. | ||||||
|  |  * | ||||||
|  |  * @param index VFS index. | ||||||
|  |  * | ||||||
|  |  * @return Pointer to the `vfs_entry_t` corresponding to the given path, which cannot be NULL. | ||||||
|  |  */ | ||||||
|  | const vfs_entry_t *get_vfs_for_index(int index); | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
| @@ -18,6 +18,7 @@ | |||||||
| #include "freertos/FreeRTOS.h" | #include "freertos/FreeRTOS.h" | ||||||
| #include "freertos/semphr.h" | #include "freertos/semphr.h" | ||||||
| #include "esp_vfs.h" | #include "esp_vfs.h" | ||||||
|  | #include "esp_vfs_private.h" | ||||||
| #include "sdkconfig.h" | #include "sdkconfig.h" | ||||||
|  |  | ||||||
| #ifdef CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT | #ifdef CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT | ||||||
| @@ -44,14 +45,6 @@ typedef struct { | |||||||
|     local_fd_t local_fd; |     local_fd_t local_fd; | ||||||
| } fd_table_t; | } fd_table_t; | ||||||
|  |  | ||||||
| typedef struct vfs_entry_ { |  | ||||||
|     esp_vfs_t vfs;          // contains pointers to VFS functions |  | ||||||
|     char path_prefix[ESP_VFS_PATH_MAX]; // path prefix mapped to this VFS |  | ||||||
|     size_t path_prefix_len; // micro-optimization to avoid doing extra strlen |  | ||||||
|     void* ctx;              // optional pointer which can be passed to VFS |  | ||||||
|     int offset;             // index of this structure in s_vfs array |  | ||||||
| } vfs_entry_t; |  | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     bool isset; // none or at least one bit is set in the following 3 fd sets |     bool isset; // none or at least one bit is set in the following 3 fd sets | ||||||
|     fd_set readfds; |     fd_set readfds; | ||||||
| @@ -65,7 +58,7 @@ static size_t s_vfs_count = 0; | |||||||
| static fd_table_t s_fd_table[MAX_FDS] = { [0 ... MAX_FDS-1] = FD_TABLE_ENTRY_UNUSED }; | static fd_table_t s_fd_table[MAX_FDS] = { [0 ... MAX_FDS-1] = FD_TABLE_ENTRY_UNUSED }; | ||||||
| static _lock_t s_fd_table_lock; | static _lock_t s_fd_table_lock; | ||||||
|  |  | ||||||
| static esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index) | esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index) | ||||||
| { | { | ||||||
|     if (len != LEN_PATH_PREFIX_IGNORED) { |     if (len != LEN_PATH_PREFIX_IGNORED) { | ||||||
|         /* empty prefix is allowed, "/" is not allowed */ |         /* empty prefix is allowed, "/" is not allowed */ | ||||||
| @@ -240,7 +233,7 @@ esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd) | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline const vfs_entry_t *get_vfs_for_index(int index) | const vfs_entry_t *get_vfs_for_index(int index) | ||||||
| { | { | ||||||
|     if (index < 0 || index >= s_vfs_count) { |     if (index < 0 || index >= s_vfs_count) { | ||||||
|         return NULL; |         return NULL; | ||||||
| @@ -285,7 +278,7 @@ static const char* translate_path(const vfs_entry_t* vfs, const char* src_path) | |||||||
|     return src_path + vfs->path_prefix_len; |     return src_path + vfs->path_prefix_len; | ||||||
| } | } | ||||||
|  |  | ||||||
| static const vfs_entry_t* get_vfs_for_path(const char* path) | const vfs_entry_t* get_vfs_for_path(const char* path) | ||||||
| { | { | ||||||
|     const vfs_entry_t* best_match = NULL; |     const vfs_entry_t* best_match = NULL; | ||||||
|     ssize_t best_match_prefix_len = -1; |     ssize_t best_match_prefix_len = -1; | ||||||
|   | |||||||
| @@ -1,16 +1,8 @@ | |||||||
| // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD | /* | ||||||
| // |  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); |  * | ||||||
| // you may not use this file except in compliance with the License. |  * SPDX-License-Identifier: Apache-2.0 | ||||||
| // You may obtain a copy of the License at |  */ | ||||||
| // |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
| // |  | ||||||
| // Unless required by applicable law or agreed to in writing, software |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
| // See the License for the specific language governing permissions and |  | ||||||
| // limitations under the License. |  | ||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| @@ -309,9 +301,7 @@ void esp_vfs_dev_cdcacm_set_rx_line_endings(esp_line_endings_t mode) | |||||||
|     s_rx_mode = mode; |     s_rx_mode = mode; | ||||||
| } | } | ||||||
|  |  | ||||||
| esp_err_t esp_vfs_dev_cdcacm_register(void) | static const esp_vfs_t vfs = { | ||||||
| { |  | ||||||
|     const esp_vfs_t vfs = { |  | ||||||
|     .flags = ESP_VFS_FLAG_DEFAULT, |     .flags = ESP_VFS_FLAG_DEFAULT, | ||||||
|     .write = &cdcacm_write, |     .write = &cdcacm_write, | ||||||
|     .open = &cdcacm_open, |     .open = &cdcacm_open, | ||||||
| @@ -320,6 +310,14 @@ esp_err_t esp_vfs_dev_cdcacm_register(void) | |||||||
|     .read = &cdcacm_read, |     .read = &cdcacm_read, | ||||||
|     .fcntl = &cdcacm_fcntl, |     .fcntl = &cdcacm_fcntl, | ||||||
|     .fsync = &cdcacm_fsync |     .fsync = &cdcacm_fsync | ||||||
|     }; | }; | ||||||
|  |  | ||||||
|  | const esp_vfs_t *esp_vfs_cdcacm_get_vfs(void) | ||||||
|  | { | ||||||
|  |     return &vfs; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t esp_vfs_dev_cdcacm_register(void) | ||||||
|  | { | ||||||
|     return esp_vfs_register("/dev/cdcacm", &vfs, NULL); |     return esp_vfs_register("/dev/cdcacm", &vfs, NULL); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										218
									
								
								components/vfs/vfs_console.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								components/vfs/vfs_console.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,218 @@ | |||||||
|  | /* | ||||||
|  |  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD | ||||||
|  |  * | ||||||
|  |  * SPDX-License-Identifier: Apache-2.0 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "esp_vfs_console.h" | ||||||
|  | #include "esp_rom_sys.h" | ||||||
|  | #include "esp_vfs_cdcacm.h" | ||||||
|  | #include "esp_vfs_private.h" | ||||||
|  | #include "esp_vfs_usb_serial_jtag.h" | ||||||
|  | #include "esp_vfs_dev.h" | ||||||
|  | #include "esp_private/usb_console.h" | ||||||
|  | #include "sdkconfig.h" | ||||||
|  |  | ||||||
|  | #define STRINGIFY(s) STRINGIFY2(s) | ||||||
|  | #define STRINGIFY2(s) #s | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This file is to concentrate all the vfs(UART, USB_SERIAL_JTAG, CDCACM) console into one single file. | ||||||
|  |  * Get the vfs information from their component (i.e. vfs_uart.c) through `esp_vfs_usb_xxx_get_console()`, | ||||||
|  |  * which can help us to output some string to two different ports(i.e both through uart and usb_serial_jtag). | ||||||
|  |  * Usually, we set a port as primary and another as secondary. For primary, it is used for all the features supported by each vfs implementation, | ||||||
|  |  * while the secondary is only used for output. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     int fd_primary; | ||||||
|  |     int fd_secondary; | ||||||
|  | } vfs_console_context_t; | ||||||
|  |  | ||||||
|  | #if CONFIG_VFS_SUPPORT_IO | ||||||
|  | // Primary register part. | ||||||
|  | #ifdef CONFIG_ESP_CONSOLE_UART | ||||||
|  | const static char *primary_path = "/dev/uart"; | ||||||
|  | #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG | ||||||
|  | const static char *primary_path = "/dev/usbserjtag"; | ||||||
|  | #elif CONFIG_ESP_CONSOLE_USB_CDC | ||||||
|  | const static char *primary_path = "/dev/cdcacm"; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // Secondary register part. | ||||||
|  | #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG | ||||||
|  | const static char *secondary_path = "/dev/secondary"; | ||||||
|  | static int secondary_vfs_index; | ||||||
|  | #endif // Secondary part | ||||||
|  |  | ||||||
|  | static int primary_vfs_index; | ||||||
|  |  | ||||||
|  | static vfs_console_context_t vfs_console= {0}; | ||||||
|  |  | ||||||
|  | int console_open(const char * path, int flags, int mode) | ||||||
|  | { | ||||||
|  | // Primary port open | ||||||
|  | #if CONFIG_ESP_CONSOLE_UART | ||||||
|  |     vfs_console.fd_primary = get_vfs_for_path(primary_path)->vfs.open("/"STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM), flags, mode); | ||||||
|  | #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG | ||||||
|  |     vfs_console.fd_primary = esp_vfs_usb_serial_jtag_get_vfs()->open("/", flags, mode); | ||||||
|  | #elif CONFIG_ESP_CONSOLE_USB_CDC | ||||||
|  |     vfs_console.fd_primary = esp_vfs_cdcacm_get_vfs()->open("/", flags, mode); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // Secondary port open | ||||||
|  | #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG | ||||||
|  |     vfs_console.fd_secondary = get_vfs_for_path(secondary_path)->vfs.open("/", flags, mode); | ||||||
|  | #endif | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ssize_t console_write(int fd, const void *data, size_t size) | ||||||
|  | { | ||||||
|  |     // All function calls are to primary, except from write and close, which will be forwarded to both primary and secondary. | ||||||
|  |     get_vfs_for_index(primary_vfs_index)->vfs.write(vfs_console.fd_primary, data, size); | ||||||
|  | #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG | ||||||
|  |     get_vfs_for_index(secondary_vfs_index)->vfs.write(vfs_console.fd_secondary, data, size); | ||||||
|  | #endif | ||||||
|  |     return size; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int console_fstat(int fd, struct stat * st) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.fstat(fd, st); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int console_close(int fd) | ||||||
|  | { | ||||||
|  |     // All function calls are to primary, except from write and close, which will be forwarded to both primary and secondary. | ||||||
|  |     get_vfs_for_index(primary_vfs_index)->vfs.close(vfs_console.fd_primary); | ||||||
|  | #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG | ||||||
|  |     get_vfs_for_index(secondary_vfs_index)->vfs.close(vfs_console.fd_secondary); | ||||||
|  | #endif | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ssize_t console_read(int fd, void * dst, size_t size) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.read(vfs_console.fd_primary, dst, size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int console_fcntl(int fd, int cmd, int arg) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.fcntl(vfs_console.fd_primary, cmd, arg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int console_fsync(int fd) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.fsync(vfs_console.fd_primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifdef CONFIG_VFS_SUPPORT_DIR | ||||||
|  | int console_access(const char *path, int amode) | ||||||
|  | { | ||||||
|  |     // currently only UART support DIR. | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.access("/"STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM), amode); | ||||||
|  | } | ||||||
|  | #endif // CONFIG_VFS_SUPPORT_DIR | ||||||
|  |  | ||||||
|  | #ifdef CONFIG_VFS_SUPPORT_SELECT | ||||||
|  | static esp_err_t console_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, | ||||||
|  |         esp_vfs_select_sem_t select_sem, void **end_select_args) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.start_select(nfds, readfds, writefds, exceptfds, select_sem, end_select_args); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t console_end_select(void *end_select_args) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.end_select(end_select_args); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif // CONFIG_VFS_SUPPORT_SELECT | ||||||
|  |  | ||||||
|  | #ifdef CONFIG_VFS_SUPPORT_TERMIOS | ||||||
|  |  | ||||||
|  | int console_tcsetattr(int fd, int optional_actions, const struct termios *p) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.tcsetattr(vfs_console.fd_primary, optional_actions, p); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int console_tcgetattr(int fd, struct termios *p) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.tcgetattr(vfs_console.fd_primary, p); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int console_tcdrain(int fd) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.tcdrain(vfs_console.fd_primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int console_tcflush(int fd, int select) | ||||||
|  | { | ||||||
|  |     return get_vfs_for_index(primary_vfs_index)->vfs.tcflush(vfs_console.fd_primary, select); | ||||||
|  | } | ||||||
|  | #endif // CONFIG_VFS_SUPPORT_TERMIOS | ||||||
|  |  | ||||||
|  | static const esp_vfs_t vfs = { | ||||||
|  |     .flags = ESP_VFS_FLAG_DEFAULT, | ||||||
|  |     .write = &console_write, | ||||||
|  |     .open = &console_open, | ||||||
|  |     .fstat = &console_fstat, | ||||||
|  |     .close = &console_close, | ||||||
|  |     .read = &console_read, | ||||||
|  |     .fcntl = &console_fcntl, | ||||||
|  |     .fsync = &console_fsync, | ||||||
|  | #ifdef CONFIG_VFS_SUPPORT_DIR | ||||||
|  |     .access = &console_access, | ||||||
|  | #endif // CONFIG_VFS_SUPPORT_DIR | ||||||
|  | #ifdef CONFIG_VFS_SUPPORT_SELECT | ||||||
|  |     .start_select = &console_start_select, | ||||||
|  |     .end_select = &console_end_select, | ||||||
|  | #endif // CONFIG_VFS_SUPPORT_SELECT | ||||||
|  | #ifdef CONFIG_VFS_SUPPORT_TERMIOS | ||||||
|  |     .tcsetattr = &console_tcsetattr, | ||||||
|  |     .tcgetattr = &console_tcgetattr, | ||||||
|  |     .tcdrain = &console_tcdrain, | ||||||
|  |     .tcflush = &console_tcflush, | ||||||
|  | #endif // CONFIG_VFS_SUPPORT_TERMIOS | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | esp_err_t esp_vfs_dev_console_register(void) | ||||||
|  | { | ||||||
|  |     return esp_vfs_register("/dev/console", &vfs, NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t esp_vfs_console_register(void) | ||||||
|  | { | ||||||
|  |     esp_err_t err = ESP_OK; | ||||||
|  | // Primary register part. | ||||||
|  | #ifdef CONFIG_ESP_CONSOLE_UART | ||||||
|  |     const esp_vfs_t *uart_vfs = esp_vfs_uart_get_vfs(); | ||||||
|  |     err = esp_vfs_register_common(primary_path, strlen(primary_path), uart_vfs, NULL, &primary_vfs_index); | ||||||
|  | #elif CONFIG_ESP_CONSOLE_USB_CDC | ||||||
|  |     const esp_vfs_t *cdcacm_vfs = esp_vfs_cdcacm_get_vfs(); | ||||||
|  |     err = esp_usb_console_init(); | ||||||
|  |     if (err != ESP_OK) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |     err = esp_vfs_register_common(primary_path, strlen(primary_path), cdcacm_vfs, NULL, &primary_vfs_index); | ||||||
|  | #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG | ||||||
|  |     const esp_vfs_t *usb_serial_jtag_vfs = esp_vfs_usb_serial_jtag_get_vfs(); | ||||||
|  |     err = esp_vfs_register_common(primary_path, strlen(primary_path), usb_serial_jtag_vfs, NULL, &primary_vfs_index); | ||||||
|  | #endif // CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG | ||||||
|  |     if (err != ESP_OK) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | // Secondary register part. | ||||||
|  | #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG | ||||||
|  |     const esp_vfs_t *usb_serial_jtag_vfs = esp_vfs_usb_serial_jtag_get_vfs(); | ||||||
|  |     err = esp_vfs_register_common(secondary_path, strlen(secondary_path), usb_serial_jtag_vfs, NULL, &secondary_vfs_index); | ||||||
|  |     if(err != ESP_OK) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     err = esp_vfs_dev_console_register(); | ||||||
|  |     return err; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif // CONFIG_VFS_SUPPORT_IO | ||||||
| @@ -1,16 +1,8 @@ | |||||||
| // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD | /* | ||||||
| // |  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); |  * | ||||||
| // you may not use this file except in compliance with the License. |  * SPDX-License-Identifier: Apache-2.0 | ||||||
| // You may obtain a copy of the License at |  */ | ||||||
| // |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
| // |  | ||||||
| // Unless required by applicable law or agreed to in writing, software |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
| // See the License for the specific language governing permissions and |  | ||||||
| // limitations under the License. |  | ||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| @@ -969,9 +961,7 @@ static int uart_tcflush(int fd, int select) | |||||||
| } | } | ||||||
| #endif // CONFIG_VFS_SUPPORT_TERMIOS | #endif // CONFIG_VFS_SUPPORT_TERMIOS | ||||||
|  |  | ||||||
| void esp_vfs_dev_uart_register(void) | static const esp_vfs_t vfs = { | ||||||
| { |  | ||||||
|     esp_vfs_t vfs = { |  | ||||||
|     .flags = ESP_VFS_FLAG_DEFAULT, |     .flags = ESP_VFS_FLAG_DEFAULT, | ||||||
|     .write = &uart_write, |     .write = &uart_write, | ||||||
|     .open = &uart_open, |     .open = &uart_open, | ||||||
| @@ -993,7 +983,15 @@ void esp_vfs_dev_uart_register(void) | |||||||
|     .tcdrain = &uart_tcdrain, |     .tcdrain = &uart_tcdrain, | ||||||
|     .tcflush = &uart_tcflush, |     .tcflush = &uart_tcflush, | ||||||
| #endif // CONFIG_VFS_SUPPORT_TERMIOS | #endif // CONFIG_VFS_SUPPORT_TERMIOS | ||||||
|     }; | }; | ||||||
|  |  | ||||||
|  | const esp_vfs_t* esp_vfs_uart_get_vfs(void) | ||||||
|  | { | ||||||
|  |     return &vfs; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void esp_vfs_dev_uart_register(void) | ||||||
|  | { | ||||||
|     ESP_ERROR_CHECK(esp_vfs_register("/dev/uart", &vfs, NULL)); |     ESP_ERROR_CHECK(esp_vfs_register("/dev/uart", &vfs, NULL)); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,16 +1,8 @@ | |||||||
| // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD | /* | ||||||
| // |  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); |  * | ||||||
| // you may not use this file except in compliance with the License. |  * SPDX-License-Identifier: Apache-2.0 | ||||||
| // You may obtain a copy of the License at |  */ | ||||||
| // |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
| // |  | ||||||
| // Unless required by applicable law or agreed to in writing, software |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
| // See the License for the specific language governing permissions and |  | ||||||
| // limitations under the License. |  | ||||||
|  |  | ||||||
| //This is a simple non-blocking (well, tx may spin for a bit if the buffer | //This is a simple non-blocking (well, tx may spin for a bit if the buffer | ||||||
| //is full) USB-serial-jtag driver. Select etc is not supported yet. | //is full) USB-serial-jtag driver. Select etc is not supported yet. | ||||||
| @@ -113,23 +105,21 @@ static int usb_serial_jtag_open(const char * path, int flags, int mode) | |||||||
| static void usb_serial_jtag_tx_char(int fd, int c) | static void usb_serial_jtag_tx_char(int fd, int c) | ||||||
| { | { | ||||||
|     uint8_t cc=(uint8_t)c; |     uint8_t cc=(uint8_t)c; | ||||||
|  |     // Try to write to the buffer as long as we still expect the buffer to have | ||||||
|  |     // a chance of being emptied by an active host. Just drop the data if there's | ||||||
|  |     // no chance anymore. | ||||||
|  |     // When we first try to send a character and the buffer is not accessible yet, | ||||||
|  |     // we wait until the time has been more than TX_FLUSH_TIMEOUT_US since we successfully | ||||||
|  |     // sent the last byte. If it takes longer than TX_FLUSH_TIMEOUT_US, we drop every | ||||||
|  |     // byte until the buffer can be accessible again. | ||||||
|  |     do { | ||||||
|         if (usb_serial_jtag_ll_txfifo_writable()) { |         if (usb_serial_jtag_ll_txfifo_writable()) { | ||||||
|         //We can write to the buffer. Immediately do so. |  | ||||||
|         usb_serial_jtag_ll_write_txfifo(&cc, 1); |  | ||||||
|         s_ctx.last_tx_ts = esp_timer_get_time(); |  | ||||||
|     } else { |  | ||||||
|         //Try to write to the buffer as long as we still expect the buffer to have |  | ||||||
|         //a chance of being emptied by an active host. Just drop the data if there's |  | ||||||
|         //no chance anymore. |  | ||||||
|         while ((esp_timer_get_time() - s_ctx.last_tx_ts) < TX_FLUSH_TIMEOUT_US) { |  | ||||||
|             if (usb_serial_jtag_ll_txfifo_writable()) { |  | ||||||
|                 //Woohoo, we can write again. Do so and exit the while loop. |  | ||||||
|             usb_serial_jtag_ll_write_txfifo(&cc, 1); |             usb_serial_jtag_ll_write_txfifo(&cc, 1); | ||||||
|             s_ctx.last_tx_ts = esp_timer_get_time(); |             s_ctx.last_tx_ts = esp_timer_get_time(); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         } |     } while ((esp_timer_get_time() - s_ctx.last_tx_ts) < TX_FLUSH_TIMEOUT_US); | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int usb_serial_jtag_rx_char(int fd) | static int usb_serial_jtag_rx_char(int fd) | ||||||
| @@ -364,10 +354,7 @@ void esp_vfs_dev_usb_serial_jtag_set_rx_line_endings(esp_line_endings_t mode) | |||||||
|     s_ctx.rx_mode = mode; |     s_ctx.rx_mode = mode; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static const esp_vfs_t vfs = { | ||||||
| esp_err_t esp_vfs_dev_usb_serial_jtag_register(void) |  | ||||||
| { |  | ||||||
|     esp_vfs_t vfs = { |  | ||||||
|     .flags = ESP_VFS_FLAG_DEFAULT, |     .flags = ESP_VFS_FLAG_DEFAULT, | ||||||
|     .write = &usb_serial_jtag_write, |     .write = &usb_serial_jtag_write, | ||||||
|     .open = &usb_serial_jtag_open, |     .open = &usb_serial_jtag_open, | ||||||
| @@ -382,7 +369,15 @@ esp_err_t esp_vfs_dev_usb_serial_jtag_register(void) | |||||||
|     .tcdrain = &usb_serial_jtag_tcdrain, |     .tcdrain = &usb_serial_jtag_tcdrain, | ||||||
|     .tcflush = &usb_serial_jtag_tcflush, |     .tcflush = &usb_serial_jtag_tcflush, | ||||||
| #endif // CONFIG_VFS_SUPPORT_TERMIOS | #endif // CONFIG_VFS_SUPPORT_TERMIOS | ||||||
|     }; | }; | ||||||
|  |  | ||||||
|  | const esp_vfs_t* esp_vfs_usb_serial_jtag_get_vfs(void) | ||||||
|  | { | ||||||
|  |     return &vfs; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | esp_err_t esp_vfs_dev_usb_serial_jtag_register(void) | ||||||
|  | { | ||||||
|     // "/dev/usb_serial_jtag" unfortunately is too long for vfs |     // "/dev/usb_serial_jtag" unfortunately is too long for vfs | ||||||
|     return esp_vfs_register("/dev/usbserjtag", &vfs, NULL); |     return esp_vfs_register("/dev/usbserjtag", &vfs, NULL); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Cao Sen Miao
					Cao Sen Miao