From 25913af2cc12cfa4667e23d931f45915a22532fe Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 11 Nov 2019 16:38:43 +0100 Subject: [PATCH] pppos_client: udated example code to use esp-netif in PPP configuration --- components/esp_netif/include/esp_netif_ppp.h | 109 ++++++ .../esp_netif/lwip/esp_netif_lwip_ppp.c | 327 ++++++++++++++++++ .../esp_netif/lwip/esp_netif_lwip_ppp.h | 76 ++++ .../port/esp32/include/netif/ethernetif.h | 2 +- .../components/modem/CMakeLists.txt | 1 + .../components/modem/include/esp_modem.h | 38 +- .../modem/include/esp_modem_netif.h | 53 +++ .../components/modem/src/esp_modem.c | 191 ++-------- .../components/modem/src/esp_modem_netif.c | 155 +++++++++ .../pppos_client/main/pppos_client_main.c | 90 ++++- 10 files changed, 838 insertions(+), 204 deletions(-) create mode 100644 components/esp_netif/include/esp_netif_ppp.h create mode 100644 components/esp_netif/lwip/esp_netif_lwip_ppp.c create mode 100644 components/esp_netif/lwip/esp_netif_lwip_ppp.h create mode 100644 examples/protocols/pppos_client/components/modem/include/esp_modem_netif.h create mode 100644 examples/protocols/pppos_client/components/modem/src/esp_modem_netif.c diff --git a/components/esp_netif/include/esp_netif_ppp.h b/components/esp_netif/include/esp_netif_ppp.h new file mode 100644 index 000000000..b6df9fdfd --- /dev/null +++ b/components/esp_netif/include/esp_netif_ppp.h @@ -0,0 +1,109 @@ +// Copyright 2019 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. +// + +#ifndef _ESP_NETIF_PPP_H_ +#define _ESP_NETIF_PPP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief PPP event base */ +ESP_EVENT_DECLARE_BASE(NETIF_PPP_STATUS); + +/** @brief Configuration structure for PPP network interface + * + */ +typedef struct esp_netif_ppp_config { + bool ppp_phase_event_enabled; /**< Enables events coming from PPP PHASE change */ + bool ppp_error_event_enabled; /**< Enables events from main PPP state machine producing errors */ +} esp_netif_ppp_config_t; + +/** @brief event id offset for PHASE related events + * + * All PPP related events are produced from esp-netif under `NETIF_PPP_STATUS`, this offset defines + * helps distinguish between error and phase events + */ +#define NETIF_PP_PHASE_OFFSET (0x100) + +/** @brief event ids for different PPP related events + * + */ +typedef enum { + NETIF_PPP_ERRORNONE = 0, /* No error. */ + NETIF_PPP_ERRORPARAM = 1, /* Invalid parameter. */ + NETIF_PPP_ERROROPEN = 2, /* Unable to open PPP session. */ + NETIF_PPP_ERRORDEVICE = 3, /* Invalid I/O device for PPP. */ + NETIF_PPP_ERRORALLOC = 4, /* Unable to allocate resources. */ + NETIF_PPP_ERRORUSER = 5, /* User interrupt. */ + NETIF_PPP_ERRORCONNECT = 6, /* Connection lost. */ + NETIF_PPP_ERRORAUTHFAIL = 7, /* Failed authentication challenge. */ + NETIF_PPP_ERRORPROTOCOL = 8, /* Failed to meet protocol. */ + NETIF_PPP_ERRORPEERDEAD = 9, /* Connection timeout */ + NETIF_PPP_ERRORIDLETIMEOUT = 10, /* Idle Timeout */ + NETIF_PPP_ERRORCONNECTTIME = 11, /* Max connect time reached */ + NETIF_PPP_ERRORLOOPBACK = 12, /* Loopback detected */ + NETIF_PPP_PHASE_DEAD = NETIF_PP_PHASE_OFFSET + 0, + NETIF_PPP_PHASE_MASTER = NETIF_PP_PHASE_OFFSET + 1, + NETIF_PPP_PHASE_HOLDOFF = NETIF_PP_PHASE_OFFSET + 2, + NETIF_PPP_PHASE_INITIALIZE = NETIF_PP_PHASE_OFFSET + 3, + NETIF_PPP_PHASE_SERIALCONN = NETIF_PP_PHASE_OFFSET + 4, + NETIF_PPP_PHASE_DORMANT = NETIF_PP_PHASE_OFFSET + 5, + NETIF_PPP_PHASE_ESTABLISH = NETIF_PP_PHASE_OFFSET + 6, + NETIF_PPP_PHASE_AUTHENTICATE = NETIF_PP_PHASE_OFFSET + 7, + NETIF_PPP_PHASE_CALLBACK = NETIF_PP_PHASE_OFFSET + 8, + NETIF_PPP_PHASE_NETWORK = NETIF_PP_PHASE_OFFSET + 9, + NETIF_PPP_PHASE_RUNNING = NETIF_PP_PHASE_OFFSET + 10, + NETIF_PPP_PHASE_TERMINATE = NETIF_PP_PHASE_OFFSET + 11, + NETIF_PPP_PHASE_DISCONNECT = NETIF_PP_PHASE_OFFSET + 12, +} esp_netif_ppp_status_event_t; + +/** @brief definitions of different authorisation types + * + */ +typedef enum { + NETIF_PPP_AUTHTYPE_PAP = 0x01, + NETIF_PPP_AUTHTYPE_CHAP = 0x02, + NETIF_PPP_AUTHTYPE_MSCHAP = 0x04, + NETIF_PPP_AUTHTYPE_MSCHAP_V2 = 0x08, + NETIF_PPP_AUTHTYPE_EAP = 0x10, +} esp_netif_auth_type_t; + +/** @brief Sets the auth parameters for the supplied esp-netif. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] authtype Authorisation type + * @param[in] user User name + * @param[in] passwd Password + * + * @return ESP_OK on success, ESP_ERR_ESP_NETIF_INVALID_PARAMS if netif null or not PPP + */ +esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t authtype, const char *user, const char *passwd); + +/** @brief Sets common parameters for the supplied esp-netif. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] config Pointer to PPP netif configuration structure + * + * @return ESP_OK on success, ESP_ERR_ESP_NETIF_INVALID_PARAMS if netif null or not PPP + */ +esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_config_t *config); + + +#ifdef __cplusplus +} +#endif + +#endif //_ESP_NETIF_PPP_H_ diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.c b/components/esp_netif/lwip/esp_netif_lwip_ppp.c new file mode 100644 index 000000000..9a5cc9b01 --- /dev/null +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.c @@ -0,0 +1,327 @@ +// Copyright 2019 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 "lwip/dns.h" +#include "esp_netif.h" +#include "netif/ppp/pppapi.h" +#include "netif/ppp/pppos.h" +#include "esp_log.h" +#include "esp_netif_net_stack.h" +#include "esp_event.h" +#include "esp_netif_ppp.h" +#include "esp_netif_lwip_internal.h" + +ESP_EVENT_DEFINE_BASE(NETIF_PPP_STATUS); + +static const char *TAG = "esp-netif_lwip-ppp"; + +#if PPPOS_SUPPORT + +/** + * @brief internal lwip_ppp context struct, used to hold PPP netif related parameters + */ +struct lwip_ppp_ctx { + bool ppp_phase_event_enabled; + bool ppp_error_event_enabled; + ppp_pcb *ppp; +}; + +/** + * @brief lwip callback from PPP client used here to produce PPP error related events, + * as well as some IP events + */ +static void on_ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx) +{ + struct netif *pppif = ppp_netif(pcb); + const ip_addr_t *dest_ip = NULL; + ip_event_ap_staipassigned_t evt = { 0 }; + esp_err_t err; + esp_netif_t *netif = ctx; + struct lwip_ppp_ctx *obj = netif->lwip_ppp_ctx; + esp_netif_ip_info_t ipinfo = { {0}, {0}, {0} }; + esp_ip4_addr_t ns1; + esp_ip4_addr_t ns2; + switch (err_code) { + case PPPERR_NONE: /* Connected */ + ESP_LOGI(TAG, "Connected"); + + ipinfo.ip.addr = pppif->ip_addr.u_addr.ip4.addr; + ipinfo.gw.addr = pppif->gw.u_addr.ip4.addr; + ipinfo.netmask.addr = pppif->netmask.u_addr.ip4.addr; + dest_ip = dns_getserver(0); + if(dest_ip != NULL){ + ns1.addr = (*dest_ip).u_addr.ip4.addr; + } + dest_ip = dns_getserver(1); + if(dest_ip != NULL){ + ns2.addr = (*dest_ip).u_addr.ip4.addr; + } + ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&ns1)); + ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&ns2)); + + evt.ip.addr = ipinfo.ip.addr; + + err = esp_event_post(IP_EVENT, netif->get_ip_event, &evt, sizeof(evt), 0); + if (ESP_OK != err) { + ESP_LOGE(TAG, "esp_event_send_internal failed with code %d", err); + } + return; + + case PPPERR_PARAM: + ESP_LOGE(TAG, "Invalid parameter"); + break; + case PPPERR_OPEN: + ESP_LOGE(TAG, "Unable to open PPP session"); + break; + case PPPERR_DEVICE: + ESP_LOGE(TAG, "Invalid I/O device for PPP"); + break; + case PPPERR_ALLOC: + ESP_LOGE(TAG, "Unable to allocate resources"); + break; + case PPPERR_USER: /* User interrupt */ + ESP_LOGI(TAG, "User interrupt"); + break; + case PPPERR_CONNECT: /* Connection lost */ + ESP_LOGI(TAG, "Connection lost"); + err = esp_event_post(IP_EVENT, netif->lost_ip_event, &evt, sizeof(evt), 0); + + if (ESP_OK != err) { + ESP_LOGE(TAG, "esp_event_send_internal failed with code %d", err); + } + return; + + case PPPERR_AUTHFAIL: + ESP_LOGE(TAG, "Failed authentication challenge"); + break; + case PPPERR_PROTOCOL: + ESP_LOGE(TAG, "Failed to meet protocol"); + break; + case PPPERR_PEERDEAD: + ESP_LOGE(TAG, "Connection timeout"); + break; + case PPPERR_IDLETIMEOUT: + ESP_LOGE(TAG, "Idle Timeout"); + break; + case PPPERR_CONNECTTIME: + ESP_LOGE(TAG, "Max connect time reached"); + break; + case PPPERR_LOOPBACK: + ESP_LOGE(TAG, "Loopback detected"); + break; + default: + ESP_LOGE(TAG, "Unknown error code %d", err_code); + break; + } + if (obj->ppp_error_event_enabled) { + err = esp_event_post(NETIF_PPP_STATUS, err_code, netif, sizeof(netif), 0); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_event_post failed with code %d", err); + } + + } +} + +#if PPP_NOTIFY_PHASE +/** + * @brief Notify phase callback which is called on each PPP internal state change + * + * @param pcb PPP control block + * @param phase Phase ID + * @param ctx Context of callback + */ +static void on_ppp_notify_phase(ppp_pcb *pcb, u8_t phase, void *ctx) +{ + switch (phase) { + case PPP_PHASE_DEAD: + ESP_LOGD(TAG, "Phase Dead"); + break; + case PPP_PHASE_INITIALIZE: + ESP_LOGD(TAG, "Phase Start"); + break; + case PPP_PHASE_ESTABLISH: + ESP_LOGD(TAG, "Phase Establish"); + break; + case PPP_PHASE_AUTHENTICATE: + ESP_LOGD(TAG, "Phase Authenticate"); + break; + case PPP_PHASE_NETWORK: + ESP_LOGD(TAG, "Phase Network"); + break; + case PPP_PHASE_RUNNING: + ESP_LOGD(TAG, "Phase Running"); + break; + case PPP_PHASE_TERMINATE: + ESP_LOGD(TAG, "Phase Terminate"); + break; + case PPP_PHASE_DISCONNECT: + ESP_LOGD(TAG, "Phase Disconnect"); + break; + default: + ESP_LOGW(TAG, "Phase Unknown: %d", phase); + break; + } + esp_netif_t *netif = ctx; + struct lwip_ppp_ctx *obj = netif->lwip_ppp_ctx; + if (obj && obj->ppp_phase_event_enabled) { + esp_err_t err = esp_event_post(NETIF_PPP_STATUS, NETIF_PP_PHASE_OFFSET + phase, netif, sizeof(netif), 0); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_event_post failed with code %d", err); + } + } +} +#endif // PPP_NOTIFY_PHASE + +/** + * @brief PPP low level output callback used to transmit data using standard esp-netif interafce + * + * @param pcb PPP control block + * @param data Buffer to write to serial port + * @param len Length of the data buffer + * @param ctx Context of callback + * + * @return uint32_t Length of data successfully sent + */ +static uint32_t pppos_low_level_output(ppp_pcb *pcb, uint8_t *data, uint32_t len, void *netif) +{ + esp_err_t ret = esp_netif_transmit(netif, data, len); + if (ret == ESP_OK) { + return len; + } + return 0; +} + +esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t authtype, const char *user, const char *passwd) +{ + if (netif == NULL || !netif->is_ppp_netif) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + struct lwip_ppp_ctx *obj = netif->lwip_ppp_ctx; +#if PAP_SUPPORT + pppapi_set_auth(obj->ppp, authtype, user, passwd); +#elif CHAP_SUPPORT + pppapi_set_auth(obj->ppp, authtype, user, passwd); +#else +#error "Unsupported AUTH Negotiation" +#endif + return ESP_OK; +} + +void esp_netif_ppp_set_default_netif(lwip_ppp_ctx_t* ppp_ctx) +{ + pppapi_set_default(ppp_ctx->ppp); +} + +lwip_ppp_ctx_t* esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) +{ + struct netif * netif_impl = esp_netif->lwip_netif; + struct lwip_ppp_ctx * ppp_obj = calloc(1, sizeof(struct lwip_ppp_ctx)); + if (ppp_obj == NULL) { + ESP_LOGE(TAG, "%s: cannot allocate lwip_ppp_ctx", __func__); + return NULL; + } + + ppp_obj->ppp = pppapi_pppos_create(netif_impl, pppos_low_level_output, on_ppp_status_changed, esp_netif); + ESP_LOGD(TAG, "%s: PPP connection created: %p", __func__, ppp_obj->ppp); + if (!ppp_obj->ppp) { + ESP_LOGE(TAG, "%s: lwIP PPP connection cannot be created", __func__); + } +#if PPP_NOTIFY_PHASE + ppp_set_notify_phase_callback(ppp_obj->ppp, on_ppp_notify_phase); +#endif + ppp_set_usepeerdns(ppp_obj->ppp, 1); + + return ppp_obj; +} + +esp_err_t esp_netif_start_ppp(lwip_ppp_ctx_t *ppp_ctx) +{ + ESP_LOGD(TAG, "%s: Starting PPP connection: %p", __func__, ppp_ctx->ppp); + esp_err_t err = pppapi_connect(ppp_ctx->ppp, 0); + if (err != ESP_OK) { + ESP_LOGE(TAG, "%s: PPP connection cannot be started", __func__); + return ESP_FAIL; + } + return ESP_OK; +} + +void esp_netif_lwip_ppp_input(void *ppp_ctx, void *buffer, size_t len, void *eb) +{ + struct lwip_ppp_ctx * obj = ppp_ctx; + err_t ret = pppos_input_tcpip(obj->ppp, buffer, len); + if (ret != ERR_OK) { + ESP_LOGE(TAG, "pppos_input_tcpip failed with %d", ret); + } +} + +esp_err_t esp_netif_stop_ppp(lwip_ppp_ctx_t *ppp_ctx) +{ + ESP_LOGD(TAG, "%s: Stopped PPP connection: %p", __func__, ppp_ctx->ppp); + err_t ret = pppapi_close(ppp_ctx->ppp, 0); + if (ret != ERR_OK) { + ESP_LOGE(TAG, "pppapi_close failed with %d", ret); + return ESP_FAIL; + } + return ESP_OK; +} + +void esp_netif_destroy_ppp(lwip_ppp_ctx_t *ppp_ctx) +{ + pppapi_free(ppp_ctx->ppp); + free(ppp_ctx); +} + +esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_config_t *config) +{ + struct lwip_ppp_ctx *obj = netif->lwip_ppp_ctx; + obj->ppp_phase_event_enabled = config->ppp_phase_event_enabled; + obj->ppp_error_event_enabled = config->ppp_error_event_enabled; + return ESP_OK; +} +#else /* PPPOS_SUPPORT */ + +/** + * @brief If PPP not enabled in menuconfig, log the error and return appropriate code indicating failure +*/ +#define LOG_PPP_DISABLED_AND_DO(action) \ + { \ + ESP_LOGE(TAG, "%s not supported, please enable PPP in lwIP component configuration", __func__); \ + action; \ + } + +esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t authtype, const char *user, const char *passwd) + LOG_PPP_DISABLED_AND_DO(return ESP_ERR_NOT_SUPPORTED) + +void esp_netif_ppp_set_default_netif(lwip_ppp_ctx_t* ppp_ctx) + LOG_PPP_DISABLED_AND_DO() + +lwip_ppp_ctx_t* esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) + LOG_PPP_DISABLED_AND_DO(return NULL) + +esp_err_t esp_netif_start_ppp(lwip_ppp_ctx_t *ppp_ctx) + LOG_PPP_DISABLED_AND_DO(return ESP_ERR_NOT_SUPPORTED) + +void esp_netif_lwip_ppp_input(void *ppp_ctx, void *buffer, size_t len, void *eb) + LOG_PPP_DISABLED_AND_DO() + +esp_err_t esp_netif_stop_ppp(lwip_ppp_ctx_t *ppp_ctx) + LOG_PPP_DISABLED_AND_DO(return ESP_ERR_NOT_SUPPORTED) + +void esp_netif_destroy_ppp(lwip_ppp_ctx_t *ppp_ctx) + LOG_PPP_DISABLED_AND_DO() + +esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_config_t *config) + LOG_PPP_DISABLED_AND_DO(return ESP_ERR_NOT_SUPPORTED) + +#endif /* PPPOS_SUPPORT */ diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.h b/components/esp_netif/lwip/esp_netif_lwip_ppp.h new file mode 100644 index 000000000..25047f795 --- /dev/null +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.h @@ -0,0 +1,76 @@ +// Copyright 2019 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. + +#ifndef _ESP_NETIF_LWIP_PPP_H_ +#define _ESP_NETIF_LWIP_PPP_H_ + +/** + * @brief Creates new PPP related structure + * + * @param[in] esp_netif pointer esp-netif instance + * @param[in] stack_config TCP/IP stack configuration structure + * + * @return + * - pointer to ppp-netif object on success + * - NULL otherwise + */ +lwip_ppp_ctx_t* esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config); + +/** + * @brief Creates new PPP related structure + * + * @param[in] ppp pointer to internal ppp context instance + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_netif_start_ppp(lwip_ppp_ctx_t *ppp); + +/** + * @brief Data path API to input incoming packets to PPP + * + * @param[in] ppp pointer to internal ppp context instance + * @param[in] buffer pointer to the incoming data + * @param[in] len length of the data + * @param[in] eb external buffer ptr not used here (to be inline with input function prototypes) + * + * @return + * - ESP_OK on success + */ +void esp_netif_lwip_ppp_input(void *ppp, void *buffer, size_t len, void *eb); + +/** + * @brief Destroys the ppp netif object + * + * @param[in] ppp pointer to internal ppp context instance + */ +void esp_netif_destroy_ppp(lwip_ppp_ctx_t *ppp); + +/** + * @brief Stops the PPP interface + * + * @param[in] ppp pointer to internal ppp context instance + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_netif_stop_ppp(lwip_ppp_ctx_t *ppp); + +/** + * @brief Sets default netif for routing priority config + * + */ +void esp_netif_ppp_set_default_netif(lwip_ppp_ctx_t* ppp_ctx); + +#endif // _ESP_NETIF_LWIP_PPP_H_ \ No newline at end of file diff --git a/components/lwip/port/esp32/include/netif/ethernetif.h b/components/lwip/port/esp32/include/netif/ethernetif.h index d5d23b3d3..406674c48 100644 --- a/components/lwip/port/esp32/include/netif/ethernetif.h +++ b/components/lwip/port/esp32/include/netif/ethernetif.h @@ -24,7 +24,7 @@ extern "C" { err_t ethernetif_init(struct netif *netif); -void ethernetif_input(void *h, void *buffer, size_t len, void *eb); +void ethernetif_input(void *netif, void *buffer, size_t len, void *eb); void netif_reg_addr_change_cb(void* cb); diff --git a/examples/protocols/pppos_client/components/modem/CMakeLists.txt b/examples/protocols/pppos_client/components/modem/CMakeLists.txt index e1bc2c0a9..a0a434316 100644 --- a/examples/protocols/pppos_client/components/modem/CMakeLists.txt +++ b/examples/protocols/pppos_client/components/modem/CMakeLists.txt @@ -1,5 +1,6 @@ set(srcs "src/esp_modem.c" "src/esp_modem_dce_service" + "src/esp_modem_netif.c" "src/sim800.c" "src/bg96.c") diff --git a/examples/protocols/pppos_client/components/modem/include/esp_modem.h b/examples/protocols/pppos_client/components/modem/include/esp_modem.h index f2da7aeb0..461c0527d 100644 --- a/examples/protocols/pppos_client/components/modem/include/esp_modem.h +++ b/examples/protocols/pppos_client/components/modem/include/esp_modem.h @@ -21,7 +21,6 @@ extern "C" { #include "esp_modem_dte.h" #include "esp_event.h" #include "driver/uart.h" -#include "lwip/ip_addr.h" /** * @brief Declare Event Base for ESP Modem @@ -35,8 +34,6 @@ ESP_EVENT_DECLARE_BASE(ESP_MODEM_EVENT); */ typedef enum { MODEM_EVENT_PPP_START, /*!< ESP Modem Start PPP Session */ - MODEM_EVENT_PPP_CONNECT, /*!< ESP Modem Connect to PPP Server */ - MODEM_EVENT_PPP_DISCONNECT, /*!< ESP Modem Disconnect from PPP Server */ MODEM_EVENT_PPP_STOP, /*!< ESP Modem Stop PPP Session*/ MODEM_EVENT_UNKNOWN /*!< ESP Modem Unknown Response */ } esp_modem_event_t; @@ -54,6 +51,12 @@ typedef struct { uint32_t baud_rate; /*!< Communication baud rate */ } esp_modem_dte_config_t; +/** + * @brief Type used for reception callback + * + */ +typedef esp_err_t (*esp_modem_on_receive)(void *buffer, size_t len, void *context); + /** * @brief ESP Modem DTE Default Configuration * @@ -88,7 +91,7 @@ modem_dte_t *esp_modem_dte_init(const esp_modem_dte_config_t *config); * - 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_add_event_handler(modem_dte_t *dte, esp_event_handler_t handler, void *handler_args); +esp_err_t esp_modem_add_event_handler(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 @@ -101,18 +104,6 @@ esp_err_t esp_modem_add_event_handler(modem_dte_t *dte, esp_event_handler_t hand */ esp_err_t esp_modem_remove_event_handler(modem_dte_t *dte, esp_event_handler_t handler); -/** - * @brief PPPoS Client IP Information - * - */ -typedef struct { - ip4_addr_t ip; /*!< IP Address */ - ip4_addr_t netmask; /*!< Net Mask */ - ip4_addr_t gw; /*!< Gateway */ - ip4_addr_t ns1; /*!< Name Server1 */ - ip4_addr_t ns2; /*!< Name Server2 */ -} ppp_client_ip_info_t; - /** * @brief Setup PPP Session * @@ -121,7 +112,7 @@ typedef struct { * - ESP_OK on success * - ESP_FAIL on error */ -esp_err_t esp_modem_setup_ppp(modem_dte_t *dte); +esp_err_t esp_modem_start_ppp(modem_dte_t *dte); /** * @brief Exit PPP Session @@ -131,7 +122,18 @@ esp_err_t esp_modem_setup_ppp(modem_dte_t *dte); * - ESP_OK on success * - ESP_FAIL on error */ -esp_err_t esp_modem_exit_ppp(modem_dte_t *dte); +esp_err_t esp_modem_stop_ppp(modem_dte_t *dte); + +/** + * @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(modem_dte_t *dte, esp_modem_on_receive receive_cb, void *receive_cb_ctx); #ifdef __cplusplus } diff --git a/examples/protocols/pppos_client/components/modem/include/esp_modem_netif.h b/examples/protocols/pppos_client/components/modem/include/esp_modem_netif.h new file mode 100644 index 000000000..1eac1b497 --- /dev/null +++ b/examples/protocols/pppos_client/components/modem/include/esp_modem_netif.h @@ -0,0 +1,53 @@ +// 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. +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @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 + */ +void *esp_modem_netif_setup(modem_dte_t *dte); + +/** + * @brief Destroys the esp-netif driver handle + * + * @param h pointer to the esp-netif adapter for esp-modem + */ +void esp_modem_netif_teardown(void *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(void *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(void *h, esp_netif_t * esp_netif); + +#ifdef __cplusplus +} +#endif diff --git a/examples/protocols/pppos_client/components/modem/src/esp_modem.c b/examples/protocols/pppos_client/components/modem/src/esp_modem.c index cf604b2b6..b171be27c 100644 --- a/examples/protocols/pppos_client/components/modem/src/esp_modem.c +++ b/examples/protocols/pppos_client/components/modem/src/esp_modem.c @@ -17,10 +17,6 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" -#include "netif/ppp/pppapi.h" -#include "netif/ppp/pppos.h" -#include "lwip/dns.h" -#include "esp_netif.h" #include "esp_modem.h" #include "esp_log.h" #include "sdkconfig.h" @@ -60,11 +56,21 @@ typedef struct { esp_event_loop_handle_t event_loop_hdl; /*!< Event loop handle */ TaskHandle_t uart_event_task_hdl; /*!< UART event task handle */ SemaphoreHandle_t process_sem; /*!< Semaphore used for indicating processing status */ - struct netif pppif; /*!< PPP network interface */ - ppp_pcb *ppp; /*!< PPP control block */ 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 */ } esp_modem_dte_t; + +esp_err_t esp_modem_set_rx_cb(modem_dte_t *dte, esp_modem_on_receive receive_cb, void *receive_cb_ctx) +{ + esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_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 * @@ -135,9 +141,9 @@ static void esp_handle_uart_data(esp_modem_dte_t *esp_dte) uart_get_buffered_data_len(esp_dte->uart_port, &length); length = MIN(ESP_MODEM_LINE_BUFFER_SIZE, length); length = uart_read_bytes(esp_dte->uart_port, esp_dte->buffer, length, portMAX_DELAY); - /* pass input data to the lwIP core thread */ + /* pass the input data to configured callback */ if (length) { - pppos_input_tcpip(esp_dte->ppp, esp_dte->buffer, length); + esp_dte->receive_cb(esp_dte->buffer, length, esp_dte->receive_cb_ctx); } } @@ -236,6 +242,8 @@ err: return -1; } + + /** * @brief Send data and wait for prompt from DCE * @@ -344,6 +352,8 @@ static esp_err_t esp_modem_dte_deinit(modem_dte_t *dte) return ESP_OK; } + + modem_dte_t *esp_modem_dte_init(const esp_modem_dte_config_t *config) { esp_err_t res; @@ -363,6 +373,7 @@ modem_dte_t *esp_modem_dte_init(const esp_modem_dte_config_t *config) 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, @@ -434,10 +445,10 @@ err_dte_mem: return NULL; } -esp_err_t esp_modem_add_event_handler(modem_dte_t *dte, esp_event_handler_t handler, void *handler_args) +esp_err_t esp_modem_add_event_handler(modem_dte_t *dte, esp_event_handler_t handler, int32_t event_id, void *handler_args) { esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent); - return esp_event_handler_register_with(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_EVENT_ANY_ID, handler, handler_args); + 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(modem_dte_t *dte, esp_event_handler_t handler) @@ -446,137 +457,7 @@ esp_err_t esp_modem_remove_event_handler(modem_dte_t *dte, esp_event_handler_t h return esp_event_handler_unregister_with(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, ESP_EVENT_ANY_ID, handler); } -/** - * @brief PPP status callback which is called on PPP status change (up, down, …) by lwIP core thread - * - * @param pcb PPP control block - * @param err_code Error code - * @param ctx Context of callback - */ -static void on_ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx) -{ - struct netif *pppif = ppp_netif(pcb); - const ip_addr_t *dest_ip = NULL; - modem_dte_t *dte = (modem_dte_t *)(ctx); - esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent); - ppp_client_ip_info_t ipinfo = {0}; - switch (err_code) { - case PPPERR_NONE: /* Connected */ - ipinfo.ip = pppif->ip_addr.u_addr.ip4; - ipinfo.gw = pppif->gw.u_addr.ip4; - ipinfo.netmask = pppif->netmask.u_addr.ip4; - dest_ip = dns_getserver(0); - if(dest_ip != NULL){ - ipinfo.ns1 = (*dest_ip).u_addr.ip4; - } - dest_ip = dns_getserver(1); - if(dest_ip != NULL){ - ipinfo.ns2 = (*dest_ip).u_addr.ip4; - } - esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, MODEM_EVENT_PPP_CONNECT, &ipinfo, sizeof(ipinfo), 0); - break; - case PPPERR_PARAM: - ESP_LOGE(MODEM_TAG, "Invalid parameter"); - break; - case PPPERR_OPEN: - ESP_LOGE(MODEM_TAG, "Unable to open PPP session"); - break; - case PPPERR_DEVICE: - ESP_LOGE(MODEM_TAG, "Invalid I/O device for PPP"); - break; - case PPPERR_ALLOC: - ESP_LOGE(MODEM_TAG, "Unable to allocate resources"); - break; - case PPPERR_USER: /* User interrupt */ - esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, MODEM_EVENT_PPP_STOP, NULL, 0, 0); - /* Free the PPP control block */ - pppapi_free(esp_dte->ppp); - break; - case PPPERR_CONNECT: /* Connection lost */ - esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, MODEM_EVENT_PPP_DISCONNECT, NULL, 0, 0); - break; - case PPPERR_AUTHFAIL: - ESP_LOGE(MODEM_TAG, "Failed authentication challenge"); - break; - case PPPERR_PROTOCOL: - ESP_LOGE(MODEM_TAG, "Failed to meet protocol"); - break; - case PPPERR_PEERDEAD: - ESP_LOGE(MODEM_TAG, "Connection timeout"); - break; - case PPPERR_IDLETIMEOUT: - ESP_LOGE(MODEM_TAG, "Idle Timeout"); - break; - case PPPERR_CONNECTTIME: - ESP_LOGE(MODEM_TAG, "Max connect time reached"); - break; - case PPPERR_LOOPBACK: - ESP_LOGE(MODEM_TAG, "Loopback detected"); - break; - default: - ESP_LOGE(MODEM_TAG, "Unknown error code %d", err_code); - break; - } -} - -#if PPP_NOTIFY_PHASE -/** - * @brief Notify phase callback which is called on each PPP internal state change - * - * @param pcb PPP control block - * @param phase Phase ID - * @param ctx Context of callback - */ -static void on_ppp_notify_phase(ppp_pcb *pcb, u8_t phase, void *ctx) -{ - switch (phase) { - case PPP_PHASE_DEAD: - ESP_LOGD(MODEM_TAG, "Phase Dead"); - break; - case PPP_PHASE_INITIALIZE: - ESP_LOGD(MODEM_TAG, "Phase Start"); - break; - case PPP_PHASE_ESTABLISH: - ESP_LOGD(MODEM_TAG, "Phase Establish"); - break; - case PPP_PHASE_AUTHENTICATE: - ESP_LOGD(MODEM_TAG, "Phase Authenticate"); - break; - case PPP_PHASE_NETWORK: - ESP_LOGD(MODEM_TAG, "Phase Network"); - break; - case PPP_PHASE_RUNNING: - ESP_LOGD(MODEM_TAG, "Phase Running"); - break; - case PPP_PHASE_TERMINATE: - ESP_LOGD(MODEM_TAG, "Phase Terminate"); - break; - case PPP_PHASE_DISCONNECT: - ESP_LOGD(MODEM_TAG, "Phase Disconnect"); - break; - default: - ESP_LOGW(MODEM_TAG, "Phase Unknown: %d", phase); - break; - } -} -#endif - -/** - * @brief PPPoS serial output callback - * - * @param pcb PPP control block - * @param data Buffer to write to serial port - * @param len Length of the data buffer - * @param ctx Context of callback - * @return uint32_t Length of data successfully sent - */ -static uint32_t pppos_low_level_output(ppp_pcb *pcb, uint8_t *data, uint32_t len, void *ctx) -{ - modem_dte_t *dte = (modem_dte_t *)ctx; - return dte->send_data(dte, (const char *)data, len); -} - -esp_err_t esp_modem_setup_ppp(modem_dte_t *dte) +esp_err_t esp_modem_start_ppp(modem_dte_t *dte) { modem_dce_t *dce = dte->dce; MODEM_CHECK(dce, "DTE has not yet bind with DCE", err); @@ -585,40 +466,18 @@ esp_err_t esp_modem_setup_ppp(modem_dte_t *dte) MODEM_CHECK(dce->define_pdp_context(dce, 1, "IP", CONFIG_EXAMPLE_MODEM_APN) == ESP_OK, "set MODEM APN failed", err); /* Enter PPP mode */ MODEM_CHECK(dte->change_mode(dte, MODEM_PPP_MODE) == ESP_OK, "enter ppp mode failed", err); - /* Create PPPoS interface */ - esp_dte->ppp = pppapi_pppos_create(&(esp_dte->pppif), pppos_low_level_output, on_ppp_status_changed, dte); - MODEM_CHECK(esp_dte->ppp, "create pppos interface failed", err); -#if PPP_NOTIFY_PHASE - ppp_set_notify_phase_callback(esp_dte->ppp, on_ppp_notify_phase); -#endif - /* Initiate PPP client connection */ - /* Set default route */ - MODEM_CHECK(pppapi_set_default(esp_dte->ppp) == ERR_OK, "set default route failed", err); - /* Ask the peer for up to 2 DNS server addresses */ - ppp_set_usepeerdns(esp_dte->ppp, 1); - /* Auth configuration */ -#if PAP_SUPPORT - pppapi_set_auth(esp_dte->ppp, PPPAUTHTYPE_PAP, CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME, CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD); -#elif CHAP_SUPPORT - pppapi_set_auth(esp_dte->ppp, PPPAUTHTYPE_CHAP, CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME, CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD); -#else -#error "Unsupported AUTH Negotiation" -#endif - /* Initiate PPP negotiation, without waiting */ - MODEM_CHECK(pppapi_connect(esp_dte->ppp, 0) == ERR_OK, "initiate ppp negotiation failed", err); + + /* post PPP mode started event */ esp_event_post_to(esp_dte->event_loop_hdl, ESP_MODEM_EVENT, MODEM_EVENT_PPP_START, NULL, 0, 0); return ESP_OK; err: return ESP_FAIL; } -esp_err_t esp_modem_exit_ppp(modem_dte_t *dte) +esp_err_t esp_modem_stop_ppp(modem_dte_t *dte) { modem_dce_t *dce = dte->dce; MODEM_CHECK(dce, "DTE has not yet bind with DCE", err); - esp_modem_dte_t *esp_dte = __containerof(dte, esp_modem_dte_t, parent); - /* Shutdown of PPP protocols */ - MODEM_CHECK(pppapi_close(esp_dte->ppp, 0) == ERR_OK, "close ppp connection failed", err); /* Enter command mode */ MODEM_CHECK(dte->change_mode(dte, MODEM_COMMAND_MODE) == ESP_OK, "enter command mode failed", err); /* Hang up */ diff --git a/examples/protocols/pppos_client/components/modem/src/esp_modem_netif.c b/examples/protocols/pppos_client/components/modem/src/esp_modem_netif.c new file mode 100644 index 000000000..c5a5a5ab2 --- /dev/null +++ b/examples/protocols/pppos_client/components/modem/src/esp_modem_netif.c @@ -0,0 +1,155 @@ +// 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 "esp_netif.h" +#include "esp_modem.h" +#include "esp_log.h" + +static const char *TAG = "esp-modem-netif"; + +/** + * @brief ESP32 Modem handle to be used as netif IO object + */ +typedef struct esp_modem_netif_driver_s { + esp_netif_driver_base_t base; /*!< base structure reserved as esp-netif driver */ + modem_dte_t *dte; /*!< ptr to the esp_modem objects (DTE) */ +} esp_modem_netif_driver_t; + +/** + * @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) +{ + 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 + */ +static esp_err_t esp_modem_post_attach_start(esp_netif_t * esp_netif, void * args) +{ + esp_modem_netif_driver_t *driver = args; + 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)); + esp_modem_start_ppp(dte); + return ESP_OK; +} + +/** + * @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; +} + +void *esp_modem_netif_setup(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_teardown(void *h) +{ + esp_modem_netif_driver_t *driver = h; + esp_netif_destroy(driver->base.netif); + free(driver); +} + +esp_err_t esp_modem_netif_clear_default_handlers(void *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(void *h, esp_netif_t * esp_netif) +{ + esp_modem_netif_driver_t *driver = h; + esp_err_t ret; + ret = esp_modem_add_event_handler(driver->dte, esp_netif_action_start, MODEM_EVENT_PPP_START, esp_netif); + if (ret != ESP_OK) { + goto set_event_failed; + } + ret = esp_modem_add_event_handler(driver->dte, esp_netif_action_stop, MODEM_EVENT_PPP_STOP, 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; +} diff --git a/examples/protocols/pppos_client/main/pppos_client_main.c b/examples/protocols/pppos_client/main/pppos_client_main.c index 7df7c4938..d31c8197e 100644 --- a/examples/protocols/pppos_client/main/pppos_client_main.c +++ b/examples/protocols/pppos_client/main/pppos_client_main.c @@ -10,8 +10,10 @@ #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #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 "sim800.h" #include "bg96.h" @@ -112,21 +114,6 @@ static void modem_event_handler(void *event_handler_arg, esp_event_base_t event_ case MODEM_EVENT_PPP_START: ESP_LOGI(TAG, "Modem PPP Started"); break; - case MODEM_EVENT_PPP_CONNECT: - ESP_LOGI(TAG, "Modem Connect to PPP Server"); - ppp_client_ip_info_t *ipinfo = (ppp_client_ip_info_t *)(event_data); - ESP_LOGI(TAG, "~~~~~~~~~~~~~~"); - ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&ipinfo->ip)); - ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&ipinfo->netmask)); - ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&ipinfo->gw)); - ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&ipinfo->ns1)); - ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&ipinfo->ns2)); - ESP_LOGI(TAG, "~~~~~~~~~~~~~~"); - xEventGroupSetBits(event_group, CONNECT_BIT); - break; - case MODEM_EVENT_PPP_DISCONNECT: - ESP_LOGI(TAG, "Modem Disconnect from PPP Server"); - break; case MODEM_EVENT_PPP_STOP: ESP_LOGI(TAG, "Modem PPP Stopped"); xEventGroupSetBits(event_group, STOP_BIT); @@ -179,15 +166,72 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) return ESP_OK; } +static void on_ppp_changed(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ESP_LOGI(TAG, "PPP state changed event %d", event_id); + if (event_id == NETIF_PPP_ERRORUSER) { + /* User interrupted event from esp-netif */ + esp_netif_t *netif = event_data; + ESP_LOGI(TAG, "User interrupted event from netif:%p", netif); + } +} + + +static void on_ip_event(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ESP_LOGI(TAG, "IP event! %d", event_id); + if (event_id == IP_EVENT_PPP_GOT_IP) { + esp_netif_dns_info_t dns_info; + + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + esp_netif_t *netif = event->esp_netif; + + ESP_LOGI(TAG, "Modem Connect to PPP Server"); + ESP_LOGI(TAG, "~~~~~~~~~~~~~~"); + ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip)); + ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask)); + ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.ip)); + esp_netif_get_dns_info(netif, 0, &dns_info); + ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4)); + esp_netif_get_dns_info(netif, 1, &dns_info); + ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4)); + ESP_LOGI(TAG, "~~~~~~~~~~~~~~"); + xEventGroupSetBits(event_group, CONNECT_BIT); + + ESP_LOGI(TAG, "GOT ip event!!!"); + } else if (event_id == IP_EVENT_PPP_LOST_IP) { + ESP_LOGI(TAG, "Modem Disconnect from PPP Server"); + } +} + void app_main(void) { +#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_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, NULL)); + event_group = xEventGroupCreate(); + + // Init netif object + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_PPP(); + esp_netif_t *esp_netif = esp_netif_new(&cfg); + assert(esp_netif); + /* create dte object */ esp_modem_dte_config_t config = ESP_MODEM_DTE_DEFAULT_CONFIG(); modem_dte_t *dte = esp_modem_dte_init(&config); /* Register event handler */ - ESP_ERROR_CHECK(esp_modem_add_event_handler(dte, modem_event_handler, NULL)); + ESP_ERROR_CHECK(esp_modem_add_event_handler(dte, modem_event_handler, ESP_EVENT_ANY_ID, NULL)); /* create dce object */ #if CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 modem_dce_t *dce = sim800_init(dte); @@ -211,10 +255,15 @@ void app_main(void) uint32_t voltage = 0, bcs = 0, bcl = 0; ESP_ERROR_CHECK(dce->get_battery_status(dce, &bcs, &bcl, &voltage)); ESP_LOGI(TAG, "Battery voltage: %d mV", voltage); - /* Setup PPP environment */ - esp_modem_setup_ppp(dte); + /* setup PPPoS network parameters */ + esp_netif_ppp_set_auth(esp_netif, auth_type, CONFIG_EXAMPLE_MODEM_PPP_AUTH_USERNAME, CONFIG_EXAMPLE_MODEM_PPP_AUTH_PASSWORD); + void *modem_netif_adapter = esp_modem_netif_setup(dte); + esp_modem_netif_set_default_handlers(modem_netif_adapter, esp_netif); + /* attach the modem to the network interface */ + esp_netif_attach(esp_netif, modem_netif_adapter); /* Wait for IP address */ xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY); + ESP_ERROR_CHECK(dce->power_down(dce)); /* Config MQTT */ esp_mqtt_client_config_t mqtt_config = { .uri = BROKER_URL, @@ -225,7 +274,10 @@ void app_main(void) xEventGroupWaitBits(event_group, GOT_DATA_BIT, pdTRUE, pdTRUE, portMAX_DELAY); esp_mqtt_client_destroy(mqtt_client); /* Exit PPP mode */ - ESP_ERROR_CHECK(esp_modem_exit_ppp(dte)); + ESP_ERROR_CHECK(esp_modem_stop_ppp(dte)); + /* Destroy the netif adapter withe events, which internally frees also the esp-netif instance */ + esp_modem_netif_clear_default_handlers(modem_netif_adapter); + esp_modem_netif_teardown(modem_netif_adapter); xEventGroupWaitBits(event_group, STOP_BIT, pdTRUE, pdTRUE, portMAX_DELAY); #if CONFIG_EXAMPLE_SEND_MSG const char *message = "Welcome to ESP32!";