remove all remaining C implementation

This commit is contained in:
David Cermak
2021-03-08 15:10:15 +01:00
parent 904cf94648
commit 2907eb9836
35 changed files with 114 additions and 4123 deletions

View File

@ -1,14 +1,4 @@
set(srcs "src/esp_modem.c"
"src/esp_modem_dce_command_lib.c"
"src/esp_modem_dce_common_commands.c"
"src/esp_modem_dce.c"
"src/esp_modem_dte.c"
"src/esp_modem_netif.c"
"src/esp_modem_recov_helper.c"
"src/esp_sim800.c"
"src/esp_sim7600.c"
"src/esp_bg96.c"
"src/esp_modem_dte.cpp"
set(srcs "src/esp_modem_dte.cpp"
"src/esp_modem_netif.cpp"
"src/esp_modem_api.cpp"
"src/esp_modem_factory.cpp"
@ -19,11 +9,6 @@ set(srcs "src/esp_modem.c"
set(include_dirs "include")
if(CONFIG_MODEM_LEGACY_API)
list(APPEND srcs "src/esp_modem_compat.c")
list(APPEND include_dirs "include_compat")
endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS private_include

View File

@ -12,12 +12,11 @@
#include "esp_netif.h"
#include "esp_netif_ppp.h"
#include "mqtt_client.h"
#include "esp_modem.h"
#include "esp_modem_netif.h"
#include "esp_log.h"
#include "cxx_include/esp_modem_dte.hpp"
#include "esp_modem_config.h"
#include "cxx_include/esp_modem_api.hpp"
#include <iostream>
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
@ -27,108 +26,6 @@ static const int CONNECT_BIT = BIT0;
static const int STOP_BIT = BIT1;
static const int GOT_DATA_BIT = BIT2;
#if CONFIG_EXAMPLE_SEND_MSG
/**
* @brief This example will also show how to send short message using the infrastructure provided by esp modem library.
* @note Not all modem support SMG.
*
*/
static esp_err_t example_default_handle(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, MODEM_STATE_FAIL);
}
return err;
}
static esp_err_t example_handle_cmgs(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, MODEM_STATE_FAIL);
} else if (!strncmp(line, "+CMGS", strlen("+CMGS"))) {
err = ESP_OK;
}
return err;
}
#define MODEM_SMS_MAX_LENGTH (128)
#define MODEM_COMMAND_TIMEOUT_SMS_MS (120000)
#define MODEM_PROMPT_TIMEOUT_MS (10)
static esp_err_t example_send_message_text(modem_dce_t *user_dce, const char *phone_num, const char *text)
{
esp_modem_dce_t *dce = &user_dce->parent;
modem_dte_t *dte = dce->dte;
dce->handle_line = example_default_handle;
/* Set text mode */
if (dte->send_cmd(dte, "AT+CMGF=1\r", MODEM_COMMAND_TIMEOUT_DEFAULT) != ESP_OK) {
ESP_LOGE(TAG, "send command failed");
goto err;
}
if (dce->state != MODEM_STATE_SUCCESS) {
ESP_LOGE(TAG, "set message format failed");
goto err;
}
ESP_LOGD(TAG, "set message format ok");
/* Specify character set */
dce->handle_line = example_default_handle;
if (dte->send_cmd(dte, "AT+CSCS=\"GSM\"\r", MODEM_COMMAND_TIMEOUT_DEFAULT) != ESP_OK) {
ESP_LOGE(TAG, "send command failed");
goto err;
}
if (dce->state != MODEM_STATE_SUCCESS) {
ESP_LOGE(TAG, "set character set failed");
goto err;
}
ESP_LOGD(TAG, "set character set ok");
/* send message */
char command[MODEM_SMS_MAX_LENGTH] = {0};
int length = snprintf(command, MODEM_SMS_MAX_LENGTH, "AT+CMGS=\"%s\"\r", phone_num);
/* set phone number and wait for "> " */
dte->send_wait(dte, command, length, "\r\n> ", MODEM_PROMPT_TIMEOUT_MS);
/* end with CTRL+Z */
snprintf(command, MODEM_SMS_MAX_LENGTH, "%s\x1A", text);
dce->handle_line = example_handle_cmgs;
if (dte->send_cmd(dte, command, MODEM_COMMAND_TIMEOUT_SMS_MS) != ESP_OK) {
ESP_LOGE(TAG, "send command failed");
goto err;
}
if (dce->state != MODEM_STATE_SUCCESS) {
ESP_LOGE(TAG, "send message failed");
goto err;
}
ESP_LOGD(TAG, "send message ok");
return ESP_OK;
err:
return ESP_FAIL;
}
#endif
static void modem_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
switch (event_id) {
case ESP_MODEM_EVENT_PPP_START:
ESP_LOGI(TAG, "Modem PPP Started");
break;
case ESP_MODEM_EVENT_PPP_STOP:
ESP_LOGI(TAG, "Modem PPP Stopped");
xEventGroupSetBits(event_group, STOP_BIT);
break;
case ESP_MODEM_EVENT_UNKNOWN:
ESP_LOGW(TAG, "Unknown line received: %s", (char *)event_data);
break;
default:
break;
}
}
//static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t)event_data;
@ -232,18 +129,6 @@ extern "C" void app_main(void)
/* Configure the DTE */
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
/* setup UART specific configuration based on kconfig options */
dte_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
dte_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
dte_config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN;
dte_config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN;
dte_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
dte_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
dte_config.pattern_queue_size = CONFIG_EXAMPLE_MODEM_UART_PATTERN_QUEUE_SIZE;
dte_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
dte_config.event_task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
dte_config.event_task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
dte_config.line_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
/* Configure the DCE */
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
@ -251,21 +136,9 @@ extern "C" void app_main(void)
/* Configure the PPP netif */
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
/* Run the modem demo app */
return modem_test_app(&dte_config, &dce_config,&netif_ppp_config);
}
#include <iostream>
static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_config_t *dce_config, esp_netif_config_t *ppp_config)
{
/* create dte object */
esp_modem_dte_t *dte; // = esp_modem_dte_new(dte_config);
// assert(dte != NULL);
// dte_config->line_buffer_size = 1000000;
uint8_t data[32] = {};
int actual_len = 0;
auto uart_dte = create_uart_dte(dte_config);
auto uart_dte = create_uart_dte(&dte_config);
uart_dte->set_mode(modem_mode::UNDEF);
uart_dte->command("+++", [&](uint8_t *data, size_t len) {
std::string response((char*)data, len);
@ -289,7 +162,7 @@ static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_con
// }, 1000);
//
// return;
esp_netif_t *esp_netif = esp_netif_new(ppp_config);
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
assert(esp_netif);
std::string apn = "internet";
@ -346,25 +219,25 @@ static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_con
while (1) {
my_dce->set_data();
/* Config MQTT */
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
esp_mqtt_client_config_t mqtt_config = { };
mqtt_config.uri = BROKER_URL;
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, NULL);
esp_mqtt_client_start(mqtt_client);
xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
esp_mqtt_client_destroy(mqtt_client);
my_dce->set_data();
/* Config MQTT */
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
esp_mqtt_client_config_t mqtt_config = { };
mqtt_config.uri = BROKER_URL;
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, NULL);
esp_mqtt_client_start(mqtt_client);
xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
esp_mqtt_client_destroy(mqtt_client);
// vTaskDelay(pdMS_TO_TICKS(20000));
my_dce->exit_data();
uart_dte->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) {
std::string response((char*)data, len);
my_dce->exit_data();
uart_dte->command("AT+CPIN?\r", [&](uint8_t *data, size_t len) {
std::string response((char*)data, len);
// ESP_LOGI("in the lambda", "len=%d data %s", len, (char*)data);
std::cout << response << std::endl;
return command_result::OK;
}, 1000);
std::cout << response << std::endl;
return command_result::OK;
}, 1000);
}
// ddd->send_command("AT+COPS=?\r", [&](uint8_t *data, size_t len) {
@ -394,64 +267,6 @@ static void modem_test_app(esp_modem_dte_config_t *dte_config, esp_modem_dce_con
std::cout << response << std::endl;
return command_result::OK;
}, 1000);
return;
/* create dce object */
#if CONFIG_EXAMPLE_MODEM_DEVICE_SIM800
dce_config->device = ESP_MODEM_DEVICE_SIM800;
#elif CONFIG_EXAMPLE_MODEM_DEVICE_BG96
dce_config->device = ESP_MODEM_DEVICE_BG96;
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600
dce_config->device = ESP_MODEM_DEVICE_SIM7600;
#else
#error "Unsupported DCE"
#endif
esp_modem_dce_t *dce = esp_modem_dce_new(dce_config);
assert(dce != NULL);
/* create netif object */
// esp_netif_t *esp_netif = esp_netif_new(ppp_config);
assert(esp_netif);
#if !defined(CONFIG_EXAMPLE_MODEM_PPP_AUTH_NONE) && (defined(CONFIG_LWIP_PPP_PAP_SUPPORT) || defined(CONFIG_LWIP_PPP_CHAP_SUPPORT))
#if CONFIG_LWIP_PPP_PAP_SUPPORT
esp_netif_auth_type_t auth_type = NETIF_PPP_AUTHTYPE_PAP;
#elif CONFIG_LWIP_PPP_CHAP_SUPPORT
esp_netif_auth_type_t auth_type = NETIF_PPP_AUTHTYPE_CHAP;
#else
#error "Unsupported AUTH Negotiation"
#endif
esp_netif_ppp_set_auth(esp_netif, auth_type, CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME, CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD);
#endif
/* Register event handler */
ESP_ERROR_CHECK(esp_modem_set_event_handler(dte, modem_event_handler, ESP_EVENT_ANY_ID, NULL));
/* attach the DCE, DTE, netif to initialize the modem */
ESP_ERROR_CHECK(esp_modem_default_attach(dte, dce, esp_netif));
while (1) {
ESP_ERROR_CHECK(esp_modem_default_start(dte));
/* Start PPP mode */
ESP_ERROR_CHECK(esp_modem_start_ppp(dte));
/* Wait for IP address */
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
/* Config MQTT */
esp_mqtt_client_config_t mqtt_config = { };
mqtt_config.uri = BROKER_URL;
esp_mqtt_client_handle_t mqtt_client = esp_mqtt_client_init(&mqtt_config);
esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, NULL);
esp_mqtt_client_start(mqtt_client);
xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
esp_mqtt_client_destroy(mqtt_client);
/* Exit PPP mode */
ESP_ERROR_CHECK(esp_modem_stop_ppp(dte));
xEventGroupWaitBits(event_group, STOP_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
ESP_LOGI(TAG, "Restart after 60 seconds");
vTaskDelay(pdMS_TO_TICKS(60000));
}
/* Default destroy all modem sub-units attached to it (DTE, DCE, netif) */
ESP_ERROR_CHECK(esp_modem_default_destroy(dte));
}

View File

@ -9,10 +9,10 @@ class GenericModule;
class SIM7600;
class SIM800;
class BG96;
struct dte_config;
struct esp_modem_dte_config;
typedef struct esp_netif_obj esp_netif_t;
std::shared_ptr<DTE> create_uart_dte(const dte_config *config);
std::shared_ptr<DTE> create_uart_dte(const esp_modem_dte_config *config);
std::shared_ptr<GenericModule> create_generic_module(const std::shared_ptr<DTE>& dte, std::string &apn);

View File

@ -16,7 +16,7 @@ namespace dce_commands {
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, TEMPLATE_ARG, MUX_ARG, ...) \
return_type name(CommandableIf *t, ## __VA_ARGS__);
DECLARE_ALL_COMMAND_APIS(forwards name(...) { device->name(...); } )
DECLARE_ALL_COMMAND_APIS(declare name(Commandable *p, ...);)
#undef ESP_MODEM_DECLARE_DCE_COMMAND

View File

@ -1,331 +0,0 @@
// 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_event.h"
#include "driver/uart.h"
#include "esp_modem_dte_config.h"
/**
* @brief Forward declare DTE and DCE objects
*
*/
typedef struct esp_modem_dte esp_modem_dte_t;
typedef struct esp_modem_dce esp_modem_dce_t;
/**
* @brief Declare Event Base for ESP Modem
*
*/
ESP_EVENT_DECLARE_BASE(ESP_MODEM_EVENT);
/**
* @brief ESP Modem Event
*
*/
typedef enum {
ESP_MODEM_EVENT_PPP_START = 0, /*!< ESP Modem Start PPP Session */
ESP_MODEM_EVENT_PPP_STOP = 3, /*!< ESP Modem Stop PPP Session*/
ESP_MODEM_EVENT_UNKNOWN = 4 /*!< ESP Modem Unknown Response */
} esp_modem_event_t;
/**
* @defgroup ESP_MODEM_DTE_TYPES DTE Types
* @brief Configuration and related types used to init and setup a new DTE object
*/
/** @addtogroup ESP_MODEM_DTE_TYPES
* @{
*/
/**
* @brief ESP Modem DTE Configuration
*
*/
typedef struct dte_config
#if 0
{
uart_port_t port_num; /*!< UART port number */
uart_word_length_t data_bits; /*!< Data bits of UART */
uart_stop_bits_t stop_bits; /*!< Stop bits of UART */
uart_parity_t parity; /*!< Parity type */
esp_modem_flow_ctrl_t flow_control; /*!< Flow control type */
uint32_t baud_rate; /*!< Communication baud rate */
int tx_io_num; /*!< TXD Pin Number */
int rx_io_num; /*!< RXD Pin Number */
int rts_io_num; /*!< RTS Pin Number */
int cts_io_num; /*!< CTS Pin Number */
int rx_buffer_size; /*!< UART RX Buffer Size */
int tx_buffer_size; /*!< UART TX Buffer Size */
int pattern_queue_size; /*!< UART Pattern Queue Size */
int event_queue_size; /*!< UART Event Queue Size */
uint32_t event_task_stack_size; /*!< UART Event Task Stack size */
int event_task_priority; /*!< UART Event Task Priority */
int line_buffer_size; /*!< Line buffer size for command mode */
}
#endif
esp_modem_dte_config_t;
/**
* @brief ESP Modem DTE Default Configuration
*
*/
#define ESP_MODEM_DTE_DEFAULT_CONFIG() \
{ \
.port_num = UART_NUM_1, \
.data_bits = UART_DATA_8_BITS, \
.stop_bits = UART_STOP_BITS_1, \
.parity = UART_PARITY_DISABLE, \
.flow_control = ESP_MODEM_FLOW_CONTROL_NONE,\
.baud_rate = 115200, \
.tx_io_num = 25, \
.rx_io_num = 26, \
.rts_io_num = 27, \
.cts_io_num = 23, \
.rx_buffer_size = 1024, \
.tx_buffer_size = 512, \
.pattern_queue_size = 20, \
.event_queue_size = 30, \
.event_task_stack_size = 4096, \
.event_task_priority = 5, \
.line_buffer_size = 512 \
}
/**
* @}
*/
/**
* @defgroup ESP_MODEM_DCE_TYPES DCE Types
* @brief Configuration and related types used to init and setup a new DCE object
*/
/** @addtogroup ESP_MODEM_DCE_TYPES
* @{
*/
/**
* @brief PDP context type used as an input parameter to esp_modem_dce_set_pdp_context
* also used as a part of configuration structure
*/
typedef struct esp_modem_dce_pdp_ctx_s {
size_t cid; /*!< PDP context identifier */
const char *type; /*!< Protocol type */
const char *apn; /*!< Modem APN (Access Point Name, a logical name to choose data network) */
} esp_modem_dce_pdp_ctx_t;
/**
* @brief Devices that the DCE will act as
*
*/
typedef enum esp_modem_dce_device_e {
ESP_MODEM_DEVICE_UNSPECIFIED,
ESP_MODEM_DEVICE_SIM800,
ESP_MODEM_DEVICE_SIM7600,
ESP_MODEM_DEVICE_BG96,
} esp_modem_dce_device_t;
/**
* @brief DCE's configuration structure
*/
typedef struct esp_modem_dce_config_s {
esp_modem_dce_pdp_ctx_t pdp_context; /*!< modem PDP context including APN */
bool populate_command_list; /*!< use command list interface: Setting this to true creates
a list of supported AT commands enabling sending
these commands, but will occupy data memory */
esp_modem_dce_device_t device; /*!< predefined device enum that the DCE will initialise as */
} esp_modem_dce_config_t;
/**
* @brief Default configuration of DCE unit of ESP-MODEM
*
*/
#define ESP_MODEM_DCE_DEFAULT_CONFIG(APN) \
{ \
.pdp_context = { \
.cid = 1, \
.type = "IP", \
.apn = APN }, \
.populate_command_list = false,\
.device = ESP_MODEM_DEVICE_UNSPECIFIED \
}
/**
* @}
*/
/**
* @defgroup ESP_MODEM_DTE_DCE DCE and DCE object init and setup API
* @brief Creating and init objects of DTE and DCE
*/
/** @addtogroup ESP_MODEM_DTE_DCE
* @{
*/
/**
* @brief Create and initialize Modem DTE object
*
* @param config configuration of ESP Modem DTE object
* @return modem_dte_t*
* - Modem DTE object
*/
esp_modem_dte_t *esp_modem_dte_new(const esp_modem_dte_config_t *config);
/**
* @brief Create and initialize Modem DCE object
*
* @param config configuration of ESP Modem DTE object
* @return modem_dce_t* Modem DCE object
*/
esp_modem_dce_t *esp_modem_dce_new(esp_modem_dce_config_t *config);
/**
* @brief Initialize the DCE object that has already been created
*
* This API is typically used to initialize extended DCE object,
* "sub-class" of esp_modem_dce_t
*
* @param config Configuration for DCE object
* @return
* - ESP_OK on success
* - ESP_FAIL on error (init issue, set specific command issue)
* - ESP_ERR_INVALID_ARG on invalid parameters
*/
esp_err_t esp_modem_dce_init(esp_modem_dce_t *dce, esp_modem_dce_config_t *config);
/**
* @}
*/
/**
* @defgroup ESP_MODEM_EVENTS Event handling API
*/
/** @addtogroup ESP_MODEM_EVENTS
* @{
*/
/**
* @brief Register event handler for ESP Modem event loop
*
* @param dte modem_dte_t type object
* @param handler event handler to register
* @param handler_args arguments for registered handler
* @return esp_err_t
* - ESP_OK on success
* - ESP_ERR_NO_MEM on allocating memory for the handler failed
* - ESP_ERR_INVALID_ARG on invalid combination of event base and event id
*/
esp_err_t esp_modem_set_event_handler(esp_modem_dte_t *dte, esp_event_handler_t handler, int32_t event_id, void *handler_args);
/**
* @brief Unregister event handler for ESP Modem event loop
*
* @param dte modem_dte_t type object
* @param handler event handler to unregister
* @return esp_err_t
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG on invalid combination of event base and event id
*/
esp_err_t esp_modem_remove_event_handler(esp_modem_dte_t *dte, esp_event_handler_t handler);
/**
* @}
*/
/**
* @defgroup ESP_MODEM_LIFECYCLE Modem lifecycle API
* @brief Basic modem API to start/stop the PPP mode
*/
/** @addtogroup ESP_MODEM_LIFECYCLE
* @{
*/
/**
* @brief Setup PPP Session
*
* @param dte Modem DTE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_start_ppp(esp_modem_dte_t *dte);
/**
* @brief Exit PPP Session
*
* @param dte Modem DTE Object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_stop_ppp(esp_modem_dte_t *dte);
/**
* @brief Basic start of the modem. This API performs default dce's start_up() function
*
* @param dte Modem DTE Object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_INVALID_ARG on invalid arguments
*/
esp_err_t esp_modem_default_start(esp_modem_dte_t *dte);
/**
* @brief Basic attach operation of modem sub-elements
*
* This API binds the supplied DCE and netif to the modem's DTE and initializes the modem
*
* @param dte Modem DTE Object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_default_attach(esp_modem_dte_t *dte, esp_modem_dce_t *dce, esp_netif_t* ppp_netif);
/**
* @brief Basic destroy operation of the modem DTE and all the sub-elements bound to it
*
* This API deletes the DCE, modem netif adapter as well as the esp_netif supplied to
* esp_modem_default_attach(). Then it deletes the DTE itself.
*
* @param dte Modem DTE Object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_INVALID_ARG on invalid arguments
*/
esp_err_t esp_modem_default_destroy(esp_modem_dte_t *dte);
/**
* @}
*/
#ifdef __cplusplus
}
#endif

View File

@ -12,7 +12,7 @@ extern "C" {
typedef struct esp_modem_dce_wrap esp_modem_t;
esp_modem_t *esp_modem_new(const dte_config *config, esp_netif_t *netif, const char* apn);
esp_modem_t *esp_modem_new(const esp_modem_dte_config *config, esp_netif_t *netif, const char* apn);
void esp_modem_destroy(esp_modem_t * dce);

View File

@ -0,0 +1,77 @@
//
// Created by david on 2/24/21.
//
#ifndef SIMPLE_CXX_CLIENT_ESP_MODEM_CONFIG_H
#define SIMPLE_CXX_CLIENT_ESP_MODEM_CONFIG_H
#include "driver/uart.h"
/**
* @brief Modem flow control type
*
*/
typedef enum {
ESP_MODEM_FLOW_CONTROL_NONE = 0,
ESP_MODEM_FLOW_CONTROL_SW,
ESP_MODEM_FLOW_CONTROL_HW
} esp_modem_flow_ctrl_t;
struct esp_modem_dte_config {
uart_port_t port_num; /*!< UART port number */
uart_word_length_t data_bits; /*!< Data bits of UART */
uart_stop_bits_t stop_bits; /*!< Stop bits of UART */
uart_parity_t parity; /*!< Parity type */
esp_modem_flow_ctrl_t flow_control; /*!< Flow control type */
int baud_rate; /*!< Communication baud rate */
int tx_io_num; /*!< TXD Pin Number */
int rx_io_num; /*!< RXD Pin Number */
int rts_io_num; /*!< RTS Pin Number */
int cts_io_num; /*!< CTS Pin Number */
int rx_buffer_size; /*!< UART RX Buffer Size */
int tx_buffer_size; /*!< UART TX Buffer Size */
int pattern_queue_size; /*!< UART Pattern Queue Size */
int event_queue_size; /*!< UART Event Queue Size */
uint32_t event_task_stack_size; /*!< UART Event Task Stack size */
int event_task_priority; /*!< UART Event Task Priority */
int line_buffer_size; /*!< Line buffer size for command mode */
};
/**
* @brief ESP Modem DTE Default Configuration
*
*/
#define ESP_MODEM_DTE_DEFAULT_CONFIG() \
{ \
.port_num = UART_NUM_1, \
.data_bits = UART_DATA_8_BITS, \
.stop_bits = UART_STOP_BITS_1, \
.parity = UART_PARITY_DISABLE, \
.flow_control = ESP_MODEM_FLOW_CONTROL_NONE,\
.baud_rate = 115200, \
.tx_io_num = 25, \
.rx_io_num = 26, \
.rts_io_num = 27, \
.cts_io_num = 23, \
.rx_buffer_size = 1024, \
.tx_buffer_size = 512, \
.pattern_queue_size = 20, \
.event_queue_size = 30, \
.event_task_stack_size = 4096, \
.event_task_priority = 5, \
.line_buffer_size = 512 \
}
struct esp_modem_dce_config {
const char* apn;
};
#define ESP_MODEM_DCE_DEFAULT_CONFIG(APN) \
{ \
.apn = APN \
}
typedef struct esp_modem_dte_config esp_modem_dte_config_t;
typedef struct esp_modem_dce_config esp_modem_dce_config_t;
#endif //SIMPLE_CXX_CLIENT_ESP_MODEM_CONFIG_H

View File

@ -1,236 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_types.h"
#include "esp_err.h"
#include "esp_modem.h"
#include "esp_modem_dte.h"
/**
* @brief Forward declaration of the command list object, which (if enabled) is used
* to populate a command palette and access commands by its symbolic name
*/
struct esp_modem_dce_cmd_list;
/**
* @brief Working state of DCE
*
*/
typedef enum {
ESP_MODEM_STATE_PROCESSING, /*!< In processing */
ESP_MODEM_STATE_SUCCESS, /*!< Process successfully */
ESP_MODEM_STATE_FAIL /*!< Process failed */
} esp_modem_state_t;
/**
* @brief Generic command type used in DCE unit
*/
typedef esp_err_t (*dce_command_t)(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Type of line handlers called fro DTE upon line response reception
*/
typedef esp_err_t (*esp_modem_dce_handle_line_t)(esp_modem_dce_t *dce, const char *line);
/**
* @brief DCE(Data Communication Equipment)
*
*/
struct esp_modem_dce {
esp_modem_state_t state; /*!< Modem working state */
esp_modem_mode_t mode; /*!< Working mode */
esp_modem_dte_t *dte; /*!< DTE which connect to DCE */
struct esp_modem_dce_cmd_list *dce_cmd_list;
esp_modem_dce_config_t config;
esp_modem_dce_handle_line_t handle_line; /*!< Handle line strategy */
void *handle_line_ctx; /*!< DCE context reserved for handle_line
processing */
// higher level actions DCE unit can take
esp_err_t (*set_working_mode)(esp_modem_dce_t *dce, esp_modem_mode_t mode); /*!< Set working mode */
esp_err_t (*deinit)(esp_modem_dce_t *dce); /*!< Destroys the DCE */
esp_err_t (*start_up)(esp_modem_dce_t *dce); /*!< Start-up sequence */
// list of essential commands for esp-modem basic work
dce_command_t hang_up; /*!< generic command for hang-up */
dce_command_t set_pdp_context; /*!< generic command for pdp context */
dce_command_t set_data_mode; /*!< generic command for data mode */
dce_command_t resume_data_mode; /*!< generic command to resume already dialed data mode */
dce_command_t set_command_mode; /*!< generic command for command mode */
dce_command_t set_echo; /*!< generic command for echo mode */
dce_command_t sync; /*!< generic command for sync */
dce_command_t set_flow_ctrl; /*!< generic command for flow-ctrl */
dce_command_t store_profile; /*!< generic command for store-profile */
};
// DCE commands building blocks
/**
* @brief Sending generic command to DCE
*
* @param[in] dce Modem DCE object
* @param[in] command String command
* @param[in] timeout Command timeout in ms
* @param[in] handle_line Function ptr which processes the command response
* @param[in] ctx Function ptr context
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_generic_command(esp_modem_dce_t *dce, const char * command, uint32_t timeout, esp_modem_dce_handle_line_t handle_line, void *ctx);
/**
* @brief Indicate that processing current command has done
*
* @param dce Modem DCE object
* @param state Modem state after processing
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_process_command_done(esp_modem_dce_t *dce, esp_modem_state_t state);
/**
* @brief Default handler for response
* Some responses for command are simple, commonly will return OK when succeed of ERROR when failed
*
* @param dce Modem DCE object
* @param line line string
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_handle_response_default(esp_modem_dce_t *dce, const char *line);
// DCE higher level commands
/**
* @brief Set Working Mode
*
* @param dce Modem DCE object
* @param mode working mode
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_set_working_mode(esp_modem_dce_t *dce, esp_modem_mode_t mode);
/**
* @brief Default start-up sequence, which sets the modem into an operational mode
*
* @param dce Modem DCE object
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_default_start_up(esp_modem_dce_t *dce);
/**
* @brief Destroys the DCE
*
* @param dce Modem DCE object
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_default_destroy(esp_modem_dce_t *dce);
/**
* @brief Initializes the DCE
*
* @param dce Modem DCE object
* @param config DCE configuration structure
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_default_init(esp_modem_dce_t *dce, esp_modem_dce_config_t* config);
/**
* @brief Sets the DCE parameters. This API updates runtime DCE config parameters,
* typically used to update PDP context data.
*
* @param dce Modem DCE object
* @param config DCE configuration structure
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_set_params(esp_modem_dce_t *dce, esp_modem_dce_config_t* config);
// list command operations
/**
* @brief Executes a specific command from the list
*
* @param dce Modem DCE object
* @param command Symbolic name of the command to execute
* @param param Generic parameter to the command
* @param result Generic output parameter
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_command_list_run(esp_modem_dce_t *dce, const char * command, void * param, void* result);
/**
* @brief Deinitialize the command list
*
* @param dce Modem DCE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_command_list_deinit(esp_modem_dce_t *dce);
/**
* @brief Initializes default command list with predefined command palette
*
* @param dce Modem DCE object
*
* @return ESP_OK on success, ESP_FAIL on error
*/
esp_err_t esp_modem_set_default_command_list(esp_modem_dce_t *dce);
/**
* @brief Add or set specific command to the command list
*
* @param dce Modem DCE object
* @param command_id Command symbolic name
* @param command Generic command function pointer
*
* @return ESP_OK on success, ESP_FAIL on error
*/
esp_err_t esp_modem_command_list_set_cmd(esp_modem_dce_t *dce, const char * command_id, dce_command_t command);
#ifdef __cplusplus
}
#endif

View File

@ -1,359 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem_dce.h"
/**
* @brief Result Code from DCE
*
*/
#define MODEM_RESULT_CODE_SUCCESS "OK" /*!< Acknowledges execution of a command */
#define MODEM_RESULT_CODE_CONNECT "CONNECT" /*!< A connection has been established */
#define MODEM_RESULT_CODE_RING "RING" /*!< Detect an incoming call signal from network */
#define MODEM_RESULT_CODE_NO_CARRIER "NO CARRIER" /*!< Connection termincated or establish a connection failed */
#define MODEM_RESULT_CODE_ERROR "ERROR" /*!< Command not recognized, command line maximum length exceeded, parameter value invalid */
#define MODEM_RESULT_CODE_NO_DIALTONE "NO DIALTONE" /*!< No dial tone detected */
#define MODEM_RESULT_CODE_BUSY "BUSY" /*!< Engaged signal detected */
#define MODEM_RESULT_CODE_NO_ANSWER "NO ANSWER" /*!< Wait for quiet answer */
/**
* @brief Specific Timeout Constraint, Unit: millisecond
*
*/
#define MODEM_COMMAND_TIMEOUT_DEFAULT (500) /*!< Default timeout value for most commands */
#define MODEM_COMMAND_TIMEOUT_OPERATOR (75000) /*!< Timeout value for getting operator status */
#define MODEM_COMMAND_TIMEOUT_RESET (60000) /*!< Timeout value for reset command */
#define MODEM_COMMAND_TIMEOUT_MODE_CHANGE (5000) /*!< Timeout value for changing working mode */
#define MODEM_COMMAND_TIMEOUT_POWEROFF (1000) /*!< Timeout value for power down */
/**
* @brief Strip the tailed "\r\n"
*
* @param str string to strip
* @param len length of string
*/
static inline void strip_cr_lf_tail(char *str, uint32_t len)
{
if (str[len - 2] == '\r') {
str[len - 2] = '\0';
} else if (str[len - 1] == '\r') {
str[len - 1] = '\0';
}
}
/**
* @brief Synchronization
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_sync(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Enable or not echo mode of DCE
*
* @param dce Modem DCE object
* @param[in] param bool casted to (void*): true to enable echo mode, false to disable echo mode
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_set_echo(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Store current parameter setting in the user profile
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_store_profile(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Set flow control mode of DCE in data mode
*
* @param[in] dce Modem DCE object
* @param[in] param esp_modem_flow_ctrl_t casted to (void*): flow control mode
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_set_flow_ctrl(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Define PDP context
*
* @param[in] dce Modem DCE object
* @param[in] param esp_modem_dce_pdp_ctx_t type defining PDP context
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_set_pdp_context(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Hang up
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_hang_up(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Signal strength structure used as a result to esp_modem_dce_get_signal_quality() API
*/
typedef struct esp_modem_dce_csq_ctx_s {
int rssi; //!< Signal strength indication
int ber; //!< Channel bit error rate
} esp_modem_dce_csq_ctx_t;
/**
* @brief Get signal quality
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result esp_modem_dce_csq_ctx_t type returning rssi and ber values
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_get_signal_quality(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Voltage status structure used as a result to esp_modem_dce_get_battery_status() API
*/
typedef struct esp_modem_dce_cbc_ctx_s {
int battery_status; //!< current status in mV
int bcs; //!< charge status (-1-Not available, 0-Not charging, 1-Charging, 2-Charging done)
int bcl; //!< 1-100% battery capacity, -1-Not available
} esp_modem_dce_cbc_ctx_t;
/**
* @brief Get battery status
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result esp_modem_dce_cbc_ctx_t type returning battery status and other fields if available
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_get_battery_status(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Get DCE module IMEI number
*
* @param[in] dce Modem DCE object
* @param[in] param size_t of output string length (casted to void*), max size the resultant string
* @param[out] result pointer to the string where the resultant IMEI number gets copied (if size param fits)
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_get_imei_number(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Get DCE module IMSI number
*
* @param[in] dce Modem DCE object
* @param[in] param size_t of output string length (casted to void*), max size the resultant string
* @param[out] result pointer to the string where the resultant IMSI number gets copied (if size param fits)
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_get_imsi_number(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Get DCE module name
*
* @param[in] dce Modem DCE object
* @param[in] param size_t of output string length (casted to void*), max size the resultant string
* @param[out] result pointer to the string where the resultant module name gets copied (if size param fits)
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_get_module_name(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Get operator name
*
* @param[in] dce Modem DCE object
* @param[in] param size_t of output string length (casted to void*), max size the resultant string
* @param[out] result pointer to the string where the resultant operator name gets copied (if size param fits)
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_get_operator_name(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Switch to data mode
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_set_data_mode(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Resume the data mode when PPP has already been started, but switched back to command
* mode (typically using the `+++` PPP escape sequence)
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_resume_data_mode(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Switch to command mode
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_set_command_mode(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Power-down the module
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_power_down(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Reset the module
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_reset(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Checks if the module waits for entering the PIN
*
* @param[in] dce Modem DCE object
* @param[in] param None
* @param[out] result pointer to bool indicating READY if set to true
* or the module is waiting for PIN if set to false
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_read_pin(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Enters the PIN number
*
* @param[in] dce Modem DCE object
* @param[in] param 4 character string pointer to the PIN
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_set_pin(esp_modem_dce_t *dce, void *param, void *result);
/**
* @brief Sets the DCE to temporarily use the baudrate specified
*
* @param[in] dce Modem DCE object
* @param[in] param string pointer to char representation of the baudrate
* @param[out] result None
*
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
* - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_set_baud_temp(esp_modem_dce_t *dce, void *param, void *result);

View File

@ -1,101 +0,0 @@
// Copyright 2018-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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_types.h"
#include "esp_err.h"
#include "esp_event.h"
/**
* @brief Working mode of Modem
*
*/
typedef enum {
ESP_MODEM_COMMAND_MODE = 0, /*!< Command Mode */
ESP_MODEM_PPP_MODE, /*!< PPP Mode */
ESP_MODEM_TRANSITION_MODE /*!< Transition Mode between data and command mode indicating that
the modem is not yet ready for sending commands nor data */
} esp_modem_mode_t;
/**
* @brief DTE(Data Terminal Equipment)
*
*/
struct esp_modem_dte {
esp_modem_flow_ctrl_t flow_ctrl; /*!< Flow control of DTE */
esp_modem_dce_t *dce; /*!< DCE which connected to the DTE */
struct esp_modem_netif_driver_s *netif_adapter;
esp_err_t (*send_cmd)(esp_modem_dte_t *dte, const char *command, uint32_t timeout); /*!< Send command to DCE */
int (*send_data)(esp_modem_dte_t *dte, const char *data, uint32_t length); /*!< Send data to DCE */
esp_err_t (*send_wait)(esp_modem_dte_t *dte, const char *data, uint32_t length,
const char *prompt, uint32_t timeout); /*!< Wait for specific prompt */
esp_err_t (*change_mode)(esp_modem_dte_t *dte, esp_modem_mode_t new_mode); /*!< Changing working mode */
esp_err_t (*process_cmd_done)(esp_modem_dte_t *dte); /*!< Callback when DCE process command done */
esp_err_t (*deinit)(esp_modem_dte_t *dte); /*!< Deinitialize */
};
/**
* @brief Type used for reception callback
*
*/
typedef esp_err_t (*esp_modem_on_receive)(void *buffer, size_t len, void *context);
/**
* @brief Setup on reception callback
*
* @param dte ESP Modem DTE object
* @param receive_cb Function pointer to the reception callback
* @param receive_cb_ctx Contextual pointer to be passed to the reception callback
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_set_rx_cb(esp_modem_dte_t *dte, esp_modem_on_receive receive_cb, void *receive_cb_ctx);
/**
* @brief Notify the modem, that ppp netif has closed
*
* @note This API should only be used internally by the modem-netif layer
*
* @param dte ESP Modem DTE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_notify_ppp_netif_closed(esp_modem_dte_t *dte);
/**
* @brief Notify the modem, that all the modem units (DTE, DCE, PPP) has
* been properly initialized and DTE loop can safely start
*
* @param dte ESP Modem DTE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_notify_initialized(esp_modem_dte_t *dte);
/**
* @brief Configure runtime parameters for the DTE. Currently supports only the baud rate to be set
*
* @param dte ESP Modem DTE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_dte_set_params(esp_modem_dte_t *dte, const esp_modem_dte_config_t *config);
#ifdef __cplusplus
}
#endif

View File

@ -1,39 +0,0 @@
//
// Created by david on 2/24/21.
//
#ifndef SIMPLE_CXX_CLIENT_ESP_MODEM_DTE_CONFIG_H
#define SIMPLE_CXX_CLIENT_ESP_MODEM_DTE_CONFIG_H
/**
* @brief Modem flow control type
*
*/
typedef enum {
ESP_MODEM_FLOW_CONTROL_NONE = 0,
ESP_MODEM_FLOW_CONTROL_SW,
ESP_MODEM_FLOW_CONTROL_HW
} esp_modem_flow_ctrl_t;
struct dte_config {
uart_port_t port_num; /*!< UART port number */
uart_word_length_t data_bits; /*!< Data bits of UART */
uart_stop_bits_t stop_bits; /*!< Stop bits of UART */
uart_parity_t parity; /*!< Parity type */
esp_modem_flow_ctrl_t flow_control; /*!< Flow control type */
int baud_rate; /*!< Communication baud rate */
int tx_io_num; /*!< TXD Pin Number */
int rx_io_num; /*!< RXD Pin Number */
int rts_io_num; /*!< RTS Pin Number */
int cts_io_num; /*!< CTS Pin Number */
int rx_buffer_size; /*!< UART RX Buffer Size */
int tx_buffer_size; /*!< UART TX Buffer Size */
int pattern_queue_size; /*!< UART Pattern Queue Size */
int event_queue_size; /*!< UART Event Queue Size */
uint32_t event_task_stack_size; /*!< UART Event Task Stack size */
int event_task_priority; /*!< UART Event Task Priority */
int line_buffer_size; /*!< Line buffer size for command mode */
};
#endif //SIMPLE_CXX_CLIENT_ESP_MODEM_DTE_CONFIG_H

View File

@ -1,103 +0,0 @@
// 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief modem netif adapter type
*
*/
typedef struct esp_modem_netif_driver_s esp_modem_netif_driver_t;
/**
* @defgroup ESP_MODEM_NETIF Modem netif adapter API
* @brief network interface adapter for esp-modem
*/
/** @addtogroup ESP_MODEM_NETIF
* @{
*/
/**
* @brief Creates handle to esp_modem used as an esp-netif driver
*
* @param dte ESP Modem DTE object
*
* @return opaque pointer to esp-modem IO driver used to attach to esp-netif
*/
esp_modem_netif_driver_t *esp_modem_netif_new(esp_modem_dte_t *dte);
/**
* @brief Destroys the esp-netif driver handle as well as the internal netif
* object attached to it
*
* @param h pointer to the esp-netif adapter for esp-modem
*/
void esp_modem_netif_destroy(esp_modem_netif_driver_t *h);
/**
* @brief Clears default handlers for esp-modem lifecycle
*
* @param h pointer to the esp-netif adapter for esp-modem
*/
esp_err_t esp_modem_netif_clear_default_handlers(esp_modem_netif_driver_t *h);
/**
* @brief Setups default handlers for esp-modem lifecycle
*
* @param h pointer to the esp-netif adapter for esp-modem
* @param esp_netif pointer corresponding esp-netif instance
*/
esp_err_t esp_modem_netif_set_default_handlers(esp_modem_netif_driver_t *h, esp_netif_t * esp_netif);
/**
* @}
*/
/**
* @defgroup ESP_MODEM_NETIF_LEGACY Modem netif adapter legacy API
* @brief Legacy API for modem netif
*/
/** @addtogroup ESP_MODEM_NETIF_LEGACY
* @{
*/
/**
* @brief Destroys the esp-netif driver handle the same way
* as esp_modem_netif_destroy()
*
* @note This API is only provided for legacy API
*/
void esp_modem_netif_teardown(esp_modem_netif_driver_t *h);
/**
* @brief The same as `esp_modem_netif_new()`, but autostarts the netif
* on esp_netif_attach().
*
* @note This API is only provided for legacy API
*/
esp_modem_netif_driver_t *esp_modem_netif_setup(esp_modem_dte_t *dte);
/**
* @}
*/
#ifdef __cplusplus
}
#endif

View File

@ -1,87 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_err.h"
#include "esp_modem_dce.h"
/**
* @brief Utility macro to define a retry method
*
*/
#define DEFINE_RETRY_CMD(name, retry, super_type) \
esp_err_t name(esp_modem_dce_t *dce, void *param, void *result) \
{ \
super_type *super = __containerof(dce, super_type, parent); \
return super->retry->run(super->retry, param, result); \
}
/**
* @brief GPIO helper object used to pull modem IOs
*
*/
typedef struct esp_modem_gpio_s {
int gpio_num;
int inactive_level;
int active_width_ms;
int inactive_width_ms;
void (*pulse)(struct esp_modem_gpio_s *pin);
void (*pulse_special)(struct esp_modem_gpio_s *pin, int active_width_ms, int inactive_width_ms);
void (*destroy)(struct esp_modem_gpio_s *pin);
} esp_modem_recov_gpio_t;
/**
* @brief Recovery helper object used to resend commands if failed or timeouted
*
*/
typedef struct esp_modem_retry_s esp_modem_recov_resend_t;
/**
* @brief User recovery function to be called upon modem command failed
*
*/
typedef esp_err_t (*esp_modem_retry_fn_t)(esp_modem_recov_resend_t *retry_cmd, esp_err_t current_err, int timeouts, int errors);
/**
* @brief Recovery helper object
*
*/
struct esp_modem_retry_s {
const char *command;
esp_err_t (*run)(struct esp_modem_retry_s *retry, void *param, void *result);
dce_command_t orig_cmd;
esp_modem_retry_fn_t recover;
esp_modem_dce_t *dce;
int retries_after_timeout; //!< Retry strategy: numbers of resending the same command on timeout
int retries_after_error; //!< Retry strategy: numbers of resending the same command on error
void (*destroy)(struct esp_modem_retry_s *this_recov);
};
/**
* @brief Create new resend object
*
*/
esp_modem_recov_resend_t *esp_modem_recov_resend_new(esp_modem_dce_t *dce, dce_command_t orig_cmd, esp_modem_retry_fn_t recover, int max_timeouts, int max_errors);
/**
* @brief Create new gpio object
*
*/
esp_modem_recov_gpio_t *esp_modem_recov_gpio_new(int gpio_num, int inactive_level, int active_width_ms, int inactive_width_ms);

View File

@ -1,16 +0,0 @@
// Copyright 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.
#pragma once
#include "esp_modem_compat.h"

View File

@ -1,71 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem.h"
#include "esp_modem_dte.h"
#include "esp_modem_dce.h"
/**
* @brief Specific Length Constraint
*
*/
#define MODEM_MAX_NAME_LENGTH (32) /*!< Max Module Name Length */
#define MODEM_MAX_OPERATOR_LENGTH (32) /*!< Max Operator Name Length */
#define MODEM_IMEI_LENGTH (15) /*!< IMEI Number Length */
#define MODEM_IMSI_LENGTH (15) /*!< IMSI Number Length */
#define esp_modem_dte_init esp_modem_dte_new
typedef esp_modem_dte_t modem_dte_t;
typedef struct modem_dce modem_dce_t;
struct modem_dce {
char imei[MODEM_IMEI_LENGTH + 1]; /*!< IMEI number */
char imsi[MODEM_IMSI_LENGTH + 1]; /*!< IMSI number */
char name[MODEM_MAX_NAME_LENGTH]; /*!< Module name */
char oper[MODEM_MAX_OPERATOR_LENGTH]; /*!< Operator name */
esp_modem_state_t state; /*!< Modem working state */
esp_modem_mode_t mode; /*!< Working mode */
modem_dte_t *dte; /*!< DTE which connect to DCE */
esp_err_t (*handle_line)(modem_dce_t *dce, const char *line); /*!< Handle line strategy */
esp_err_t (*sync)(modem_dce_t *dce); /*!< Synchronization */
esp_err_t (*echo_mode)(modem_dce_t *dce, bool on); /*!< Echo command on or off */
esp_err_t (*store_profile)(modem_dce_t *dce); /*!< Store user settings */
esp_err_t (*set_flow_ctrl)(modem_dce_t *dce, esp_modem_flow_ctrl_t flow_ctrl); /*!< Flow control on or off */
esp_err_t (*get_signal_quality)(modem_dce_t *dce, uint32_t *rssi, uint32_t *ber); /*!< Get signal quality */
esp_err_t (*get_battery_status)(modem_dce_t *dce, uint32_t *bcs,
uint32_t *bcl, uint32_t *voltage); /*!< Get battery status */
esp_err_t (*define_pdp_context)(modem_dce_t *dce, uint32_t cid,
const char *type, const char *apn); /*!< Set PDP Contex */
esp_err_t (*set_working_mode)(modem_dce_t *dce, esp_modem_mode_t mode); /*!< Set working mode */
esp_err_t (*hang_up)(modem_dce_t *dce); /*!< Hang up */
esp_err_t (*power_down)(modem_dce_t *dce); /*!< Normal power down */
esp_err_t (*deinit)(modem_dce_t *dce); /*!< Deinitialize */
esp_modem_dce_t parent;
};
modem_dce_t *sim800_init(modem_dte_t *dte);
modem_dce_t *sim7600_init(modem_dte_t *dte);
modem_dce_t *bg96_init(modem_dte_t *dte);
#ifdef __cplusplus
}
#endif

View File

@ -1,16 +0,0 @@
// Copyright 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.
#pragma once
#include "esp_modem_compat.h"

View File

@ -1,16 +0,0 @@
// Copyright 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.
#pragma once
#include "esp_modem_compat.h"

View File

@ -1,62 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem_dce.h"
#include "esp_modem.h"
/**
* @brief Finds the command par its symbolic name
*
* @param dce Modem DCE object
* @param command Symbolic name of the command
*
* @return Function pointer to the
*/
dce_command_t esp_modem_dce_find_command(esp_modem_dce_t *dce, const char *command);
/**
* @brief Delete specific command from the list
*
* @param dce Modem DCE object
* @param command Symbolic name of the command to delete
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_dce_delete_command(esp_modem_dce_t *dce, const char *command_id);
/**
* @brief Deletes all commands in the list
*
* @param dce Modem DCE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_dce_delete_all_commands(esp_modem_dce_t *dce);
/**
* @brief Creates internal structure for holding the command list
*
* @return Pointer to the command list struct on success, NULL otherwise
*/
struct esp_modem_dce_cmd_list *esp_modem_command_list_create(void);
#ifdef __cplusplus
}
#endif

View File

@ -1,51 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_modem.h"
/**
* @brief Specific init of SIM800 device
*
* @param dce Modem DCE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_sim800_specific_init(esp_modem_dce_t *dce);
/**
* @brief Specific init of SIM7600 device
*
* @param dce Modem DCE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_sim7600_specific_init(esp_modem_dce_t *dce);
/**
* @brief Specific init of BG96 device
*
* @param dce Modem DCE object
*
* @return ESP_OK on success
*/
esp_err_t esp_modem_bg96_specific_init(esp_modem_dce_t *dce);
#ifdef __cplusplus
}
#endif

View File

@ -1,57 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_log.h"
#include "esp_modem.h"
#include "esp_modem_dte.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
/**
* @brief Main lifecycle states of the esp-modem
*
* The bits below are used to indicate events in process_group
* field of the esp_modem_dte_internal_t
*/
#define ESP_MODEM_START_BIT BIT0
#define ESP_MODEM_COMMAND_BIT BIT1
#define ESP_MODEM_STOP_PPP_BIT BIT2
#define ESP_MODEM_STOP_BIT BIT3
/**
* @brief ESP32 Modem DTE
*
*/
typedef struct {
uart_port_t uart_port; /*!< UART port */
uint8_t *buffer; /*!< Internal buffer to store response lines/data from DCE */
QueueHandle_t event_queue; /*!< UART event queue handle */
esp_event_loop_handle_t event_loop_hdl; /*!< Event loop handle */
TaskHandle_t uart_event_task_hdl; /*!< UART event task handle */
EventGroupHandle_t process_group; /*!< Event group used for indicating DTE state changes */
esp_modem_dte_t parent; /*!< DTE interface that should extend */
esp_modem_on_receive receive_cb; /*!< ptr to data reception */
void *receive_cb_ctx; /*!< ptr to rx fn context data */
int line_buffer_size; /*!< line buffer size in command mode */
int pattern_queue_size; /*!< UART pattern queue size */
} esp_modem_dte_internal_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,48 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_log.h"
#include "esp_modem.h"
/**
* @brief Macro defined for error checking
*
*/
#define ESP_MODEM_ERR_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
/**
* @brief common modem delay function
*
*/
static inline void esp_modem_wait_ms(size_t time)
{
vTaskDelay(pdMS_TO_TICKS(time));
}
#ifdef __cplusplus
}
#endif

View File

@ -7,10 +7,9 @@
#include "cxx_include/esp_modem_dte.hpp"
struct esp_modem_dte_config;
struct dte_config;
std::unique_ptr<Terminal> create_uart_terminal(const dte_config *config);
std::unique_ptr<Terminal> create_uart_terminal(const esp_modem_dte_config *config);

View File

@ -1,25 +0,0 @@
// 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.
#include "esp_modem_internal.h"
static const char *TAG = "bg96";
esp_err_t esp_modem_bg96_specific_init(esp_modem_dce_t *dce)
{
ESP_MODEM_ERR_CHECK(dce, "failed to specific init with zero dce", err_params);
// BG96 specifics is the same as the default DCE, as of now
return ESP_OK;
err_params:
return ESP_ERR_INVALID_ARG;
}

View File

@ -1,185 +0,0 @@
// Copyright 2015-2018 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 <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_modem.h"
#include "esp_modem_dce.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_modem_internal.h"
#include "esp_modem_dte_internal.h"
#include "esp_modem_device_specific_dce.h"
#include "esp_modem_netif.h"
static const char *TAG = "esp-modem";
ESP_EVENT_DEFINE_BASE(ESP_MODEM_EVENT);
esp_err_t esp_modem_set_event_handler(esp_modem_dte_t *dte, esp_event_handler_t handler, int32_t event_id, void *handler_args)
{
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
return esp_event_handler_register_with(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, event_id, handler, handler_args);
}
esp_err_t esp_modem_remove_event_handler(esp_modem_dte_t *dte, esp_event_handler_t handler)
{
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
return esp_event_handler_unregister_with(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_EVENT_ANY_ID, handler);
}
esp_err_t esp_modem_start_ppp(esp_modem_dte_t *dte)
{
esp_modem_dce_t *dce = dte->dce;
ESP_MODEM_ERR_CHECK(dce, "DTE has not yet bind with DCE", err);
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
/* Enter PPP mode */
ESP_MODEM_ERR_CHECK(dte->change_mode(dte, ESP_MODEM_PPP_MODE) == ESP_OK, "enter ppp mode failed", err);
/* post PPP mode started event */
esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_MODEM_EVENT_PPP_START, NULL, 0, 0);
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_stop_ppp(esp_modem_dte_t *dte)
{
esp_modem_dce_t *dce = dte->dce;
ESP_MODEM_ERR_CHECK(dce, "DTE has not yet bind with DCE", err);
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
/* Enter command mode */
ESP_MODEM_ERR_CHECK(dte->change_mode(dte, ESP_MODEM_COMMAND_MODE) == ESP_OK, "enter command mode failed", err);
/* post PPP mode stopped event */
esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_MODEM_EVENT_PPP_STOP, NULL, 0, 0);
/* wait for the PPP mode to exit gracefully */
EventBits_t bits = xEventGroupWaitBits(esp_dte->process_group, ESP_MODEM_STOP_PPP_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(20000));
if (!(bits & ESP_MODEM_STOP_PPP_BIT)) {
ESP_LOGW(TAG, "Failed to exit the PPP mode gracefully");
}
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_notify_ppp_netif_closed(esp_modem_dte_t *dte)
{
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
EventBits_t bits = xEventGroupSetBits(esp_dte->process_group, ESP_MODEM_STOP_PPP_BIT);
return bits & ESP_MODEM_STOP_BIT ? ESP_FAIL : ESP_OK; // set error if the group indicated MODEM_STOP condition
}
esp_err_t esp_modem_notify_initialized(esp_modem_dte_t *dte)
{
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
EventBits_t bits = xEventGroupSetBits(esp_dte->process_group, ESP_MODEM_START_BIT);
return bits & ESP_MODEM_START_BIT ? ESP_OK : ESP_FAIL; // START bit should be set (since it's not auto-cleared)
// report error otherwise
}
esp_err_t esp_modem_default_destroy(esp_modem_dte_t *dte)
{
ESP_MODEM_ERR_CHECK(dte, "Cannot destroy NULL dte", err_params);
esp_modem_netif_driver_t *netif_adapter = dte->netif_adapter;
esp_modem_dce_t *dce = dte->dce;
ESP_MODEM_ERR_CHECK(dce && netif_adapter, "Cannot destroy dce or netif_adapter", err_params);
ESP_MODEM_ERR_CHECK(esp_modem_netif_clear_default_handlers(netif_adapter) == ESP_OK,
"modem_netif failed to clread handlers", err);
esp_modem_netif_destroy(netif_adapter);
dte->netif_adapter = NULL;
ESP_MODEM_ERR_CHECK(dce->deinit(dce) == ESP_OK, "failed to deinit dce", err);
dte->dce = NULL;
ESP_MODEM_ERR_CHECK(dte->deinit(dte) == ESP_OK, "failed to deinit ", err);
return ESP_OK;
err:
return ESP_FAIL;
err_params:
return ESP_ERR_INVALID_ARG;
}
esp_err_t esp_modem_default_start(esp_modem_dte_t *dte)
{
ESP_MODEM_ERR_CHECK(dte, "failed to start zero DTE", err_params);
esp_modem_dce_t *dce = dte->dce;
ESP_MODEM_ERR_CHECK(dce, "failed to start zero DCE", err_params);
return dce->start_up(dce);
err_params:
return ESP_ERR_INVALID_ARG;
}
esp_err_t esp_modem_default_attach(esp_modem_dte_t *dte, esp_modem_dce_t *dce, esp_netif_t* ppp_netif)
{
/* Bind DTE with DCE */
dce->dte = dte;
dte->dce = dce;
/* Init and bind DTE with the PPP netif adapter */
esp_modem_netif_driver_t *modem_netif_adapter = esp_modem_netif_new(dte);
ESP_MODEM_ERR_CHECK(esp_modem_netif_set_default_handlers(modem_netif_adapter, ppp_netif) == ESP_OK,
"modem_netif failed to set handlers", err);
ESP_MODEM_ERR_CHECK(esp_netif_attach(ppp_netif, modem_netif_adapter) == ESP_OK,
"attach netif to modem adapter failed", err);
ESP_MODEM_ERR_CHECK(esp_modem_notify_initialized(dte) == ESP_OK, "DTE init notification failed", err);
return ESP_OK;
err:
return ESP_FAIL;
}
esp_modem_dce_t *esp_modem_dce_new(esp_modem_dce_config_t *config)
{
ESP_MODEM_ERR_CHECK(config, "failed to init with zero configuration", err);
esp_modem_dce_t *dce = calloc(1, sizeof(esp_modem_dce_t));
ESP_MODEM_ERR_CHECK(dce, "calloc of esp_modem_dce_t failed", err);
ESP_MODEM_ERR_CHECK(esp_modem_dce_init(dce, config) == ESP_OK, "esp_modem_dce_init has failed", err);
return dce;
err:
return NULL;
}
esp_err_t esp_modem_dce_init(esp_modem_dce_t *dce, esp_modem_dce_config_t *config)
{
esp_err_t err = ESP_OK;
/* init the default DCE first */
ESP_MODEM_ERR_CHECK(dce && config, "failed to init with zero dce or configuration", err_params);
ESP_MODEM_ERR_CHECK(esp_modem_dce_default_init(dce, config) == ESP_OK, "dce default init has failed", err);
if (config->populate_command_list) {
ESP_MODEM_ERR_CHECK(esp_modem_set_default_command_list(dce) == ESP_OK, "esp_modem_dce_set_default_commands failed", err);
}
switch (config->device) {
case ESP_MODEM_DEVICE_SIM800:
err = esp_modem_sim800_specific_init(dce);
break;
case ESP_MODEM_DEVICE_SIM7600:
err = esp_modem_sim7600_specific_init(dce);
break;
case ESP_MODEM_DEVICE_BG96:
err = esp_modem_bg96_specific_init(dce);
break;
default:
case ESP_MODEM_DEVICE_UNSPECIFIED:
break;
}
ESP_MODEM_ERR_CHECK(err == ESP_OK, "dce specific initialization has failed for %d type device", err, config->device);
return ESP_OK;
err:
return ESP_FAIL;
err_params:
return ESP_ERR_INVALID_ARG;
}

View File

@ -6,11 +6,12 @@
#include "esp_log.h"
#include "cxx_include/esp_modem_api.hpp"
#include "esp_modem_api.h"
#include "esp_modem_config.h"
static const char *TAG = "dce_factory";
struct PdpContext;
std::shared_ptr<DTE> create_uart_dte(const dte_config *config)
std::shared_ptr<DTE> create_uart_dte(const esp_modem_dte_config *config)
{
try {
auto term = create_uart_terminal(config);
@ -85,7 +86,7 @@ static inline esp_err_t command_response_to_esp_err(command_result res)
return ESP_ERR_INVALID_ARG;
}
extern "C" esp_modem_t *esp_modem_new(const dte_config *config, esp_netif_t *netif, const char* apn)
extern "C" esp_modem_t *esp_modem_new(const esp_modem_dte_config *config, esp_netif_t *netif, const char* apn)
{
auto dce_wrap = new (std::nothrow) esp_modem_dce_wrap;
if (dce_wrap == nullptr)

View File

@ -1,247 +0,0 @@
// Copyright 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.
#include <stdlib.h>
#include "esp_log.h"
#include "esp_modem.h"
#include "esp_modem_dte.h"
#include "esp_modem_dce.h"
#include "esp_modem_compat.h"
#include "esp_modem_dce_common_commands.h"
/**
* @brief Error check macro
*
*/
#define ESP_MODEM_COMPAT_CHECK(a, str, goto_tag, ...) \
do \
{ \
if (!(a)) \
{ \
ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
goto goto_tag; \
} \
} while (0)
static const char *TAG = "esp-modem-compat";
/**
* @note Below are the backward compatible functions defined using esp_modem_dce framework
*
*/
static esp_err_t compat_hang_up(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_dce->hang_up(esp_dce, NULL, NULL);
}
static esp_err_t compat_echo(modem_dce_t *dce, bool on)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_dce->set_echo(esp_dce, (void*)on, NULL);
}
static esp_err_t compat_define_pdp_context(modem_dce_t *dce, uint32_t cid, const char *type, const char *apn)
{
esp_modem_dce_pdp_ctx_t pdp = { .type = type, .cid = cid, .apn = apn };
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_dce->set_pdp_context(esp_dce, &pdp, NULL);
}
static esp_err_t compat_sync(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_dce->sync(esp_dce, NULL, NULL);
}
static esp_err_t compat_set_flow_ctrl(modem_dce_t *dce, esp_modem_flow_ctrl_t flow_ctrl)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_dce->set_flow_ctrl(esp_dce, (void*)flow_ctrl, NULL);
}
static esp_err_t compat_store_profile(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_dce->store_profile(esp_dce, NULL, NULL);
}
static esp_err_t compat_get_signal_quality(modem_dce_t *dce, uint32_t *rssi, uint32_t *ber)
{
esp_modem_dce_csq_ctx_t result;
esp_modem_dce_t* esp_dce = &dce->parent;
esp_err_t err = esp_modem_command_list_run(esp_dce, "get_signal_quality", NULL, &result);
if (err == ESP_OK) {
*rssi = result.rssi;
*ber = result.ber;
}
return err;
}
static esp_err_t compat_get_battery_status(modem_dce_t *dce, uint32_t *bcs, uint32_t *bcl, uint32_t *voltage)
{
esp_modem_dce_cbc_ctx_t result;
esp_modem_dce_t* esp_dce = &dce->parent;
esp_err_t err = esp_modem_command_list_run(esp_dce, "get_battery_status", NULL, &result);
if (err == ESP_OK) {
*bcs = result.bcs;
*bcl = result.bcl;
*voltage = result.battery_status;
}
return err;
}
static esp_err_t compat_set_working_mode(modem_dce_t *dce, esp_modem_mode_t mode)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_modem_dce_set_working_mode(esp_dce, mode);
}
static esp_err_t compat_get_module_name(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_modem_command_list_run(esp_dce, "get_module_name", (void *) sizeof(dce->name), dce->name);
}
static esp_err_t compat_get_imei_number(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_modem_command_list_run(esp_dce, "get_imei_number", (void *) sizeof(dce->imei), dce->imei);
}
static esp_err_t compat_get_operator_name(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_modem_command_list_run(esp_dce, "get_operator_name", (void *) sizeof(dce->oper), dce->oper);
}
static esp_err_t compat_get_imsi_number(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_modem_command_list_run(esp_dce, "get_imsi_number", (void *) sizeof(dce->imsi), dce->imsi);
}
static esp_err_t compat_power_down(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
return esp_modem_command_list_run(esp_dce, "power_down", (void *) sizeof(dce->imsi), dce->imsi);
}
/**
* @brief Compatibility deinitialize
*
* @param dce Modem DCE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on fail
*/
static esp_err_t compat_deinit(modem_dce_t *dce)
{
esp_modem_dce_t* esp_dce = &dce->parent;
esp_err_t err = esp_modem_command_list_deinit(esp_dce);
if (err == ESP_OK) {
free(dce);
}
return err;
}
/**
* @brief Compatibility init
*
*/
static modem_dce_t *esp_modem_compat_init(modem_dte_t *dte, esp_modem_dce_device_t device)
{
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_MODEM_PPP_APN);
dce_config.device = device;
dce_config.populate_command_list = true;
modem_dce_t *dce = calloc(1, sizeof(modem_dce_t));
if (dce == NULL) {
return NULL;
}
if (esp_modem_dce_init(&dce->parent, &dce_config) != ESP_OK) {
free(dce);
return NULL;
}
dce->sync = compat_sync;
dce->echo_mode = compat_echo;
dce->store_profile = compat_store_profile;
dce->set_flow_ctrl = compat_set_flow_ctrl;
dce->define_pdp_context = compat_define_pdp_context;
dce->hang_up = compat_hang_up;
dce->get_signal_quality = compat_get_signal_quality;
dce->get_battery_status = compat_get_battery_status;
dce->set_working_mode = compat_set_working_mode;
dce->power_down = compat_power_down;
dce->deinit = compat_deinit;
esp_modem_dce_t* esp_dce = &dce->parent;
/* Bind DTE with DCE */
esp_dce->dte = dte;
dte->dce = esp_dce;
/* All units initialized, notify the modem before sending commands */
ESP_MODEM_COMPAT_CHECK(esp_modem_notify_initialized(dte) == ESP_OK, "modem start notification failed", err);
ESP_MODEM_COMPAT_CHECK(compat_sync(dce) == ESP_OK, "sync failed", err);
/* Close echo */
ESP_MODEM_COMPAT_CHECK(compat_echo(dce, false) == ESP_OK, "close echo mode failed", err);
bool ready;
ESP_ERROR_CHECK(esp_modem_command_list_run(esp_dce, "read_pin", NULL, &ready));
if (!ready) {
ESP_LOGE(TAG, "PIN not ready man");
ESP_ERROR_CHECK(esp_modem_command_list_run(esp_dce, "set_pin", "1234", NULL));
}
/* Get Module name */
ESP_MODEM_COMPAT_CHECK(compat_get_module_name(dce) == ESP_OK, "get module name failed", err);
/* Get IMEI number */
ESP_MODEM_COMPAT_CHECK(compat_get_imei_number(dce) == ESP_OK, "get imei number failed", err);
/* Get IMSI number */
ESP_MODEM_COMPAT_CHECK(compat_get_imsi_number(dce) == ESP_OK, "get imsi number failed", err);
/* Get operator name */
ESP_MODEM_COMPAT_CHECK(compat_get_operator_name(dce) == ESP_OK, "get operator name failed", err);
return dce;
err:
return NULL;
}
/**
* @brief Legacy init of SIM800 module
*
*/
modem_dce_t *sim800_init(modem_dte_t *dte)
{
return esp_modem_compat_init(dte, ESP_MODEM_DEVICE_SIM800);
}
/**
* @brief Legacy init of BG96 module
*
*/
modem_dce_t *bg96_init(modem_dte_t *dte)
{
return esp_modem_compat_init(dte, ESP_MODEM_DEVICE_BG96);
}
/**
* @brief Legacy init of SIM7600 module
*
*/
modem_dce_t *sim7600_init(modem_dte_t *dte)
{
return esp_modem_compat_init(dte, ESP_MODEM_DEVICE_SIM7600);
}

View File

@ -1,180 +0,0 @@
// 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.
#include <string.h>
#include "esp_modem_dce.h"
#include "esp_modem_dce_command_lib.h"
#include "esp_modem_dce_common_commands.h"
#include "esp_modem_internal.h"
#include "esp_log.h"
static const char *TAG = "esp_modem_dce";
esp_err_t esp_modem_dce_generic_command(esp_modem_dce_t *dce, const char * command, uint32_t timeout, esp_modem_dce_handle_line_t handle_line, void *ctx)
{
esp_modem_dte_t *dte = dce->dte;
ESP_LOGD(TAG, "%s(%d): Sending command:%s\n", __func__, __LINE__, command );
dce->handle_line = handle_line;
dce->handle_line_ctx = ctx;
if (dte->send_cmd(dte, command, timeout) != ESP_OK) {
ESP_LOGW(TAG, "%s(%d): Command:%s response timeout", __func__, __LINE__, command );
return ESP_ERR_TIMEOUT;
}
if (dce->state == ESP_MODEM_STATE_FAIL) {
ESP_LOGW(TAG, "%s(%d): Command:%s\n...failed", __func__, __LINE__, command );
return ESP_FAIL;
}
ESP_LOGD(TAG, "%s(%d): Command:%s\n succeeded", __func__, __LINE__, command );
return ESP_OK;
}
esp_err_t esp_modem_dce_set_params(esp_modem_dce_t *dce, esp_modem_dce_config_t* config)
{
// save the config
memcpy(&dce->config, config, sizeof(esp_modem_dce_config_t));
return ESP_OK;
}
esp_err_t esp_modem_dce_default_init(esp_modem_dce_t *dce, esp_modem_dce_config_t* config)
{
// Check parameters
ESP_MODEM_ERR_CHECK(dce && config, "dce object or configuration is NULL", err);
// Set default commands needed for the DCE to operate
// note: command links will be overwritten if cmd-list enabled
dce->set_data_mode = esp_modem_dce_set_data_mode;
dce->resume_data_mode = esp_modem_dce_resume_data_mode;
dce->set_command_mode = esp_modem_dce_set_command_mode;
dce->set_pdp_context = esp_modem_dce_set_pdp_context;
dce->hang_up = esp_modem_dce_hang_up;
dce->set_echo = esp_modem_dce_set_echo;
dce->sync = esp_modem_dce_sync;
dce->set_flow_ctrl = esp_modem_dce_set_flow_ctrl;
dce->store_profile = esp_modem_dce_store_profile;
ESP_MODEM_ERR_CHECK(esp_modem_dce_set_params(dce, config) == ESP_OK, "Failed to configure dce object", err);
// set DCE basic API
dce->start_up = esp_modem_dce_default_start_up;
dce->deinit = esp_modem_dce_default_destroy;
dce->set_working_mode = esp_modem_dce_set_working_mode;
// initialize the list if enabled
if (config->populate_command_list) {
dce->dce_cmd_list = esp_modem_command_list_create();
ESP_MODEM_ERR_CHECK(dce->dce_cmd_list, "Allocation of dce internal object has failed", err);
}
return ESP_OK;
err:
return ESP_ERR_NO_MEM;
}
esp_err_t esp_modem_dce_default_destroy(esp_modem_dce_t *dce)
{
ESP_MODEM_ERR_CHECK(esp_modem_command_list_deinit(dce) == ESP_OK, "failed", err);
free(dce);
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_handle_response_default(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
}
return err;
}
esp_err_t esp_modem_process_command_done(esp_modem_dce_t *dce, esp_modem_state_t state)
{
dce->state = state;
return dce->dte->process_cmd_done(dce->dte);
}
static esp_err_t esp_modem_switch_to_command_mode(esp_modem_dce_t *dce)
{
esp_modem_wait_ms(1000); // 1s delay for the device to recognize the data escape sequence
if (dce->set_command_mode(dce, NULL, NULL) != ESP_OK) {
// exiting data mode could fail if the modem is already in command mode via PPP netif closed
ESP_MODEM_ERR_CHECK(dce->sync(dce, NULL, NULL) == ESP_OK, "sync after PPP exit failed", err);
} else {
// hang-up if exit PPP succeeded
dce->mode = ESP_MODEM_COMMAND_MODE;
ESP_MODEM_ERR_CHECK(dce->hang_up(dce, NULL, NULL) == ESP_OK, "hang-up after PPP exit failed", err);
}
dce->mode = ESP_MODEM_COMMAND_MODE;
return ESP_OK;
err:
return ESP_FAIL;
}
static esp_err_t esp_modem_switch_to_data_mode(esp_modem_dce_t *dce)
{
// before going to data mode, set the PDP data context
ESP_MODEM_ERR_CHECK(dce->set_pdp_context(dce, &dce->config.pdp_context, NULL) == ESP_OK, "setting pdp context failed", err);
// now set the data mode
if (dce->set_data_mode(dce, NULL, NULL) != ESP_OK) {
// Initiate PPP mode could fail, if we've already "dialed" the data call before.
// in that case we retry to just resume the data mode
ESP_LOGD(TAG, "set_data_mode, retry with resume_data_mode");
ESP_MODEM_ERR_CHECK(dce->resume_data_mode(dce, NULL, NULL) == ESP_OK, "setting data mode failed", err);
}
dce->mode = ESP_MODEM_PPP_MODE;
return ESP_OK;
err:
return ESP_FAIL;
}
/**
* @brief Set Working Mode
*
* @param dce Modem DCE object
* @param mode working mode
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_set_working_mode(esp_modem_dce_t *dce, esp_modem_mode_t mode)
{
switch (mode) {
case ESP_MODEM_COMMAND_MODE:
ESP_MODEM_ERR_CHECK(esp_modem_switch_to_command_mode(dce) == ESP_OK, "Setting command mode failed", err);
break;
case ESP_MODEM_PPP_MODE:
ESP_MODEM_ERR_CHECK(esp_modem_switch_to_data_mode(dce) == ESP_OK, "Setting data mode failed", err);
break;
default:
ESP_LOGW(TAG, "unsupported working mode: %d", mode);
goto err;
}
return ESP_OK;
err:
return ESP_FAIL;
}
esp_err_t esp_modem_dce_default_start_up(esp_modem_dce_t *dce)
{
ESP_MODEM_ERR_CHECK(dce->sync(dce, NULL, NULL) == ESP_OK, "sending sync failed", err);
ESP_MODEM_ERR_CHECK(dce->set_echo(dce, (void*)false, NULL) == ESP_OK, "set_echo failed", err);
ESP_MODEM_ERR_CHECK(dce->set_flow_ctrl(dce, (void*)ESP_MODEM_FLOW_CONTROL_NONE, NULL) == ESP_OK, "set_flow_ctrl failed", err);
ESP_MODEM_ERR_CHECK(dce->store_profile(dce, NULL, NULL) == ESP_OK, "store_profile failed", err);
return ESP_OK;
err:
return ESP_FAIL;
}

View File

@ -1,202 +0,0 @@
// 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.
#include <string.h>
#include "esp_log.h"
#include "esp_modem_dce_command_lib.h"
#include "esp_modem_internal.h"
#include "esp_modem_dce_common_commands.h"
static const char *TAG = "esp_modem_command_lib";
typedef struct cmd_item_s cmd_item_t;
/**
* struct for one item in command list
*/
struct cmd_item_s {
const char *command; //!< command name
dce_command_t function; //!< function pointer
SLIST_ENTRY(cmd_item_s) next; //!< next command in the list
};
/**
* private struct defined for dce internal object
*/
struct esp_modem_dce_cmd_list {
SLIST_HEAD(cmd_list_, cmd_item_s) command_list;
};
/**
* @brief List of common AT commands in the library
*
*/
static const cmd_item_t s_command_list[] = {
{ .command = "sync", .function = esp_modem_dce_sync },
{ .command = "get_imei_number", .function = esp_modem_dce_get_imei_number },
{ .command = "get_imsi_number", .function = esp_modem_dce_get_imsi_number },
{ .command = "get_module_name", .function = esp_modem_dce_get_module_name },
{ .command = "get_operator_name", .function = esp_modem_dce_get_operator_name },
{ .command = "set_echo", .function = esp_modem_dce_set_echo },
{ .command = "store_profile", .function = esp_modem_dce_store_profile },
{ .command = "set_flow_ctrl", .function = esp_modem_dce_set_flow_ctrl },
{ .command = "set_pdp_context", .function = esp_modem_dce_set_pdp_context },
{ .command = "hang_up", .function = esp_modem_dce_hang_up },
{ .command = "get_signal_quality", .function = esp_modem_dce_get_signal_quality },
{ .command = "set_data_mode", .function = esp_modem_dce_set_data_mode },
{ .command = "resume_data_mode", .function = esp_modem_dce_resume_data_mode },
{ .command = "set_command_mode", .function = esp_modem_dce_set_command_mode },
{ .command = "get_battery_status", .function = esp_modem_dce_get_battery_status },
{ .command = "power_down", .function = esp_modem_dce_power_down },
{ .command = "reset", .function = esp_modem_dce_reset },
{ .command = "set_pin", .function = esp_modem_dce_set_pin },
{ .command = "read_pin", .function = esp_modem_dce_read_pin },
{ .command = "set_baud", .function = esp_modem_dce_set_baud_temp },
};
static esp_err_t update_internal_command_refs(esp_modem_dce_t *dce)
{
ESP_MODEM_ERR_CHECK(dce->set_data_mode = esp_modem_dce_find_command(dce, "set_data_mode"), "cmd not found", err);
ESP_MODEM_ERR_CHECK(dce->resume_data_mode = esp_modem_dce_find_command(dce, "resume_data_mode"), "cmd not found", err);
ESP_MODEM_ERR_CHECK(dce->set_command_mode = esp_modem_dce_find_command(dce, "set_command_mode"), "cmd not found", err);
ESP_MODEM_ERR_CHECK(dce->set_pdp_context = esp_modem_dce_find_command(dce, "set_pdp_context"), "cmd not found", err);
ESP_MODEM_ERR_CHECK(dce->hang_up = esp_modem_dce_find_command(dce, "hang_up"), "cmd not found", err);
ESP_MODEM_ERR_CHECK(dce->set_echo = esp_modem_dce_find_command(dce, "set_echo"), "cmd not found", err);
ESP_MODEM_ERR_CHECK(dce->sync = esp_modem_dce_find_command(dce, "sync"), "cmd not found", err);
ESP_MODEM_ERR_CHECK(dce->set_flow_ctrl = esp_modem_dce_find_command(dce, "set_flow_ctrl"), "cmd not found", err);
ESP_MODEM_ERR_CHECK(dce->store_profile = esp_modem_dce_find_command(dce, "store_profile"), "cmd not found", err);
return ESP_OK;
err:
return ESP_FAIL;
}
static esp_err_t esp_modem_dce_init_command_list(esp_modem_dce_t *dce, size_t commands, const cmd_item_t *command_list)
{
if (commands < 1 || command_list == NULL || dce->dce_cmd_list == NULL) {
return ESP_ERR_INVALID_ARG;
}
SLIST_INIT(&dce->dce_cmd_list->command_list);
for (int i=0; i < commands; ++i) {
cmd_item_t *new_item = calloc(1, sizeof(struct cmd_item_s));
new_item->command = command_list[i].command;
new_item->function = command_list[i].function;
SLIST_INSERT_HEAD(&dce->dce_cmd_list->command_list, new_item, next);
}
return ESP_OK;
}
esp_err_t esp_modem_set_default_command_list(esp_modem_dce_t *dce)
{
esp_err_t err = esp_modem_dce_init_command_list(dce, sizeof(s_command_list) / sizeof(cmd_item_t), s_command_list);
if (err == ESP_OK) {
return update_internal_command_refs(dce);
}
return err;
}
esp_err_t esp_modem_command_list_run(esp_modem_dce_t *dce, const char * command, void * param, void* result)
{
if (dce == NULL || dce->dce_cmd_list == NULL) {
return ESP_ERR_INVALID_ARG;
}
cmd_item_t *item;
SLIST_FOREACH(item, &dce->dce_cmd_list->command_list, next) {
if (strcmp(item->command, command) == 0) {
return item->function(dce, param, result);
}
}
return ESP_ERR_NOT_FOUND;
}
dce_command_t esp_modem_dce_find_command(esp_modem_dce_t *dce, const char * command)
{
if (dce == NULL || dce->dce_cmd_list == NULL) {
return NULL;
}
cmd_item_t *item;
SLIST_FOREACH(item, &dce->dce_cmd_list->command_list, next) {
if (strcmp(item->command, command) == 0) {
return item->function;
}
}
return NULL;
}
esp_err_t esp_modem_dce_delete_all_commands(esp_modem_dce_t *dce)
{
if (dce->dce_cmd_list) {
while (!SLIST_EMPTY(&dce->dce_cmd_list->command_list)) {
cmd_item_t *item = SLIST_FIRST(&dce->dce_cmd_list->command_list);
SLIST_REMOVE_HEAD(&dce->dce_cmd_list->command_list, next);
free(item);
}
}
return ESP_OK;
}
esp_err_t esp_modem_dce_delete_command(esp_modem_dce_t *dce, const char * command_id)
{
cmd_item_t *item;
SLIST_FOREACH(item, &dce->dce_cmd_list->command_list, next) {
if (strcmp(item->command, command_id) == 0) {
SLIST_REMOVE(&dce->dce_cmd_list->command_list, item, cmd_item_s, next);
free(item);
return ESP_OK;
}
}
return ESP_ERR_NOT_FOUND;
}
esp_err_t esp_modem_command_list_set_cmd(esp_modem_dce_t *dce, const char * command_id, dce_command_t command)
{
if (dce == NULL || dce->dce_cmd_list == NULL) {
return ESP_ERR_INVALID_ARG;
}
cmd_item_t *item;
SLIST_FOREACH(item, &dce->dce_cmd_list->command_list, next) {
if (strcmp(item->command, command_id) == 0) {
item->function = command;
return update_internal_command_refs(dce);
}
}
cmd_item_t *new_item = calloc(1, sizeof(struct cmd_item_s));
new_item->command = command_id;
new_item->function = command;
SLIST_INSERT_HEAD(&dce->dce_cmd_list->command_list, new_item, next);
return update_internal_command_refs(dce);;
}
struct esp_modem_dce_cmd_list* esp_modem_command_list_create(void)
{
return calloc(1, sizeof(struct esp_modem_dce_cmd_list));
}
esp_err_t esp_modem_command_list_deinit(esp_modem_dce_t *dce)
{
if (dce->dte) {
dce->dte->dce = NULL;
}
esp_modem_dce_delete_all_commands(dce);
free(dce->dce_cmd_list);
return ESP_OK;
}

View File

@ -1,357 +0,0 @@
// 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.
#include <string.h>
#include "esp_log.h"
#include "esp_modem_dce.h"
#include "esp_modem_dce_common_commands.h"
typedef struct common_string_s {
const char * command;
char * string;
size_t len;
} common_string_t;
static inline esp_err_t generic_command_default_handle(esp_modem_dce_t *dce, const char * command)
{
return esp_modem_dce_generic_command(dce, command, MODEM_COMMAND_TIMEOUT_DEFAULT, esp_modem_dce_handle_response_default, NULL);
}
static esp_err_t common_handle_string(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
} else {
common_string_t *result_str = dce->handle_line_ctx;
assert(result_str->string != NULL && result_str->len != 0);
int len = snprintf(result_str->string, result_str->len, "%s", line);
if (len > 2) {
/* Strip "\r\n" */
strip_cr_lf_tail(result_str->string, len);
err = ESP_OK;
}
}
return err;
}
/**
* @brief Handle response from AT+CBC
*/
static esp_err_t esp_modem_dce_common_handle_cbc(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
} else if (!strncmp(line, "+CBC", strlen("+CBC"))) {
esp_modem_dce_cbc_ctx_t *cbc = dce->handle_line_ctx;
/* +CBC: <bcs>,<bcl>,<voltage> */
sscanf(line, "%*s%d,%d,%d", &cbc->bcs, &cbc->bcl, &cbc->battery_status);
err = ESP_OK;
}
return err;
}
/**
* @brief Handle response from AT+CSQ
*/
static esp_err_t esp_modem_dce_common_handle_csq(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
} else if (!strncmp(line, "+CSQ", strlen("+CSQ"))) {
/* store value of rssi and ber */
esp_modem_dce_csq_ctx_t *csq = dce->handle_line_ctx;
/* +CSQ: <rssi>,<ber> */
sscanf(line, "%*s%d,%d", &csq->rssi, &csq->ber);
err = ESP_OK;
}
return err;
}
/**
* @brief Handle response from AT+QPOWD=1
*/
static esp_err_t esp_modem_dce_handle_power_down(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = ESP_OK;
} else if (strstr(line, "POWERED DOWN")) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
}
return err;
}
/**
* @brief Handle response from exiting the PPP mode
*/
static esp_err_t esp_modem_dce_handle_exit_data_mode(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_NO_CARRIER)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
}
return err;
}
/**
* @brief Handle response from entry of the PPP mode
*/
static esp_err_t esp_modem_dce_handle_atd_ppp(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_CONNECT)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
}
return err;
}
static esp_err_t esp_modem_dce_handle_read_pin(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, "READY")) {
bool *ready = (bool*)dce->handle_line_ctx;
*ready = true;
err = ESP_OK;
} else if (strstr(line, "PIN") || strstr(line, "PUK")) {
bool *ready = (bool*)dce->handle_line_ctx;
*ready = false;
err = ESP_OK;
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
}
return err;
}
static esp_err_t esp_modem_dce_handle_reset(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_OK;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = ESP_OK;
} else
if (strstr(line, "PB DONE")) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
}
return err;
}
esp_err_t esp_modem_dce_sync(esp_modem_dce_t *dce, void *param, void *result)
{
return generic_command_default_handle(dce, "AT\r");
}
esp_err_t esp_modem_dce_set_echo(esp_modem_dce_t *dce, void *param, void *result)
{
bool echo_on = (bool)param;
if (echo_on) {
return generic_command_default_handle(dce, "ATE1\r");
} else {
return generic_command_default_handle(dce, "ATE0\r");
}
}
static esp_err_t common_get_operator_after_mode_format(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
} else if (!strncmp(line, "+COPS", strlen("+COPS"))) {
common_string_t *result_str = dce->handle_line_ctx;
assert(result_str->string != NULL && result_str->len != 0);
/* there might be some random spaces in operator's name, we can not use sscanf to parse the result */
/* strtok will break the string, we need to create a copy */
char *line_copy = strdup(line);
/* +COPS: <mode>[, <format>[, <oper>]] */
char *str_ptr = NULL;
char *p[3];
uint8_t i = 0;
/* strtok will broke string by replacing delimiter with '\0' */
p[i] = strtok_r(line_copy, ",", &str_ptr);
while (p[i]) {
p[++i] = strtok_r(NULL, ",", &str_ptr);
}
if (i >= 3) {
int len = snprintf(result_str->string, result_str->len, "%s", p[2]);
if (len > 2) {
/* Strip "\r\n" */
strip_cr_lf_tail(result_str->string, len);
err = ESP_OK;
}
}
free(line_copy);
}
return err;
}
static esp_err_t common_get_common_string(esp_modem_dce_t *dce, void *ctx)
{
common_string_t * param_str = ctx;
return esp_modem_dce_generic_command(dce, param_str->command, MODEM_COMMAND_TIMEOUT_DEFAULT, common_handle_string, ctx);
}
esp_err_t esp_modem_dce_get_imei_number(esp_modem_dce_t *dce, void *param, void *result)
{
common_string_t common_str = { .command = "AT+CGSN\r", .string = result, .len = (size_t)param };
return common_get_common_string(dce, &common_str);
}
esp_err_t esp_modem_dce_get_imsi_number(esp_modem_dce_t *dce, void *param, void *result)
{
common_string_t common_str = { .command = "AT+CIMI\r", .string = result, .len = (size_t)param };
return common_get_common_string(dce, &common_str);
}
esp_err_t esp_modem_dce_get_module_name(esp_modem_dce_t *dce, void *param, void *result)
{
common_string_t common_str = { .command = "AT+CGMM\r", .string = result, .len = (size_t)param };
return common_get_common_string(dce, &common_str);
}
esp_err_t esp_modem_dce_get_operator_name(esp_modem_dce_t *dce, void *param, void *result)
{
common_string_t common_str = { .command = "AT+COPS?\r", .string = result, .len = (size_t)param };
return esp_modem_dce_generic_command(dce, common_str.command, MODEM_COMMAND_TIMEOUT_OPERATOR,
common_get_operator_after_mode_format, &common_str);
}
esp_err_t esp_modem_dce_reset(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "AT+CRESET\r", MODEM_COMMAND_TIMEOUT_RESET, esp_modem_dce_handle_reset, NULL);
}
esp_err_t esp_modem_dce_set_pin(esp_modem_dce_t *dce, void *param, void *result)
{
char command[] = "AT+CPIN=0000\r";
memcpy(command + 8, param, 4); // copy 4 bytes to the "0000" placeholder
esp_err_t err = esp_modem_dce_generic_command(dce, command, MODEM_COMMAND_TIMEOUT_DEFAULT, esp_modem_dce_handle_response_default, NULL);
return err;
}
esp_err_t esp_modem_dce_read_pin(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "AT+CPIN?\r", MODEM_COMMAND_TIMEOUT_DEFAULT, esp_modem_dce_handle_read_pin, result);
}
esp_err_t esp_modem_dce_store_profile(esp_modem_dce_t *dce, void *param, void *result)
{
return generic_command_default_handle(dce, "AT&W\r");
}
esp_err_t esp_modem_dce_set_flow_ctrl(esp_modem_dce_t *dce, void *param, void *result)
{
esp_modem_dte_t *dte = dce->dte;
esp_modem_flow_ctrl_t flow_ctrl = (esp_modem_flow_ctrl_t)param;
char *command;
int len = asprintf(&command, "AT+IFC=%d,%d\r", dte->flow_ctrl, flow_ctrl);
if (len <= 0) {
return ESP_ERR_NO_MEM;
}
esp_err_t err = generic_command_default_handle(dce, command);
free(command);
return err;
}
esp_err_t esp_modem_dce_set_pdp_context(esp_modem_dce_t *dce, void *param, void *result)
{
esp_modem_dce_pdp_ctx_t *pdp = param;
char *command;
int len = asprintf(&command, "AT+CGDCONT=%d,\"%s\",\"%s\"\r", pdp->cid, pdp->type, pdp->apn);
if (len <= 0) {
return ESP_ERR_NO_MEM;
}
esp_err_t err = generic_command_default_handle(dce, command);
free(command);
return err;
}
#define MODEM_COMMAND_TIMEOUT_HANG_UP (90000) /*!< Timeout value for hang up */
esp_err_t esp_modem_dce_hang_up(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "ATH\r", MODEM_COMMAND_TIMEOUT_HANG_UP,
esp_modem_dce_handle_response_default, NULL);
}
esp_err_t esp_modem_dce_get_signal_quality(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "AT+CSQ\r", MODEM_COMMAND_TIMEOUT_DEFAULT,
esp_modem_dce_common_handle_csq, result);
}
esp_err_t esp_modem_dce_get_battery_status(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "AT+CBC\r", MODEM_COMMAND_TIMEOUT_DEFAULT,
esp_modem_dce_common_handle_cbc, result);
}
esp_err_t esp_modem_dce_set_data_mode(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "ATD*99***1#\r", MODEM_COMMAND_TIMEOUT_MODE_CHANGE,
esp_modem_dce_handle_atd_ppp, NULL);
}
esp_err_t esp_modem_dce_resume_data_mode(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "ATO\r", MODEM_COMMAND_TIMEOUT_MODE_CHANGE,
esp_modem_dce_handle_atd_ppp, NULL);
}
esp_err_t esp_modem_dce_set_command_mode(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "+++", MODEM_COMMAND_TIMEOUT_MODE_CHANGE,
esp_modem_dce_handle_exit_data_mode, NULL);
}
esp_err_t esp_modem_dce_power_down(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "AT+QPOWD=1\r", MODEM_COMMAND_TIMEOUT_POWEROFF,
esp_modem_dce_handle_power_down, NULL);
}
esp_err_t esp_modem_dce_set_baud_temp(esp_modem_dce_t *dce, void *param, void *result)
{
char command[] = "AT+IPR=3686400\r"; // reserve space with max baud placeholder
size_t cmd_placeholder_len = strlen(command);
strncpy(command + 7, param, cmd_placeholder_len-7); // copy param string to the param
size_t cmd_len = strlen(command);
if (cmd_len+1 >= cmd_placeholder_len) {
return ESP_FAIL;
}
command[cmd_len] = '\r';
command[cmd_len+1] = '\0';
return esp_modem_dce_generic_command(dce, command, MODEM_COMMAND_TIMEOUT_DEFAULT,
esp_modem_dce_handle_response_default, NULL);
}

View File

@ -1,549 +0,0 @@
// Copyright 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.
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_modem.h"
#include "esp_modem_dce.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_modem_internal.h"
#include "esp_modem_dte_internal.h"
#define ESP_MODEM_EVENT_QUEUE_SIZE (16)
#define MIN_PATTERN_INTERVAL (9)
#define MIN_POST_IDLE (0)
#define MIN_PRE_IDLE (0)
/**
* @brief Macro defined for error checking
*
*/
static const char *TAG = "esp-modem-dte";
/**
* @brief Returns true if the supplied string contains only CR or LF
*
* @param str string to check
* @param len length of string
*/
static inline bool is_only_cr_lf(const char *str, uint32_t len)
{
for (int i=0; i<len; ++i) {
if (str[i] != '\r' && str[i] != '\n') {
return false;
}
}
return true;
}
esp_err_t esp_modem_set_rx_cb(esp_modem_dte_t *dte, esp_modem_on_receive receive_cb, void *receive_cb_ctx)
{
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
esp_dte->receive_cb_ctx = receive_cb_ctx;
esp_dte->receive_cb = receive_cb;
return ESP_OK;
}
/**
* @brief Handle one line in DTE
*
* @param esp_dte ESP modem DTE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t esp_dte_handle_line(esp_modem_dte_internal_t *esp_dte)
{
esp_err_t err = ESP_FAIL;
esp_modem_dce_t *dce = esp_dte->parent.dce;
ESP_MODEM_ERR_CHECK(dce, "DTE has not yet bind with DCE", err);
const char *line = (const char *)(esp_dte->buffer);
size_t len = strlen(line);
/* Skip pure "\r\n" lines */
if (len > 2 && !is_only_cr_lf(line, len)) {
if (dce->handle_line == NULL) {
/* Received an asynchronous line, but no handler waiting this this */
ESP_LOGD(TAG, "No handler for line: %s", line);
err = ESP_OK; /* Not an error, just propagate the line to user handler */
goto post_event_unknown;
}
ESP_MODEM_ERR_CHECK(dce->handle_line(dce, line) == ESP_OK, "handle line failed", err);
}
return ESP_OK;
post_event_unknown:
/* Send ESP_MODEM_EVENT_UNKNOWN signal to event loop */
esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_MODEM_EVENT_UNKNOWN,
(void *)line, strlen(line) + 1, pdMS_TO_TICKS(100));
err:
return err;
}
/**
* @brief Handle when a pattern has been detected by UART
*
* @param esp_dte ESP32 Modem DTE object
*/
static void esp_handle_uart_pattern(esp_modem_dte_internal_t *esp_dte)
{
int pos = uart_pattern_pop_pos(esp_dte->uart_port);
int read_len = 0;
if (esp_dte->parent.dce->mode == ESP_MODEM_PPP_MODE) {
ESP_LOGD(TAG, "Pattern event in PPP mode ignored");
// Ignore potential pattern detection events in PPP mode
// Note 1: the interrupt is disabled, but some events might still be pending
// Note 2: checking the mode *after* uart_pattern_pop_pos() to consume the event
return;
}
if (pos != -1) {
if (pos < esp_dte->line_buffer_size - 1) {
/* read one line(include '\n') */
read_len = pos + 1;
} else {
ESP_LOGW(TAG, "ESP Modem Line buffer too small");
read_len = esp_dte->line_buffer_size - 1;
}
read_len = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, read_len, pdMS_TO_TICKS(100));
if (read_len) {
/* make sure the line is a standard string */
esp_dte->buffer[read_len] = '\0';
/* Send new line to handle */
esp_dte_handle_line(esp_dte);
} else {
ESP_LOGE(TAG, "uart read bytes failed");
}
} else {
size_t length = 0;
uart_get_buffered_data_len(esp_dte->uart_port, &length);
if (length) {
ESP_LOGD(TAG, "Pattern not found in the pattern queue, uart data length = %d", length);
length = MIN(esp_dte->line_buffer_size-1, length);
length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY);
ESP_LOG_BUFFER_HEXDUMP("esp-modem-pattern: debug_data", esp_dte->buffer, length, ESP_LOG_DEBUG);
}
uart_flush(esp_dte->uart_port);
}
}
/**
* @brief Handle when new data received by UART
*
* @param esp_dte ESP32 Modem DTE object
*/
static void esp_handle_uart_data(esp_modem_dte_internal_t *esp_dte)
{
size_t length = 0;
uart_get_buffered_data_len(esp_dte->uart_port, &length);
ESP_LOGD(TAG, "esp-modem:esp_handle_uart_data");
if (esp_dte->parent.dce->mode != ESP_MODEM_PPP_MODE && length) {
// Check if matches the pattern to process the data as pattern
int pos = uart_pattern_get_pos(esp_dte->uart_port);
if (pos > -1) {
esp_handle_uart_pattern(esp_dte);
return;
}
// Read the data and process it using `handle_line` logic
length = MIN(esp_dte->line_buffer_size-1, length);
length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY);
esp_dte->buffer[length] = '\0';
if (strchr((char*)esp_dte->buffer, '\n') == NULL) {
size_t max = esp_dte->line_buffer_size-1;
size_t bytes;
// if pattern not found in the data,
// continue reading as long as the modem is in MODEM_STATE_PROCESSING, checking for the pattern
while (length < max && esp_dte->buffer[length-1] != '\n' &&
esp_dte->parent.dce->state == ESP_MODEM_STATE_PROCESSING) {
bytes = uart_read_bytes(esp_dte->uart_port,
esp_dte->buffer + length, 1, pdMS_TO_TICKS(100));
length += bytes;
ESP_LOGV("esp-modem: debug_data", "Continuous read in non-data mode: length: %d char: %x", length, esp_dte->buffer[length-1]);
}
esp_dte->buffer[length] = '\0';
}
ESP_LOG_BUFFER_HEXDUMP("esp-modem: debug_data", esp_dte->buffer, length, ESP_LOG_DEBUG);
ESP_LOGI(TAG, "%s", esp_dte->buffer);
if (esp_dte->parent.dce->handle_line) {
/* Send new line to handle if handler registered */
esp_dte_handle_line(esp_dte);
}
return;
}
length = MIN(esp_dte->line_buffer_size, length);
length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY);
/* pass the input data to configured callback */
if (length) {
ESP_LOG_BUFFER_HEXDUMP("esp-modem-dte: ppp_input", esp_dte->buffer, length, ESP_LOG_VERBOSE);
esp_dte->receive_cb(esp_dte->buffer, length, esp_dte->receive_cb_ctx);
}
}
/**
* @brief UART Event Task Entry
*
* @param param task parameter
*/
static void uart_event_task_entry(void *param)
{
esp_modem_dte_internal_t *esp_dte = (esp_modem_dte_internal_t *)param;
uart_event_t event;
EventBits_t bits = xEventGroupWaitBits(esp_dte->process_group, (ESP_MODEM_START_BIT|ESP_MODEM_STOP_BIT), pdFALSE, pdFALSE, portMAX_DELAY);
if (bits & ESP_MODEM_STOP_BIT) {
vTaskDelete(NULL);
}
while (xEventGroupGetBits(esp_dte->process_group) & ESP_MODEM_START_BIT) {
/* Drive the event loop */
esp_event_loop_run(esp_dte->event_loop_hdl, pdMS_TO_TICKS(0));
/* Process UART events */
if (xQueueReceive(esp_dte->event_queue, &event, pdMS_TO_TICKS(100))) {
if (esp_dte->parent.dce == NULL) {
ESP_LOGD(TAG, "Ignore UART event for DTE with no DCE attached");
// No action on any uart event with null DCE.
// This might happen before DCE gets initialized and attached to running DTE,
// or after destroying the DCE when DTE is up and gets a data event.
uart_flush(esp_dte->uart_port);
continue;
}
switch (event.type) {
case UART_DATA:
esp_handle_uart_data(esp_dte);
break;
case UART_FIFO_OVF:
ESP_LOGW(TAG, "HW FIFO Overflow");
uart_flush_input(esp_dte->uart_port);
xQueueReset(esp_dte->event_queue);
break;
case UART_BUFFER_FULL:
ESP_LOGW(TAG, "Ring Buffer Full");
uart_flush_input(esp_dte->uart_port);
xQueueReset(esp_dte->event_queue);
break;
case UART_BREAK:
ESP_LOGW(TAG, "Rx Break");
break;
case UART_PARITY_ERR:
ESP_LOGE(TAG, "Parity Error");
break;
case UART_FRAME_ERR:
ESP_LOGE(TAG, "Frame Error");
break;
case UART_PATTERN_DET:
esp_handle_uart_pattern(esp_dte);
break;
default:
ESP_LOGW(TAG, "unknown uart event type: %d", event.type);
break;
}
}
}
vTaskDelete(NULL);
}
/**
* @brief Send command to DCE
*
* @param dte Modem DTE object
* @param command command string
* @param timeout timeout value, unit: ms
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t esp_modem_dte_send_cmd(esp_modem_dte_t *dte, const char *command, uint32_t timeout)
{
esp_err_t ret = ESP_FAIL;
esp_modem_dce_t *dce = dte->dce;
ESP_MODEM_ERR_CHECK(dce, "DTE has not yet bind with DCE", err);
ESP_MODEM_ERR_CHECK(command, "command is NULL", err);
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
/* Calculate timeout clock tick */
/* Reset runtime information */
dce->state = ESP_MODEM_STATE_PROCESSING;
/* Send command via UART */
uart_write_bytes(esp_dte->uart_port, command, strlen(command));
/* Check timeout */
EventBits_t bits = xEventGroupWaitBits(esp_dte->process_group, (ESP_MODEM_COMMAND_BIT|ESP_MODEM_STOP_BIT), pdTRUE, pdFALSE, pdMS_TO_TICKS(timeout));
ESP_MODEM_ERR_CHECK(bits&ESP_MODEM_COMMAND_BIT, "process command timeout", err);
ret = ESP_OK;
err:
dce->handle_line = NULL;
return ret;
}
/**
* @brief Send data to DCE
*
* @param dte Modem DTE object
* @param data data buffer
* @param length length of data to send
* @return int actual length of data that has been send out
*/
static int esp_modem_dte_send_data(esp_modem_dte_t *dte, const char *data, uint32_t length)
{
ESP_MODEM_ERR_CHECK(data, "data is NULL", err);
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
if (esp_dte->parent.dce->mode == ESP_MODEM_TRANSITION_MODE) {
ESP_LOGD(TAG, "Not sending data in transition mode");
return -1;
}
if (esp_dte->parent.dce->mode == ESP_MODEM_TRANSITION_MODE) {
ESP_LOGD(TAG, "Not sending data in transition mode");
return -1;
}
ESP_LOG_BUFFER_HEXDUMP("esp-modem-dte: ppp_output", data, length, ESP_LOG_VERBOSE);
return uart_write_bytes(esp_dte->uart_port, data, length);
err:
return -1;
}
/**
* @brief Send data and wait for prompt from DCE
*
* @param dte Modem DTE object
* @param data data buffer
* @param length length of data to send
* @param prompt pointer of specific prompt
* @param timeout timeout value (unit: ms)
* @return esp_err_t
* ESP_OK on success
* ESP_FAIL on error
*/
static esp_err_t esp_modem_dte_send_wait(esp_modem_dte_t *dte, const char *data, uint32_t length,
const char *prompt, uint32_t timeout)
{
ESP_MODEM_ERR_CHECK(data, "data is NULL", err_param);
ESP_MODEM_ERR_CHECK(prompt, "prompt is NULL", err_param);
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
// We'd better disable pattern detection here for a moment in case prompt string contains the pattern character
uart_disable_pattern_det_intr(esp_dte->uart_port);
// uart_disable_rx_intr(esp_dte->uart_port);
ESP_MODEM_ERR_CHECK(uart_write_bytes(esp_dte->uart_port, data, length) >= 0, "uart write bytes failed", err_write);
uint32_t len = strlen(prompt);
uint8_t *buffer = calloc(len + 1, sizeof(uint8_t));
int res = uart_read_bytes(esp_dte->uart_port, buffer, len, pdMS_TO_TICKS(timeout));
ESP_MODEM_ERR_CHECK(res >= len, "wait prompt [%s] timeout", err, prompt);
ESP_MODEM_ERR_CHECK(!strncmp(prompt, (const char *)buffer, len), "get wrong prompt: %s", err, buffer);
free(buffer);
uart_enable_pattern_det_baud_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
return ESP_OK;
err:
free(buffer);
err_write:
uart_enable_pattern_det_baud_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
err_param:
return ESP_FAIL;
}
/**
* @brief Change Modem's working mode
*
* @param dte Modem DTE object
* @param new_mode new working mode
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t esp_modem_dte_change_mode(esp_modem_dte_t *dte, esp_modem_mode_t new_mode)
{
esp_modem_dce_t *dce = dte->dce;
ESP_MODEM_ERR_CHECK(dce, "DTE has not yet bind with DCE", err);
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
ESP_MODEM_ERR_CHECK(dce->mode != new_mode, "already in mode: %d", err, new_mode);
esp_modem_mode_t current_mode = dce->mode;
ESP_MODEM_ERR_CHECK(current_mode != new_mode, "already in mode: %d", err, new_mode);
dce->mode = ESP_MODEM_TRANSITION_MODE; // mode switching will be finished in set_working_mode() on success
// (or restored on failure)
switch (new_mode) {
case ESP_MODEM_PPP_MODE:
ESP_MODEM_ERR_CHECK(dce->set_working_mode(dce, new_mode) == ESP_OK, "set new working mode:%d failed", err_restore_mode, new_mode);
uart_disable_pattern_det_intr(esp_dte->uart_port);
uart_set_rx_full_threshold(esp_dte->uart_port, 64);
uart_enable_rx_intr(esp_dte->uart_port);
break;
case ESP_MODEM_COMMAND_MODE:
ESP_MODEM_ERR_CHECK(dce->set_working_mode(dce, new_mode) == ESP_OK, "set new working mode:%d failed", err_restore_mode, new_mode);
uart_disable_rx_intr(esp_dte->uart_port);
uart_flush(esp_dte->uart_port);
uart_enable_pattern_det_baud_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
uart_pattern_queue_reset(esp_dte->uart_port, esp_dte->pattern_queue_size);
break;
default:
break;
}
return ESP_OK;
err_restore_mode:
dce->mode = current_mode;
err:
return ESP_FAIL;
}
static esp_err_t esp_modem_dte_process_cmd_done(esp_modem_dte_t *dte)
{
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
EventBits_t bits = xEventGroupSetBits(esp_dte->process_group, ESP_MODEM_COMMAND_BIT);
return bits & ESP_MODEM_STOP_BIT ? ESP_FAIL : ESP_OK; // report error if the group indicated MODEM_STOP condition
}
/**
* @brief Deinitialize a Modem DTE object
*
* @param dte Modem DTE object
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t esp_modem_dte_deinit(esp_modem_dte_t *dte)
{
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
/* Clear the start bit */
xEventGroupClearBits(esp_dte->process_group, ESP_MODEM_START_BIT);
/* Delete UART event task */
vTaskDelete(esp_dte->uart_event_task_hdl);
/* Delete semaphore */
vEventGroupDelete(esp_dte->process_group);
/* Delete event loop */
esp_event_loop_delete(esp_dte->event_loop_hdl);
/* Uninstall UART Driver */
uart_driver_delete(esp_dte->uart_port);
/* Free memory */
free(esp_dte->buffer);
if (dte->dce) {
dte->dce->dte = NULL;
}
free(esp_dte);
return ESP_OK;
}
/**
* @brief Create and init Modem DTE object
*
*/
esp_modem_dte_t *esp_modem_dte_new(const esp_modem_dte_config_t *config)
{
esp_err_t res;
/* malloc memory for esp_dte object */
esp_modem_dte_internal_t *esp_dte = calloc(1, sizeof(esp_modem_dte_internal_t));
ESP_MODEM_ERR_CHECK(esp_dte, "calloc esp_dte failed", err_dte_mem);
/* malloc memory to storing lines from modem dce */
esp_dte->line_buffer_size = config->line_buffer_size;
esp_dte->buffer = calloc(1, config->line_buffer_size);
ESP_MODEM_ERR_CHECK(esp_dte->buffer, "calloc line memory failed", err_line_mem);
/* Set attributes */
esp_dte->uart_port = config->port_num;
esp_dte->parent.flow_ctrl = config->flow_control;
/* Bind methods */
esp_dte->parent.send_cmd = esp_modem_dte_send_cmd;
esp_dte->parent.send_data = esp_modem_dte_send_data;
esp_dte->parent.send_wait = esp_modem_dte_send_wait;
esp_dte->parent.change_mode = esp_modem_dte_change_mode;
esp_dte->parent.process_cmd_done = esp_modem_dte_process_cmd_done;
esp_dte->parent.deinit = esp_modem_dte_deinit;
/* Config UART */
uart_config_t uart_config = {
.baud_rate = config->baud_rate,
.data_bits = config->data_bits,
.parity = config->parity,
.stop_bits = config->stop_bits,
.source_clk = UART_SCLK_REF_TICK,
.flow_ctrl = (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) ? UART_HW_FLOWCTRL_CTS_RTS : UART_HW_FLOWCTRL_DISABLE
};
ESP_MODEM_ERR_CHECK(uart_param_config(esp_dte->uart_port, &uart_config) == ESP_OK, "config uart parameter failed", err_uart_config);
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
res = uart_set_pin(esp_dte->uart_port, config->tx_io_num, config->rx_io_num,
config->rts_io_num, config->cts_io_num);
} else {
res = uart_set_pin(esp_dte->uart_port, config->tx_io_num, config->rx_io_num,
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
ESP_MODEM_ERR_CHECK(res == ESP_OK, "config uart gpio failed", err_uart_config);
/* Set flow control threshold */
if (config->flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
res = uart_set_hw_flow_ctrl(esp_dte->uart_port, 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(esp_dte->uart_port, true, 8, UART_FIFO_LEN - 8);
}
ESP_MODEM_ERR_CHECK(res == ESP_OK, "config uart flow control failed", err_uart_config);
/* Install UART driver and get event queue used inside driver */
res = uart_driver_install(esp_dte->uart_port, config->rx_buffer_size, config->tx_buffer_size,
config->event_queue_size, &(esp_dte->event_queue), 0);
ESP_MODEM_ERR_CHECK(res == ESP_OK, "install uart driver failed", err_uart_config);
res = uart_set_rx_timeout(esp_dte->uart_port, 1);
ESP_MODEM_ERR_CHECK(res == ESP_OK, "set rx timeout failed", err_uart_config);
/* Set pattern interrupt, used to detect the end of a line. */
res = uart_enable_pattern_det_baud_intr(esp_dte->uart_port, '\n', 1, MIN_PATTERN_INTERVAL, MIN_POST_IDLE, MIN_PRE_IDLE);
/* Set pattern queue size */
esp_dte->pattern_queue_size = config->pattern_queue_size;
res |= uart_pattern_queue_reset(esp_dte->uart_port, config->pattern_queue_size);
/* Starting in command mode -> explicitly disable RX interrupt */
uart_set_rx_full_threshold(esp_dte->uart_port, 64);
uart_enable_rx_intr(esp_dte->uart_port);
//
// uart_disable_rx_intr(esp_dte->uart_port);
// uart_set_rx_full_threshold(esp_dte->uart_port, 64);
ESP_MODEM_ERR_CHECK(res == ESP_OK, "config uart pattern failed", err_uart_pattern);
/* Create Event loop */
esp_event_loop_args_t loop_args = {
.queue_size = ESP_MODEM_EVENT_QUEUE_SIZE,
.task_name = NULL
};
ESP_MODEM_ERR_CHECK(esp_event_loop_create(&loop_args, &esp_dte->event_loop_hdl) == ESP_OK, "create event loop failed", err_eloop);
/* Create semaphore */
esp_dte->process_group = xEventGroupCreate();
ESP_MODEM_ERR_CHECK(esp_dte->process_group, "create process semaphore failed", err_sem);
/* Create UART Event task */
BaseType_t ret = xTaskCreate(uart_event_task_entry, //Task Entry
"uart_event", //Task Name
config->event_task_stack_size, //Task Stack Size(Bytes)
esp_dte, //Task Parameter
config->event_task_priority, //Task Priority
& (esp_dte->uart_event_task_hdl) //Task Handler
);
ESP_MODEM_ERR_CHECK(ret == pdTRUE, "create uart event task failed", err_tsk_create);
return &(esp_dte->parent);
/* Error handling */
err_tsk_create:
vEventGroupDelete(esp_dte->process_group);
err_sem:
esp_event_loop_delete(esp_dte->event_loop_hdl);
err_eloop:
uart_disable_pattern_det_intr(esp_dte->uart_port);
err_uart_pattern:
uart_driver_delete(esp_dte->uart_port);
err_uart_config:
free(esp_dte->buffer);
err_line_mem:
free(esp_dte);
err_dte_mem:
return NULL;
}
esp_err_t esp_modem_dte_set_params(esp_modem_dte_t *dte, const esp_modem_dte_config_t *config)
{
esp_modem_dte_internal_t *esp_dte = __containerof(dte, esp_modem_dte_internal_t, parent);
return uart_set_baudrate(esp_dte->uart_port, config->baud_rate);
}

View File

@ -1,212 +0,0 @@
// 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.
#include "esp_netif.h"
#include "esp_modem.h"
#include "esp_modem_netif.h"
#include "esp_modem_dte.h"
#include "esp_log.h"
#include "esp_netif_ppp.h"
static const char *TAG = "esp-modem-netif";
/**
* @brief ESP32 Modem handle to be used as netif IO object
*/
struct esp_modem_netif_driver_s {
esp_netif_driver_base_t base; /*!< base structure reserved as esp-netif driver */
esp_modem_dte_t *dte; /*!< ptr to the esp_modem objects (DTE) */
};
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
esp_modem_dte_t *dte = arg;
if (event_id < NETIF_PP_PHASE_OFFSET) {
ESP_LOGI(TAG, "PPP state changed event %d", event_id);
// only notify the modem on state/error events, ignoring phase transitions
esp_modem_notify_ppp_netif_closed(dte);
}
}
/**
* @brief Transmit function called from esp_netif to output network stack data
*
* Note: This API has to conform to esp-netif transmit prototype
*
* @param h Opaque pointer representing esp-netif driver, esp_dte in this case of esp_modem
* @param data data buffer
* @param length length of data to send
*
* @return ESP_OK on success
*/
static esp_err_t esp_modem_dte_transmit(void *h, void *buffer, size_t len)
{
esp_modem_dte_t *dte = h;
if (dte->send_data(dte, (const char *)buffer, len) > 0) {
return ESP_OK;
}
return ESP_FAIL;
}
/**
* @brief Post attach adapter for esp-modem
*
* Used to exchange internal callbacks, context between esp-netif nad modem-netif
*
* @param esp_netif handle to esp-netif object
* @param args pointer to modem-netif driver
*
* @return ESP_OK on success, modem-start error code if starting failed
*/
static esp_err_t esp_modem_post_attach_init(esp_netif_t * esp_netif, void * args)
{
esp_modem_netif_driver_t *driver = args;
esp_modem_dte_t *dte = driver->dte;
const esp_netif_driver_ifconfig_t driver_ifconfig = {
.driver_free_rx_buffer = NULL,
.transmit = esp_modem_dte_transmit,
.handle = dte
};
driver->base.netif = esp_netif;
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));
// check if PPP error events are enabled, if not, do enable the error occurred/state changed
// to notify the modem layer when switching modes
esp_netif_ppp_config_t ppp_config;
esp_netif_ppp_get_params(esp_netif, &ppp_config);
if (!ppp_config.ppp_error_event_enabled) {
ppp_config.ppp_error_event_enabled = true;
esp_netif_ppp_set_params(esp_netif, &ppp_config);
}
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, dte));
return ESP_OK;
}
/**
* @brief Post attach adapter for esp-modem with autostart functionality
*
*/
static esp_err_t esp_modem_post_attach_start(esp_netif_t * esp_netif, void * args)
{
esp_modem_netif_driver_t *driver = args;
ESP_ERROR_CHECK(esp_modem_post_attach_init(esp_netif, args));
return esp_modem_start_ppp(driver->dte);
}
/**
* @brief Data path callback from esp-modem to pass data to esp-netif
*
* @param buffer data pointer
* @param len data length
* @param context context data used for esp-modem-netif handle
*
* @return ESP_OK on success
*/
static esp_err_t modem_netif_receive_cb(void *buffer, size_t len, void *context)
{
esp_modem_netif_driver_t *driver = context;
esp_netif_receive(driver->base.netif, buffer, len, NULL);
return ESP_OK;
}
esp_modem_netif_driver_t *esp_modem_netif_new(esp_modem_dte_t *dte)
{
esp_modem_netif_driver_t *driver = esp_modem_netif_setup(dte);
if (driver) {
driver->base.post_attach = esp_modem_post_attach_init;
return driver;
}
return NULL;
}
esp_modem_netif_driver_t *esp_modem_netif_setup(esp_modem_dte_t *dte)
{
esp_modem_netif_driver_t *driver = calloc(1, sizeof(esp_modem_netif_driver_t));
if (driver == NULL) {
ESP_LOGE(TAG, "Cannot allocate esp_modem_netif_driver_t");
goto drv_create_failed;
}
esp_err_t err = esp_modem_set_rx_cb(dte, modem_netif_receive_cb, driver);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_modem_set_rx_cb failed with: %d", err);
goto drv_create_failed;
}
driver->base.post_attach = esp_modem_post_attach_start;
driver->dte = dte;
return driver;
drv_create_failed:
return NULL;
}
void esp_modem_netif_destroy(esp_modem_netif_driver_t *driver)
{
esp_netif_destroy(driver->base.netif);
return esp_modem_netif_teardown(driver);
}
void esp_modem_netif_teardown(esp_modem_netif_driver_t *driver)
{
free(driver);
}
esp_err_t esp_modem_netif_clear_default_handlers(esp_modem_netif_driver_t *h)
{
esp_modem_netif_driver_t *driver = h;
esp_err_t ret;
ret = esp_modem_remove_event_handler(driver->dte, esp_netif_action_start);
if (ret != ESP_OK) {
goto clear_event_failed;
}
ret = esp_modem_remove_event_handler(driver->dte, esp_netif_action_stop);
if (ret != ESP_OK) {
goto clear_event_failed;
}
return ESP_OK;
clear_event_failed:
ESP_LOGE(TAG, "Failed to unregister event handlers");
return ESP_FAIL;
}
esp_err_t esp_modem_netif_set_default_handlers(esp_modem_netif_driver_t *h, esp_netif_t * esp_netif)
{
esp_modem_netif_driver_t *driver = h;
esp_err_t ret;
ret = esp_modem_set_event_handler(driver->dte, esp_netif_action_start, ESP_MODEM_EVENT_PPP_START, esp_netif);
if (ret != ESP_OK) {
goto set_event_failed;
}
ret = esp_modem_set_event_handler(driver->dte, esp_netif_action_stop, ESP_MODEM_EVENT_PPP_STOP, esp_netif);
if (ret != ESP_OK) {
goto set_event_failed;
}
ret = esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, esp_netif);
if (ret != ESP_OK) {
goto set_event_failed;
}
ret = esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_LOST_IP, esp_netif_action_disconnected, esp_netif);
if (ret != ESP_OK) {
goto set_event_failed;
}
return ESP_OK;
set_event_failed:
ESP_LOGE(TAG, "Failed to register event handlers");
esp_modem_netif_clear_default_handlers(driver);
return ESP_FAIL;
}

View File

@ -1,136 +0,0 @@
// Copyright 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.
#include "esp_modem_recov_helper.h"
#include <stdlib.h>
#include "driver/gpio.h"
#include "esp_modem_internal.h"
#include "esp_log.h"
static const char *TAG = "esp_modem_recov_helper";
static void pulse_destroy(esp_modem_recov_gpio_t *pin)
{
free(pin);
}
static void retry_destroy(esp_modem_recov_resend_t *retry)
{
free(retry);
}
static void pulse_special(esp_modem_recov_gpio_t * pin, int active_width_ms, int inactive_width_ms)
{
gpio_set_level(pin->gpio_num, !pin->inactive_level);
esp_modem_wait_ms(active_width_ms);
gpio_set_level(pin->gpio_num, pin->inactive_level);
esp_modem_wait_ms(inactive_width_ms);
}
static void pulse(esp_modem_recov_gpio_t * pin)
{
gpio_set_level(pin->gpio_num, !pin->inactive_level);
esp_modem_wait_ms(pin->active_width_ms);
gpio_set_level(pin->gpio_num, pin->inactive_level);
esp_modem_wait_ms(pin->inactive_width_ms);
}
static esp_err_t esp_modem_retry_run(esp_modem_recov_resend_t * retry, void *param, void *result)
{
esp_modem_dce_t *dce = retry->dce;
int errors = 0;
int timeouts = 0;
esp_err_t err = ESP_FAIL;
while (timeouts <= retry->retries_after_timeout &&
errors <= retry->retries_after_error) {
if (timeouts || errors) {
// provide recovery action based on the defined strategy
if (retry->recover(retry, err, timeouts, errors) != ESP_OK) {
// fail the retry mechanism once the recovery fails
return ESP_FAIL;
}
}
if (retry->command) {
ESP_LOGD(TAG, "%s(%d): executing:%s...", __func__, __LINE__, retry->command );
}
// Execute the command
err = retry->orig_cmd(dce, param, result);
// Check for timeout
if (err == ESP_ERR_TIMEOUT) {
if (retry->command) {
ESP_LOGW(TAG, "%s(%d): Command:%s response timeout", __func__, __LINE__, retry->command);
}
timeouts++;
continue;
// Check for errors
} else if (err != ESP_OK) {
if (retry->command) {
ESP_LOGW(TAG, "%s(%d): Command:%s failed", __func__, __LINE__, retry->command);
}
errors++;
continue;
}
// Success
if (retry->command) {
ESP_LOGD(TAG, "%s(%d): Command:%s succeeded", __func__, __LINE__, retry->command);
}
return ESP_OK;
}
return err;
}
esp_modem_recov_resend_t *esp_modem_recov_resend_new(esp_modem_dce_t *dce, dce_command_t orig_cmd, esp_modem_retry_fn_t recover, int max_timeouts, int max_errors)
{
esp_modem_recov_resend_t * retry = calloc(1, sizeof(esp_modem_recov_resend_t));
ESP_MODEM_ERR_CHECK(retry, "failed to allocate pin structure", err);
retry->retries_after_error = max_errors;
retry->retries_after_timeout = max_timeouts;
retry->orig_cmd = orig_cmd;
retry->recover = recover;
retry->destroy = retry_destroy;
retry->dce = dce;
retry->run = esp_modem_retry_run;
return retry;
err:
return NULL;
}
esp_modem_recov_gpio_t *esp_modem_recov_gpio_new(int gpio_num, int inactive_level, int active_width_ms, int inactive_width_ms)
{
gpio_config_t io_config = {
.pin_bit_mask = BIT64(gpio_num),
.mode = GPIO_MODE_OUTPUT
};
gpio_config(&io_config);
gpio_set_level(gpio_num, inactive_level);
gpio_set_level(gpio_num, inactive_level);
esp_modem_recov_gpio_t * pin = calloc(1, sizeof(esp_modem_recov_gpio_t));
ESP_MODEM_ERR_CHECK(pin, "failed to allocate pin structure", err);
pin->inactive_level = inactive_level;
pin->active_width_ms = active_width_ms;
pin->inactive_width_ms = inactive_width_ms;
pin->gpio_num = gpio_num;
pin->pulse = pulse;
pin->pulse_special = pulse_special;
pin->destroy = pulse_destroy;
return pin;
err:
return NULL;
}

View File

@ -6,14 +6,14 @@
#include "esp_log.h"
#include "esp_event.h"
#include "driver/uart.h"
#include "esp_modem_dte_config.h"
#include "esp_modem_config.h"
#define ESP_MODEM_EVENT_QUEUE_SIZE (16)
static const char *TAG = "uart_terminal";
struct uart_resource {
explicit uart_resource(const struct dte_config *config);
explicit uart_resource(const esp_modem_dte_config *config);
~uart_resource();
@ -72,7 +72,7 @@ uart_resource::~uart_resource()
}
uart_resource::uart_resource(const struct dte_config *config):
uart_resource::uart_resource(const esp_modem_dte_config *config):
port(-1)
{
esp_err_t res;
@ -119,7 +119,7 @@ uart_resource::uart_resource(const struct dte_config *config):
class uart_terminal: public Terminal {
public:
explicit uart_terminal(const struct dte_config *config):
explicit uart_terminal(const esp_modem_dte_config *config):
uart(config), event_loop(), signal(),
task_handle(config->event_task_stack_size, config->event_task_priority, this, s_task) {}
@ -162,7 +162,7 @@ private:
};
std::unique_ptr<Terminal> create_uart_terminal(const dte_config *config)
std::unique_ptr<Terminal> create_uart_terminal(const esp_modem_dte_config *config)
{
try {
auto term = std::make_unique<uart_terminal>(config);

View File

@ -1,104 +0,0 @@
// Copyright 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.
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_modem_dce_common_commands.h"
#include "esp_modem_internal.h"
/**
* @brief This module supports SIM7600 module, which has a very similar interface
* to the BG96, so it just references most of the handlers from BG96 and implements
* only those that differ.
*/
static const char *TAG = "sim7600";
/**
* @brief Handle response from AT+CBC
*/
static esp_err_t sim7600_handle_cbc(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
} else if (!strncmp(line, "+CBC", strlen("+CBC"))) {
esp_modem_dce_cbc_ctx_t *cbc = dce->handle_line_ctx;
int32_t volts = 0, fraction = 0;
/* +CBC: <voltage in Volts> V*/
sscanf(line, "+CBC: %d.%dV", &volts, &fraction);
/* Since the "read_battery_status()" API (besides voltage) returns also values for BCS, BCL (charge status),
* which are not applicable to this modem, we return -1 to indicate invalid value
*/
cbc->bcs = -1; // BCS
cbc->bcl = -1; // BCL
cbc->battery_status = volts*1000 + fraction;
err = ESP_OK;
}
return err;
}
/**
* @brief Get battery status
*
* @param dce Modem DCE object
* @param bcs Battery charge status
* @param bcl Battery connection level
* @param voltage Battery voltage
* @return esp_err_t
* - ESP_OK on success
* - ESP_FAIL on error
*/
static esp_err_t sim7600_get_battery_status(esp_modem_dce_t *dce, void *p, void *r)
{
return esp_modem_dce_generic_command(dce, "AT+CBC\r", 20000,
sim7600_handle_cbc, r);
}
static esp_err_t sim7600_handle_power_down(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_OK;
if (strstr(line, MODEM_RESULT_CODE_SUCCESS)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_NO_CARRIER)) {
err = ESP_OK;
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
}
return err;
}
static esp_err_t sim7600_power_down(esp_modem_dce_t *dce, void *p, void *r)
{
return esp_modem_dce_generic_command(dce, " AT+CPOF\r", MODEM_COMMAND_TIMEOUT_POWEROFF,
sim7600_handle_power_down, NULL);
}
esp_err_t esp_modem_sim7600_specific_init(esp_modem_dce_t *dce)
{
ESP_MODEM_ERR_CHECK(dce, "failed to specific init with zero dce", err_params);
if (dce->config.populate_command_list) {
ESP_MODEM_ERR_CHECK(esp_modem_set_default_command_list(dce) == ESP_OK, "esp_modem_dce_set_default_commands failed", err);
/* Update some commands which differ from the defaults */
ESP_MODEM_ERR_CHECK(esp_modem_command_list_set_cmd(dce, "power_down", sim7600_power_down) == ESP_OK, "esp_modem_dce_set_command failed", err);
ESP_MODEM_ERR_CHECK(
esp_modem_command_list_set_cmd(dce, "get_battery_status", sim7600_get_battery_status) == ESP_OK, "esp_modem_dce_set_command failed", err);
}
return ESP_OK;
err:
return ESP_FAIL;
err_params:
return ESP_ERR_INVALID_ARG;
}

View File

@ -1,96 +0,0 @@
// 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.
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_modem_dce_common_commands.h"
#include "esp_modem_internal.h"
static const char *TAG = "esp_sim800";
/**
* @brief @brief Response to the SIM800 specific power-down command
*/
static esp_err_t sim800_handle_power_down(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, "POWER DOWN")) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
}
return err;
}
/**
* @brief Response to the SIM800 specific data mode command
*
*/
static esp_err_t sim800_handle_atd_ppp(esp_modem_dce_t *dce, const char *line)
{
esp_err_t err = ESP_FAIL;
if (strstr(line, MODEM_RESULT_CODE_CONNECT)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_SUCCESS);
} else if (strstr(line, MODEM_RESULT_CODE_ERROR)) {
err = esp_modem_process_command_done(dce, ESP_MODEM_STATE_FAIL);
}
return err;
}
/**
* @brief Set data mode specific to SIM800
*
*/
static esp_err_t sim800_set_data_mode(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "ATD*99##\r", MODEM_COMMAND_TIMEOUT_MODE_CHANGE,
sim800_handle_atd_ppp, NULL);
}
/**
* @brief Specific power down command to SMI800
*
*/
static esp_err_t sim800_power_down(esp_modem_dce_t *dce, void *param, void *result)
{
return esp_modem_dce_generic_command(dce, "AT+CPOWD=1\r", MODEM_COMMAND_TIMEOUT_POWEROFF,
sim800_handle_power_down, NULL);
}
static esp_err_t sim800_start_up(esp_modem_dce_t* dce)
{
if (esp_modem_dce_default_start_up(dce) != ESP_OK) {
esp_modem_wait_ms(30000); // SIM800 wakes-up 30s after sending a command
}
return esp_modem_dce_default_start_up(dce);
}
esp_err_t esp_modem_sim800_specific_init(esp_modem_dce_t *dce)
{
ESP_MODEM_ERR_CHECK(dce, "failed to specific init with zero dce", err_params);
/* Update some commands which differ from the defaults */
if (dce->config.populate_command_list) {
ESP_MODEM_ERR_CHECK(esp_modem_command_list_set_cmd(dce, "set_data_mode", sim800_set_data_mode) == ESP_OK, "esp_modem_dce_set_command failed", err);
ESP_MODEM_ERR_CHECK(esp_modem_command_list_set_cmd(dce, "power_down", sim800_power_down) == ESP_OK, "esp_modem_dce_set_command failed", err);
} else {
dce->set_data_mode = sim800_set_data_mode;
}
dce->start_up = sim800_start_up;
return ESP_OK;
err:
return ESP_FAIL;
err_params:
return ESP_ERR_INVALID_ARG;
}