mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-20 14:02:21 +02:00
fix(esp_modem): Implement movable unique_buffer to bundle data, size, ptr
Also improves and fixes tests
This commit is contained in:
@ -0,0 +1,50 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
/**
|
||||
* Common unique buffer, which is transferable between DTE and CMUX
|
||||
*
|
||||
*/
|
||||
struct unique_buffer {
|
||||
explicit unique_buffer(size_t size);
|
||||
unique_buffer (unique_buffer const&) = delete;
|
||||
unique_buffer& operator=(unique_buffer const&) = delete;
|
||||
unique_buffer(unique_buffer&& other) noexcept
|
||||
{
|
||||
data = std::move(other.data);
|
||||
size = other.size;
|
||||
consumed = 0;
|
||||
}
|
||||
unique_buffer& operator=(unique_buffer&& other) noexcept
|
||||
{
|
||||
if (&other == this) {
|
||||
return *this;
|
||||
}
|
||||
data = std::move(other.data);
|
||||
size = other.size;
|
||||
consumed = 0;
|
||||
return *this;
|
||||
}
|
||||
[[nodiscard]] uint8_t *get() const { return data.get(); }
|
||||
|
||||
std::unique_ptr<uint8_t[]> data;
|
||||
size_t size{};
|
||||
size_t consumed{};
|
||||
};
|
||||
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_modem_terminal.hpp"
|
||||
#include "cxx_include/esp_modem_buffer.hpp"
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
@ -54,8 +55,8 @@ class CMuxInstance;
|
||||
*/
|
||||
class CMux {
|
||||
public:
|
||||
explicit CMux(std::shared_ptr<Terminal> t, std::unique_ptr<uint8_t[]> b, size_t buff_size):
|
||||
term(std::move(t)), payload_start(nullptr), total_payload_size(0), buffer_size(buff_size), buffer(std::move(b)) {}
|
||||
explicit CMux(std::shared_ptr<Terminal> t, unique_buffer&& b):
|
||||
term(std::move(t)), payload_start(nullptr), total_payload_size(0), buffer(std::move(b)) {}
|
||||
~CMux() = default;
|
||||
|
||||
/**
|
||||
@ -65,11 +66,17 @@ public:
|
||||
[[nodiscard]] bool init();
|
||||
|
||||
/**
|
||||
* @brief Closes CMux protocol and ejects attached terminal and buffer
|
||||
* @return nullptr on failure
|
||||
* tuple of the original terminal and buffer on success
|
||||
* @brief Closes and deinits CMux protocol
|
||||
* @return true on success
|
||||
*/
|
||||
std::tuple<std::shared_ptr<Terminal>, std::unique_ptr<uint8_t[]>, size_t> deinit_and_eject();
|
||||
[[nodiscard]] bool deinit();
|
||||
|
||||
/**
|
||||
* @brief Ejects the attached terminal and buffer,
|
||||
* so they could be used as traditional command/data DTE's
|
||||
* @return pair of the original terminal and buffer
|
||||
*/
|
||||
std::pair<std::shared_ptr<Terminal>, unique_buffer> detach();
|
||||
|
||||
/**
|
||||
* @brief Sets read callback for the appropriate terminal
|
||||
@ -91,10 +98,8 @@ private:
|
||||
static uint8_t fcs_crc(const uint8_t frame[6]); /*!< Utility to calculate FCS CRC */
|
||||
void data_available(uint8_t *data, size_t len); /*!< Called when valid data available */
|
||||
void send_sabm(size_t i); /*!< Sending initial SABM */
|
||||
void send_disc(size_t i); /*!< Sending closing request for each virtual terminal */
|
||||
void close_down(); /*!< Close up the control terminla (term=0) */
|
||||
bool exit_cmux_protocol(); /*!< Sequence of exit of all virtual terms and control term */
|
||||
bool on_cmux_data(uint8_t *data, size_t len); /*!< Called from terminal layer when raw CMUX protocol data available */
|
||||
void send_disconnect(size_t i); /*!< Sending closing request for each virtual or control terminal */
|
||||
bool on_cmux_data(uint8_t *data, size_t len); /*!< Called from terminal layer when raw CMUX protocol data available */
|
||||
|
||||
struct CMuxFrame; /*!< Forward declare the Frame struct, used in protocol decoders */
|
||||
/**
|
||||
@ -127,10 +132,9 @@ private:
|
||||
int sabm_ack;
|
||||
|
||||
/**
|
||||
* Processing buffer size and pointer
|
||||
* Processing unique buffer (reused and transferred from it's parent DTE)
|
||||
*/
|
||||
size_t buffer_size;
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
unique_buffer buffer;
|
||||
|
||||
Lock lock;
|
||||
};
|
||||
@ -157,7 +161,6 @@ public:
|
||||
}
|
||||
void start() override { }
|
||||
void stop() override { }
|
||||
CMux* get_cmux() { return cmux.get(); }
|
||||
private:
|
||||
std::shared_ptr<CMux> cmux;
|
||||
size_t instance;
|
||||
|
@ -15,18 +15,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include "cxx_include/esp_modem_primitives.hpp"
|
||||
#include "cxx_include/esp_modem_terminal.hpp"
|
||||
#include "cxx_include/esp_modem_cmux.hpp"
|
||||
#include "cxx_include/esp_modem_types.hpp"
|
||||
#include "cxx_include/esp_modem_buffer.hpp"
|
||||
|
||||
struct esp_modem_dte_config;
|
||||
|
||||
namespace esp_modem {
|
||||
|
||||
class CMux;
|
||||
|
||||
/**
|
||||
* @defgroup ESP_MODEM_DTE
|
||||
* @brief Definition of DTE and related classes
|
||||
@ -104,19 +106,17 @@ protected:
|
||||
private:
|
||||
static const size_t GOT_LINE = SignalGroup::bit0; /*!< Bit indicating response available */
|
||||
|
||||
[[nodiscard]] bool setup_cmux(); /*!< Internal setup of CMUX mode */
|
||||
[[nodiscard]] bool exit_cmux(); /*!< Exit of CMUX mode */
|
||||
[[nodiscard]] bool setup_cmux(); /*!< Internal setup of CMUX mode */
|
||||
[[nodiscard]] bool exit_cmux(); /*!< Exit of CMUX mode */
|
||||
|
||||
Lock internal_lock{}; /*!< Locks DTE operations */
|
||||
size_t buffer_size; /*!< Size of available DTE buffer */
|
||||
size_t consumed; /*!< Indication of already processed portion in DTE buffer */
|
||||
std::unique_ptr<uint8_t[]> buffer; /*!< DTE buffer */
|
||||
Lock internal_lock{}; /*!< Locks DTE operations */
|
||||
unique_buffer buffer; /*!< DTE buffer */
|
||||
std::shared_ptr<CMux> cmux_term; /*!< Primary terminal for this DTE */
|
||||
std::shared_ptr<Terminal> command_term; /*!< Reference to the terminal used for sending commands */
|
||||
std::shared_ptr<Terminal> data_term; /*!< Secondary terminal for this DTE */
|
||||
modem_mode mode; /*!< DTE operation mode */
|
||||
modem_mode mode; /*!< DTE operation mode */
|
||||
SignalGroup signal; /*!< Event group used to signal request-response operations */
|
||||
std::function<bool(uint8_t *data, size_t len)> on_data; /*!< on data callback for current terminal */
|
||||
std::function<bool(uint8_t *data, size_t len)> on_data; /*!< on data callback for current terminal */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,7 @@ private:
|
||||
using TaskT = TaskHandle_t;
|
||||
using SignalT = EventGroupHandle_t;
|
||||
#else
|
||||
using Lock = std::mutex;
|
||||
using Lock = std::recursive_mutex;
|
||||
struct SignalGroupInternal;
|
||||
using SignalT = std::unique_ptr<SignalGroupInternal>;
|
||||
using TaskT = std::thread;
|
||||
|
Reference in New Issue
Block a user