Getting ready for release...

pull/30/head
Jeroen Domburg 10 years ago
parent 290fe32e46
commit aef27aaa5b
  1. 5
      Makefile
  2. 44
      driver/Makefile
  3. 248
      driver/uart.c
  4. 13
      html/led.html
  5. 7
      html/test.html
  6. 12
      html/test2.html
  7. 10
      html/test3.html
  8. 103
      include/driver/uart.h
  9. 128
      include/driver/uart_register.h
  10. 1
      include/espmissingincludes.h
  11. 7
      mkespfsimage/Makefile
  12. 203
      user/cgi.c
  13. 6
      user/cgi.h
  14. 38
      user/espfs.c
  15. 1
      user/heatshrink_config_httpd.h
  16. 41
      user/httpd.c
  17. 6
      user/httpd.h
  18. 14
      user/httpdespfs.c
  19. 11
      user/io.c
  20. 21
      user/user_main.c

@ -14,6 +14,9 @@ FW_BASE = firmware
# Base directory for the compiler
XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin
#Extra Tensilica includes from the ESS VM
SDK_EXTRA_INCLUDES ?= /opt/Espressif/include
# base directory of the ESP8266 SDK package, absolute
SDK_BASE ?= /opt/Espressif/ESP8266_SDK
@ -29,7 +32,7 @@ MODULES = driver user
EXTRA_INCDIR = include \
. \
lib/heatshrink/ \
./../esp_iot_sdk_novm_unpacked/usr/xtensa/XtDevTools/install/builds/RC-2010.1-win32/lx106/xtensa-elf/include/
$(SDK_EXTRA_INCLUDES)
# libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal phy net80211 lwip wpa main

@ -1,44 +0,0 @@
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libdriver.a
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

@ -1,248 +0,0 @@
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: uart.c
*
* Description: Two UART mode configration and interrupt handler.
* Check your hardware connection while use this mode.
*
* Modification history:
* 2014/3/12, v1.0 create this file.
*******************************************************************************/
#include "espmissingincludes.h"
#include "ets_sys.h"
#include "osapi.h"
#include "driver/uart.h"
#include "driver/uart_register.h"
//#include "ssc.h"
//#include "at.h"
// UartDev is defined and initialized in rom code.
extern UartDevice UartDev;
//extern os_event_t at_recvTaskQueue[at_recvTaskQueueLen];
LOCAL void uart0_rx_intr_handler(void *para);
/******************************************************************************
* 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);
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
}
uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));
WRITE_PERI_REG(UART_CONF0(uart_no), UartDev.exist_parity
| UartDev.parity
| (UartDev.stop_bits << UART_STOP_BIT_NUM_S)
| (UartDev.data_bits << 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);
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
//set rx fifo trigger
// WRITE_PERI_REG(UART_CONF1(uart_no),
// ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
// ((96 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) |
// UART_RX_FLOW_EN);
if (uart_no == UART0)
{
//set rx fifo trigger
WRITE_PERI_REG(UART_CONF1(uart_no),
((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
((0x01 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) |
UART_RX_FLOW_EN);
}
else
{
WRITE_PERI_REG(UART_CONF1(uart_no),
((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S));
}
//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);
}
/******************************************************************************
* FunctionName : uart1_tx_one_char
* Description : Internal used function
* Use uart1 interface to transfer one char
* Parameters : uint8 TxChar - character to tx
* Returns : OK
*******************************************************************************/
LOCAL 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 : uart1_write_char
* Description : Internal used function
* Do some special deal while tx char is '\r' or '\n'
* Parameters : char c - character to tx
* Returns : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
uart0_write_char(char c)
{
if (c == '\n')
{
uart_tx_one_char(UART0, '\r');
uart_tx_one_char(UART0, '\n');
}
else if (c == '\r')
{
}
else
{
uart_tx_one_char(UART0, c);
}
}
/******************************************************************************
* FunctionName : uart0_tx_buffer
* Description : use uart0 to transfer buffer
* Parameters : uint8 *buf - point to send buffer
* uint16 len - buffer len
* Returns :
*******************************************************************************/
void ICACHE_FLASH_ATTR
uart0_tx_buffer(uint8 *buf, uint16 len)
{
uint16 i;
for (i = 0; i < len; i++)
{
uart_tx_one_char(UART0, buf[i]);
}
}
/******************************************************************************
* FunctionName : uart0_sendStr
* Description : use uart0 to transfer buffer
* Parameters : uint8 *buf - point to send buffer
* uint16 len - buffer len
* Returns :
*******************************************************************************/
void ICACHE_FLASH_ATTR
uart0_sendStr(const char *str)
{
while(*str)
{
uart_tx_one_char(UART0, *str++);
}
}
/******************************************************************************
* 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
*******************************************************************************/
//extern void at_recvTask(void);
LOCAL void
uart0_rx_intr_handler(void *para)
{
/* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
* uart1 and uart0 respectively
*/
// RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para;
// uint8 RcvChar;
uint8 uart_no = UART0;//UartDev.buff_uart_no;
// if (UART_RXFIFO_FULL_INT_ST != (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
// {
// return;
// }
if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST))
{
// at_recvTask();
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
}
// WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
// if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S))
// {
// RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
// at_recvTask();
// *(pRxBuff->pWritePos) = RcvChar;
// system_os_post(at_recvTaskPrio, NULL, RcvChar);
// //insert here for get one command line from uart
// if (RcvChar == '\r')
// {
// pRxBuff->BuffState = WRITE_OVER;
// }
//
// pRxBuff->pWritePos++;
//
// if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE))
// {
// // overflow ...we may need more error handle here.
// pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ;
// }
// }
}
/******************************************************************************
* FunctionName : uart_init
* Description : user interface for init uart
* Parameters : UartBautRate uart0_br - uart0 bautrate
* UartBautRate uart1_br - uart1 bautrate
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
{
// rom use 74880 baut_rate, here reinitialize
UartDev.baut_rate = uart0_br;
uart_config(UART0);
UartDev.baut_rate = uart1_br;
uart_config(UART1);
ETS_UART_INTR_ENABLE();
// install uart0 putc callback
os_install_putc1((void *)uart0_write_char);
}
void ICACHE_FLASH_ATTR
uart_reattach()
{
uart_init(BIT_RATE_74880, BIT_RATE_74880);
// ETS_UART_INTR_ATTACH(uart_rx_intr_handler_ssc, &(UartDev.rcv_buff));
// ETS_UART_INTR_ENABLE();
}

@ -1,13 +0,0 @@
<html><head><title>Test</title></head>
<body>
<p>
There's a LED. You can't see it, so it's no use clicking any of the buttons below. The buttons
do, however, turn the LED on and off.
</p>
<form method="post" action="led.cgi">
<input type="submit" name="led" value="1">
<input type="submit" name="led" value="0">
</form>
</body></html>

@ -1,7 +0,0 @@
<html>
<head><title>Test</title></head>
<body>
<h1>Test!</h1>
<p>Yay, the cpio filesystem thingy works. Click <a href="/test2.html">here</a> to see
if the 2nd page works too.
</p>

@ -1,12 +0,0 @@
<html>
<head><title>Test</title></head>
<body>
<h1>Test2!</h1>
<p><b>New!</b>You can also control the <a href="led.html">LED</a>...</p>
<p>Here's an image of a cat (hopefully...)<br />
<img src="cat.jpeg"><br />
<img src="ceilingcat.jpg"><br />
<img src="disapprove.jpg"><br />
<img src="invisiblepogostick.jpg"><br />
</p>
</body></html>

@ -1,10 +0,0 @@
<html><head><title>Test</title></head>
<body>
<form method="post" action="test.cgi">
<input type="text" name="Test1" value="t1">
<input type="text" name="Test2" value="t2">
<input type="submit" name="DoIt" value="Do It">
</form>
</body></html>

@ -1,103 +0,0 @@
#ifndef UART_APP_H
#define UART_APP_H
#include "uart_register.h"
#include "eagle_soc.h"
#include "c_types.h"
#define RX_BUFF_SIZE 256
#define TX_BUFF_SIZE 100
#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 = 0,
ONE_HALF_STOP_BIT = BIT2,
TWO_STOP_BIT = BIT2
} UartStopBitsNum;
typedef enum {
NONE_BITS = 0,
ODD_BITS = 0,
EVEN_BITS = BIT4
} UartParityMode;
typedef enum {
STICK_PARITY_DIS = 0,
STICK_PARITY_EN = BIT3 | BIT5
} UartExistParity;
typedef enum {
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
} UartBautRate;
typedef enum {
NONE_CTRL,
HARDWARE_CTRL,
XON_XOFF_CTRL
} UartFlowCtrl;
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; // chip size in byte
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);
#endif

@ -1,128 +0,0 @@
//Generated at 2012-07-03 18:44:06
/*
* Copyright (c) 2010 - 2011 Espressif System
*
*/
#ifndef UART_REGISTER_H_INCLUDED
#define UART_REGISTER_H_INCLUDED
#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_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 (BIT(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

@ -26,6 +26,7 @@ char *ets_strcpy(char *dest, const char *src);
char *ets_strncpy(char *dest, const char *src, size_t n);
char *ets_strstr(const char *haystack, const char *needle);
int ets_sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
int os_printf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void uart_div_modify(int no, int freq);
void ets_isr_unmask(int intr);

@ -1,5 +1,10 @@
CFLAGS=-I../lib/heatshrink -std=gnu99
OBJS=main.o heatshrink_encoder.o
TARGET=mkespfsimage
mkespfsimage: main.o heatshrink_encoder.o
$(TARGET): $(OBJS)
$(CC) -o $@ $^
clean:
rm -f $(TARGET) $(OBJS)

@ -2,6 +2,16 @@
Some random cgi routines.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include <string.h>
#include <osapi.h>
#include "user_interface.h"
@ -11,6 +21,10 @@ Some random cgi routines.
#include "io.h"
#include "espmissingincludes.h"
//cause I can't be bothered to write an ioGetLed()
static char currLedState=0;
//Cgi that turns the LED on or off according to the 'led' param in the POST data
int ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) {
int len;
char buff[1024];
@ -21,169 +35,35 @@ int ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) {
}
len=httpdFindArg(connData->postBuff, "led", buff, sizeof(buff));
if (len!=0) ioLed(atoi(buff));
if (len!=0) {
currLedState=atoi(buff);
ioLed(currLedState);
}
httpdRedirect(connData, "led.html");
return HTTPD_CGI_DONE;
}
//WiFi access point data
typedef struct {
char ssid[32];
char rssi;
char enc;
} ApData;
//Scan resolt
typedef struct {
char scanInProgress;
ApData **apData;
int noAps;
} ScanResultData;
//Static scan status storage.
ScanResultData cgiWifiAps;
void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
int n;
struct bss_info *bss_link = (struct bss_info *)arg;
os_printf("wifiScanDoneCb %d\n", status);
if (status!=OK) {
cgiWifiAps.scanInProgress=0;
wifi_station_disconnect(); //test HACK
return;
}
//Clear prev ap data if needed.
if (cgiWifiAps.apData!=NULL) {
for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]);
os_free(cgiWifiAps.apData);
}
//Count amount of access points found.
n=0;
while (bss_link != NULL) {
bss_link = bss_link->next.stqe_next;
n++;
}
//Allocate memory for access point data
cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n);
cgiWifiAps.noAps=n;
//Copy access point data to the static struct
n=0;
bss_link = (struct bss_info *)arg;
while (bss_link != NULL) {
cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData));
cgiWifiAps.apData[n]->rssi=bss_link->rssi;
cgiWifiAps.apData[n]->enc=bss_link->authmode;
strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32);
bss_link = bss_link->next.stqe_next;
n++;
}
os_printf("Scan done: found %d APs\n", n);
//We're done.
cgiWifiAps.scanInProgress=0;
}
static void ICACHE_FLASH_ATTR wifiStartScan() {
int x;
cgiWifiAps.scanInProgress=1;
x=wifi_station_get_connect_status();
if (x!=STATION_GOT_IP) {
//Unit probably is trying to connect to a bogus AP. This messes up scanning. Stop that.
os_printf("STA status = %d. Disconnecting STA...\n", x);
wifi_station_disconnect();
}
wifi_station_scan(NULL, wifiScanDoneCb);
}
int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) {
int len;
int i;
char buff[1024];
httpdStartResponse(connData, 200);
httpdHeader(connData, "Content-Type", "text/json");
httpdEndHeaders(connData);
if (cgiWifiAps.scanInProgress==1) {
len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n");
espconn_sent(connData->conn, (uint8 *)buff, len);
} else {
len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"0\", \n\"APs\": [\n");
espconn_sent(connData->conn, (uint8 *)buff, len);
if (cgiWifiAps.apData==NULL) cgiWifiAps.noAps=0;
for (i=0; i<cgiWifiAps.noAps; i++) {
len=os_sprintf(buff, "{\"essid\": \"%s\", \"rssi\": \"%d\", \"enc\": \"%d\"}%s\n",
cgiWifiAps.apData[i]->ssid, cgiWifiAps.apData[i]->rssi,
cgiWifiAps.apData[i]->enc, (i==cgiWifiAps.noAps-1)?"":",");
espconn_sent(connData->conn, (uint8 *)buff, len);
}
len=os_sprintf(buff, "]\n}\n}\n");
espconn_sent(connData->conn, (uint8 *)buff, len);
wifiStartScan();
}
return HTTPD_CGI_DONE;
}
static struct station_config stconf;
//Template code for the led page.
void ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) {
char buff[128];
if (token==NULL) return;
static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
int x=wifi_station_get_connect_status();
if (x==STATION_GOT_IP) {
//Go to STA mode. This needs a reset, so do that.
wifi_set_opmode(1);
system_restart();
os_strcpy(buff, "Unknown");
if (os_strcmp(token, "ledstate")==0) {
if (currLedState) {
os_strcpy(buff, "on");
} else {
os_printf("Connect fail. Not going into STA-only mode.\n");
}
}
static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) {
int x;
static ETSTimer resetTimer;
wifi_station_disconnect();
wifi_station_set_config(&stconf);
wifi_station_connect();
x=wifi_get_opmode();
if (x!=1) {
//Schedule disconnect/connect
os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_arm(&resetTimer, 4000, 0);
os_strcpy(buff, "off");
}
}
int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
char essid[128];
char passwd[128];
static ETSTimer reassTimer;
if (connData->conn==NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
espconn_sent(connData->conn, (uint8 *)buff, os_strlen(buff));
}
httpdFindArg(connData->postBuff, "essid", essid, sizeof(essid));
httpdFindArg(connData->postBuff, "passwd", passwd, sizeof(passwd));
os_strncpy((char*)stconf.ssid, essid, 32);
os_strncpy((char*)stconf.password, passwd, 64);
//Schedule disconnect/connect
os_timer_disarm(&reassTimer);
os_timer_setfn(&reassTimer, reassTimerCb, NULL);
os_timer_arm(&reassTimer, 1000, 0);
httpdRedirect(connData, "connecting.html");
return HTTPD_CGI_DONE;
}
//Cgi that reads the SPI flash. Assumes 512KByte flash.
int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) {
@ -206,30 +86,3 @@ int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) {
if (*pos>=0x40200000+(512*1024)) return HTTPD_CGI_DONE; else return HTTPD_CGI_MORE;
}
int ICACHE_FLASH_ATTR cgiTest(HttpdConnData *connData) {
return HTTPD_CGI_DONE;
}
void ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) {
char buff[1024];
int x;
static struct station_config stconf;
if (token==NULL) return;
wifi_station_get_config(&stconf);
os_strcpy(buff, "Unknown");
if (os_strcmp(token, "WiFiMode")==0) {
x=wifi_get_opmode();
if (x==1) os_strcpy(buff, "Client");
if (x==2) os_strcpy(buff, "SoftAP");
if (x==3) os_strcpy(buff, "STA+AP");
} else if (os_strcmp(token, "currSsid")==0) {
os_strcpy(buff, (char*)stconf.ssid);
} else if (os_strcmp(token, "WiFiPasswd")==0) {
os_strcpy(buff, (char*)stconf.password);
}
espconn_sent(connData->conn, (uint8 *)buff, os_strlen(buff));
}

@ -4,11 +4,7 @@
#include "httpd.h"
int cgiLed(HttpdConnData *connData);
void tplLed(HttpdConnData *connData, char *token, void **arg);
int cgiReadFlash(HttpdConnData *connData);
int cgiTest(HttpdConnData *connData);
int cgiWiFiScan(HttpdConnData *connData);
void ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg);
int ICACHE_FLASH_ATTR cgiWiFi(HttpdConnData *connData);
int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData);
#endif

@ -4,9 +4,22 @@ mkespfsimg tool, and can use that block to do abstracted operations on the files
It's written for use with httpd, but doesn't need to be used as such.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
//These routines can also be tested by comping them in with the espfstest tool. This
//simplifies debugging, but needs some slightly different headers. The #ifdef takes
//care of that.
#ifdef __ets__
//esp build
#include "driver/uart.h"
#include "c_types.h"
#include "user_interface.h"
#include "espconn.h"
@ -51,7 +64,7 @@ struct EspFsFile {
/*
Available locations, at least in my flash, with boundaries partially guessed. This
is using 0.9.1 SDK on a not-too-new module.
is using 0.9.1/0.9.2 SDK on a not-too-new module.
0x00000 (0x10000): Code/data (RAM data?)
0x10000 (0x02000): Gets erased by something?
0x12000 (0x2E000): Free (filled with zeroes) (parts used by ESPCloud and maybe SSL)
@ -83,7 +96,7 @@ void ICACHE_FLASH_ATTR memcpyAligned(char *dst, char *src, int len) {
}
//Open a file and return a pointer to the file desc struct.
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
#ifdef __ets__
char *p=(char *)(ESPFS_POS+0x40200000);
@ -94,11 +107,12 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
char namebuf[256];
EspFsHeader h;
EspFsFile *r;
//Skip initial slashes
//Strip initial slashes
while(fileName[0]=='/') fileName++;
//Go find that file!
while(1) {
hpos=p;
//Grab the next file header.
os_memcpy(&h, p, sizeof(EspFsHeader));
if (h.magic!=0x73665345) {
os_printf("Magic mismatch. EspFS image broken.\n");
@ -108,13 +122,15 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
os_printf("End of image.\n");
return NULL;
}
//Grab the name of the file.
p+=sizeof(EspFsHeader);
os_memcpy(namebuf, p, sizeof(namebuf));
os_printf("Found file '%s'. Namelen=%x fileLenComp=%x, compr=%d flags=%d\n",
namebuf, (unsigned int)h.nameLen, (unsigned int)h.fileLenComp, h.compression, h.flags);
if (os_strcmp(namebuf, fileName)==0) {
p+=h.nameLen;
r=(EspFsFile *)os_malloc(sizeof(EspFsFile));
//Yay, this is the file we need!
p+=h.nameLen; //Skip to content.
r=(EspFsFile *)os_malloc(sizeof(EspFsFile)); //Alloc file desc mem
if (r==NULL) return NULL;
r->header=(EspFsHeader *)hpos;
r->decompressor=h.compression;
@ -125,6 +141,7 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
r->decompData=NULL;
#ifdef EFS_HEATSHRINK
} else if (h.compression==COMPRESS_HEATSHRINK) {
//File is compressed with Heatshrink.
char parm;
heatshrink_decoder *dec;
//Decoder params are stored in 1st byte.
@ -132,7 +149,6 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
r->posComp++;
os_printf("Heatshrink compressed file; decode parms = %x\n", parm);
dec=heatshrink_decoder_alloc(16, (parm>>4)&0xf, parm&0xf);
heatshrink_decoder_reset(dec);
r->decompData=dec;
#endif
} else {
@ -141,18 +157,19 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
}
return r;
}
//Skip name and file
//We don't need this file. Skip name and file
p+=h.nameLen+h.fileLenComp;
if ((int)p&3) p+=4-((int)p&3); //align to next 32bit val
// os_printf("Next addr = %x\n", (int)p);
}
}
//Read len bytes from the given file into buff. Returns the actual amount of bytes read.
int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) {
int flen;
if (fh==NULL) return 0;
//Cache file length.
memcpyAligned((char*)&flen, (char*)&fh->header->fileLenComp, 4);
//Do stuff depending on the way the file is compressed.
if (fh->decompressor==COMPRESS_NONE) {
int toRead;
toRead=flen-(fh->posComp-fh->posStart);
@ -194,6 +211,7 @@ int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) {
return 0;
}
//Close the file.
void ICACHE_FLASH_ATTR espFsClose(EspFsFile *fh) {
if (fh==NULL) return;
#ifdef EFS_HEATSHRINK

@ -1,3 +1,4 @@
//Heatshrink config for the decompressor.
#ifndef HEATSHRINK_CONFIG_H
#define HEATSHRINK_CONFIG_H

@ -1,5 +1,16 @@
//Esp8266 http server - core routines
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "espmissingincludes.h"
#include "driver/uart.h"
#include "c_types.h"
#include "user_interface.h"
#include "espconn.h"
@ -11,7 +22,7 @@
#include "io.h"
#include "espfs.h"
//Max length of head (plus POST data)
//Max length of request head
#define MAX_HEAD_LEN 1024
//Max amount of connections
#define MAX_CONN 8
@ -41,6 +52,8 @@ typedef struct {
const char *mimetype;
} MimeMap;
//The mappings from file extensions to mime types. If you need an extra mime type,
//add it here.
static const MimeMap mimeTypes[]={
{"htm", "text/htm"},
{"html", "text/html"},
@ -49,9 +62,10 @@ static const MimeMap mimeTypes[]={
{"jpg", "image/jpeg"},
{"jpeg", "image/jpeg"},
{"png", "image/png"},
{NULL, "text/html"},
{NULL, "text/html"}, //default value
};
//Returns a static char* to a mime type for a given url to a file.
const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
int i=0;
//Go find the extension
@ -63,7 +77,7 @@ const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
return mimeTypes[i].mimetype;
}
//Looks up the connData info for a specific esp connection
static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) {
int i;
for (i=0; i<MAX_CONN; i++) {
@ -73,7 +87,7 @@ static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) {
return NULL; //WtF?
}
//Retires a connection for re-use
static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
if (conn->postBuff!=NULL) os_free(conn->postBuff);
conn->postBuff=NULL;
@ -81,6 +95,7 @@ static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
conn->conn=NULL;
}
//Stupid li'l helper function that returns the value of a hex char.
static int httpdHexVal(char c) {
if (c>='0' && c<='9') return c-'0';
if (c>='A' && c<='F') return c-'A'+10;
@ -88,7 +103,10 @@ static int httpdHexVal(char c) {
return 0;
}
//Decode a percent-encoded value
//Decode a percent-encoded value.
//Takes the valLen bytes stored in val, and converts it into at most retLen bytes that
//are stored in the ret buffer. Returns the actual amount of bytes used in ret. Also
//zero-terminates the ret buffer.
int httpdUrlDecode(char *val, int valLen, char *ret, int retLen) {
int s=0, d=0;
int esced=0, escVal=0;
@ -114,7 +132,9 @@ int httpdUrlDecode(char *val, int valLen, char *ret, int retLen) {
}
//Find a specific arg in a string of get- or post-data.
//Returns len of arg or -1 if not found.
//Line is the string of post/get-data, arg is the name of the value to find. The
//zero-terminated result is written in buff, with at most buffLen bytes used. The
//function returns the length of the result, or -1 if the value wasn't found.
int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLen) {
char *p, *e;
if (line==NULL) return 0;
@ -135,8 +155,8 @@ int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLe
return -1; //not found
}
static const char *httpNotFoundHeader="HTTP/1.0 404 Not Found\r\nServer: esp8266-httpd/0.1\r\nContent-Type: text/plain\r\n\r\nNot Found.\r\n";
//Start the response headers.
void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code) {
char buff[128];
int l;
@ -144,7 +164,7 @@ void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code) {
espconn_sent(conn->conn, (uint8 *)buff, l);
}
//Send a http header.
void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const char *val) {
char buff[256];
int l;
@ -152,6 +172,7 @@ void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const
espconn_sent(conn->conn, (uint8 *)buff, l);
}
//Finish the headers.
void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn) {
espconn_sent(conn->conn, (uint8 *)"\r\n", 2);
}
@ -193,6 +214,8 @@ static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) {
}
}
static const char *httpNotFoundHeader="HTTP/1.0 404 Not Found\r\nServer: esp8266-httpd/0.1\r\nContent-Type: text/plain\r\n\r\nNot Found.\r\n";
static void ICACHE_FLASH_ATTR httpdSendResp(HttpdConnData *conn) {
int i=0;
int r;

@ -26,10 +26,8 @@ struct HttpdConnData {
char *postBuff;
};
//A struct describing an url that's not in the filesystem or otherwise available.
//Also the way cgi functions get connected to an URL.
//A struct describing an url. This is the main struct that's used to send different URL requests to
//different routines.
typedef struct {
const char *url;
cgiSendCallback cgiCb;

@ -2,6 +2,15 @@
Connector to let httpd use the espfs filesystem to serve the files in that.
*/
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "espmissingincludes.h"
#include <string.h>
#include <osapi.h>
@ -15,6 +24,9 @@ Connector to let httpd use the espfs filesystem to serve the files in that.
#include "httpdespfs.h"
//This is a catch-all cgi function. It takes the url passed to it, looks up the corresponding
//path in the filesystem and if it exists, passes the file through. This simulates what a normal
//webserver would do with static files.
int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) {
EspFsFile *file=connData->cgiData;
int len;
@ -52,6 +64,8 @@ int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) {
}
//cgiEspFsTemplate can be used as a template.
typedef struct {
EspFsFile *file;
void *tplArg;

@ -1,3 +1,14 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "espmissingincludes.h"
#include "c_types.h"
#include "user_interface.h"

@ -1,30 +1,45 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#include "espmissingincludes.h"
#include "ets_sys.h"
#include "driver/uart.h"
#include "osapi.h"
#include "httpd.h"
#include "io.h"
#include "httpdespfs.h"
#include "cgi.h"
#include "cgiwifi.h"
#include "stdout.h"
HttpdBuiltInUrl builtInUrls[]={
{"/", cgiRedirect, "/test2.html"},
{"/flash.bin", cgiReadFlash, NULL},
{"/led.tpl", cgiEspFsTemplate, tplLed},
{"/led.cgi", cgiLed, NULL},
//Routines to make the /wifi URL and everything beneath it work.
{"/wifi", cgiRedirect, "/wifi/wifi.tpl"},
{"/wifi/", cgiRedirect, "/wifi/wifi.tpl"},
{"/wifi/wifiscan.cgi", cgiWiFiScan, NULL},
{"/wifi/wifi.tpl", cgiEspFsTemplate, tplWlan},
{"/wifi/connect.cgi", cgiWiFiConnect},
{"*", cgiEspFsHook, NULL},
{"*", cgiEspFsHook, NULL}, //Catch-all cgi function for the filesystem
{NULL, NULL, NULL}
};
void user_init(void) {
uart_init(BIT_RATE_115200, BIT_RATE_115200);
stdoutInit();
ioInit();
httpdInit(builtInUrls, 80);
os_printf("\nReady\n");

Loading…
Cancel
Save