mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-17 20:42:21 +02:00
esp-modem(VFS): Reworked decouple resources from the file system
This commit is contained in:
@ -14,43 +14,29 @@
|
||||
|
||||
#include <optional>
|
||||
#include <unistd.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include "cxx_include/esp_modem_dte.hpp"
|
||||
#include "esp_log.h"
|
||||
#include "esp_modem_config.h"
|
||||
#include "exception_stub.hpp"
|
||||
#include "uart_resource.hpp" // In case of VFS using UART
|
||||
|
||||
static const char *TAG = "fs_terminal";
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
class Resource {
|
||||
public:
|
||||
explicit Resource(const esp_modem_dte_config *config, int fd):
|
||||
uart(config->vfs_config.resource == ESP_MODEM_VFS_IS_EXTERN? std::nullopt : std::make_optional<uart_resource>(config, nullptr, fd))
|
||||
{}
|
||||
|
||||
std::optional<uart_resource> uart;
|
||||
};
|
||||
|
||||
struct File {
|
||||
explicit File(const char *name): fd(-1)
|
||||
{
|
||||
fd = open(name, O_RDWR);
|
||||
throw_if_false(fd >= 0, "Cannot open the fd");
|
||||
|
||||
// Set the FD to non-blocking mode
|
||||
int flags = fcntl(fd, F_GETFL, nullptr) | O_NONBLOCK;
|
||||
fcntl(fd, F_SETFL, flags);
|
||||
}
|
||||
explicit File(const esp_modem_dte_config *config):
|
||||
fd(config->vfs_config.fd), deleter(config->vfs_config.deleter), resource(config->vfs_config.resource)
|
||||
{}
|
||||
|
||||
~File() {
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
if (deleter) {
|
||||
deleter(fd, resource);
|
||||
}
|
||||
}
|
||||
int fd;
|
||||
void (*deleter)(int fd, struct esp_modem_vfs_resource *res);
|
||||
struct esp_modem_vfs_resource *resource;
|
||||
};
|
||||
|
||||
class FdTerminal : public Terminal {
|
||||
@ -85,7 +71,6 @@ private:
|
||||
static const size_t TASK_PARAMS = SignalGroup::bit3;
|
||||
|
||||
File f;
|
||||
Resource resource;
|
||||
SignalGroup signal;
|
||||
Task task_handle;
|
||||
};
|
||||
@ -99,7 +84,7 @@ std::unique_ptr<Terminal> create_vfs_terminal(const esp_modem_dte_config *config
|
||||
}
|
||||
|
||||
FdTerminal::FdTerminal(const esp_modem_dte_config *config) :
|
||||
f(config->vfs_config.dev_name), resource(config, f.fd), signal(),
|
||||
f(config), signal(),
|
||||
task_handle(config->task_stack_size, config->task_priority, this, [](void* p){
|
||||
auto t = static_cast<FdTerminal *>(p);
|
||||
t->task();
|
||||
|
@ -25,51 +25,51 @@ uart_resource::~uart_resource()
|
||||
}
|
||||
}
|
||||
|
||||
uart_resource::uart_resource(const esp_modem_dte_config *config, QueueHandle_t* event_queue, int fd)
|
||||
uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t* event_queue, int fd)
|
||||
:port(-1)
|
||||
{
|
||||
esp_err_t res;
|
||||
|
||||
/* Config UART */
|
||||
uart_config_t uart_config = {};
|
||||
uart_config.baud_rate = config->uart_config.baud_rate;
|
||||
uart_config.data_bits = config->uart_config.data_bits;
|
||||
uart_config.parity = config->uart_config.parity;
|
||||
uart_config.stop_bits = config->uart_config.stop_bits;
|
||||
uart_config.flow_ctrl = (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS
|
||||
uart_config.baud_rate = config->baud_rate;
|
||||
uart_config.data_bits = config->data_bits;
|
||||
uart_config.parity = config->parity;
|
||||
uart_config.stop_bits = config->stop_bits;
|
||||
uart_config.flow_ctrl = (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS
|
||||
: UART_HW_FLOWCTRL_DISABLE;
|
||||
uart_config.source_clk = UART_SCLK_APB;
|
||||
|
||||
throw_if_esp_fail(uart_param_config(config->uart_config.port_num, &uart_config), "config uart parameter failed");
|
||||
throw_if_esp_fail(uart_param_config(config->port_num, &uart_config), "config uart parameter failed");
|
||||
|
||||
if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
res = uart_set_pin(config->uart_config.port_num, config->uart_config.tx_io_num, config->uart_config.rx_io_num,
|
||||
config->uart_config.rts_io_num, config->uart_config.cts_io_num);
|
||||
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
res = uart_set_pin(config->port_num, config->tx_io_num, config->rx_io_num,
|
||||
config->rts_io_num, config->cts_io_num);
|
||||
} else {
|
||||
res = uart_set_pin(config->uart_config.port_num, config->uart_config.tx_io_num, config->uart_config.rx_io_num,
|
||||
res = uart_set_pin(config->port_num, config->tx_io_num, config->rx_io_num,
|
||||
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
}
|
||||
throw_if_esp_fail(res, "config uart gpio failed");
|
||||
/* Set flow control threshold */
|
||||
if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
res = uart_set_hw_flow_ctrl(config->uart_config.port_num, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8);
|
||||
} else if (config->uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_SW) {
|
||||
res = uart_set_sw_flow_ctrl(config->uart_config.port_num, true, 8, UART_FIFO_LEN - 8);
|
||||
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||
res = uart_set_hw_flow_ctrl(config->port_num, UART_HW_FLOWCTRL_CTS_RTS, UART_FIFO_LEN - 8);
|
||||
} else if (config->flow_control == ESP_MODEM_FLOW_CONTROL_SW) {
|
||||
res = uart_set_sw_flow_ctrl(config->port_num, true, 8, UART_FIFO_LEN - 8);
|
||||
}
|
||||
throw_if_esp_fail(res, "config uart flow control failed");
|
||||
|
||||
/* Install UART driver and get event queue used inside driver */
|
||||
res = uart_driver_install(config->uart_config.port_num,
|
||||
config->uart_config.rx_buffer_size, config->uart_config.tx_buffer_size,
|
||||
config->uart_config.event_queue_size, config->uart_config.event_queue_size ? event_queue : nullptr,
|
||||
res = uart_driver_install(config->port_num,
|
||||
config->rx_buffer_size, config->tx_buffer_size,
|
||||
config->event_queue_size, config->event_queue_size ? event_queue : nullptr,
|
||||
0);
|
||||
throw_if_esp_fail(res, "install uart driver failed");
|
||||
throw_if_esp_fail(uart_set_rx_timeout(config->uart_config.port_num, 1), "set rx timeout failed");
|
||||
throw_if_esp_fail(uart_set_rx_timeout(config->port_num, 1), "set rx timeout failed");
|
||||
|
||||
throw_if_esp_fail(uart_set_rx_full_threshold(config->uart_config.port_num, 64), "config rx full threshold failed");
|
||||
throw_if_esp_fail(uart_set_rx_full_threshold(config->port_num, 64), "config rx full threshold failed");
|
||||
|
||||
/* mark UART as initialized */
|
||||
port = config->uart_config.port_num;
|
||||
port = config->port_num;
|
||||
}
|
||||
|
||||
} // namespace esp_modem
|
||||
|
@ -47,7 +47,7 @@ struct uart_task {
|
||||
class UartTerminal : public Terminal {
|
||||
public:
|
||||
explicit UartTerminal(const esp_modem_dte_config *config) :
|
||||
event_queue(), uart(config, &event_queue, -1), signal(),
|
||||
event_queue(), uart(&config->uart_config, &event_queue, -1), signal(),
|
||||
task_handle(config->task_stack_size, config->task_priority, this, s_task) {}
|
||||
|
||||
~UartTerminal() override = default;
|
||||
|
@ -23,7 +23,7 @@ namespace esp_modem {
|
||||
|
||||
constexpr const char *TAG = "uart_resource";
|
||||
|
||||
uart_resource::uart_resource(const esp_modem_dte_config *config, QueueHandle_t* event_queue, int fd): port(-1)
|
||||
uart_resource::uart_resource(const esp_modem_uart_term_config *config, QueueHandle_t* event_queue, int fd): port(-1)
|
||||
{
|
||||
ESP_LOGD(TAG, "Creating uart resource" );
|
||||
struct termios tty = {};
|
||||
|
104
components/esp_modem/src/esp_modem_vfs_socket_creator.cpp
Normal file
104
components/esp_modem/src/esp_modem_vfs_socket_creator.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
// 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.
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_modem_config.h"
|
||||
#include "cxx_include/esp_modem_exception.hpp"
|
||||
#include "exception_stub.hpp"
|
||||
#include "uart_resource.hpp"
|
||||
#include "vfs_resource/vfs_create.hpp"
|
||||
|
||||
|
||||
constexpr const char *TAG = "vfs_socket_creator";
|
||||
|
||||
/**
|
||||
* @brief socket VFS
|
||||
* @note: Remote command:
|
||||
* socat TCP-L:2222 GOPEN:/dev/ttyS0,ispeed=115200,ospeed=1152000,b115200,raw,echo=0
|
||||
*/
|
||||
static esp_err_t hostname_to_fd(const char *host, int port, int* fd)
|
||||
{
|
||||
struct sockaddr_storage address = {};
|
||||
struct addrinfo *address_info;
|
||||
struct addrinfo hints = {};
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
int res = getaddrinfo(host, nullptr, &hints, &address_info);
|
||||
if (res != 0 || address_info == nullptr) {
|
||||
ESP_LOGE(TAG, "couldn't get hostname for :%s: "
|
||||
"getaddrinfo() returns %d, addrinfo=%p", host, res, address_info);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
*fd = socket(address_info->ai_family, address_info->ai_socktype, address_info->ai_protocol);
|
||||
if (*fd < 0) {
|
||||
ESP_LOGE(TAG, "Failed to create socket (family %d socktype %d protocol %d)", address_info->ai_family, address_info->ai_socktype, address_info->ai_protocol);
|
||||
freeaddrinfo(address_info);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (address_info->ai_family == AF_INET) {
|
||||
auto *p = reinterpret_cast<struct sockaddr_in *>(address_info->ai_addr);
|
||||
p->sin_port = htons(port);
|
||||
ESP_LOGI(TAG, "[sock=%d] Resolved IPv4 address: %s", *fd, inet_ntoa(p->sin_addr));
|
||||
memcpy(&address, p, sizeof(struct sockaddr ));
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unsupported protocol family %d", address_info->ai_family);
|
||||
close(*fd);
|
||||
freeaddrinfo(address_info);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
freeaddrinfo(address_info);
|
||||
if (connect(*fd, (struct sockaddr *)&address, sizeof(struct sockaddr)) < 0) {
|
||||
ESP_LOGE(TAG, "[sock=%d] Failed to connect", *fd);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static void vfs_destroy_socket(int fd, struct esp_modem_vfs_resource * resource)
|
||||
{
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
bool vfs_create_socket(struct esp_modem_vfs_socket_creator *config, struct esp_modem_vfs_term_config *created_config)
|
||||
{
|
||||
if (config == nullptr || created_config == nullptr) {
|
||||
return false;
|
||||
}
|
||||
TRY_CATCH_OR_DO(
|
||||
int fd = -1;
|
||||
esp_modem::throw_if_esp_fail(hostname_to_fd(config->host_name, config->port, &fd));
|
||||
|
||||
// Set the FD to non-blocking mode
|
||||
int flags = fcntl(fd, F_GETFL, nullptr) | O_NONBLOCK;
|
||||
fcntl(fd, F_SETFL, flags);
|
||||
|
||||
created_config->fd = fd;
|
||||
created_config->deleter = vfs_destroy_socket;
|
||||
, return false)
|
||||
return true;
|
||||
}
|
64
components/esp_modem/src/esp_modem_vfs_uart_creator.cpp
Normal file
64
components/esp_modem/src/esp_modem_vfs_uart_creator.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// 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.
|
||||
|
||||
#include <optional>
|
||||
#include <unistd.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_modem_config.h"
|
||||
#include "cxx_include/esp_modem_exception.hpp"
|
||||
#include "exception_stub.hpp"
|
||||
#include "uart_resource.hpp"
|
||||
#include "vfs_resource/vfs_create.hpp"
|
||||
|
||||
constexpr const char *TAG = "vfs_uart_creator";
|
||||
|
||||
|
||||
struct esp_modem_vfs_resource {
|
||||
explicit esp_modem_vfs_resource(const esp_modem_uart_term_config *config, int fd)
|
||||
: internal(config, nullptr, fd) {}
|
||||
|
||||
esp_modem::uart_resource internal;
|
||||
};
|
||||
|
||||
|
||||
static void vfs_destroy_uart(int fd, struct esp_modem_vfs_resource * resource)
|
||||
{
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
delete resource;
|
||||
}
|
||||
|
||||
bool vfs_create_uart(struct esp_modem_vfs_uart_creator *config, struct esp_modem_vfs_term_config *created_config)
|
||||
{
|
||||
if (!config->dev_name || created_config == nullptr) {
|
||||
return false;
|
||||
}
|
||||
TRY_CATCH_OR_DO(
|
||||
int fd = open(config->dev_name, O_RDWR);
|
||||
esp_modem::throw_if_false(fd >= 0, "Cannot open the fd");
|
||||
|
||||
created_config->resource = new esp_modem_vfs_resource(&config->uart, fd);
|
||||
created_config->fd = fd;
|
||||
created_config->deleter = vfs_destroy_uart;
|
||||
|
||||
// Set the FD to non-blocking mode
|
||||
int flags = fcntl(fd, F_GETFL, nullptr) | O_NONBLOCK;
|
||||
fcntl(fd, F_SETFL, flags);
|
||||
|
||||
, return false)
|
||||
|
||||
return true;
|
||||
}
|
Reference in New Issue
Block a user