Initial commit

This commit is contained in:
Michael Smith 2018-03-09 14:21:54 +01:00
commit c3ff7276a9
28 changed files with 8779 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build/

143
Makefile Normal file
View File

@ -0,0 +1,143 @@
# Makefile for ESP8266 projects
#
# Thanks to:
# - zarya
# - Jeroen Domburg (Sprite_tm)
# - Christian Klippel (mamalala)
# - Tommie Gannert (tommie)
#
# Changelog:
# - 2014-10-06: Changed the variables to include the header file directory
# - 2014-10-06: Added global var for the Xtensa tool root
# - 2014-11-23: Updated for SDK 0.9.3
# - 2014-12-25: Replaced esptool by esptool.py
BUILD_AREA = /Volumes/case-sensitive/esp8266-dev
# Output directors to store intermediate compiled files
# relative to the project directory
BUILD_BASE = build
FW_BASE = firmware
# base directory for the compiler
XTENSA_TOOLS_ROOT ?= $(BUILD_AREA)/esp-open-sdk/xtensa-lx106-elf/bin
# # base directory of the ESP8266 SDK package, absolute
SDK_BASE ?= $(BUILD_AREA)/esp-open-sdk/sdk
# # esptool.py path and port
ESPTOOL ?= $(BUILD_AREA)/esp-open-sdk/esptool/esptool.py
#ESPTOOL ?= /home/martin/.local/bin/esptool.py
ESPPORT ?= /dev/tty.wchusbserial1420
ESPTOOLBAUD ?= 115200
ESPTOOLOPTS = -ff 40m -fm dio -fs 32m
# name for the target project
TARGET = app
# which modules (subdirectories) of the project to include in compiling
MODULES = driver user easygpio
EXTRA_INCDIR = include $(BUILD_AREA)/esp-open-sdk/esp-open-lwip/include
#EXTRA_INCDIR = include
# libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal pp phy net80211 lwip_open_napt wpa main
# compiler flags using during compilation of source files
CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DLWIP_OPEN_SRC -DUSE_OPTIMIZE_PRINTF
# linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -L.
# linker script used for the above linkier step
LD_SCRIPT = eagle.app.v6.ld
# various paths from the SDK used in this project
SDK_LIBDIR = lib
SDK_LDDIR = ld
SDK_INCDIR = include include/json
# we create two different files for uploading into the flash
# these are the names and options to generate them
FW_FILE_1_ADDR = 0x00000
FW_FILE_2_ADDR = 0x10000
# select which tools to use as compiler, librarian and linker
CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc
AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar
LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc
####
#### no user configurable options below here
####
SRC_DIR := $(MODULES)
BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES))
SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR))
SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR))
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC))
LIBS := $(addprefix -l,$(LIBS))
APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a)
TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out)
LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT))
INCDIR := $(addprefix -I,$(SRC_DIR))
EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR))
MODULE_INCDIR := $(addsuffix /include,$(INCDIR))
FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin)
FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin)
V ?= $(VERBOSE)
ifeq ("$(V)","1")
Q :=
vecho := @true
else
Q := @
vecho := @echo
endif
vpath %.c $(SRC_DIR)
define compile-objects
$1/%.o: %.c
$(vecho) "CC $$<"
$(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@
endef
.PHONY: all checkdirs flash clean
all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2)
$(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE)
$(vecho) "FW $(FW_BASE)/"
$(Q) $(ESPTOOL) elf2image -o $(FW_BASE)/ $(TARGET_OUT)
$(TARGET_OUT): $(APP_AR)
$(vecho) "LD $@"
$(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@
$(APP_AR): $(OBJ)
$(vecho) "AR $@"
$(Q) $(AR) cru $@ $^
checkdirs: $(BUILD_DIR) $(FW_BASE)
$(BUILD_DIR):
$(Q) mkdir -p $@
$(FW_BASE):
$(Q) mkdir -p $@
flash: $(FW_FILE_1) $(FW_FILE_2)
$(ESPTOOL) --port $(ESPPORT) --baud $(ESPTOOLBAUD) write_flash $(ESPTOOLOPTS) $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2)
clean:
$(Q) rm -rf $(FW_BASE) $(BUILD_BASE)
$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))

14
README.md Normal file
View File

@ -0,0 +1,14 @@
# ESPerPass
A 3DS HomePass implementation for the ESP8266 programmable WiFi chip.
Inspired by [this reddit post](https://www.reddit.com/r/3DS/comments/80k0qb/homepass_for_cheap_using_an_esp8266/)
and largely based on the great work done by [Martin Ger's ESP WiFi Repeater](https://github.com/martin-ger/esp_wifi_repeater).
## Instructions (need improvement)
1. Flash firmware.
2. Connect ESP8266 to USB and connect with terminal program.
3. Power cycle ESP8266.
3. Follow instructions in terminal program.
## TODO
* Implement firewall rules to restrict connections to official servers.
* Implement mac address list management through console.

471
driver/new_uart.c Normal file
View File

@ -0,0 +1,471 @@
/*
* File : uart.c
* Copyright (C) 2013 - 2016, Espressif Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ets_sys.h"
#include "osapi.h"
#include "driver/uart.h"
#include "osapi.h"
#include "driver/uart_register.h"
#include "mem.h"
#include "os_type.h"
#ifdef _ENABLE_RING_BUFFER
static ringbuf_t rxBuff;
static ringbuf_t txBuff;
#endif
#ifdef _ENABLE_CONSOLE_INTEGRATION
uint8_t linked_to_console = 0;
#endif
extern UartDevice UartDev;
/* Local variables */
static uint8 uart_recvTaskPrio = 0;
/* Internal Functions */
static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no);
static void uart0_rx_intr_handler(void *para);
/* Public APIs */
void ICACHE_FLASH_ATTR UART_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 recv_task_priority);
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DBG
#define DBG1 os_printf
#define DBG2 os_printf
#else
#define DBG
#define DBG1
#define DBG2
#endif
#if _ENABLE_CONSOLE_INTEGRATION == 1
void ICACHE_FLASH_ATTR UART_init_console(UartBautRate uart0_br,
uint8 recv_task_priority,
ringbuf_t rxbuffer,
ringbuf_t txBuffer)
{
/* Set the task which should receive the signals once the data is received */
uart_recvTaskPrio = recv_task_priority;
UartDev.baut_rate = uart0_br;
rxBuff = rxbuffer;
txBuff = txBuffer;
linked_to_console = 1;
uart_config(UART0);
UART_SetPrintPort(UART0);
UartDev.baut_rate = uart0_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
}
#endif
void ICACHE_FLASH_ATTR UART_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 recv_task_priority)
{
/* Set the task which should receive the signals once the data is received */
uart_recvTaskPrio = recv_task_priority;
UartDev.baut_rate = uart0_br;
uart_config(UART0);
UART_SetPrintPort(UART0);
UartDev.baut_rate = uart1_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
#if _ENABLE_CONSOLE_INTEGRATION == 0
#if _ENABLE_RING_BUFFER == 1
rxBuff = ringbuf_new(RX_RING_BUFFER_SIZE);
#endif
#endif
}
/******************************************************************************
* FunctionName : uart_config
* Description : Internal used function
* UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled
* UART1 just used for debug output
* Parameters : uart_no, use UART0 or UART1 defined ahead
* Returns : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR uart_config(uint8 uart_no)
{
if (uart_no == UART1)
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
}
else
{
/* rcv_buff size if 0x100 */
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff));
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
#if UART_HW_RTS
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); //HW FLOW CONTROL RTS PIN
#endif
#if UART_HW_CTS
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS); //HW FLOW CONTROL CTS PIN
#endif
}
uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));//SET BAUDRATE
WRITE_PERI_REG(UART_CONF0(uart_no), ((UartDev.exist_parity & UART_PARITY_EN_M) << UART_PARITY_EN_S) //SET BIT AND PARITY MODE
| ((UartDev.parity & UART_PARITY_M) <<UART_PARITY_S )
| ((UartDev.stop_bits & UART_STOP_BIT_NUM) << UART_STOP_BIT_NUM_S)
| ((UartDev.data_bits & UART_BIT_NUM) << UART_BIT_NUM_S));
//clear rx and tx fifo,not ready
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); //RESET FIFO
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
if (uart_no == UART0)
{
int rx_threshold = 10;
#if _ENABLE_CONSOLE_INTEGRATION == 1
rx_threshold = 1;
#endif
//set rx fifo trigger
WRITE_PERI_REG(UART_CONF1(uart_no),
((rx_threshold & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
#if UART_HW_RTS
((110 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) |
UART_RX_FLOW_EN | //enbale rx flow control
#endif
// (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S |
// UART_RX_TOUT_EN|
((0x10 & UART_TXFIFO_EMPTY_THRHD)<<UART_TXFIFO_EMPTY_THRHD_S));//wjl
#if UART_HW_CTS
SET_PERI_REG_MASK( UART_CONF0(uart_no),UART_TX_FLOW_EN); //add this sentense to add a tx flow control via MTCK( CTS )
#endif
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_TOUT_INT_ENA |UART_FRM_ERR_INT_ENA);
}
else
{
WRITE_PERI_REG(UART_CONF1(uart_no),((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S));//TrigLvl default val == 1
}
//clear all interrupt
WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff);
//enable rx_interrupt
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_OVF_INT_ENA);
}
/******************************************************************************
* FunctionName : UART_Recv
* Description : Public API, unloads the contents of the Rx FIFO for specified
* uart into the buffer specified. Will unload upto buffer size
* only
* Parameters : IN uart number (uart_no)
* IN/OUT char *buffer
* IN int max_buf_len
* Returns : int (number of bytes unloaded ) 0 if FIFO is empty
*******************************************************************************/
int UART_Recv(uint8 uart_no, char *buffer, int max_buf_len)
{
uint8 max_unload, index = -1;
#if _ENABLE_RING_BUFFER == 1
/* If the ring buffer is enabled, then unload from Rx Ring Buffer */
uint8 bytes_ringbuffer = ringbuf_bytes_used(rxBuff);
//ring_buffer_dump(rxBuff);
if (bytes_ringbuffer)
{
max_unload = (bytes_ringbuffer<max_buf_len ? bytes_ringbuffer: max_buf_len);
ringbuf_memcpy_from(buffer, rxBuff, max_unload);
}
#else
/* If the ring buffer is not enabled, then unload from Rx FIFO */
uint8 fifo_len = (READ_PERI_REG(UART_STATUS(uart_no))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
if (fifo_len)
{
max_unload = (fifo_len<max_buf_len ? fifo_len : max_buf_len);
DBG1("Rx Fifo contains %d characters have to unload %d\r\n", fifo_len , max_unload);
for (index=0;index<max_unload; index++)
{
*(buffer+index) = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
}
//return index;
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
uart_rx_intr_enable(uart_no);
}
#endif
return index;
}
int UART_Send(uint8 uart_no, char *buffer, int len)
{
int index = 0;
char ch ;
//DBG1("Sending: %s\n", buffer);
for (index=0; index <len; index ++)
{
ch = *(buffer+index);
uart_tx_one_char(uart_no, ch);
}
}
/*---------------------------------------------------------------------------*
* Internal Functions
*---------------------------------------------------------------------------*/
/******************************************************************************
* FunctionName : uart_rx_intr_disable
* Description : Internal used function disables the uart interrupts
* Parameters : IN uart number (uart_no)
* Returns : NONE
*******************************************************************************/
void uart_rx_intr_disable(uint8 uart_no)
{
//DBG1("RxIntr Disabled\r\n");
#if 1
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
#else
ETS_UART_INTR_DISABLE();
#endif
}
/******************************************************************************
* FunctionName : uart_rx_intr_enable
* Description : Internal used function enables the uart interrupts
* Parameters : IN uart number (uart_no)
* Returns : NONE
*******************************************************************************/
void uart_rx_intr_enable(uint8 uart_no)
{
//DBG1("RxIntr Enabled\r\n");
#if 1
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
#else
ETS_UART_INTR_ENABLE();
#endif
}
/******************************************************************************
* FunctionName : uart0_rx_intr_handler
* Description : Internal used function
* UART0 interrupt handler, add self handle code inside
* Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg
* Returns : NONE
*******************************************************************************/
static void uart0_rx_intr_handler(void *para)
{
uint8 uart_no = UART0;//UartDev.buff_uart_no;
/* Is the frame Error interrupt set ? */
if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST))
{
/* The Frame Error (UART_FRM_ERR_INT_ST) has bee set */
DBG1("Frame Error\r\n");
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
goto end_int_handler;
}
if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
{
/* Rx FIFO is full, hence the interrupt */
#if _ENABLE_RING_BUFFER == 1
uint16_t index;
uint16_t fifo_len = (READ_PERI_REG(UART_STATUS(uart_no))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
//DBG1("RX FIFO FULL [%d]\r\n", fifo_len );
if (fifo_len)
{
//DBG1("Rx Fifo contains %d characters have to unload\r\n", fifo_len);
for (index=0;index<fifo_len; index++)
{
uint8_t ch = (READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);
//if (ch == '\r') ch = '\n';
ringbuf_memcpy_into(rxBuff, &ch, 1);
#if _ENABLE_CONSOLE_INTEGRATION == 1
uart_tx_one_char(uart_no, ch);
if (ch == '\r')
{
system_os_post(0, SIG_CONSOLE_RX, 0);
}
#endif
}
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
uart_rx_intr_enable(uart_no);
#if _ENABLE_CONSOLE_INTEGRATION == 0
system_os_post(uart_recvTaskPrio, SIG_UART0, 0);
#endif
}
#else
DBG1("RX FIFO FULL [%d]\r\n", (READ_PERI_REG(UART_STATUS(uart_no))>>UART_RXFIFO_CNT_S)& UART_RXFIFO_CNT);
uart_rx_intr_disable(UART0);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
system_os_post(uart_recvTaskPrio, SIG_UART0, 0);
#endif
goto end_int_handler;
}
if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST))
{
/* The Time out threshold for Rx/Tx is being execeeded */
DBG1("Rx Timeout Threshold not being met \r\n");
uart_rx_intr_disable(UART0);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
system_os_post(uart_recvTaskPrio, SIG_UART0, 0);
goto end_int_handler;
}
if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST))
{
/* The Tx FIFO is empty, the FIFO needs to be fed with new data */
DBG1("Tx FIFO is empty\r\n");
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
#if UART_BUFF_EN
tx_start_uart_buffer(UART0);
#endif
//system_os_post(uart_recvTaskPrio, 1, 0);
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);
}
end_int_handler:
return;
}
/******************************************************************************
* FunctionName : uart_tx_one_char_no_wait
* Description : uart tx a single char without waiting for fifo
* Parameters : uint8 uart - uart port
* uint8 TxChar - char to tx
* Returns : STATUS
*******************************************************************************/
STATUS uart_tx_one_char(uint8 uart, uint8 TxChar)
{
while (true)
{
uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<<UART_TXFIFO_CNT_S);
if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
break;
}
}
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
return OK;
}
/******************************************************************************
* FunctionName : uart_tx_one_char_no_wait
* Description : uart tx a single char without waiting for fifo
* Parameters : uint8 uart - uart port
* uint8 TxChar - char to tx
* Returns : STATUS
*******************************************************************************/
STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar)
{
uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(uart))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT);
if (fifo_cnt < 126)
{
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
}
return OK;
}
/******************************************************************************
* FunctionName : uart0_write_char_no_wait
* Description : tx a single char without waiting for uart 0.
helper function for os_printf output to fifo or tx buffer
* Parameters : uint8 uart - uart port
* uint8 TxChar - char to tx
* Returns : STATUS
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR uart0_write_char_no_wait(char c)
{
#if UART_BUFF_EN //send to uart0 fifo but do not wait
uint8 chr;
if (c == '\n'){
chr = '\r';
tx_buff_enq(&chr, 1);
chr = '\n';
tx_buff_enq(&chr, 1);
}else if (c == '\r'){
}else{
tx_buff_enq(&c,1);
}
#else //send to uart tx buffer
if (c == '\n')
{
uart_tx_one_char(UART0, '\r');
uart_tx_one_char(UART0, '\n');
//uart_tx_one_char_no_wait(UART0, '\r');
//uart_tx_one_char_no_wait(UART0, '\n');
}
else
if (c == '\r')
{
uart_tx_one_char(UART0, c);
}
else
{
uart_tx_one_char(UART0, c);
//uart_tx_one_char_no_wait(UART0, c);
}
#endif
}
/******************************************************************************
* FunctionName : UART_SetPrintPort
* Description :
*
* Parameters :
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR UART_SetPrintPort(uint8 uart_no)
{
if(uart_no==1)
{
//os_install_putc1(uart1_write_char);
}
else
{
/*option 1: do not wait if uart fifo is full,drop current character*/
//os_install_putc1(uart0_write_char_no_wait);
/*option 2: wait for a while if uart fifo is full*/
//os_install_putc1(uart0_write_char);
}
}

343
easygpio/easygpio.c Normal file
View File

@ -0,0 +1,343 @@
/*
* easygpio.c
*
* Copyright (c) 2015, eadf (https://github.com/eadf)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "easygpio.h"
#include "gpio.h"
#include "osapi.h"
#include "ets_sys.h"
#define EASYGPIO_USE_GPIO_INPUT_GET
static void ICACHE_FLASH_ATTR
gpio16_output_conf(void) {
WRITE_PERI_REG(PAD_XPD_DCDC_CONF,
(READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbcUL) | 0x1UL); // mux configuration for XPD_DCDC to output rtc_gpio0
WRITE_PERI_REG(RTC_GPIO_CONF,
(READ_PERI_REG(RTC_GPIO_CONF) & 0xfffffffeUL) | 0x0UL); //mux configuration for out enable
WRITE_PERI_REG(RTC_GPIO_ENABLE,
(READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL) | 0x1UL); //out enable
}
static void ICACHE_FLASH_ATTR
gpio16_input_conf(void) {
WRITE_PERI_REG(PAD_XPD_DCDC_CONF,
(READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbcUL) | 0x1UL); // mux configuration for XPD_DCDC and rtc_gpio0 connection
WRITE_PERI_REG(RTC_GPIO_CONF,
(READ_PERI_REG(RTC_GPIO_CONF) & 0xfffffffeUL) | 0x0UL); //mux configuration for out enable
WRITE_PERI_REG(RTC_GPIO_ENABLE,
READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL); //out disable
}
/**
* Returns the number of active pins in the gpioMask.
*/
uint8_t ICACHE_FLASH_ATTR
easygpio_countBits(uint32_t gpioMask) {
uint8_t i=0;
uint8_t numberOfPins=0;
for (i=0; i<32; i++){
numberOfPins += (gpioMask & BIT(i))?1:0;
}
return numberOfPins;
}
/**
* Returns the gpio name and func for a specific pin.
*/
bool ICACHE_FLASH_ATTR
easygpio_getGPIONameFunc(uint8_t gpio_pin, uint32_t *gpio_name, uint8_t *gpio_func) {
if (gpio_pin == 6 || gpio_pin == 7 || gpio_pin == 8 || gpio_pin == 11 || gpio_pin >= 17) {
os_printf("easygpio_getGPIONameFunc Error: There is no GPIO%d, check your code\n", gpio_pin);
return false;
}
if (gpio_pin == 16) {
os_printf("easygpio_getGPIONameFunc Error: GPIO16 does not have gpio_name and gpio_func\n");
return false;
}
switch ( gpio_pin ) {
case 0:
*gpio_func = FUNC_GPIO0;
*gpio_name = PERIPHS_IO_MUX_GPIO0_U;
return true;
case 1:
*gpio_func = FUNC_GPIO1;
*gpio_name = PERIPHS_IO_MUX_U0TXD_U;
return true;
case 2:
*gpio_func = FUNC_GPIO2;
*gpio_name = PERIPHS_IO_MUX_GPIO2_U;
return true;
case 3:
*gpio_func = FUNC_GPIO3;
*gpio_name = PERIPHS_IO_MUX_U0RXD_U;
return true;
case 4:
*gpio_func = FUNC_GPIO4;
*gpio_name = PERIPHS_IO_MUX_GPIO4_U;
return true;
case 5:
*gpio_func = FUNC_GPIO5;
*gpio_name = PERIPHS_IO_MUX_GPIO5_U;
return true;
case 9:
*gpio_func = FUNC_GPIO9;
*gpio_name = PERIPHS_IO_MUX_SD_DATA2_U;
return true;
case 10:
*gpio_func = FUNC_GPIO10;
*gpio_name = PERIPHS_IO_MUX_SD_DATA3_U;
return true;
case 12:
*gpio_func = FUNC_GPIO12;
*gpio_name = PERIPHS_IO_MUX_MTDI_U;
return true;
case 13:
*gpio_func = FUNC_GPIO13;
*gpio_name = PERIPHS_IO_MUX_MTCK_U;
return true;
case 14:
*gpio_func = FUNC_GPIO14;
*gpio_name = PERIPHS_IO_MUX_MTMS_U;
return true;
case 15:
*gpio_func = FUNC_GPIO15;
*gpio_name = PERIPHS_IO_MUX_MTDO_U;
return true;
default:
return false;
}
return true;
}
/**
* Sets the pull up registers for a pin.
*/
static void ICACHE_FLASH_ATTR
easygpio_setupPullsByName(uint32_t gpio_name, EasyGPIO_PullStatus pullStatus) {
if (EASYGPIO_PULLUP == pullStatus) {
PIN_PULLUP_EN(gpio_name);
} else {
PIN_PULLUP_DIS(gpio_name);
}
}
/**
* Sets the pull registers for a pin.
*/
bool ICACHE_FLASH_ATTR
easygpio_pullMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus) {
uint32_t gpio_name;
uint8_t gpio_func;
if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) {
return false;
}
easygpio_setupPullsByName(gpio_name, pullStatus);
return true;
}
/**
* Sets the 'gpio_pin' pin as a GPIO and sets the pull register for that pin.
* 'pullStatus' has no effect on output pins or GPIO16
*/
bool ICACHE_FLASH_ATTR
easygpio_pinMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, EasyGPIO_PinMode pinMode) {
uint32_t gpio_name;
uint8_t gpio_func;
if (16==gpio_pin) {
// ignoring pull status on GPIO16 for now
if (EASYGPIO_OUTPUT == pinMode) {
gpio16_output_conf();
} else {
gpio16_input_conf();
}
return true;
} else if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) {
return false;
}
PIN_FUNC_SELECT(gpio_name, gpio_func);
easygpio_setupPullsByName(gpio_name, pullStatus);
if (EASYGPIO_OUTPUT != pinMode) {
GPIO_DIS_OUTPUT(GPIO_ID_PIN(gpio_pin));
} else {
// must enable the pin or else the WRITE_PERI_REG won't work
gpio_output_set(0, 0, BIT(GPIO_ID_PIN(gpio_pin)),0);
}
return true;
}
/**
* Sets the 'gpio_pin' pin as a GPIO and sets the interrupt to trigger on that pin.
* The 'interruptArg' is the function argument that will be sent to your interruptHandler
*/
bool ICACHE_FLASH_ATTR
easygpio_attachInterrupt(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, void (*interruptHandler)(void *arg), void *interruptArg) {
uint32_t gpio_name;
uint8_t gpio_func;
if (gpio_pin == 16) {
os_printf("easygpio_setupInterrupt Error: GPIO16 does not have interrupts\n");
return false;
}
if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) {
return false;
}
ETS_GPIO_INTR_ATTACH(interruptHandler, interruptArg);
ETS_GPIO_INTR_DISABLE();
PIN_FUNC_SELECT(gpio_name, gpio_func);
easygpio_setupPullsByName(gpio_name, pullStatus);
// disable output
GPIO_DIS_OUTPUT(gpio_pin);
gpio_register_set(GPIO_PIN_ADDR(gpio_pin), GPIO_PIN_INT_TYPE_SET(GPIO_PIN_INTR_DISABLE)
| GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_DISABLE)
| GPIO_PIN_SOURCE_SET(GPIO_AS_PIN_SOURCE));
//clear gpio14 status
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(gpio_pin));
ETS_GPIO_INTR_ENABLE();
return true;
}
/**
* Detach the interrupt handler from the 'gpio_pin' pin.
*/
bool ICACHE_FLASH_ATTR
easygpio_detachInterrupt(uint8_t gpio_pin) {
if (gpio_pin == 16) {
os_printf("easygpio_setupInterrupt Error: GPIO16 does not have interrupts\n");
return false;
}
// Don't know how to detach interrupt, yet.
// Quick and dirty fix - just disable the interrupt
gpio_pin_intr_state_set(GPIO_ID_PIN(gpio_pin), GPIO_PIN_INTR_DISABLE);
return true;
}
/**
* Uniform way of setting GPIO output value. Handles GPIO 0-16.
*
* You can not rely on that this function will switch the gpio to an output like GPIO_OUTPUT_SET does.
* Use easygpio_outputEnable() to change an input gpio to output mode.
*/
void
easygpio_outputSet(uint8_t gpio_pin, uint8_t value) {
if (16==gpio_pin) {
WRITE_PERI_REG(RTC_GPIO_OUT,
(READ_PERI_REG(RTC_GPIO_OUT) & 0xfffffffeUL) | (0x1UL & value));
} else {
#ifdef EASYGPIO_USE_GPIO_OUTPUT_SET
GPIO_OUTPUT_SET(GPIO_ID_PIN(gpio_pin), value);
#else
if (value&1){
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR, READ_PERI_REG(PERIPHS_GPIO_BASEADDR) | BIT(gpio_pin));
} else {
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR, READ_PERI_REG(PERIPHS_GPIO_BASEADDR) & ~BIT(gpio_pin));
}
#endif
}
}
/**
* Uniform way of getting GPIO input value. Handles GPIO 0-16.
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
* If you know that you won't be using GPIO16 then you'd better off by just using GPIO_INPUT_GET().
*/
uint8_t
easygpio_inputGet(uint8_t gpio_pin) {
if (16==gpio_pin) {
return (READ_PERI_REG(RTC_GPIO_IN_DATA) & 1UL);
} else {
#ifdef EASYGPIO_USE_GPIO_INPUT_GET
return GPIO_INPUT_GET(GPIO_ID_PIN(gpio_pin));
#else
// this does *not* work, maybe GPIO_IN_ADDRESS is the wrong address
return ((GPIO_REG_READ(GPIO_IN_ADDRESS) > gpio_pin) & 1UL);
#endif
}
}
/**
* Uniform way of turning an output GPIO pin into input mode. Handles GPIO 0-16.
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
* This function does the same thing as GPIO_DIS_OUTPUT, but works on GPIO16 too.
*/
void easygpio_outputDisable(uint8_t gpio_pin) {
if (16==gpio_pin) {
WRITE_PERI_REG(RTC_GPIO_ENABLE,
READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL); //out disable
} else {
GPIO_DIS_OUTPUT(GPIO_ID_PIN(gpio_pin));
}
}
/**
* Uniform way of turning an input GPIO pin into output mode. Handles GPIO 0-16.
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
*
* This function:
* - should only be used to convert a input pin into an output pin.
* - is a little bit slower than easygpio_outputSet() so you should use that
* function to just change output value.
* - does the same thing as GPIO_OUTPUT_SET, but works on GPIO16 too.
*/
void easygpio_outputEnable(uint8_t gpio_pin, uint8_t value) {
if (16==gpio_pin) {
// write the value before flipping to output
// - so we don't flash previous value for a few ns.
WRITE_PERI_REG(RTC_GPIO_OUT,
(READ_PERI_REG(RTC_GPIO_OUT) & 0xfffffffeUL) | (0x1UL & value));
WRITE_PERI_REG(RTC_GPIO_ENABLE,
(READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL) | 0x1UL); //out enable
} else {
GPIO_OUTPUT_SET(GPIO_ID_PIN(gpio_pin), value);
}
}

114
easygpio/easygpio.h Normal file
View File

@ -0,0 +1,114 @@
/*
* easygpio.h
*
* Copyright (c) 2015, eadf (https://github.com/eadf)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_
#define EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_
#include "c_types.h"
typedef enum {
EASYGPIO_INPUT=0,
EASYGPIO_OUTPUT=1
} EasyGPIO_PinMode;
typedef enum {
EASYGPIO_PULLUP=3,
EASYGPIO_NOPULL=4
} EasyGPIO_PullStatus;
/**
* Returns the gpio name and func for a specific pin.
*/
bool easygpio_getGPIONameFunc(uint8_t gpio_pin, uint32_t *gpio_name, uint8_t *gpio_func);
/**
* Sets the 'gpio_pin' pin as a GPIO and sets the interrupt to trigger on that pin.
* The 'interruptArg' is the function argument that will be sent to your interruptHandler
* (this way you can several interrupts with one interruptHandler)
*/
bool easygpio_attachInterrupt(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, void (*interruptHandler)(void *arg), void *interruptArg);
/**
* Deatach the interrupt handler from the 'gpio_pin' pin.
*/
bool easygpio_detachInterrupt(uint8_t gpio_pin);
/**
* Returns the number of active pins in the gpioMask.
*/
uint8_t easygpio_countBits(uint32_t gpioMask);
/**
* Sets the 'gpio_pin' pin as a GPIO and enables/disables the pull-up on that pin.
* 'pullStatus' has no effect on output pins or GPIO16
*/
bool easygpio_pinMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, EasyGPIO_PinMode pinMode);
/**
* Enable or disable the internal pull up for a pin.
*/
bool easygpio_pullMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus);
/**
* Uniform way of getting GPIO input value. Handles GPIO 0-16.
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
* If you know that you won't be using GPIO16 then you'd better off by just using GPIO_INPUT_GET().
*/
uint8_t easygpio_inputGet(uint8_t gpio_pin);
/**
* Uniform way of setting GPIO output value. Handles GPIO 0-16.
*
* You can not rely on that this function will switch the gpio to an output like GPIO_OUTPUT_SET does.
* Use easygpio_outputEnable() to change an input gpio to output mode.
*/
void easygpio_outputSet(uint8_t gpio_pin, uint8_t value);
/**
* Uniform way of turning an output GPIO pin into input mode. Handles GPIO 0-16.
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
* This function does the same thing as GPIO_DIS_OUTPUT, but works on GPIO16 too.
*/
void easygpio_outputDisable(uint8_t gpio_pin);
/**
* Uniform way of turning an input GPIO pin into output mode. Handles GPIO 0-16.
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
*
* This function:
* - should only be used to convert a input pin into an output pin.
* - is a little bit slower than easygpio_outputSet() so you should use that
* function to just change output value.
* - does the same thing as GPIO_OUTPUT_SET, but works on GPIO16 too.
*/
void easygpio_outputEnable(uint8_t gpio_pin, uint8_t value);
#endif /* EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_ */

14
firewall.txt Normal file
View File

@ -0,0 +1,14 @@
# Scrapbook of firewall rules to restrict connections only
# to official servers.
# Clear outging rules
acl from_sta clear
# Allow outgoing connections to specified IP
acl from_sta IP any 185.43.124.6 allow
# Allow outgoing DNS requests
acl from_sta UDP any any any 53 allow
# Deny everything else
acl from_sta IP any any deny

BIN
firmware/0x00000.bin Normal file

Binary file not shown.

BIN
firmware/0x10000.bin Normal file

Binary file not shown.

233
include/driver/uart.h Normal file
View File

@ -0,0 +1,233 @@
/*
* File : uart.h
* Copyright (C) 2013 - 2016, Espressif Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UART_APP_H
#define UART_APP_H
#include "uart_register.h"
#include "eagle_soc.h"
#include "c_types.h"
#define UART_TX_BUFFER_SIZE 256 //Ring buffer length of tx buffer
#define UART_RX_BUFFER_SIZE 256 //Ring buffer length of rx buffer
#define UART_BUFF_EN 0 //use uart buffer , FOR UART0
#define UART_SELFTEST 0 //set 1:enable the loop test demo for uart buffer, FOR UART0
#define UART_HW_RTS 0 //set 1: enable uart hw flow control RTS, PIN MTDO, FOR UART0
#define UART_HW_CTS 0 //set1: enable uart hw flow contrl CTS , PIN MTCK, FOR UART0
#define _ENABLE_CONSOLE_INTEGRATION 1
#define _ENABLE_RING_BUFFER 1
#ifdef _ENABLE_RING_BUFFER
#include "ringbuf.h"
#define RX_RING_BUFFER_SIZE 250
#endif
#define UART0 0
#define UART1 1
typedef enum {
FIVE_BITS = 0x0,
SIX_BITS = 0x1,
SEVEN_BITS = 0x2,
EIGHT_BITS = 0x3
} UartBitsNum4Char;
typedef enum {
ONE_STOP_BIT = 0x1,
ONE_HALF_STOP_BIT = 0x2,
TWO_STOP_BIT = 0x3
} UartStopBitsNum;
typedef enum {
NONE_BITS = 0x2,
ODD_BITS = 1,
EVEN_BITS = 0
} UartParityMode;
typedef enum {
STICK_PARITY_DIS = 0,
STICK_PARITY_EN = 1
} UartExistParity;
typedef enum {
UART_None_Inverse = 0x0,
UART_Rxd_Inverse = UART_RXD_INV,
UART_CTS_Inverse = UART_CTS_INV,
UART_Txd_Inverse = UART_TXD_INV,
UART_RTS_Inverse = UART_RTS_INV,
} UART_LineLevelInverse;
typedef enum {
BIT_RATE_300 = 300,
BIT_RATE_600 = 600,
BIT_RATE_1200 = 1200,
BIT_RATE_2400 = 2400,
BIT_RATE_4800 = 4800,
BIT_RATE_9600 = 9600,
BIT_RATE_19200 = 19200,
BIT_RATE_38400 = 38400,
BIT_RATE_57600 = 57600,
BIT_RATE_74880 = 74880,
BIT_RATE_115200 = 115200,
BIT_RATE_230400 = 230400,
BIT_RATE_460800 = 460800,
BIT_RATE_921600 = 921600,
BIT_RATE_1843200 = 1843200,
BIT_RATE_3686400 = 3686400,
} UartBautRate;
typedef enum {
NONE_CTRL,
HARDWARE_CTRL,
XON_XOFF_CTRL
} UartFlowCtrl;
typedef enum {
USART_HardwareFlowControl_None = 0x0,
USART_HardwareFlowControl_RTS = 0x1,
USART_HardwareFlowControl_CTS = 0x2,
USART_HardwareFlowControl_CTS_RTS = 0x3
} UART_HwFlowCtrl;
typedef enum {
EMPTY,
UNDER_WRITE,
WRITE_OVER
} RcvMsgBuffState;
typedef struct {
uint32 RcvBuffSize;
uint8 *pRcvMsgBuff;
uint8 *pWritePos;
uint8 *pReadPos;
uint8 TrigLvl; //JLU: may need to pad
RcvMsgBuffState BuffState;
} RcvMsgBuff;
typedef struct {
uint32 TrxBuffSize;
uint8 *pTrxBuff;
} TrxMsgBuff;
typedef enum {
BAUD_RATE_DET,
WAIT_SYNC_FRM,
SRCH_MSG_HEAD,
RCV_MSG_BODY,
RCV_ESC_CHAR,
} RcvMsgState;
typedef struct {
UartBautRate baut_rate;
UartBitsNum4Char data_bits;
UartExistParity exist_parity;
UartParityMode parity;
UartStopBitsNum stop_bits;
UartFlowCtrl flow_ctrl;
RcvMsgBuff rcv_buff;
TrxMsgBuff trx_buff;
RcvMsgState rcv_state;
int received;
int buff_uart_no; //indicate which uart use tx/rx buffer
} UartDevice;
void uart_init(UartBautRate uart0_br, UartBautRate uart1_br);
void uart0_sendStr(const char *str);
///////////////////////////////////////
#define UART_FIFO_LEN 128 //define the tx fifo length
#define UART_TX_EMPTY_THRESH_VAL 0x10
struct UartBuffer{
uint32 UartBuffSize;
uint8 *pUartBuff;
uint8 *pInPos;
uint8 *pOutPos;
STATUS BuffState;
uint16 Space; //remanent space of the buffer
uint8 TcpControl;
struct UartBuffer * nextBuff;
};
struct UartRxBuff{
uint32 UartRxBuffSize;
uint8 *pUartRxBuff;
uint8 *pWritePos;
uint8 *pReadPos;
STATUS RxBuffState;
uint32 Space; //remanent space of the buffer
} ;
typedef enum {
RUN = 0,
BLOCK = 1,
} TCPState;
//void ICACHE_FLASH_ATTR uart_test_rx();
STATUS uart_tx_one_char(uint8 uart, uint8 TxChar);
STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar);
void uart1_sendStr_no_wait(const char *str);
struct UartBuffer* Uart_Buf_Init();
#if UART_BUFF_EN
LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len);
void uart_buf_free(struct UartBuffer* pBuff);
void tx_buff_enq(char* pdata, uint16 data_len );
LOCAL void tx_fifo_insert(struct UartBuffer* pTxBuff, uint8 data_len, uint8 uart_no);
void tx_start_uart_buffer(uint8 uart_no);
uint16 rx_buff_deq(char* pdata, uint16 data_len );
void Uart_rx_buff_enq();
#endif
void uart_rx_intr_enable(uint8 uart_no);
void uart_rx_intr_disable(uint8 uart_no);
void uart0_tx_buffer(uint8 *buf, uint16 len);
//==============================================
#define FUNC_UART0_CTS 4
#define FUNC_U0CTS 4
#define FUNC_U1TXD_BK 2
#define UART_LINE_INV_MASK (0x3f<<19)
void UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len);
void UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num);
void UART_SetLineInverse(uint8 uart_no, UART_LineLevelInverse inverse_mask);
void UART_SetParity(uint8 uart_no, UartParityMode Parity_mode);
void UART_SetBaudrate(uint8 uart_no,uint32 baud_rate);
void UART_SetFlowCtrl(uint8 uart_no,UART_HwFlowCtrl flow_ctrl,uint8 rx_thresh);
void UART_WaitTxFifoEmpty(uint8 uart_no , uint32 time_out_us); //do not use if tx flow control enabled
void UART_ResetFifo(uint8 uart_no);
void UART_ClearIntrStatus(uint8 uart_no,uint32 clr_mask);
void UART_SetIntrEna(uint8 uart_no,uint32 ena_mask);
void UART_SetPrintPort(uint8 uart_no);
bool UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us);
//==============================================
void UART_init_console(UartBautRate uart0_br,
uint8 recv_task_priority,
ringbuf_t rxbuffer,
ringbuf_t txBuffer);
#endif

View File

@ -0,0 +1,156 @@
/*
* File : uart_register.h
* Copyright (C) 2013 - 2016, Espressif Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (c) 2010 - 2011 Espressif System
*
*/
#ifndef UART_REGISTER_H_
#define UART_REGISTER_H_
#define REG_UART_BASE(i) (0x60000000 + (i)*0xf00)
//version value:32'h062000
#define UART_FIFO(i) (REG_UART_BASE(i) + 0x0)
#define UART_RXFIFO_RD_BYTE 0x000000FF
#define UART_RXFIFO_RD_BYTE_S 0
#define UART_INT_RAW(i) (REG_UART_BASE(i) + 0x4)
#define UART_RXFIFO_TOUT_INT_RAW (BIT(8))
#define UART_BRK_DET_INT_RAW (BIT(7))
#define UART_CTS_CHG_INT_RAW (BIT(6))
#define UART_DSR_CHG_INT_RAW (BIT(5))
#define UART_RXFIFO_OVF_INT_RAW (BIT(4))
#define UART_FRM_ERR_INT_RAW (BIT(3))
#define UART_PARITY_ERR_INT_RAW (BIT(2))
#define UART_TXFIFO_EMPTY_INT_RAW (BIT(1))
#define UART_RXFIFO_FULL_INT_RAW (BIT(0))
#define UART_INT_ST(i) (REG_UART_BASE(i) + 0x8)
#define UART_RXFIFO_TOUT_INT_ST (BIT(8))
#define UART_BRK_DET_INT_ST (BIT(7))
#define UART_CTS_CHG_INT_ST (BIT(6))
#define UART_DSR_CHG_INT_ST (BIT(5))
#define UART_RXFIFO_OVF_INT_ST (BIT(4))
#define UART_FRM_ERR_INT_ST (BIT(3))
#define UART_PARITY_ERR_INT_ST (BIT(2))
#define UART_TXFIFO_EMPTY_INT_ST (BIT(1))
#define UART_RXFIFO_FULL_INT_ST (BIT(0))
#define UART_INT_ENA(i) (REG_UART_BASE(i) + 0xC)
#define UART_RXFIFO_TOUT_INT_ENA (BIT(8))
#define UART_BRK_DET_INT_ENA (BIT(7))
#define UART_CTS_CHG_INT_ENA (BIT(6))
#define UART_DSR_CHG_INT_ENA (BIT(5))
#define UART_RXFIFO_OVF_INT_ENA (BIT(4))
#define UART_FRM_ERR_INT_ENA (BIT(3))
#define UART_PARITY_ERR_INT_ENA (BIT(2))
#define UART_TXFIFO_EMPTY_INT_ENA (BIT(1))
#define UART_RXFIFO_FULL_INT_ENA (BIT(0))
#define UART_INT_CLR(i) (REG_UART_BASE(i) + 0x10)
#define UART_RXFIFO_TOUT_INT_CLR (BIT(8))
#define UART_BRK_DET_INT_CLR (BIT(7))
#define UART_CTS_CHG_INT_CLR (BIT(6))
#define UART_DSR_CHG_INT_CLR (BIT(5))
#define UART_RXFIFO_OVF_INT_CLR (BIT(4))
#define UART_FRM_ERR_INT_CLR (BIT(3))
#define UART_PARITY_ERR_INT_CLR (BIT(2))
#define UART_TXFIFO_EMPTY_INT_CLR (BIT(1))
#define UART_RXFIFO_FULL_INT_CLR (BIT(0))
#define UART_CLKDIV(i) (REG_UART_BASE(i) + 0x14)
#define UART_CLKDIV_CNT 0x000FFFFF
#define UART_CLKDIV_S 0
#define UART_AUTOBAUD(i) (REG_UART_BASE(i) + 0x18)
#define UART_GLITCH_FILT 0x000000FF
#define UART_GLITCH_FILT_S 8
#define UART_AUTOBAUD_EN (BIT(0))
#define UART_STATUS(i) (REG_UART_BASE(i) + 0x1C)
#define UART_TXD (BIT(31))
#define UART_RTSN (BIT(30))
#define UART_DTRN (BIT(29))
#define UART_TXFIFO_CNT 0x000000FF
#define UART_TXFIFO_CNT_S 16
#define UART_RXD (BIT(15))
#define UART_CTSN (BIT(14))
#define UART_DSRN (BIT(13))
#define UART_RXFIFO_CNT 0x000000FF
#define UART_RXFIFO_CNT_S 0
#define UART_CONF0(i) (REG_UART_BASE(i) + 0x20)
#define UART_DTR_INV (BIT(24))
#define UART_RTS_INV (BIT(23))
#define UART_TXD_INV (BIT(22))
#define UART_DSR_INV (BIT(21))
#define UART_CTS_INV (BIT(20))
#define UART_RXD_INV (BIT(19))
#define UART_TXFIFO_RST (BIT(18))
#define UART_RXFIFO_RST (BIT(17))
#define UART_IRDA_EN (BIT(16))
#define UART_TX_FLOW_EN (BIT(15))
#define UART_LOOPBACK (BIT(14))
#define UART_IRDA_RX_INV (BIT(13))
#define UART_IRDA_TX_INV (BIT(12))
#define UART_IRDA_WCTL (BIT(11))
#define UART_IRDA_TX_EN (BIT(10))
#define UART_IRDA_DPLX (BIT(9))
#define UART_TXD_BRK (BIT(8))
#define UART_SW_DTR (BIT(7))
#define UART_SW_RTS (BIT(6))
#define UART_STOP_BIT_NUM 0x00000003
#define UART_STOP_BIT_NUM_S 4
#define UART_BIT_NUM 0x00000003
#define UART_BIT_NUM_S 2
#define UART_PARITY_EN (BIT(1))
#define UART_PARITY_EN_M 0x00000001
#define UART_PARITY_EN_S 1
#define UART_PARITY (BIT(0))
#define UART_PARITY_M 0x00000001
#define UART_PARITY_S 0
#define UART_CONF1(i) (REG_UART_BASE(i) + 0x24)
#define UART_RX_TOUT_EN (BIT(31))
#define UART_RX_TOUT_THRHD 0x0000007F
#define UART_RX_TOUT_THRHD_S 24
#define UART_RX_FLOW_EN (BIT(23))
#define UART_RX_FLOW_THRHD 0x0000007F
#define UART_RX_FLOW_THRHD_S 16
#define UART_TXFIFO_EMPTY_THRHD 0x0000007F
#define UART_TXFIFO_EMPTY_THRHD_S 8
#define UART_RXFIFO_FULL_THRHD 0x0000007F
#define UART_RXFIFO_FULL_THRHD_S 0
#define UART_LOWPULSE(i) (REG_UART_BASE(i) + 0x28)
#define UART_LOWPULSE_MIN_CNT 0x000FFFFF
#define UART_LOWPULSE_MIN_CNT_S 0
#define UART_HIGHPULSE(i) (REG_UART_BASE(i) + 0x2C)
#define UART_HIGHPULSE_MIN_CNT 0x000FFFFF
#define UART_HIGHPULSE_MIN_CNT_S 0
#define UART_PULSE_NUM(i) (REG_UART_BASE(i) + 0x30)
#define UART_PULSE_NUM_CNT 0x0003FF
#define UART_PULSE_NUM_CNT_S 0
#define UART_DATE(i) (REG_UART_BASE(i) + 0x78)
#define UART_ID(i) (REG_UART_BASE(i) + 0x7C)
#endif // UART_REGISTER_H_INCLUDED

View File

@ -0,0 +1,106 @@
#ifndef __DHCPS_H__
#define __DHCPS_H__
#define USE_DNS
typedef struct dhcps_state{
sint16_t state;
} dhcps_state;
// <20><><EFBFBD><EFBFBD>dhcpclient<6E>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>DHCP msg<73><EFBFBD><E1B9B9>
typedef struct dhcps_msg {
uint8_t op, htype, hlen, hops;
uint8_t xid[4];
uint16_t secs, flags;
uint8_t ciaddr[4];
uint8_t yiaddr[4];
uint8_t siaddr[4];
uint8_t giaddr[4];
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
uint8_t options[312];
}dhcps_msg;
#ifndef LWIP_OPEN_SRC
struct dhcps_lease {
bool enable;
struct ip_addr start_ip;
struct ip_addr end_ip;
};
enum dhcps_offer_option{
OFFER_START = 0x00,
OFFER_ROUTER = 0x01,
OFFER_END
};
#endif
struct dhcps_pool{
struct ip_addr ip;
uint8 mac[6];
uint32 lease_timer;
};
typedef struct _list_node{
void *pnode;
struct _list_node *pnext;
}list_node;
extern uint32 dhcps_lease_time;
#define DHCPS_LEASE_TIMER dhcps_lease_time //0x05A0
#define DHCPS_MAX_LEASE 0x64
#define BOOTP_BROADCAST 0x8000
#define DHCP_REQUEST 1
#define DHCP_REPLY 2
#define DHCP_HTYPE_ETHERNET 1
#define DHCP_HLEN_ETHERNET 6
#define DHCP_MSG_LEN 236
#define DHCPS_SERVER_PORT 67
#define DHCPS_CLIENT_PORT 68
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCP_OPTION_SUBNET_MASK 1
#define DHCP_OPTION_ROUTER 3
#define DHCP_OPTION_DNS_SERVER 6
#define DHCP_OPTION_REQ_IPADDR 50
#define DHCP_OPTION_LEASE_TIME 51
#define DHCP_OPTION_MSG_TYPE 53
#define DHCP_OPTION_SERVER_ID 54
#define DHCP_OPTION_INTERFACE_MTU 26
#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31
#define DHCP_OPTION_BROADCAST_ADDRESS 28
#define DHCP_OPTION_REQ_LIST 55
#define DHCP_OPTION_END 255
//#define USE_CLASS_B_NET 1
#define DHCPS_DEBUG 0
#define MAX_STATION_NUM 8
#define DHCPS_STATE_OFFER 1
#define DHCPS_STATE_DECLINE 2
#define DHCPS_STATE_ACK 3
#define DHCPS_STATE_NAK 4
#define DHCPS_STATE_IDLE 5
#define DHCPS_STATE_RELEASE 6
#define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0)
void dhcps_start(struct ip_info *info);
void dhcps_stop(void);
void dhcps_set_DNS(struct ip_addr *dns_ip) ICACHE_FLASH_ATTR;
struct dhcps_pool *dhcps_get_mapping(uint16_t no) ICACHE_FLASH_ATTR;
void dhcps_set_mapping(struct ip_addr *addr, uint8 *mac, uint32 lease_time) ICACHE_FLASH_ATTR;
#endif

115
include/lwip/lwip_napt.h Normal file
View File

@ -0,0 +1,115 @@
#ifndef __LWIP_NAPT_H__
#define __LWIP_NAPT_H__
#include "lwip/opt.h"
#ifdef __cplusplus
extern "C" {
#endif
#if IP_FORWARD
#if IP_NAPT
/* Default size of the tables used for NAPT */
#define IP_NAPT_MAX 512
#define IP_PORTMAP_MAX 32
/* Timeouts in sec for the various protocol types */
#define IP_NAPT_TIMEOUT_MS_TCP (30*60*1000)
#define IP_NAPT_TIMEOUT_MS_TCP_DISCON (20*1000)
#define IP_NAPT_TIMEOUT_MS_UDP (2*1000)
#define IP_NAPT_TIMEOUT_MS_ICMP (2*1000)
#define IP_NAPT_PORT_RANGE_START 49152
#define IP_NAPT_PORT_RANGE_END 61439
struct napt_table {
u32_t last;
u32_t src;
u32_t dest;
u16_t sport;
u16_t dport;
u16_t mport;
u8_t proto;
u8_t fin1 : 1;
u8_t fin2 : 1;
u8_t finack1 : 1;
u8_t finack2 : 1;
u8_t synack : 1;
u8_t rst : 1;
u16_t next, prev;
};
struct portmap_table {
u32_t maddr;
u32_t daddr;
u16_t mport;
u16_t dport;
u8_t proto;
u8 valid;
};
extern struct portmap_table *ip_portmap_table;
/**
* Allocates and initializes the NAPT tables.
*
* @param max_nat max number of enties in the NAPT table (use IP_NAPT_MAX if in doubt)
* @param max_portmap max number of enties in the NAPT table (use IP_PORTMAP_MAX if in doubt)
*/
void ICACHE_FLASH_ATTR
ip_napt_init(uint16_t max_nat, uint8_t max_portmap);
/**
* Enable/Disable NAPT for a specified interface.
*
* @param addr ip address of the interface
* @param enable non-zero to enable NAPT, or 0 to disable.
*/
void ICACHE_FLASH_ATTR
ip_napt_enable(u32_t addr, int enable);
/**
* Enable/Disable NAPT for a specified interface.
*
* @param netif number of the interface
* @param enable non-zero to enable NAPT, or 0 to disable.
*/
void ICACHE_FLASH_ATTR
ip_napt_enable_no(u8_t number, int enable);
/**
* Register port mapping on the external interface to internal interface.
* When the same port mapping is registered again, the old mapping is overwritten.
* In this implementation, only 1 unique port mapping can be defined for each target address/port.
*
* @param proto target protocol
* @param maddr ip address of the external interface
* @param mport mapped port on the external interface, in host byte order.
* @param daddr destination ip address
* @param dport destination port, in host byte order.
*/
u8_t ICACHE_FLASH_ATTR
ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport);
/**
* Unregister port mapping on the external interface to internal interface.
*
* @param proto target protocol
* @param maddr ip address of the external interface
*/
u8_t ICACHE_FLASH_ATTR
ip_portmap_remove(u8_t proto, u16_t mport);
#endif /* IP_NAPT */
#endif /* IP_FORWARD */
#ifdef __cplusplus
}
#endif
#endif /* __LWIP_NAPT_H__ */

323
include/lwip/netif.h Normal file
View File

@ -0,0 +1,323 @@
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_NETIF_H__
#define __LWIP_NETIF_H__
#include "lwip/opt.h"
#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
#include "lwip/err.h"
#include "lwip/ip_addr.h"
#include "lwip/def.h"
#include "lwip/pbuf.h"
#if LWIP_DHCP
struct dhcp;
#endif
#if LWIP_AUTOIP
struct autoip;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Throughout this file, IP addresses are expected to be in
* the same byte order as in IP_PCB. */
/** must be the maximum of all used hardware address lengths
across all types of interfaces in use */
#define NETIF_MAX_HWADDR_LEN 6U
/** Whether the network interface is 'up'. This is
* a software flag used to control whether this network
* interface is enabled and processes traffic.
* It is set by the startup code (for static IP configuration) or
* by dhcp/autoip when an address has been assigned.
*/
#define NETIF_FLAG_UP 0x01U
/** If set, the netif has broadcast capability.
* Set by the netif driver in its init function. */
#define NETIF_FLAG_BROADCAST 0x02U
/** If set, the netif is one end of a point-to-point connection.
* Set by the netif driver in its init function. */
#define NETIF_FLAG_POINTTOPOINT 0x04U
/** If set, the interface is configured using DHCP.
* Set by the DHCP code when starting or stopping DHCP. */
#define NETIF_FLAG_DHCP 0x08U
/** If set, the interface has an active link
* (set by the network interface driver).
* Either set by the netif driver in its init function (if the link
* is up at that time) or at a later point once the link comes up
* (if link detection is supported by the hardware). */
#define NETIF_FLAG_LINK_UP 0x10U
/** If set, the netif is an ethernet device using ARP.
* Set by the netif driver in its init function.
* Used to check input packet types and use of DHCP. */
#define NETIF_FLAG_ETHARP 0x20U
/** If set, the netif is an ethernet device. It might not use
* ARP or TCP/IP if it is used for PPPoE only.
*/
#define NETIF_FLAG_ETHERNET 0x40U
/** If set, the netif has IGMP capability.
* Set by the netif driver in its init function. */
#define NETIF_FLAG_IGMP 0x80U
/** Function prototype for netif init functions. Set up flags and output/linkoutput
* callback functions in this function.
*
* @param netif The netif to initialize
*/
typedef err_t (*netif_init_fn)(struct netif *netif);
/** Function prototype for netif->input functions. This function is saved as 'input'
* callback function in the netif struct. Call it when a packet has been received.
*
* @param p The received packet, copied into a pbuf
* @param inp The netif which received the packet
*/
typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
/** Function prototype for netif->output functions. Called by lwIP when a packet
* shall be sent. For ethernet netif, set this to 'etharp_output' and set
* 'linkoutput'.
*
* @param netif The netif which shall send a packet
* @param p The packet to send (p->payload points to IP header)
* @param ipaddr The IP address to which the packet shall be sent
*/
typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
ip_addr_t *ipaddr);
/** Function prototype for netif->linkoutput functions. Only used for ethernet
* netifs. This function is called by ARP when a packet shall be sent.
*
* @param netif The netif which shall send a packet
* @param p The packet to send (raw ethernet packet)
*/
typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p);
/** Function prototype for netif status- or link-callback functions. */
typedef void (*netif_status_callback_fn)(struct netif *netif);
/** Function prototype for netif igmp_mac_filter functions */
typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
ip_addr_t *group, u8_t action);
/*add DHCP event processing by LiuHan*/
typedef void (*dhcp_event_fn)(void);
/** Generic data structure used for all lwIP network interfaces.
* The following fields should be filled in by the initialization
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
struct netif {
/** pointer to next in linked list */
struct netif *next;
/** IP address configuration in network byte order */
ip_addr_t ip_addr;
ip_addr_t netmask;
ip_addr_t gw;
/** This function is called by the network device driver
* to pass a packet up the TCP/IP stack. IP层输入数据包*/
netif_input_fn input;
/** This function is called by the IP module when it wants
* to send a packet on the interface. This function typically
* first resolves the hardware address, then sends the packet. IP数据包*/
netif_output_fn output;
/** This function is called by the ARP module when it wants
* to send a packet on the interface. This function outputs
* the pbuf as-is on the link medium. */
netif_linkoutput_fn linkoutput;
#if LWIP_NETIF_STATUS_CALLBACK
/** This function is called when the netif state is set to up or down
*/
netif_status_callback_fn status_callback;
#endif /* LWIP_NETIF_STATUS_CALLBACK */
#if LWIP_NETIF_LINK_CALLBACK
/** This function is called when the netif link is set to up or down
*/
netif_status_callback_fn link_callback;
#endif /* LWIP_NETIF_LINK_CALLBACK */
/** This field can be set by the device driver and could point
* to state information for the device. */
void *state;
#if LWIP_DHCP
/** the DHCP client state information for this netif */
struct dhcp *dhcp;
struct udp_pcb *dhcps_pcb; //dhcps
dhcp_event_fn dhcp_event;
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
/** the AutoIP client state information for this netif */
struct autoip *autoip;
#endif
#if LWIP_NETIF_HOSTNAME
/* the hostname for this netif, NULL is a valid value */
char* hostname;
#endif /* LWIP_NETIF_HOSTNAME */
/** maximum transfer unit (in bytes) 该接口允许的最大数据包长度多是1500*/
u16_t mtu;
/** number of bytes used in hwaddr该接口物理地址长度 */
u8_t hwaddr_len;
/** link level hardware address of this interface 该接口物理地址*/
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
/** flags (see NETIF_FLAG_ above) 该接口状态、属性字段*/
u8_t flags;
/** descriptive abbreviation 该接口的名字*/
char name[2];
/** number of this interface 该接口的编号*/
u8_t num;
#if LWIP_SNMP
/** link type (from "snmp_ifType" enum from snmp.h) */
u8_t link_type;
/** (estimate) link speed */
u32_t link_speed;
/** timestamp at last change made (up/down) */
u32_t ts;
/** counters */
u32_t ifinoctets;
u32_t ifinucastpkts;
u32_t ifinnucastpkts;
u32_t ifindiscards;
u32_t ifoutoctets;
u32_t ifoutucastpkts;
u32_t ifoutnucastpkts;
u32_t ifoutdiscards;
#endif /* LWIP_SNMP */
#if LWIP_IGMP
/** This function could be called to add or delete a entry in the multicast
filter table of the ethernet MAC.*/
netif_igmp_mac_filter_fn igmp_mac_filter;
#endif /* LWIP_IGMP */
#if LWIP_NETIF_HWADDRHINT
u8_t *addr_hint;
#endif /* LWIP_NETIF_HWADDRHINT */
#if ENABLE_LOOPBACK
/* List of packets to be queued for ourselves. 指向发送给自己的数据包的pbuf*/
struct pbuf *loop_first;//第一个
struct pbuf *loop_last;//最后一个
#if LWIP_LOOPBACK_MAX_PBUFS
u16_t loop_cnt_current;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
#endif /* ENABLE_LOOPBACK */
#if IP_NAPT
u8_t napt;
#endif
};
#if LWIP_SNMP
#define NETIF_INIT_SNMP(netif, type, speed) \
/* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \
(netif)->link_type = (type); \
/* your link speed here (units: bits per second) */ \
(netif)->link_speed = (speed); \
(netif)->ts = 0; \
(netif)->ifinoctets = 0; \
(netif)->ifinucastpkts = 0; \
(netif)->ifinnucastpkts = 0; \
(netif)->ifindiscards = 0; \
(netif)->ifoutoctets = 0; \
(netif)->ifoutucastpkts = 0; \
(netif)->ifoutnucastpkts = 0; \
(netif)->ifoutdiscards = 0
#else /* LWIP_SNMP */
#define NETIF_INIT_SNMP(netif, type, speed)
#endif /* LWIP_SNMP */
/** The list of network interfaces. */
extern struct netif *netif_list;
/** The default network interface. */
extern struct netif *netif_default;
void netif_init(void)ICACHE_FLASH_ATTR;
struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)ICACHE_FLASH_ATTR;
void
netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
ip_addr_t *gw)ICACHE_FLASH_ATTR;
void netif_remove(struct netif * netif)ICACHE_FLASH_ATTR;
/* Returns a network interface given its name. The name is of the form
"et0", where the first two letters are the "name" field in the
netif structure, and the digit is in the num field in the same
structure. */
struct netif *netif_find(char *name)ICACHE_FLASH_ATTR;
void netif_set_default(struct netif *netif)ICACHE_FLASH_ATTR;
void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)ICACHE_FLASH_ATTR;
void netif_set_netmask(struct netif *netif, ip_addr_t *netmask)ICACHE_FLASH_ATTR;
void netif_set_gw(struct netif *netif, ip_addr_t *gw)ICACHE_FLASH_ATTR;
void netif_set_up(struct netif *netif)ICACHE_FLASH_ATTR;
void netif_set_down(struct netif *netif)ICACHE_FLASH_ATTR;
/** Ask if an interface is up */
#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0)
#if LWIP_NETIF_STATUS_CALLBACK
void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)ICACHE_FLASH_ATTR;
#endif /* LWIP_NETIF_STATUS_CALLBACK */
void netif_set_link_up(struct netif *netif)ICACHE_FLASH_ATTR;
void netif_set_link_down(struct netif *netif)ICACHE_FLASH_ATTR;
/** Ask if a link is up */
#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0)
#if LWIP_NETIF_LINK_CALLBACK
void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)ICACHE_FLASH_ATTR;
#endif /* LWIP_NETIF_LINK_CALLBACK */
#if LWIP_NETIF_HOSTNAME
#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0)
#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL)
#endif /* LWIP_NETIF_HOSTNAME */
#if LWIP_IGMP
#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0)
#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL)
#endif /* LWIP_IGMP */
#if ENABLE_LOOPBACK
err_t netif_loop_output(struct netif *netif, struct pbuf *p, ip_addr_t *dest_ip)ICACHE_FLASH_ATTR;
void netif_poll(struct netif *netif)ICACHE_FLASH_ATTR;
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
void netif_poll_all(void)ICACHE_FLASH_ATTR;
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
#endif /* ENABLE_LOOPBACK */
#ifdef __cplusplus
}
#endif
#endif /* __LWIP_NETIF_H__ */

2054
include/lwip/opt.h Normal file

File diff suppressed because it is too large Load Diff

2097
include/lwipopts.h Normal file

File diff suppressed because it is too large Load Diff

1
include/string.h Normal file
View File

@ -0,0 +1 @@
//Nothing here.

BIN
liblwip_open_napt.a Normal file

Binary file not shown.

310
user/acl.c Normal file
View File

@ -0,0 +1,310 @@
#include "c_types.h"
#include "mem.h"
#include "ets_sys.h"
#include "osapi.h"
#include "os_type.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/tcp_impl.h"
#include "netif/etharp.h"
#include "user_interface.h"
#include "string.h"
#include "acl.h"
acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES];
uint8_t acl_freep[MAX_NO_ACLS];
uint32_t acl_allow_count;
uint32_t acl_deny_count;
static packet_deny_cb my_deny_cb;
void ICACHE_FLASH_ATTR
acl_init()
{
int i;
acl_allow_count = acl_deny_count = 0;
my_deny_cb = NULL;
for(i=0; i< MAX_NO_ACLS; i++)
{
acl_freep[i] = 0;
acl_clear_stats(i);
}
}
bool ICACHE_FLASH_ATTR
acl_is_empty(uint8_t acl_no)
{
if (acl_no >= MAX_NO_ACLS)
{
return true;
}
return acl_freep[acl_no] == 0;
}
void ICACHE_FLASH_ATTR
acl_clear(uint8_t acl_no)
{
if (acl_no >= MAX_NO_ACLS)
{
return;
}
acl_freep[acl_no] = 0;
acl_clear_stats(acl_no);
}
void ICACHE_FLASH_ATTR
acl_clear_stats(uint8_t acl_no)
{
int i;
if (acl_no >= MAX_NO_ACLS)
{
return;
}
my_deny_cb = NULL;
for(i=0; i< MAX_ACL_ENTRIES; i++)
acl[acl_no][i].hit_count = 0;
}
bool ICACHE_FLASH_ATTR
acl_add(uint8_t acl_no,
uint32_t src,
uint32_t s_mask,
uint32_t dest,
uint32_t d_mask,
uint8_t proto,
uint16_t s_port,
uint16_t d_port,
uint8_t allow)
{
acl_entry *my_entry;
if (acl_no >= MAX_NO_ACLS || acl_freep[acl_no] >= MAX_ACL_ENTRIES)
{
return false;
}
my_entry = &acl[acl_no][acl_freep[acl_no]];
my_entry->src = src & s_mask;
my_entry->s_mask = s_mask;
my_entry->dest = dest & d_mask;
my_entry->d_mask = d_mask;
my_entry->proto = proto;
my_entry->s_port = s_port;
my_entry->d_port = d_port;
my_entry->allow = allow;
my_entry->hit_count = 0;
acl_freep[acl_no]++;
return true;
}
uint8_t ICACHE_FLASH_ATTR
acl_check_packet(uint8_t acl_no, struct pbuf *p)
{
struct eth_hdr *mac_h;
struct ip_hdr *ip_h;
uint8_t proto;
struct udp_hdr *udp_h;
struct tcp_hdr *tcp_h;
uint16_t src_port, dest_port;
uint8_t *packet;
int i;
acl_entry *my_entry;
uint8_t allow;
if (acl_no >= MAX_NO_ACLS)
{
return ACL_DENY;
}
if (p->len < sizeof(struct eth_hdr))
{
return ACL_DENY;
}
mac_h = (struct eth_hdr *)p->payload;
// Allow ARP
if (ntohs(mac_h->type) == ETHTYPE_ARP)
{
acl_allow_count++;
return ACL_ALLOW;
}
// Drop anything else if not IPv4
if (ntohs(mac_h->type) != ETHTYPE_IP)
{
acl_deny_count++;
return ACL_DENY;
}
if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr))
{
acl_deny_count++;
return ACL_DENY;
}
allow = ACL_DENY;
packet = (uint8_t*)p->payload;
ip_h = (struct ip_hdr *)&packet[sizeof(struct eth_hdr)];
proto = IPH_PROTO(ip_h);
switch (proto) {
case IP_PROTO_UDP:
{
if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct udp_hdr))
{
return;
}
udp_h = (struct udp_hdr *)&packet[sizeof(struct eth_hdr)+sizeof(struct ip_hdr)];
src_port = ntohs(udp_h->src);
dest_port = ntohs(udp_h->dest);
} break;
case IP_PROTO_TCP:
{
if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct tcp_hdr))
{
return;
}
tcp_h = (struct tcp_hdr *)&packet[sizeof(struct eth_hdr)+sizeof(struct ip_hdr)];
src_port = ntohs(tcp_h->src);
dest_port = ntohs(tcp_h->dest);
} break;
case IP_PROTO_ICMP:
{
src_port = dest_port = 0;
} break;
// Drop anything that is not UDP, TCP, or ICMP
default:
{
acl_deny_count++;
return ACL_DENY;
} break;
}
// os_printf("Src: %d.%d.%d.%d Dst: %d.%d.%d.%d Proto: %s SP:%d DP:%d\n",
// IP2STR(&ip_h->src), IP2STR(&ip_h->dest),
// proto==IP_PROTO_TCP?"TCP":proto==IP_PROTO_UDP?"UDP":"IP4", src_port, dest_port);
for(i=0; i<acl_freep[acl_no]; i++)
{
my_entry = &acl[acl_no][i];
if ((my_entry->proto == 0 || proto == my_entry->proto) &&
(my_entry->src == 0 || my_entry->src == (ip_h->src.addr&my_entry->s_mask)) &&
(my_entry->dest == 0 || my_entry->dest == (ip_h->dest.addr&my_entry->d_mask)) &&
(my_entry->s_port == 0 || my_entry->s_port == src_port) &&
(my_entry->d_port == 0 || my_entry->d_port == dest_port))
{
allow = my_entry->allow;
my_entry->hit_count++;
goto done;
}
}
done:
if (!(allow & ACL_ALLOW) && my_deny_cb != NULL)
{
allow = my_deny_cb(proto, ip_h->src.addr, src_port,
ip_h->dest.addr, dest_port, allow);
}
if (allow & ACL_ALLOW)
{
acl_allow_count++;
}
else
{
acl_deny_count++;
}
// os_printf(" allow: %d\r\n", allow);
return allow;
}
void
acl_set_deny_cb(packet_deny_cb cb)
{
my_deny_cb = cb;
}
void ICACHE_FLASH_ATTR
addr2str(uint8_t *buf, uint32_t addr, uint32_t mask)
{
uint8_t clidr;
if (addr == 0)
{
os_sprintf(buf, "any");
return;
}
mask = ntohl(mask);
for (clidr = 0; mask; mask <<= 1,clidr++);
if (clidr < 32)
{
os_sprintf(buf, "%d.%d.%d.%d/%d", IP2STR((ip_addr_t*)&addr), clidr);
}
else
{
os_sprintf(buf, "%d.%d.%d.%d", IP2STR((ip_addr_t*)&addr));
}
}
void ICACHE_FLASH_ATTR
port2str(uint8_t *buf, uint16_t port)
{
if (port == 0)
{
os_sprintf(buf, "any");
}
else
{
os_sprintf(buf, "%d", port);
}
}
void ICACHE_FLASH_ATTR
acl_show(uint8_t acl_no, uint8_t *buf)
{
int i;
acl_entry *my_entry;
uint8_t line[80], addr1[21], addr2[21], port1[6], port2[6];
buf[0] = 0;
if (acl_no >= MAX_NO_ACLS)
{
return;
}
for(i = 0; i < acl_freep[acl_no]; i++)
{
my_entry = &acl[acl_no][i];
addr2str(addr1, my_entry->src, my_entry->s_mask);
port2str(port1, my_entry->s_port);
addr2str(addr2, my_entry->dest, my_entry->d_mask);
port2str(port2, my_entry->d_port);
if (my_entry->proto != 0)
{
os_sprintf(line, "%s %s:%s %s:%s %s%s (%d hits)\r\n",
my_entry->proto==IP_PROTO_TCP?"TCP":"UDP",
addr1, port1, addr2, port2,
(my_entry->allow & ACL_ALLOW)?"allow":"deny",
(my_entry->allow & ACL_MONITOR)?"_monitor":"",
my_entry->hit_count);
}
else
{
os_sprintf(line, "IP %s %s %s%s (%d hits)\r\n",
addr1, addr2,
(my_entry->allow & ACL_ALLOW)?"allow":"deny",
(my_entry->allow & ACL_MONITOR)?"_monitor":"",
my_entry->hit_count);
}
os_memcpy(&buf[os_strlen(buf)], line, os_strlen(line)+1);
}
}

51
user/acl.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef _ACL_H_
#define _ACL_H_
#include "lwip/ip.h"
#include "lwip/pbuf.h"
#define MAX_NO_ACLS 4
#define MAX_ACL_ENTRIES 16
#define ACL_DENY 0x0
#define ACL_ALLOW 0x1
#define ACL_MONITOR 0x2
typedef struct _acl_entry
{
uint32_t src;
uint32_t s_mask;
uint32_t dest;
uint32_t d_mask;
uint16_t s_port;
uint16_t d_port;
uint8_t proto;
uint8_t allow;
uint32_t hit_count;
} acl_entry;
extern acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES];
extern uint8_t acl_freep[MAX_NO_ACLS];
extern uint32_t acl_allow_count;
extern uint32_t acl_deny_count;
typedef uint8_t (*packet_deny_cb)(uint8_t proto, uint32_t saddr, uint16_t s_port, uint32_t daddr, uint16_t d_port, uint8_t allow);
void acl_init();
bool acl_is_empty(uint8_t acl_no);
void acl_clear(uint8_t acl_no);
void acl_clear_stats(uint8_t acl_no);
bool acl_add(uint8_t acl_no,
uint32_t src,
uint32_t s_mask,
uint32_t dest,
uint32_t d_mask,
uint8_t proto,
uint16_t s_port,
uint16_t d_port,
uint8_t allow);
uint8_t acl_check_packet(uint8_t acl_no, struct pbuf *p);
void acl_set_deny_cb(packet_deny_cb cb);
void acl_show(uint8_t acl_no, uint8_t *buf);
#endif /* _ACL_H_ */

153
user/config_flash.c Normal file
View File

@ -0,0 +1,153 @@
#include "user_interface.h"
#include "lwip/ip.h"
#include "config_flash.h"
/* From the document 99A-SDK-Espressif IOT Flash RW Operation_v0.2 *
* -------------------------------------------------------------------------*
* Flash is erased sector by sector, which means it has to erase 4Kbytes one
* time at least. When you want to change some data in flash, you have to
* erase the whole sector, and then write it back with the new data.
*--------------------------------------------------------------------------*/
void
config_load_default(sysconfig_p config)
{
uint8_t mac[6];
wifi_get_macaddr(STATION_IF, mac);
os_memset(config, 0, sizeof(sysconfig_t));
os_printf("Loading default configuration\r\n");
config->magic_number = MAGIC_NUMBER;
config->length = sizeof(sysconfig_t);
os_sprintf(config->ssid,"%s", WIFI_SSID);
os_sprintf(config->password,"%s", WIFI_PASSWORD);
config->auto_connect = 0;
os_memset(config->bssid, 0, 6);
os_sprintf(config->sta_hostname, "ESP_%02x%02x%02x", mac[3], mac[4], mac[5]);
os_sprintf(config->ap_ssid,"%s", WIFI_AP_SSID);
config->first_run = 1;
config->ap_watchdog = -1;
config->client_watchdog = -1;
IP4_ADDR(&config->network_addr, 192, 168, 4, 1);
config->dns_addr.addr = 0; // use DHCP
config->my_addr.addr = 0; // use DHCP
config->my_netmask.addr = 0; // use DHCP
config->my_gw.addr = 0; // use DHCP
#ifdef PHY_MODE
config->phy_mode = 3; // mode n
#endif
config->clock_speed = 80;
config->status_led = STATUS_LED_GPIO;
wifi_get_macaddr(STATION_IF, config->STA_MAC_address);
config->dhcps_entries = 0;
#ifdef ACLS
acl_init(); // initializes the ACLs, written in config during save
#endif
config->current_mac_address = 0;
// Interval to change mac address in seconds
// Default: 28800 (8 hours)
config->mac_change_interval = 600;
// list of mac addresses
// from https://docs.google.com/spreadsheets/d/1su5u-vPrQwkTixR6YnOTWSi_Ls9lV-_XNJHaWIJspv4/edit#gid=0
ets_str2macaddr(config->mac_list[0], "4E:53:50:4F:4F:40");
ets_str2macaddr(config->mac_list[1], "4E:53:50:4F:4F:41");
ets_str2macaddr(config->mac_list[2], "4E:53:50:4F:4F:42");
ets_str2macaddr(config->mac_list[3], "4E:53:50:4F:4F:43");
ets_str2macaddr(config->mac_list[4], "4E:53:50:4F:4F:44");
ets_str2macaddr(config->mac_list[5], "4E:53:50:4F:4F:45");
ets_str2macaddr(config->mac_list[6], "4E:53:50:4F:4F:46");
ets_str2macaddr(config->mac_list[7], "4E:53:50:4F:4F:47");
ets_str2macaddr(config->mac_list[8], "4E:53:50:4F:4F:48");
ets_str2macaddr(config->mac_list[9], "4E:53:50:4F:4F:49");
ets_str2macaddr(config->mac_list[10], "4E:53:50:4F:4F:4A");
ets_str2macaddr(config->mac_list[11], "4E:53:50:4F:4F:4B");
ets_str2macaddr(config->mac_list[12], "4E:53:50:4F:4F:4C");
ets_str2macaddr(config->mac_list[13], "4E:53:50:4F:4F:4D");
ets_str2macaddr(config->mac_list[14], "4E:53:50:4F:4F:4E");
ets_str2macaddr(config->mac_list[15], "4E:53:50:4F:4F:4F");
}
int
config_load(sysconfig_p config)
{
if (config == NULL)
{
return -1;
}
uint16_t base_address = FLASH_BLOCK_NO;
spi_flash_read(base_address* SPI_FLASH_SEC_SIZE, &config->magic_number, 4);
if((config->magic_number != MAGIC_NUMBER))
{
os_printf("\r\nNo config found, saving default in flash\r\n");
config_load_default(config);
config_save(config);
return -1;
}
os_printf("\r\nConfig found and loaded\r\n");
spi_flash_read(base_address * SPI_FLASH_SEC_SIZE,
(uint32 *) config,
sizeof(sysconfig_t));
if (config->length != sizeof(sysconfig_t))
{
os_printf("Length Mismatch, probably old version of config, loading defaults\r\n");
config_load_default(config);
config_save(config);
return -1;
}
#ifdef ACLS
os_memcpy(&acl, &(config->acl), sizeof(acl));
os_memcpy(&acl_freep, &(config->acl_freep), sizeof(acl_freep));
#endif
return 0;
}
void
config_save(sysconfig_p config)
{
uint16_t base_address = FLASH_BLOCK_NO;
#ifdef ACLS
os_memcpy(&(config->acl), &acl, sizeof(acl));
os_memcpy(&(config->acl_freep), &acl_freep, sizeof(acl_freep));
#endif
os_printf("Saving configuration\r\n");
spi_flash_erase_sector(base_address);
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE,
(uint32 *)config,
sizeof(sysconfig_t));
}
void
blob_save(uint8_t blob_no, uint32_t *data, uint16_t len)
{
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
spi_flash_erase_sector(base_address);
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, data, len);
}
void
blob_load(uint8_t blob_no, uint32_t *data, uint16_t len)
{
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
spi_flash_read(base_address * SPI_FLASH_SEC_SIZE, data, len);
}
void
blob_zero(uint8_t blob_no, uint16_t len)
{
int i;
uint8_t z[len];
os_memset(z, 0,len);
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
spi_flash_erase_sector(base_address);
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, (uint32_t *)z, len);
}

81
user/config_flash.h Normal file
View File

@ -0,0 +1,81 @@
#ifndef _CONFIG_FLASH_H_
#define _CONFIG_FLASH_H_
#include "c_types.h"
#include "mem.h"
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "os_type.h"
#include "spi_flash.h"
#include "lwip/app/dhcpserver.h"
#include "user_config.h"
#include "acl.h"
#define FLASH_BLOCK_NO 0xc
#define MAGIC_NUMBER 0x112005fc
#define MAX_MAC_LIST_LENGTH 15
typedef struct
{
// To check if the structure is initialized or not in flash
uint32_t magic_number;
// Length of the structure, since this is a evolving library,
// the variant may change hence used for verification
uint16_t length;
/* Below variables are specific to my code */
uint8_t ssid[32]; // SSID of the AP to connect to
uint8_t password[64]; // Password of the network
uint8_t auto_connect; // Should we auto connect
uint8_t bssid[6]; // Optional: BSSID the AP
uint8_t sta_hostname[32]; // Name of the station
uint8_t ap_ssid[32]; // SSID of the own AP
uint8_t first_run; // Has ESPerPass been configured yet?
uint8_t current_mac_address; // Holds currently broadcasted HomePass mac address index
int32_t mac_change_interval; // Interval to rotate HomePass mac address (in seconds)
// Seconds without ap traffic will cause reset (-1 off, default)
int32_t ap_watchdog;
// Seconds without client traffic will cause reset (-1 off, default)
int32_t client_watchdog;
ip_addr_t network_addr; // Address of the internal network
ip_addr_t dns_addr; // Optional: address of the dns server
ip_addr_t my_addr; // Optional (if not DHCP): IP address of the uplink side
ip_addr_t my_netmask; // Optional (if not DHCP): IP netmask of the uplink side
ip_addr_t my_gw; // Optional (if not DHCP): Gateway of the uplink side
#ifdef PHY_MODE
uint16_t phy_mode; // WiFi PHY mode
#endif
uint16_t clock_speed; // Freq of the CPU
uint16_t status_led; // GPIO pin os the status LED (>16 disabled)
uint8_t STA_MAC_address[6]; // MAC address of the STA
uint16_t dhcps_entries; // number of allocated entries in the following table
struct dhcps_pool dhcps_p[MAX_DHCP]; // DHCP entries
#ifdef ACLS
acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES]; // ACL entries
uint8_t acl_freep[MAX_NO_ACLS]; // ACL free pointers
#endif
// HomePass mac list
// Allow 20 slots
uint8_t mac_list[19][6];
} sysconfig_t, *sysconfig_p;
int config_load(sysconfig_p config);
void config_save(sysconfig_p config);
void blob_save(uint8_t blob_no, uint32_t *data, uint16_t len);
void blob_load(uint8_t blob_no, uint32_t *data, uint16_t len);
void blob_zero(uint8_t blob_no, uint16_t len);
#endif

250
user/ringbuf.c Normal file
View File

@ -0,0 +1,250 @@
/*
* ringbuf.c - C ring buffer (FIFO) implementation.
*
* Written in 2011 by Drew Hess <dhess-src@bothan.net>.
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to
* the public domain worldwide. This software is distributed without
* any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "ringbuf.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/param.h>
#include "osapi.h"
#include "mem.h"
#define assert(x)
/*
* The code is written for clarity, not cleverness or performance, and
* contains many assert()s to enforce invariant assumptions and catch
* bugs. Feel free to optimize the code and to remove asserts for use
* in your own projects, once you're comfortable that it functions as
* intended.
*/
struct ringbuf_t
{
uint8_t *buf;
uint8_t *head, *tail;
size_t size;
};
ringbuf_t
ringbuf_new(size_t capacity)
{
ringbuf_t rb = (ringbuf_t)os_malloc(sizeof(struct ringbuf_t));
if (rb) {
/* One byte is used for detecting the full condition. */
rb->size = capacity + 1;
rb->buf = (uint8_t *)os_malloc(rb->size);
if (rb->buf)
ringbuf_reset(rb);
else {
os_free(rb);
return 0;
}
}
return rb;
}
size_t
ringbuf_buffer_size(const struct ringbuf_t *rb)
{
return rb->size;
}
void
ringbuf_reset(ringbuf_t rb)
{
rb->head = rb->tail = rb->buf;
}
void
ringbuf_free(ringbuf_t *rb)
{
assert(rb && *rb);
os_free((*rb)->buf);
os_free(*rb);
*rb = 0;
}
size_t
ringbuf_capacity(const struct ringbuf_t *rb)
{
return ringbuf_buffer_size(rb) - 1;
}
/*
* Return a pointer to one-past-the-end of the ring buffer's
* contiguous buffer. You shouldn't normally need to use this function
* unless you're writing a new ringbuf_* function.
*/
static const uint8_t *
ringbuf_end(const struct ringbuf_t *rb)
{
return rb->buf + ringbuf_buffer_size(rb);
}
size_t
ringbuf_bytes_free(const struct ringbuf_t *rb)
{
if (rb->head >= rb->tail)
return ringbuf_capacity(rb) - (rb->head - rb->tail);
else
return rb->tail - rb->head - 1;
}
size_t
ringbuf_bytes_used(const struct ringbuf_t *rb)
{
return ringbuf_capacity(rb) - ringbuf_bytes_free(rb);
}
int
ringbuf_is_full(const struct ringbuf_t *rb)
{
return ringbuf_bytes_free(rb) == 0;
}
int
ringbuf_is_empty(const struct ringbuf_t *rb)
{
return ringbuf_bytes_free(rb) == ringbuf_capacity(rb);
}
const void *
ringbuf_tail(const struct ringbuf_t *rb)
{
return rb->tail;
}
const void *
ringbuf_head(const struct ringbuf_t *rb)
{
return rb->head;
}
/*
* Given a ring buffer rb and a pointer to a location within its
* contiguous buffer, return the a pointer to the next logical
* location in the ring buffer.
*/
static uint8_t *
ringbuf_nextp(ringbuf_t rb, const uint8_t *p)
{
/*
* The assert guarantees the expression (++p - rb->buf) is
* non-negative; therefore, the modulus operation is safe and
* portable.
*/
assert((p >= rb->buf) && (p < ringbuf_end(rb)));
return rb->buf + ((++p - rb->buf) % ringbuf_buffer_size(rb));
}
void *
ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count)
{
const uint8_t *u8src = src;
const uint8_t *bufend = ringbuf_end(dst);
int overflow = count > ringbuf_bytes_free(dst);
size_t nread = 0;
while (nread != count) {
/* don't copy beyond the end of the buffer */
assert(bufend > dst->head);
size_t n = MIN(bufend - dst->head, count - nread);
os_memcpy(dst->head, u8src + nread, n);
dst->head += n;
nread += n;
/* wrap? */
if (dst->head == bufend)
dst->head = dst->buf;
}
if (overflow) {
dst->tail = ringbuf_nextp(dst, dst->head);
assert(ringbuf_is_full(dst));
}
return dst->head;
}
void *
ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count)
{
size_t bytes_used = ringbuf_bytes_used(src);
if (count > bytes_used)
return 0;
uint8_t *u8dst = dst;
const uint8_t *bufend = ringbuf_end(src);
size_t nwritten = 0;
while (nwritten != count) {
assert(bufend > src->tail);
size_t n = MIN(bufend - src->tail, count - nwritten);
os_memcpy(u8dst + nwritten, src->tail, n);
src->tail += n;
nwritten += n;
/* wrap ? */
if (src->tail == bufend)
src->tail = src->buf;
}
assert(count + ringbuf_bytes_used(src) == bytes_used);
return src->tail;
}
void *
ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count)
{
size_t src_bytes_used = ringbuf_bytes_used(src);
if (count > src_bytes_used)
return 0;
int overflow = count > ringbuf_bytes_free(dst);
const uint8_t *src_bufend = ringbuf_end(src);
const uint8_t *dst_bufend = ringbuf_end(dst);
size_t ncopied = 0;
while (ncopied != count) {
assert(src_bufend > src->tail);
size_t nsrc = MIN(src_bufend - src->tail, count - ncopied);
assert(dst_bufend > dst->head);
size_t n = MIN(dst_bufend - dst->head, nsrc);
os_memcpy(dst->head, src->tail, n);
src->tail += n;
dst->head += n;
ncopied += n;
/* wrap ? */
if (src->tail == src_bufend)
src->tail = src->buf;
if (dst->head == dst_bufend)
dst->head = dst->buf;
}
assert(count + ringbuf_bytes_used(src) == src_bytes_used);
if (overflow) {
dst->tail = ringbuf_nextp(dst, dst->head);
assert(ringbuf_is_full(dst));
}
return dst->head;
}

167
user/ringbuf.h Normal file
View File

@ -0,0 +1,167 @@
#ifndef INCLUDED_RINGBUF_H
#define INCLUDED_RINGBUF_H
/*
* ringbuf.h - C ring buffer (FIFO) interface.
*
* Written in 2011 by Drew Hess <dhess-src@bothan.net>.
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to
* the public domain worldwide. This software is distributed without
* any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/*
* A byte-addressable ring buffer FIFO implementation.
*
* The ring buffer's head pointer points to the starting location
* where data should be written when copying data *into* the buffer
* (e.g., with ringbuf_read). The ring buffer's tail pointer points to
* the starting location where data should be read when copying data
* *from* the buffer (e.g., with ringbuf_write).
*/
#include <stddef.h>
#include <sys/types.h>
typedef struct ringbuf_t *ringbuf_t;
/*
* Create a new ring buffer with the given capacity (usable
* bytes). Note that the actual internal buffer size may be one or
* more bytes larger than the usable capacity, for bookkeeping.
*
* Returns the new ring buffer object, or 0 if there's not enough
* memory to fulfill the request for the given capacity.
*/
ringbuf_t
ringbuf_new(size_t capacity);
/*
* The size of the internal buffer, in bytes. One or more bytes may be
* unusable in order to distinguish the "buffer full" state from the
* "buffer empty" state.
*
* For the usable capacity of the ring buffer, use the
* ringbuf_capacity function.
*/
size_t
ringbuf_buffer_size(const struct ringbuf_t *rb);
/*
* Deallocate a ring buffer, and, as a side effect, set the pointer to
* 0.
*/
void
ringbuf_free(ringbuf_t *rb);
/*
* Reset a ring buffer to its initial state (empty).
*/
void
ringbuf_reset(ringbuf_t rb);
/*
* The usable capacity of the ring buffer, in bytes. Note that this
* value may be less than the ring buffer's internal buffer size, as
* returned by ringbuf_buffer_size.
*/
size_t
ringbuf_capacity(const struct ringbuf_t *rb);
/*
* The number of free/available bytes in the ring buffer. This value
* is never larger than the ring buffer's usable capacity.
*/
size_t
ringbuf_bytes_free(const struct ringbuf_t *rb);
/*
* The number of bytes currently being used in the ring buffer. This
* value is never larger than the ring buffer's usable capacity.
*/
size_t
ringbuf_bytes_used(const struct ringbuf_t *rb);
int
ringbuf_is_full(const struct ringbuf_t *rb);
int
ringbuf_is_empty(const struct ringbuf_t *rb);
/*
* Const access to the head and tail pointers of the ring buffer.
*/
const void *
ringbuf_tail(const struct ringbuf_t *rb);
const void *
ringbuf_head(const struct ringbuf_t *rb);
/*
* Copy n bytes from a contiguous memory area src into the ring buffer
* dst. Returns the ring buffer's new head pointer.
*
* It is possible to copy more data from src than is available in the
* buffer; i.e., it's possible to overflow the ring buffer using this
* function. When an overflow occurs, the state of the ring buffer is
* guaranteed to be consistent, including the head and tail pointers;
* old data will simply be overwritten in FIFO fashion, as
* needed. However, note that, if calling the function results in an
* overflow, the value of the ring buffer's tail pointer may be
* different than it was before the function was called.
*/
void *
ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count);
/*
* Copy n bytes from the ring buffer src, starting from its tail
* pointer, into a contiguous memory area dst. Returns the value of
* src's tail pointer after the copy is finished.
*
* Note that this copy is destructive with respect to the ring buffer:
* the n bytes copied from the ring buffer are no longer available in
* the ring buffer after the copy is complete, and the ring buffer
* will have n more free bytes than it did before the function was
* called.
*
* This function will *not* allow the ring buffer to underflow. If
* count is greater than the number of bytes used in the ring buffer,
* no bytes are copied, and the function will return 0.
*/
void *
ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count);
/*
* Copy count bytes from ring buffer src, starting from its tail
* pointer, into ring buffer dst. Returns dst's new head pointer after
* the copy is finished.
*
* Note that this copy is destructive with respect to the ring buffer
* src: any bytes copied from src into dst are no longer available in
* src after the copy is complete, and src will have 'count' more free
* bytes than it did before the function was called.
*
* It is possible to copy more data from src than is available in dst;
* i.e., it's possible to overflow dst using this function. When an
* overflow occurs, the state of dst is guaranteed to be consistent,
* including the head and tail pointers; old data will simply be
* overwritten in FIFO fashion, as needed. However, note that, if
* calling the function results in an overflow, the value dst's tail
* pointer may be different than it was before the function was
* called.
*
* It is *not* possible to underflow src; if count is greater than the
* number of bytes used in src, no bytes are copied, and the function
* returns 0.
*/
void *
ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count);
#endif /* INCLUDED_RINGBUF_H */

36
user/sys_time.c Normal file
View File

@ -0,0 +1,36 @@
#include "c_types.h"
#include "osapi.h"
typedef union _timer {
uint32_t time_s[2];
uint64_t time_l;
} long_time_t;
static long_time_t time;
static uint32_t old;
uint64_t ICACHE_FLASH_ATTR
get_long_systime()
{
uint32_t now = system_get_time();
if (now < old)
{
time.time_s[1]++;
}
old = now;
time.time_s[0] = now;
return time.time_l;
}
uint64_t ICACHE_FLASH_ATTR
get_low_systime()
{
get_long_systime();
return time.time_s[0];
}
void init_long_systime()
{
old = system_get_time();
time.time_l = (uint64_t)old;
}

13
user/sys_time.h Normal file
View File

@ -0,0 +1,13 @@
#include "c_types.h"
// returns time until boot in us
uint64_t ICACHE_FLASH_ATTR
get_long_systime();
// returns lower half of time until boot in us
uint64_t ICACHE_FLASH_ATTR
get_low_systime();
// initializes the timer
void
init_long_systime();

38
user/user_config.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef _USER_CONFIG_
#define _USER_CONFIG_
#define ESPERPASS_VERSION "V0.0.1"
#define WIFI_SSID "ssid"
#define WIFI_PASSWORD "password"
#define WIFI_AP_SSID "attwifi"
#define MAX_CLIENTS 8
#define MAX_DHCP 8
//
// Size of the console buffers
//
#define MAX_CON_SEND_SIZE 1024
#define MAX_CON_CMD_SIZE 80
//
// Define this if you have a status LED connected to a GPIO pin
//
#define STATUS_LED_GPIO 2
//
// Define this to support the setting of the WiFi PHY mode
//
#define PHY_MODE 1
//
// Define this if you want to have ACLs for the SoftAP.
//
#define ACLS 1
// Internal
typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SIG_CONSOLE_RX, SIG_CONSOLE_TX, SIG_CONSOLE_TX_RAW, SIG_GPIO_INT} USER_SIGNALS;
#endif

1494
user/user_main.c Normal file

File diff suppressed because it is too large Load Diff