mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-04 06:11:06 +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
 | 
			
		||||
#define LEAKS "800"
 | 
			
		||||
#elif CONFIG_IDF_TARGET_ESP32C3
 | 
			
		||||
#define LEAKS "600"
 | 
			
		||||
#define LEAKS "700"
 | 
			
		||||
#else
 | 
			
		||||
#error "unknown target in CXX tests, can't set leaks threshold"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -95,8 +95,30 @@ menu "Common ESP-related"
 | 
			
		||||
            bool "None"
 | 
			
		||||
    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
 | 
			
		||||
        # Internal option, indicates that console UART is used (and not USB, for example)
 | 
			
		||||
        bool
 | 
			
		||||
        default y if ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_CUSTOM
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -53,9 +53,7 @@
 | 
			
		||||
#include "esp_pm.h"
 | 
			
		||||
#include "esp_private/pm_impl.h"
 | 
			
		||||
#include "esp_pthread.h"
 | 
			
		||||
#include "esp_private/usb_console.h"
 | 
			
		||||
#include "esp_vfs_cdcacm.h"
 | 
			
		||||
#include "esp_vfs_usb_serial_jtag.h"
 | 
			
		||||
#include "esp_vfs_console.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."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define STRINGIFY(s) STRINGIFY2(s)
 | 
			
		||||
#define STRINGIFY2(s) #s
 | 
			
		||||
 | 
			
		||||
uint64_t g_startup_time = 0;
 | 
			
		||||
 | 
			
		||||
#if SOC_APB_BACKUP_DMA
 | 
			
		||||
@@ -273,23 +268,14 @@ static void do_core_init(void)
 | 
			
		||||
    esp_timer_early_init();
 | 
			
		||||
    esp_newlib_time_init();
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_VFS_SUPPORT_IO
 | 
			
		||||
#ifdef CONFIG_ESP_CONSOLE_UART
 | 
			
		||||
    esp_vfs_dev_uart_register();
 | 
			
		||||
    const char *default_stdio_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
 | 
			
		||||
#endif // CONFIG_ESP_CONSOLE_UART
 | 
			
		||||
#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 CONFIG_VFS_SUPPORT_IO
 | 
			
		||||
    // VFS console register.
 | 
			
		||||
    esp_err_t vfs_err = esp_vfs_console_register();
 | 
			
		||||
    assert(vfs_err == ESP_OK && "Failed to register vfs console");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE)
 | 
			
		||||
    const static char *default_stdio_dev = "/dev/console/";
 | 
			
		||||
    esp_reent_init(_GLOBAL_REENT);
 | 
			
		||||
    _GLOBAL_REENT->_stdin  = fopen(default_stdio_dev, "r");
 | 
			
		||||
    _GLOBAL_REENT->_stdout = fopen(default_stdio_dev, "w");
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,15 @@
 | 
			
		||||
idf_component_register(SRCS "vfs.c"
 | 
			
		||||
                            "vfs_uart.c"
 | 
			
		||||
                            "vfs_semihost.c"
 | 
			
		||||
                            "vfs_console.c"
 | 
			
		||||
                    PRIV_INCLUDE_DIRS private_include
 | 
			
		||||
                    INCLUDE_DIRS include)
 | 
			
		||||
 | 
			
		||||
if(CONFIG_ESP_CONSOLE_USB_CDC)
 | 
			
		||||
    target_sources(${COMPONENT_LIB} PRIVATE "vfs_cdcacm.c")
 | 
			
		||||
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")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
COMPONENT_PRIV_INCLUDEDIRS := private_include
 | 
			
		||||
ifndef CONFIG_ESP_CONSOLE_USB_CDC
 | 
			
		||||
    COMPONENT_OBJEXCLUDE := vfs_cdcacm.o
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
@@ -246,7 +246,6 @@ typedef struct
 | 
			
		||||
#endif // CONFIG_VFS_SUPPORT_SELECT
 | 
			
		||||
} esp_vfs_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Register a virtual filesystem for given path prefix.
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,8 @@
 | 
			
		||||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// 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.
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// 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.
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,8 @@
 | 
			
		||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// 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.
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#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/semphr.h"
 | 
			
		||||
#include "esp_vfs.h"
 | 
			
		||||
#include "esp_vfs_private.h"
 | 
			
		||||
#include "sdkconfig.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT
 | 
			
		||||
@@ -44,14 +45,6 @@ typedef struct {
 | 
			
		||||
    local_fd_t local_fd;
 | 
			
		||||
} 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 {
 | 
			
		||||
    bool isset; // none or at least one bit is set in the following 3 fd sets
 | 
			
		||||
    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 _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) {
 | 
			
		||||
        /* 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
        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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    ssize_t best_match_prefix_len = -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,8 @@
 | 
			
		||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// 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.
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
@@ -309,17 +301,23 @@ void esp_vfs_dev_cdcacm_set_rx_line_endings(esp_line_endings_t mode)
 | 
			
		||||
    s_rx_mode = mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const esp_vfs_t vfs = {
 | 
			
		||||
    .flags = ESP_VFS_FLAG_DEFAULT,
 | 
			
		||||
    .write = &cdcacm_write,
 | 
			
		||||
    .open = &cdcacm_open,
 | 
			
		||||
    .fstat = &cdcacm_fstat,
 | 
			
		||||
    .close = &cdcacm_close,
 | 
			
		||||
    .read = &cdcacm_read,
 | 
			
		||||
    .fcntl = &cdcacm_fcntl,
 | 
			
		||||
    .fsync = &cdcacm_fsync
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const esp_vfs_t *esp_vfs_cdcacm_get_vfs(void)
 | 
			
		||||
{
 | 
			
		||||
    return &vfs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
esp_err_t esp_vfs_dev_cdcacm_register(void)
 | 
			
		||||
{
 | 
			
		||||
    const esp_vfs_t vfs = {
 | 
			
		||||
        .flags = ESP_VFS_FLAG_DEFAULT,
 | 
			
		||||
        .write = &cdcacm_write,
 | 
			
		||||
        .open = &cdcacm_open,
 | 
			
		||||
        .fstat = &cdcacm_fstat,
 | 
			
		||||
        .close = &cdcacm_close,
 | 
			
		||||
        .read = &cdcacm_read,
 | 
			
		||||
        .fcntl = &cdcacm_fcntl,
 | 
			
		||||
        .fsync = &cdcacm_fsync
 | 
			
		||||
    };
 | 
			
		||||
    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
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// 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.
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
@@ -969,31 +961,37 @@ static int uart_tcflush(int fd, int select)
 | 
			
		||||
}
 | 
			
		||||
#endif // CONFIG_VFS_SUPPORT_TERMIOS
 | 
			
		||||
 | 
			
		||||
void esp_vfs_dev_uart_register(void)
 | 
			
		||||
{
 | 
			
		||||
    esp_vfs_t vfs = {
 | 
			
		||||
        .flags = ESP_VFS_FLAG_DEFAULT,
 | 
			
		||||
        .write = &uart_write,
 | 
			
		||||
        .open = &uart_open,
 | 
			
		||||
        .fstat = &uart_fstat,
 | 
			
		||||
        .close = &uart_close,
 | 
			
		||||
        .read = &uart_read,
 | 
			
		||||
        .fcntl = &uart_fcntl,
 | 
			
		||||
        .fsync = &uart_fsync,
 | 
			
		||||
static const esp_vfs_t vfs = {
 | 
			
		||||
    .flags = ESP_VFS_FLAG_DEFAULT,
 | 
			
		||||
    .write = &uart_write,
 | 
			
		||||
    .open = &uart_open,
 | 
			
		||||
    .fstat = &uart_fstat,
 | 
			
		||||
    .close = &uart_close,
 | 
			
		||||
    .read = &uart_read,
 | 
			
		||||
    .fcntl = &uart_fcntl,
 | 
			
		||||
    .fsync = &uart_fsync,
 | 
			
		||||
#ifdef CONFIG_VFS_SUPPORT_DIR
 | 
			
		||||
        .access = &uart_access,
 | 
			
		||||
    .access = &uart_access,
 | 
			
		||||
#endif // CONFIG_VFS_SUPPORT_DIR
 | 
			
		||||
#ifdef CONFIG_VFS_SUPPORT_SELECT
 | 
			
		||||
        .start_select = &uart_start_select,
 | 
			
		||||
        .end_select = &uart_end_select,
 | 
			
		||||
    .start_select = &uart_start_select,
 | 
			
		||||
    .end_select = &uart_end_select,
 | 
			
		||||
#endif // CONFIG_VFS_SUPPORT_SELECT
 | 
			
		||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
 | 
			
		||||
        .tcsetattr = &uart_tcsetattr,
 | 
			
		||||
        .tcgetattr = &uart_tcgetattr,
 | 
			
		||||
        .tcdrain = &uart_tcdrain,
 | 
			
		||||
        .tcflush = &uart_tcflush,
 | 
			
		||||
    .tcsetattr = &uart_tcsetattr,
 | 
			
		||||
    .tcgetattr = &uart_tcgetattr,
 | 
			
		||||
    .tcdrain = &uart_tcdrain,
 | 
			
		||||
    .tcflush = &uart_tcflush,
 | 
			
		||||
#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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,8 @@
 | 
			
		||||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// 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.
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
//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.
 | 
			
		||||
@@ -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)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t cc=(uint8_t)c;
 | 
			
		||||
    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);
 | 
			
		||||
                s_ctx.last_tx_ts = esp_timer_get_time();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
    // 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()) {
 | 
			
		||||
            usb_serial_jtag_ll_write_txfifo(&cc, 1);
 | 
			
		||||
            s_ctx.last_tx_ts = esp_timer_get_time();
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    } while ((esp_timer_get_time() - s_ctx.last_tx_ts) < TX_FLUSH_TIMEOUT_US);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int usb_serial_jtag_rx_char(int fd)
 | 
			
		||||
@@ -364,25 +354,30 @@ void esp_vfs_dev_usb_serial_jtag_set_rx_line_endings(esp_line_endings_t mode)
 | 
			
		||||
    s_ctx.rx_mode = mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const esp_vfs_t vfs = {
 | 
			
		||||
    .flags = ESP_VFS_FLAG_DEFAULT,
 | 
			
		||||
    .write = &usb_serial_jtag_write,
 | 
			
		||||
    .open = &usb_serial_jtag_open,
 | 
			
		||||
    .fstat = &usb_serial_jtag_fstat,
 | 
			
		||||
    .close = &usb_serial_jtag_close,
 | 
			
		||||
    .read = &usb_serial_jtag_read,
 | 
			
		||||
    .fcntl = &usb_serial_jtag_fcntl,
 | 
			
		||||
    .fsync = &usb_serial_jtag_fsync,
 | 
			
		||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
 | 
			
		||||
    .tcsetattr = &usb_serial_jtag_tcsetattr,
 | 
			
		||||
    .tcgetattr = &usb_serial_jtag_tcgetattr,
 | 
			
		||||
    .tcdrain = &usb_serial_jtag_tcdrain,
 | 
			
		||||
    .tcflush = &usb_serial_jtag_tcflush,
 | 
			
		||||
#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)
 | 
			
		||||
{
 | 
			
		||||
    esp_vfs_t vfs = {
 | 
			
		||||
        .flags = ESP_VFS_FLAG_DEFAULT,
 | 
			
		||||
        .write = &usb_serial_jtag_write,
 | 
			
		||||
        .open = &usb_serial_jtag_open,
 | 
			
		||||
        .fstat = &usb_serial_jtag_fstat,
 | 
			
		||||
        .close = &usb_serial_jtag_close,
 | 
			
		||||
        .read = &usb_serial_jtag_read,
 | 
			
		||||
        .fcntl = &usb_serial_jtag_fcntl,
 | 
			
		||||
        .fsync = &usb_serial_jtag_fsync,
 | 
			
		||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
 | 
			
		||||
        .tcsetattr = &usb_serial_jtag_tcsetattr,
 | 
			
		||||
        .tcgetattr = &usb_serial_jtag_tcgetattr,
 | 
			
		||||
        .tcdrain = &usb_serial_jtag_tcdrain,
 | 
			
		||||
        .tcflush = &usb_serial_jtag_tcflush,
 | 
			
		||||
#endif // CONFIG_VFS_SUPPORT_TERMIOS
 | 
			
		||||
    };
 | 
			
		||||
    // "/dev/usb_serial_jtag" unfortunately is too long for vfs
 | 
			
		||||
    return esp_vfs_register("/dev/usbserjtag", &vfs, NULL);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user