Enable lwip PPPoS support

* Fix some lwip api bugs
 * Added PPP_SUPPORT parameter to lwip Kconfig
 * Added example pppos_client

Merges #272 https://github.com/espressif/esp-idf/pull/272
This commit is contained in:
Adrian Muzyka 2017-01-20 12:05:38 +01:00 committed by Angus Gratton
parent 793003d0fa
commit 47c722d674
13 changed files with 459 additions and 14 deletions

View file

@ -187,6 +187,12 @@ config SYSTEM_EVENT_TASK_STACK_SIZE
help
Config system event task stack size in different application.
config TCPIP_TASK_STACK_SIZE
int "TCP/IP Task Stack Size"
default 2048
help
Configure TCP/IP task stack size, used by LWIP to process multi-threaded TCP/IP operations.
The default is 2048 bytes, setting this stack too small will result in stack overflow crashes.
config MAIN_TASK_STACK_SIZE
int "Main task stack size"

View file

@ -46,7 +46,7 @@
#define ESP_TASKD_EVENT_PRIO (ESP_TASK_PRIO_MAX - 5)
#define ESP_TASKD_EVENT_STACK CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE
#define ESP_TASK_TCPIP_PRIO (ESP_TASK_PRIO_MAX - 7)
#define ESP_TASK_TCPIP_STACK 2048
#define ESP_TASK_TCPIP_STACK CONFIG_TCPIP_TASK_STACK_SIZE
#define ESP_TASK_MAIN_PRIO (ESP_TASK_PRIO_MIN + 1)
#define ESP_TASK_MAIN_STACK CONFIG_MAIN_TASK_STACK_SIZE

View file

@ -89,6 +89,46 @@ config LWIP_DHCP_DOES_ARP_CHECK
Enabling this option allows check if the offered IP address is not already
in use by another host on the network.
config PPP_SUPPORT
bool "Enable PPP support"
default 0
help
Enable PPP stack. Now only PPP over serial is supported
if PPP_SUPPORT
config PPP_PAP_SUPPORT
bool "Enable PAP support"
default 0
help
Enable Password Authentication Protocol (PAP) support
config PPP_CHAP_SUPPORT
bool "Enable CHAP support"
default 0
help
Enable Challenge Handshake Authentication Protocol (CHAP) support
config PPP_MSCHAP_SUPPORT
bool "Enable MSCHAP support"
default 0
help
Enable Microsoft version of the Challenge-Handshake Authentication Protocol (MSCHAP) support
config PPP_MPPE_SUPPORT
bool "Enable MPPE support"
default 0
help
Enable Microsoft Point-to-Point Encryption (MPPE) support
config PPP_DEBUG_ON
bool "Enable PPP debug logs"
default 0
help
Enable PPP debug logs
endif
endmenu

View file

@ -73,10 +73,10 @@ pppapi_set_default(ppp_pcb *pcb)
static err_t
pppapi_do_ppp_set_auth(struct tcpip_api_call *m)
{
struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m;
struct pppapi_msg *msg = (struct pppapi_msg *)m;
ppp_set_auth(msg->ppp, msg->msg.setauth.authtype,
msg->msg.setauth.user, msg->msg.setauth.passwd);
ppp_set_auth(msg->msg.ppp, msg->msg.msg.setauth.authtype,
msg->msg.msg.setauth.user, msg->msg.msg.setauth.passwd);
return ERR_OK;
}
@ -131,10 +131,10 @@ pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_pha
static err_t
pppapi_do_pppos_create(struct tcpip_api_call *m)
{
struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m;
struct pppapi_msg *msg = (struct pppapi_msg *)(m);
msg->ppp = pppos_create(msg->msg.serialcreate.pppif, msg->msg.serialcreate.output_cb,
msg->msg.serialcreate.link_status_cb, msg->msg.serialcreate.ctx_cb);
msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb,
msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb);
return ERR_OK;
}
@ -247,9 +247,9 @@ pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipad
static err_t
pppapi_do_ppp_connect(struct tcpip_api_call *m)
{
struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m;
struct pppapi_msg *msg = (struct pppapi_msg *)m;
return ppp_connect(msg->ppp, msg->msg.connect.holdoff);
return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff);
}
/**
@ -300,9 +300,9 @@ pppapi_listen(ppp_pcb *pcb, struct ppp_addrs *addrs)
static err_t
pppapi_do_ppp_close(struct tcpip_api_call *m)
{
struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m;
struct pppapi_msg *msg = (struct pppapi_msg *)m;
return ppp_close(msg->ppp, msg->msg.close.nocarrier);
return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier);
}
/**
@ -349,9 +349,9 @@ pppapi_free(ppp_pcb *pcb)
static err_t
pppapi_do_ppp_ioctl(struct tcpip_api_call *m)
{
struct pppapi_msg_msg *msg = (struct pppapi_msg_msg *)m;
struct pppapi_msg *msg = (struct pppapi_msg *)m;
return ppp_ioctl(msg->ppp, msg->msg.ioctl.cmd, msg->msg.ioctl.arg);
return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg);
}
/**

View file

@ -4,9 +4,11 @@
COMPONENT_ADD_INCLUDEDIRS := include/lwip include/lwip/port include/lwip/posix apps/ping
COMPONENT_SRCDIRS := api apps/sntp apps/ping apps core/ipv4 core/ipv6 core netif port/freertos port/netif port/debug port
COMPONENT_SRCDIRS := api apps/sntp apps/ping apps core/ipv4 core/ipv6 core netif netif/ppp netif/ppp/polarssl port/freertos port/netif port/debug port
CFLAGS += -Wno-address # lots of LWIP source files evaluate macros that check address of stack variables
api/tcpip.o apps/dhcpserver.o: CFLAGS += -Wno-unused-variable
apps/dhcpserver.o core/pbuf.o core/tcp_in.o: CFLAGS += -Wno-unused-but-set-variable
netif/ppp/pppos.o: CFLAGS += -Wno-type-limits

View file

@ -503,6 +503,56 @@
---------------------------------
*/
/**
* PPP_SUPPORT==1: Enable PPP.
*/
#define PPP_SUPPORT CONFIG_PPP_SUPPORT
#if PPP_SUPPORT
/**
* PAP_SUPPORT==1: Support PAP.
*/
#define PAP_SUPPORT CONFIG_PPP_PAP_SUPPORT
/**
* CHAP_SUPPORT==1: Support CHAP.
*/
#define CHAP_SUPPORT CONFIG_PPP_CHAP_SUPPORT
/**
* MSCHAP_SUPPORT==1: Support MSCHAP.
*/
#define MSCHAP_SUPPORT CONFIG_PPP_MSCHAP_SUPPORT
/**
* CCP_SUPPORT==1: Support CCP.
*/
#define MPPE_SUPPORT CONFIG_PPP_MPPE_SUPPORT
/**
* PPP_MAXIDLEFLAG: Max Xmit idle time (in ms) before resend flag char.
* TODO: If PPP_MAXIDLEFLAG > 0 and next package is send during PPP_MAXIDLEFLAG time,
* then 0x7E is not added at the begining of PPP package but 0x7E termination
* is always at the end. This behaviour brokes PPP dial with GSM (PPPoS).
* The PPP package should always start and end with 0x7E.
*/
#define PPP_MAXIDLEFLAG 0
/**
* PPP_DEBUG: Enable debugging for PPP.
*/
#define PPP_DEBUG_ON CONFIG_PPP_DEBUG_ON
#if PPP_DEBUG_ON
#define PPP_DEBUG LWIP_DBG_ON
#else
#define PPP_DEBUG LWIP_DBG_OFF
#endif
#endif
/*
--------------------------------------
---------- Checksum options ----------

View file

@ -435,6 +435,13 @@ sys_init(void)
}
}
/*-----------------------------------------------------------------------------------*/
u32_t
sys_jiffies(void)
{
return xTaskGetTickCount();
}
/*-----------------------------------------------------------------------------------*/
u32_t
sys_now(void)

View file

@ -0,0 +1,9 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := pppos_client
include $(IDF_PATH)/make/project.mk

View file

@ -0,0 +1,9 @@
#PPP over Serial (PPPoS) client example
It shows example of ppp client using lwip PPPoS api and GSM.
Before you run this example, make sure your GSM is in command mode
and is registered to network.
Tested with GSM Telit GL865-DUAL V3.
See the README.md file in the upper level 'examples' directory for more information about examples.

View file

@ -0,0 +1,21 @@
menu "GSM configuration"
config GSM_INTERNET_USER
string "Internet User"
default ""
help
Network provider internet user.
config GSM_INTERNET_PASSWORD
string "Internet password"
default ""
help
Network provider internet password
config GSM_APN
string "Internet APN"
default "playmetric"
help
APN from network provider for internet access
endmenu

View file

@ -0,0 +1,4 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View file

@ -0,0 +1,292 @@
/* PPPoS Client Example with GSM (tested with Telit GL865-DUAL-V3)
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "netif/ppp/pppos.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "lwip/pppapi.h"
/* The examples use simple GSM configuration that you can set via
'make menuconfig'.
*/
#define BUF_SIZE (1024)
const char *PPP_User = CONFIG_GSM_INTERNET_USER;
const char *PPP_Pass = CONFIG_GSM_INTERNET_PASSWORD;
const char *PPP_ApnATReq = "AT+CGDCONT=1,\"IP\",\"" \
CONFIG_GSM_APN \
"\"";
/* UART */
int uart_num = UART_NUM_1;
/* The PPP control block */
ppp_pcb *ppp;
/* The PPP IP interface */
struct netif ppp_netif;
static const char *TAG = "example";
typedef struct {
char *cmd;
uint16_t cmdSize;
char *cmdResponseOnOk;
uint32_t timeoutMs;
} GSM_Cmd;
#define GSM_OK_Str "OK"
GSM_Cmd GSM_MGR_InitCmds[] = {
{
.cmd = "AT\r",
.cmdSize = sizeof("AT\r") - 1,
.cmdResponseOnOk = GSM_OK_Str,
.timeoutMs = 3000,
},
{
.cmd = "ATE0\r",
.cmdSize = sizeof("ATE0\r") - 1,
.cmdResponseOnOk = GSM_OK_Str,
.timeoutMs = 3000,
},
{
.cmd = "AT+CPIN?\r",
.cmdSize = sizeof("AT+CPIN?\r") - 1,
.cmdResponseOnOk = "CPIN: READY",
.timeoutMs = 3000,
},
{
//AT+CGDCONT=1,"IP","apn"
.cmd = "AT+CGDCONT=1,\"IP\",\"playmetric\"\r",
.cmdSize = sizeof("AT+CGDCONT=1,\"IP\",\"playmetric\"\r") - 1,
.cmdResponseOnOk = GSM_OK_Str,
.timeoutMs = 3000,
},
{
.cmd = "ATDT*99***1#\r",
.cmdSize = sizeof("ATDT*99***1#\r") - 1,
.cmdResponseOnOk = "CONNECT",
.timeoutMs = 30000,
}
};
#define GSM_MGR_InitCmdsSize (sizeof(GSM_MGR_InitCmds)/sizeof(GSM_Cmd))
/* PPP status callback example */
static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx)
{
struct netif *pppif = ppp_netif(pcb);
LWIP_UNUSED_ARG(ctx);
switch (err_code) {
case PPPERR_NONE: {
ESP_LOGI(TAG, "status_cb: Connected\n");
#if PPP_IPV4_SUPPORT
ESP_LOGI(TAG, " our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr));
ESP_LOGI(TAG, " his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw));
ESP_LOGI(TAG, " netmask = %s\n", ipaddr_ntoa(&pppif->netmask));
#endif /* PPP_IPV4_SUPPORT */
#if PPP_IPV6_SUPPORT
ESP_LOGI(TAG, " our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
#endif /* PPP_IPV6_SUPPORT */
break;
}
case PPPERR_PARAM: {
ESP_LOGE(TAG, "status_cb: Invalid parameter\n");
break;
}
case PPPERR_OPEN: {
ESP_LOGE(TAG, "status_cb: Unable to open PPP session\n");
break;
}
case PPPERR_DEVICE: {
ESP_LOGE(TAG, "status_cb: Invalid I/O device for PPP\n");
break;
}
case PPPERR_ALLOC: {
ESP_LOGE(TAG, "status_cb: Unable to allocate resources\n");
break;
}
case PPPERR_USER: {
ESP_LOGE(TAG, "status_cb: User interrupt\n");
break;
}
case PPPERR_CONNECT: {
ESP_LOGE(TAG, "status_cb: Connection lost\n");
break;
}
case PPPERR_AUTHFAIL: {
ESP_LOGE(TAG, "status_cb: Failed authentication challenge\n");
break;
}
case PPPERR_PROTOCOL: {
ESP_LOGE(TAG, "status_cb: Failed to meet protocol\n");
break;
}
case PPPERR_PEERDEAD: {
ESP_LOGE(TAG, "status_cb: Connection timeout\n");
break;
}
case PPPERR_IDLETIMEOUT: {
ESP_LOGE(TAG, "status_cb: Idle Timeout\n");
break;
}
case PPPERR_CONNECTTIME: {
ESP_LOGE(TAG, "status_cb: Max connect time reached\n");
break;
}
case PPPERR_LOOPBACK: {
ESP_LOGE(TAG, "status_cb: Loopback detected\n");
break;
}
default: {
ESP_LOGE(TAG, "status_cb: Unknown error code %d\n", err_code);
break;
}
}
/*
* This should be in the switch case, this is put outside of the switch
* case for example readability.
*/
if (err_code == PPPERR_NONE) {
return;
}
/* ppp_close() was previously called, don't reconnect */
if (err_code == PPPERR_USER) {
/* ppp_free(); -- can be called here */
return;
}
/*
* Try to reconnect in 30 seconds, if you need a modem chatscript you have
* to do a much better signaling here ;-)
*/
//ppp_connect(pcb, 30);
/* OR ppp_listen(pcb); */
}
static u32_t ppp_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx)
{
ESP_LOGI(TAG, "PPP tx len %d", len);
return uart_write_bytes(uart_num, (const char *)data, len);
}
static void pppos_client_task()
{
char *data = (char *) malloc(BUF_SIZE);
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS
};
//Configure UART1 parameters
uart_param_config(uart_num, &uart_config);
//Set UART1 pins(TX: IO17, RX: IO16, RTS: IO18, CTS: IO23)
uart_set_pin(uart_num, 17, 16, 18, 23);
uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0);
while (1) {
//init gsm
int gsmCmdIter = 0;
while (1) {
ESP_LOGI(TAG, "%s", GSM_MGR_InitCmds[gsmCmdIter].cmd);
uart_write_bytes(uart_num, (const char *)GSM_MGR_InitCmds[gsmCmdIter].cmd,
GSM_MGR_InitCmds[gsmCmdIter].cmdSize);
int timeoutCnt = 0;
while (1) {
memset(data, 0, BUF_SIZE);
int len = uart_read_bytes(uart_num, (uint8_t *)data, BUF_SIZE, 500 / portTICK_RATE_MS);
if (len > 0) {
ESP_LOGI(TAG, "%s", data);
}
timeoutCnt += 500;
if (strstr(data, GSM_MGR_InitCmds[gsmCmdIter].cmdResponseOnOk) != NULL) {
break;
}
if (timeoutCnt > GSM_MGR_InitCmds[gsmCmdIter].timeoutMs) {
ESP_LOGE(TAG, "Gsm Init Error");
return;
}
}
gsmCmdIter++;
if (gsmCmdIter >= GSM_MGR_InitCmdsSize) {
break;
}
}
ESP_LOGI(TAG, "Gsm init end");
ppp = pppapi_pppos_create(&ppp_netif,
ppp_output_callback, ppp_status_cb, NULL);
ESP_LOGI(TAG, "After pppapi_pppos_create");
if (ppp == NULL) {
ESP_LOGE(TAG, "Error init pppos");
return;
}
pppapi_set_default(ppp);
ESP_LOGI(TAG, "After pppapi_set_default");
pppapi_set_auth(ppp, PPPAUTHTYPE_PAP, PPP_User, PPP_Pass);
ESP_LOGI(TAG, "After pppapi_set_auth");
pppapi_connect(ppp, 0);
ESP_LOGI(TAG, "After pppapi_connect");
while (1) {
memset(data, 0, BUF_SIZE);
int len = uart_read_bytes(uart_num, (uint8_t *)data, BUF_SIZE, 10 / portTICK_RATE_MS);
if (len > 0) {
ESP_LOGI(TAG, "PPP rx len %d", len);
pppos_input_tcpip(ppp, (u8_t *)data, len);
}
}
}
}
void app_main()
{
tcpip_adapter_init();
xTaskCreate(&pppos_client_task, "pppos_client_task", 2048, NULL, 5, NULL);
while (1) {
vTaskDelay(1000 / portTICK_RATE_MS);
}
}

View file

@ -0,0 +1,5 @@
# Override some defaults to enable PPP
CONFIG_PPP_SUPPORT=y
CONFIG_PPP_PAP_SUPPORT=y
CONFIG_PPP_DEBUG_ON=y
CONFIG_TCPIP_TASK_STACK_SIZE=4096