Modularize esp8266 components

This commit is contained in:
con-f-use 2016-08-19 00:13:41 +02:00
parent 1dd31cc7c3
commit 63be61e225
42 changed files with 65 additions and 4026 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "embedded8266/esp82xx"]
path = embedded8266/esp82xx
url = git@github.com:cnlohr/esp82xx.git

View file

@ -1,31 +0,0 @@
*Note if you use the ESP8266 port, you are bound to this license as well as
the regular ColorChord license.* (Yes, I'm aware one is a BSD-based license
and the other is a MIT-based license, but this is not really a problem for
the ESP8266 as long as you follow the ColorChord license and only use it on
the ESP8266)
ESPRSSIF MIT License
Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
Portions Copyright (c) 2015 Charles Lohr
Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only,
in which case, it is free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1
embedded8266/LICENSE Symbolic link
View file

@ -0,0 +1 @@
esp82xx/LICENSE

View file

@ -1,79 +1,13 @@
include makeconf.inc # Look here for user configuration
include user.cfg
include esp82xx/common.mf
include esp82xx/main.mf
.PHONY : all clean cleanall netburn burnweb burn
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
TARGET = image.elf
FW_FILE1 = $(TARGET)-0x00000.bin
FW_FILE2 = $(TARGET)-0x40000.bin
SRCS = \
driver/uart.c \
common/mystuff.c \
common/flash_rewriter.c \
common/http.c \
common/http_custom.c \
common/mfs.c \
user/ws2812_i2s.c \
SRCS += user/ws2812_i2s.c \
user/hpatimer.c \
user/custom_commands.c \
driver/adc.c \
user/adc.c \
../embeddedcommon/DFT32.c \
../embeddedcommon/embeddednf.c \
../embeddedcommon/embeddedout.c \
user/user_main.c \
common/commonservices.c
../embeddedcommon/embeddedout.c
LIBS = main lwip ssl upgrade net80211 wpa net80211 phy lwip pp crypto
INCL = $(SDK)/include myclib include .
LDFLAGS_CORE += -Wl,-Map,output.map
CFLAGS = -mlongcalls -Os $(addprefix -I,$(INCL) $(call uniq, $(patsubst %/,%,$(dir $(SRCS))))) $(OPTS)
LDFLAGS_CORE = -nostdlib -L$(XTLIB) -L$(XTGCCLIB) \
$(addprefix $(SDK)/lib/lib,$(addsuffix .a,$(LIBS))) \
$(XTGCCLIB) -T $(SDK)/ld/eagle.app.v6.ld -Wl,-Map,output.map
# -flto -Wl,--relax -Wl,--gc-sections
LINKFLAGS = $(LDFLAGS_CORE) -B$(XTLIB)
##########################################################################RULES
all : $(FW_FILE1) $(FW_FILE2)
$(FW_FILE1) $(FW_FILE2) : $(TARGET)
@echo "FW $@"
export PATH="$(FOLDERPREFIX):$$PATH"; $(ESPTOOL_PY) elf2image $(TARGET)
$(TARGET) : $(SRCS)
$(CC) $(CFLAGS) $^ $(LINKFLAGS) -o $@
ifeq ($(CHIP), 8285)
burn : $(FW_FILE1) $(FW_FILE2)
($(ESPTOOL_PY) --port $(PORT) write_flash -fs 8m -fm dout 0x00000 $(FW_FILE1) 0x40000 $(FW_FILE2))||(true)
else ifeq ($(CHIP), 8266)
burn : $(FW_FILE1) $(FW_FILE2)
($(ESPTOOL_PY) --port $(PORT) write_flash 0x00000 $(FW_FILE1) 0x40000 $(FW_FILE2))||(true)
else
$(error Error: Unknown chip '$(CHIP)')
endif
burnweb :
@cd web && $(MAKE) $(MFLAGS) $(MAKEOVERRIDES) page.mpfs
($(ESPTOOL_PY) --port $(PORT) write_flash 0x10000 web/page.mpfs)||(true)
#If you have space, MFS should live at 0x100000. It can also live at
#0x10000. But, then it is limited to 180kB. You might need to do this if
# you have a 512kB ESP variant.
netburn : $(FW_FILE1) $(FW_FILE2)
@cd web && $(MAKE) $(MFLAGS) $(MAKEOVERRIDES) execute_reflash
web/execute_reflash $(IP) $(FW_FILE1) $(FW_FILE2)
netweb :
@cd web && $(MAKE) $(MFLAGS) $(MAKEOVERRIDES) push
clean :
$(RM) $(patsubst %.c,%.o,$(SRCS)) $(TARGET)
purge : clean
@cd web && $(MAKE) $(MFLAGS) $(MAKEOVERRIDES) clean
$(RM) $(FW_FILE1) $(FW_FILE2)

View file

@ -1,7 +1,7 @@
#ifndef _CCCONFIG_H
#define _CCCONFIG_H
#include "c_types.h"
#include <c_types.h>
#define HPABUFFSIZE 512

View file

@ -1,629 +0,0 @@
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
// ColorChord License. You Choose.
#include "commonservices.h"
#include "mem.h"
#include "c_types.h"
#include "user_interface.h"
#include "ets_sys.h"
#include "osapi.h"
#include "espconn.h"
#include "mystuff.h"
#include "ip_addr.h"
#include "http.h"
#include "spi_flash.h"
#include "esp8266_rom.h"
#include <gpio.h>
#include "flash_rewriter.h"
static struct espconn *pUdpServer;
static struct espconn *pHTTPServer;
struct espconn *pespconn;
uint16_t g_gpiooutputmask = 0;
int ets_str2macaddr(void *, void *);
static int need_to_switch_back_to_soft_ap = 0; //0 = no, 1 = will need to. 2 = do it now.
#define MAX_STATIONS 20
struct totalscan_t
{
char name[32];
char mac[18]; //string
int8_t rssi;
uint8_t channel;
uint8_t encryption;
} totalscan[MAX_STATIONS];
int scanplace = 0;
static void ICACHE_FLASH_ATTR scandone(void *arg, STATUS status)
{
scaninfo *c = arg;
struct bss_info *inf;
if( need_to_switch_back_to_soft_ap == 1 )
need_to_switch_back_to_soft_ap = 2;
printf("!%p\n",c->pbss);
if (!c->pbss) {
scanplace = -1;
return;
}
// printf("!%s\n",inf->ssid);
STAILQ_FOREACH(inf, c->pbss, next) {
printf( "%s\n", inf->ssid );
ets_memcpy( totalscan[scanplace].name, inf->ssid, 32 );
ets_sprintf( totalscan[scanplace].mac, MACSTR, MAC2STR( inf->bssid ) );
//ets_memcpy( totalscan[scanplace].mac, "not implemented", 16 );
totalscan[scanplace].rssi = inf->rssi;
totalscan[scanplace].channel = inf->channel;
totalscan[scanplace].encryption = inf->authmode;
inf = (struct bss_info *) &inf->next;
scanplace++;
if( scanplace == MAX_STATIONS ) break;
}
}
int ICACHE_FLASH_ATTR issue_command(char * buffer, int retsize, char *pusrdata, unsigned short len)
{
char * buffend = buffer;
pusrdata[len] = 0;
switch( pusrdata[0] )
{
case 'e': case 'E': //Echo
if( retsize > len )
{
ets_memcpy( buffend, pusrdata, len );
return len;
}
else
{
return -1;
}
case 'f': case 'F': //Flashing commands (F_)
{
flashchip->chip_size = 0x01000000;
const char * colon = (const char *) ets_strstr( (char*)&pusrdata[2], "\t" );
int nr = my_atoi( &pusrdata[2] );
switch (pusrdata[1])
{
case 'e': case 'E': //(FE#\n) <- # = sector.
{
if( nr < 16 )
{
buffend += ets_sprintf(buffend, "!FE%d\r\n", nr );
break;
}
EnterCritical();
spi_flash_erase_sector( nr ); //SPI_FLASH_SEC_SIZE 4096
ExitCritical();
buffend += ets_sprintf(buffend, "FE%d\r\n", nr );
break;
}
case 'b': case 'B': //(FB#\n) <- # = block.
{
if( nr < 1 ) //Not allowed to erase boot sector.
{
buffend += ets_sprintf(buffend, "!FB%d\r\n", nr );
break;
}
EnterCritical();
SPIEraseBlock( nr );
ExitCritical();
buffend += ets_sprintf(buffend, "FB%d\r\n", nr );
break;
}
case 'm': case 'M': //Execute the flash re-writer
{
int r = (*GlobalRewriteFlash)( &pusrdata[2], len-2 );
buffend += ets_sprintf( buffend, "!FM%d\r\n", r );
break;
}
case 'w': case 'W': //Flash Write (FW#\n) <- # = byte pos. Reads until end-of-packet.
if( colon )
{
colon++;
const char * colon2 = (const char *) ets_strstr( (char*)colon, "\t" );
if( colon2 && nr >= 65536)
{
colon2++;
int datlen = (int)len - (colon2 - pusrdata);
ets_memcpy( buffer, colon2, datlen );
EnterCritical();
spi_flash_write( nr, (uint32*)buffer, (datlen/4)*4 );
ExitCritical();
#ifdef VERIFY_FLASH_WRITE
#define VFW_SIZE 128
printf( "FW%d\r\n", nr );
int jj;
uint8_t __attribute__ ((aligned (32))) buf[VFW_SIZE];
for(jj=0; jj<datlen; jj+=VFW_SIZE) {
spi_flash_read( nr+jj, (uint32*)buf, VFW_SIZE );
if( ets_memcmp( buf, buffer+jj, jj+VFW_SIZE>datlen ? datlen%VFW_SIZE : VFW_SIZE ) != 0 ) goto failw;
}
#endif
buffend += ets_sprintf(buffend, "FW%d\r\n", nr );
break;
}
}
failw:
buffend += ets_sprintf(buffend, "!FW\r\n" );
break;
case 'x': case 'X': //Flash Write Hex (FX#\t#\tDATTAAAAA) <- a = byte pos. b = length (in hex-pairs). Generally used for web-browser.
if( colon )
{
int i;
int siz = 0;
colon++;
char * colon2 = (char *) ets_strstr( (char*)colon, "\t" );
if( colon2 )
{
*colon2 = 0;
siz = my_atoi( colon );
}
//nr = place to write.
//siz = size to write.
//colon2 = data start.
if( colon2 && nr >= 524288)
{
colon2++;
int datlen = ((int)len - (colon2 - pusrdata))/2;
if( datlen > siz ) datlen = siz;
for( i = 0; i < datlen; i++ )
{
int8_t r1 = fromhex1( *(colon2++) );
int8_t r2 = fromhex1( *(colon2++) );
if( r1 == -1 || r2 == -1 ) goto failfx;
buffend[i] = (r1 << 4) | r2;
}
//ets_memcpy( buffer, colon2, datlen );
EnterCritical();
spi_flash_write( nr, (uint32*)buffend, (datlen/4)*4 );
ExitCritical();
#ifdef VERIFY_FLASH_WRITE
// uint8_t __attribute__ ((aligned (32))) buf[1300];
// spi_flash_read( nr, (uint32*)buf, (datlen/4)*4 );
// if( ets_memcmp( buf, buffer, (datlen/4)*4 ) != 0 ) break;
// Rather do it in chunks, to avoid allocationg huge buf
#define VFW_SIZE 128
printf( "FW%d\r\n", nr );
int jj;
uint8_t __attribute__ ((aligned (32))) buf[VFW_SIZE];
for(jj=0; jj<datlen; jj+=VFW_SIZE) {
spi_flash_read( nr+jj, (uint32*)buf, VFW_SIZE );
if( ets_memcmp( buf, buffer+jj, jj+VFW_SIZE>datlen ? datlen%VFW_SIZE : VFW_SIZE ) != 0 ) goto failfx;
}
#endif
buffend += ets_sprintf(buffend, "FX%d\t%d\r\n", nr, siz );
break;
}
}
failfx:
buffend += ets_sprintf(buffend, "!FX\r\n" );
break;
case 'r': case 'R': //Flash Read (FR#\n) <- # = sector.
if( colon )
{
colon++;
int datlen = my_atoi( colon );
datlen = (datlen/4)*4; //Must be multiple of 4 bytes
if( datlen <= 1280 )
{
buffend += ets_sprintf(buffend, "FR%08d\t%04d\t", nr, datlen ); //Caution: This string must be a multiple of 4 bytes.
spi_flash_read( nr, (uint32*)buffend, datlen );
buffend += datlen;
break;
}
}
buffend += ets_sprintf(buffend, "!FR\r\n" );
break;
}
flashchip->chip_size = 0x00080000;
return buffend - buffer;
}
case 'i': case 'I': //Respond with device info.
{
buffend += ets_sprintf(buffend, "I" );
int i;
for( i = 0; i < 2 ;i++ )
{
struct ip_info ipi;
wifi_get_ip_info( i, &ipi );
buffend += ets_sprintf(buffend, "\t"IPSTR, IP2STR(&ipi.ip) );
}
buffend += ets_sprintf(buffend, "\r\n" );
return buffend - buffer;
}
case 'w': case 'W': // (W1:SSID:PASSWORD) (To connect) or (W2) to be own base station. ...or WI, to get info... or WS to scan.
{
int c1l = 0;
int c2l = 0;
char * colon = (char *) ets_strstr( (char*)&pusrdata[2], "\t" );
char * colon2 = (colon)?((char *)ets_strstr( (char*)(colon+1), "\t" )):0;
char * colon3 = (colon2)?((char *)ets_strstr( (char*)(colon2+1), "\t" )):0;
char * colon4 = (colon3)?((char *)ets_strstr( (char*)(colon3+1), "\t" )):0;
char * extra = colon2;
char mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
int bssid_set = 0;
if( colon ) { *colon = 0; colon++; }
if( colon2 ) { *colon2 = 0; colon2++; }
if( colon3 ) { *colon3 = 0; colon3++; }
if( colon4 ) { *colon4 = 0; colon4++; }
if( colon ) { c1l = ets_strlen( colon ); }
if( colon2 ) { c2l = ets_strlen( colon2 ); }
if( colon3 )
{
bssid_set = ets_str2macaddr( mac, colon3 )?1:0;
if( ( mac[0] == 0x00 || mac[0] == 0xff ) &&
( mac[1] == 0x00 || mac[1] == 0xff ) &&
( mac[2] == 0x00 || mac[2] == 0xff ) &&
( mac[3] == 0x00 || mac[3] == 0xff ) &&
( mac[4] == 0x00 || mac[4] == 0xff ) &&
( mac[5] == 0x00 || mac[5] == 0xff ) ) bssid_set = 0;
}
if( extra )
{
for( ; *extra; extra++ )
{
if( *extra < 32 )
{
*extra = 0;
break;
}
}
}
switch (pusrdata[1])
{
case '1': //Station mode
case '2': //AP Mode
if( colon && colon2 && ets_strlen( colon ) > 1 )
{
if( c1l > 31 ) c1l = 31;
if( c2l > 63 ) c2l = 63;
printf( "Switching to: \"%s\"/\"%s\" (%d/%d). BSSID_SET: %d [%c]\n", colon, colon2, c1l, c2l, bssid_set, pusrdata[1] );
if( pusrdata[1] == '1' )
{
struct station_config stationConf;
wifi_station_get_config(&stationConf);
os_memcpy(&stationConf.ssid, colon, c1l);
os_memcpy(&stationConf.password, colon2, c2l);
stationConf.ssid[c1l] = 0;
stationConf.password[c2l] = 0;
stationConf.bssid_set = bssid_set;
os_memcpy( stationConf.bssid, mac, 6 );
printf( "-->'%s'\n",stationConf.ssid);
printf( "-->'%s'\n",stationConf.password);
EnterCritical();
// wifi_station_set_config(&stationConf);
wifi_set_opmode( 1 );
wifi_station_set_config(&stationConf);
wifi_station_connect();
ExitCritical();
// wifi_station_get_config( &stationConf );
buffend += ets_sprintf( buffend, "W1\r\n" );
printf( "Switching.\n" );
}
else
{
struct softap_config config;
char macaddr[6];
wifi_softap_get_config( &config );
wifi_get_macaddr(SOFTAP_IF, macaddr);
os_memcpy( &config.ssid, colon, c1l );
os_memcpy( &config.password, colon2, c2l );
config.ssid_len = c1l;
#if 0 //We don't support encryption.
config.ssid[c1l] = 0;
config.password[c2l] = 0;
config.authmode = 0;
if( colon3 )
{
int k;
for( k = 0; enctypes[k]; k++ )
{
if( strcmp( colon3, enctypes[k] ) == 0 )
config.authmode = k;
}
}
#endif
int chan = (colon4)?my_atoi(colon4):config.channel;
if( chan == 0 || chan > 13 ) chan = 1;
config.channel = chan;
// printf( "Mode now. %s %s %d %d %d %d %d\n", config.ssid, config.password, config.ssid_len, config.channel, config.authmode, config.max_connection );
// printf( "Mode Set. %d\n", wifi_get_opmode() );
EnterCritical();
wifi_softap_set_config(&config);
wifi_set_opmode( 2 );
ExitCritical();
printf( "Switching SoftAP: %d %d.\n", chan, config.authmode );
buffend += ets_sprintf( buffend, "W2\r\n" );
}
}
break;
case 'I':
{
char macmap[15];
int mode = wifi_get_opmode();
buffend += ets_sprintf( buffend, "WI%d", mode );
if( mode == 2 )
{
uint8_t mac[6];
struct softap_config ap;
wifi_softap_get_config( &ap );
wifi_get_macaddr( 1, mac );
ets_sprintf( macmap, MACSTR, MAC2STR( mac ) );
buffend += ets_sprintf( buffend, "\t%s\t%s\t%s\t%d", ap.ssid, ap.password, macmap, ap.channel );
}
else
{
struct station_config sc;
ets_memset( &sc, 0, sizeof( sc ) );
wifi_station_get_config( &sc );
if( sc.bssid_set )
ets_sprintf( macmap, MACSTR, MAC2STR( sc.bssid ) );
else
macmap[0] = 0;
buffend += ets_sprintf( buffend, "\t%s\t%s\t%s\t%d", sc.ssid, sc.password, macmap, wifi_get_channel() );
}
}
break;
case 'X': case 'x':
{
int rssi = wifi_station_get_rssi();
if( rssi >= 0 )
{
buffend += ets_sprintf( buffend, "WX-" );
}
else
{
buffend += ets_sprintf( buffend, "WX%d", wifi_station_get_rssi() );
}
break;
}
case 'S': case 's':
{
int i, r;
struct scan_config sc;
scanplace = 0;
sc.ssid = 0;
sc.bssid = 0;
sc.channel = 0;
sc.show_hidden = 1;
EnterCritical();
if( wifi_get_opmode() == SOFTAP_MODE )
{
wifi_set_opmode_current( STATION_MODE );
need_to_switch_back_to_soft_ap = 1;
}
r = wifi_station_scan(&sc, scandone );
ExitCritical();
buffend += ets_sprintf( buffend, "WS%d\n", r );
uart0_sendStr(buffer);
break;
}
break;
case 'R': case 'r':
{
int i, r;
buffend += ets_sprintf( buffend, "WR%d\n", scanplace );
for( i = 0; i < scanplace && buffend - buffer < retsize - 64; i++ )
{
buffend += ets_sprintf( buffend, "#%s\t%s\t%d\t%d\t%s\n",
totalscan[i].name, totalscan[i].mac, totalscan[i].rssi, totalscan[i].channel, enctypes[totalscan[i].encryption] );
}
break;
}
break;
}
return buffend - buffer;
}
case 'G': case 'g':
{
static const uint32_t AFMapper[16] = {
0, PERIPHS_IO_MUX_U0TXD_U, 0, PERIPHS_IO_MUX_U0RXD_U,
0, 0, 1, 1,
1, 1, 1, 1,
PERIPHS_IO_MUX_MTDI_U, PERIPHS_IO_MUX_MTCK_U, PERIPHS_IO_MUX_MTMS_U, PERIPHS_IO_MUX_MTDO_U };
int nr = my_atoi( &pusrdata[2] );
if( AFMapper[nr] == 1 )
{
buffend += ets_sprintf( buffend, "!G%c%d\n", pusrdata[1], nr );
return buffend - buffer;
}
else if( AFMapper[nr] )
{
PIN_FUNC_SELECT( AFMapper[nr], 3); //Select AF pin to be GPIO.
}
switch( pusrdata[1] )
{
case '0':
case '1':
GPIO_OUTPUT_SET(GPIO_ID_PIN(nr), pusrdata[1]-'0' );
buffend += ets_sprintf( buffend, "G%c%d", pusrdata[1], nr );
g_gpiooutputmask |= (1<<nr);
break;
case 'i': case 'I':
GPIO_DIS_OUTPUT(GPIO_ID_PIN(nr));
buffend += ets_sprintf( buffend, "GI%d\n", nr );
g_gpiooutputmask &= ~(1<<nr);
break;
case 'f': case 'F':
{
int on = GPIO_INPUT_GET( GPIO_ID_PIN(nr) );
on = !on;
GPIO_OUTPUT_SET(GPIO_ID_PIN(nr), on );
g_gpiooutputmask |= (1<<nr);
buffend += ets_sprintf( buffend, "GF%d\t%d\n", nr, on );
break;
}
case 'g': case 'G':
buffend += ets_sprintf( buffend, "GG%d\t%d\n", nr, GPIO_INPUT_GET( GPIO_ID_PIN(nr) ) );
break;
case 's': case 'S':
{
uint32_t rmask = 0;
int i;
for( i = 0; i < 16; i++ )
{
rmask |= GPIO_INPUT_GET( GPIO_ID_PIN(i) )?(1<<i):0;
}
buffend += ets_sprintf( buffend, "GS\t%d\t%d\n", g_gpiooutputmask, rmask );
break;
}
}
return buffend - buffer;
}
case 'c': case 'C':
return CustomCommand( buffer, retsize, pusrdata, len);
}
return -1;
}
void ICACHE_FLASH_ATTR issue_command_udp(void *arg, char *pusrdata, unsigned short len)
{
char __attribute__ ((aligned (32))) retbuf[1300];
int r = issue_command( retbuf, 1300, pusrdata, len );
if( r > 0 )
{
//YUCK! Since SDK 1.4.0, we have to do this ridiculous thing to respond to senders.
struct espconn * rc = (struct espconn *)arg;
remot_info * ri = 0;
espconn_get_connection_info( rc, &ri, 0);
ets_memcpy( rc->proto.udp->remote_ip, ri->remote_ip, 4 );
rc->proto.udp->remote_port = ri->remote_port;
espconn_sendto( rc, retbuf, r );
}
}
void ICACHE_FLASH_ATTR CSPreInit()
{
int opmode = wifi_get_opmode();
printf( "Opmode: %d\n", opmode );
if( opmode == 1 )
{
struct station_config sc;
wifi_station_get_config(&sc);
printf( "Station mode: \"%s\":\"%s\" (bssid_set:%d)\n", sc.ssid, sc.password, sc.bssid_set );
if( sc.ssid[0] == 0 && !sc.bssid_set )
{
wifi_set_opmode( 2 );
opmode = 2;
}
else
{
wifi_station_connect();
}
}
if( opmode == 2 )
{
struct softap_config sc;
wifi_softap_get_config(&sc);
printf( "SoftAP mode: \"%s\":\"%s\"\n", sc.ssid, sc.password );
}
}
void ICACHE_FLASH_ATTR CSInit()
{
pUdpServer = (struct espconn *)os_zalloc(sizeof(struct espconn));
ets_memset( pUdpServer, 0, sizeof( struct espconn ) );
pUdpServer->type = ESPCONN_UDP;
pUdpServer->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
pUdpServer->proto.udp->local_port = 7878;
espconn_regist_recvcb(pUdpServer, issue_command_udp);
espconn_create( pUdpServer );
pHTTPServer = (struct espconn *)os_zalloc(sizeof(struct espconn));
ets_memset( pHTTPServer, 0, sizeof( struct espconn ) );
espconn_create( pHTTPServer );
pHTTPServer->type = ESPCONN_TCP;
pHTTPServer->state = ESPCONN_NONE;
pHTTPServer->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
pHTTPServer->proto.tcp->local_port = 80;
espconn_regist_connectcb(pHTTPServer, httpserver_connectcb);
espconn_accept(pHTTPServer);
espconn_regist_time(pHTTPServer, 15, 0); //timeout
}
void ICACHE_FLASH_ATTR CSTick( int slowtick )
{
static uint8_t tick_flag = 0;
if( slowtick )
{
tick_flag = 1;
return;
}
if( need_to_switch_back_to_soft_ap == 2 )
{
need_to_switch_back_to_soft_ap = 0;
EnterCritical();
wifi_set_opmode_current( SOFTAP_MODE );
ExitCritical();
}
HTTPTick(0);
//TRICKY! If we use the timer to initiate this, connecting to people's networks
//won't work! I don't know why, so I do it here. this does mean sometimes it'll
//pause, though.
if( tick_flag )
{
tick_flag = 0;
HTTPTick(1);
}
}

View file

@ -1,30 +0,0 @@
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
// ColorChord License. You Choose.
#ifndef _COMMON_H
#define _COMMON_H
#include "c_types.h"
//Returns nr bytes to return. You must allocate retdata.
//It MUST be at least 1,300 bytes large and it MUST be 32-bit aligned.
//NOTE: It is SAFE to use pusrdata and retdata as the same buffer.
int ICACHE_FLASH_ATTR issue_command(char * retdata, int retsize, char *pusrdata, unsigned short len);
//Includes UDP Control + HTTP Interfaces
void ICACHE_FLASH_ATTR CSPreInit();
void ICACHE_FLASH_ATTR CSInit();
void ICACHE_FLASH_ATTR CSTick( int slowtick );
//You must provide:
//Critical should not lock interrupts, just disable services that have problems
//with double-interrupt faults. I.e. turn off/on any really fast timer interrupts.
//These generally only get called when doing serious operations like reflashing.
void EnterCritical();
void ExitCritical();
//If we receive a command that's not F, E or W (Flash Echo Wifi)
int ICACHE_FLASH_ATTR CustomCommand(char * buffer, int retsize, char *pusrdata, unsigned short len);
#endif

View file

@ -1,92 +0,0 @@
#ifndef _ESP8266_ROM_FUNCTS
#define _ESP8266_ROM_FUNCTS
//This is my best guess at some of the ROM functions for the ESP8266.
//I have no idea if this stuff is correct!
#include <spi_flash.h>
#include <c_types.h>
void Cache_Read_Disable(); //Can't seem to operate...
void Cache_Read_Enable();
//PROVIDE ( Cache_Read_Disable = 0x400047f0 );
//PROVIDE ( Cache_Read_Enable = 0x40004678 );
typedef struct {
uint32_t i[2];
uint32_t buf[4];
unsigned char in[64];
unsigned char digest[16];
} MD5_CTX;
void MD5Init ( MD5_CTX *mdContext);
void MD5Update( MD5_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen);
void MD5Final ( unsigned char hash[], MD5_CTX *mdContext);
//SHA Stuff from: https://github.com/pvvx/esp8266web/blob/master/app/include/bios/cha1.h
#define SHA1_HASH_LEN 20
typedef struct {
uint32 state[5];
uint32 count[2];
uint8 buffer[64];
uint8 extra[40];
} SHA1_CTX;
void SHA1Init(SHA1_CTX* context);
void SHA1Update(SHA1_CTX* context,
const uint8 *data,
size_t len);
void SHA1Final(uint8 digest[SHA1_HASH_LEN], SHA1_CTX* context);
void SHA1Transform(uint32 state[5], const uint8 buffer[64]);
//SPI_FLASH_SEC_SIZE 4096
void SPIEraseSector(uint16 sec);
void SPIEraseArea(uint32 start,uint32 len); //Doesn't work?
void SPIEraseBlock(uint16 blk);
void SPIWrite(uint32 des_addr, uint32_t *src_addr, uint32_t size);
void SPIRead(uint32 src_addr, uint32_t *des_addr, uint16_t size);
void SPILock( uint16_t sec ); //??? I don't use this?
void SPIUnlock( ); //??? I don't use this? -> Seems to crash.
extern SpiFlashChip * flashchip; //don't forget: flashchip->chip_size = 0x01000000;
/*
flashchip->chip_size = 0x01000000;
{
uint32_t __attribute__ ((aligned (16))) t[1024];
t[0] = 0xAABBCCDD;
t[1] = 0xEEFF0011;
for( i = 0; i < 10000; i++ ) uart0_sendStr("A\n");
SPIEraseSector( 1000000/4096 );
for( i = 0; i < 10000; i++ ) uart0_sendStr("B\n");
SPIWrite( 1000000, t, 8 );
}
for( i = 0; i < 10000; i++ ) uart0_sendStr("C\n");
while(1)
{
char ct[32];
uint32_t __attribute__ ((aligned (16))) ret = 0x12345678;
// SPIRead( 1000000, &ret, 4 );
ret = *(uint32_t*)(0x40200000+1000004);
ets_sprintf( ct, "%08x\n", ret );
printf( ct );
}
*/
void software_reset();
#endif

View file

@ -1,285 +0,0 @@
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
// ColorChord License. You Choose.
#include "flash_rewriter.h"
#include <c_types.h>
#include <esp8266_rom.h>
#include <stdio.h>
#define SRCSIZE 4096
#define BLKSIZE 65536
static const char * key = "";
static int keylen = 0;
static int MyRewriteFlash( char * command, int commandlen )
{
MD5_CTX md5ctx;
char __attribute__ ((aligned (32))) buffer[512];
char * colons[8];
int i, ipl = 0;
int p;
//[from_address]\t[to_address]\t[size]\t[MD5(key+data)]\t[from_address]\t[to_address]\t[size]\t[MD5(key+data)]
command[commandlen] = 0;
flashchip->chip_size = 0x01000000;
ets_wdt_disable();
colons[ipl++] = &command[0];
for( i = 0; i < commandlen; i++ )
{
if( command[i] == 0 ) break;
if( command[i] == '\t' )
{
if( ipl >= 8 ) break;
command[i] = 0;
colons[ipl++] = &command[i+1];
}
}
if( ipl != 8 )
{
return 1;
}
uint32_t from1 = my_atoi( colons[0] );
uint32_t to1 = my_atoi( colons[1] );
int32_t size1 = my_atoi( colons[2] );
char * md51 = colons[3];
char md5h1raw[48];
char md5h1[48];
uint32_t from2 = my_atoi( colons[4] );
uint32_t to2 = my_atoi( colons[5] );
int32_t size2 = my_atoi( colons[6] );
char * md52 = colons[7];
char md5h2raw[48];
char md5h2[48];
if( from1 == 0 || from2 == 0 || size1 == 0 )
{
return 2;
}
if( ( from1 & 0xfff ) || ( from2 & 0xfff ) || ( to1 & 0xfff ) || ( to2 & 0xfff ) )
{
return 3;
}
///////////////////////////////
char st[400];
/*
ets_sprintf( st, "!!%08x", (((uint32_t*)(0x40200000 + from1))) );
uart0_sendStr( st );
for( i = 0; i < 200; i++ )
{
ets_sprintf( st, "%08x", (uint32_t)(((uint32_t*)(0x40200000 + from1))[i]) );
uart0_sendStr( st );
}
uart0_sendStr( "+\n" );
/*
uint32_t __attribute__ ((aligned (32))) readr = 0xAAAAAAAA;
SPIRead( from1, &readr, 4 );
ets_sprintf( st, ":%08x\n", readr );
uart0_sendStr( st );
readr = 0x12345678;
SPIRead( from1+4, &readr, 4 );
ets_sprintf( st, ":%08x\n", readr );
uart0_sendStr( st );
uart0_sendStr( "\n" );
ets_sprintf( st, "TT: %08x ADDY: %08x\n", from1, &readr );
uart0_sendStr( st );
readr = 0xAAAAAAAA;
spi_flash_read( from1, &readr, 4 );
ets_sprintf( st, "+%08x\n", readr );
uart0_sendStr( st );
readr = 0xbbbbbbbb;
spi_flash_read( from1+4, &readr, 4 );
ets_sprintf( st, "+%08x\n", readr );
uart0_sendStr( st );
*/
/*
MD5Init( &md5ctx );
MD5Update( &md5ctx, (uint8_t*)0x40200000 + from1, 4 );
MD5Final( md5h1raw, &md5ctx );
for( i = 0; i < 16; i++ )
{
ets_sprintf( md5h1+i*2, "%02x", md5h1raw[i] );
}
uart0_sendStr( "Hash 1:" );
uart0_sendStr( md5h1 );
uart0_sendStr( "!\n" );
*/
//////////////////////////////
ets_sprintf( st, "Computing Hash 1: %08x size %d\n", from1, size1 );
uart0_sendStr( st );
MD5Init( &md5ctx );
if( keylen )
MD5Update( &md5ctx, key, keylen );
// MD5Update( &md5ctx, (uint8_t*)0x40200000 + from1, size1 );
SafeMD5Update( &md5ctx, (uint8_t*)0x40200000 + from1, size1 );
MD5Final( md5h1raw, &md5ctx );
for( i = 0; i < 16; i++ )
{
ets_sprintf( md5h1+i*2, "%02x", md5h1raw[i] );
}
uart0_sendStr( "Hash 1:" );
uart0_sendStr( md5h1 );
uart0_sendStr( "\n" );
for( i = 0; i < 32; i++ )
{
if( md5h1[i] != md51[i] )
{
//printf( "%s != %s", md5h1, md51 );
uart0_sendStr( "File 1 MD5 mismatch\nActual:" );
uart0_sendStr( md5h1 );
uart0_sendStr( "\nExpected:" );
uart0_sendStr( md51 );
uart0_sendStr( "\n" );
return 4;
}
}
ets_sprintf( st, "Computing Hash 2: %08x size %d\n", from2, size2 );
uart0_sendStr( st );
MD5Init( &md5ctx );
if( keylen )
MD5Update( &md5ctx, key, keylen );
SafeMD5Update( &md5ctx, (uint8_t*)0x40200000 + from2, size2 );
MD5Final( md5h2raw, &md5ctx );
for( i = 0; i < 16; i++ )
{
ets_sprintf( md5h2+i*2, "%02x", md5h2raw[i] );
}
uart0_sendStr( "Hash 2:" );
uart0_sendStr( md5h2 );
uart0_sendStr( "\n" );
/* for( i = 0; i <= size2/4; i++ )
{
uint32_t j = ((uint32_t*)(0x40200000 + from2))[i];
ets_sprintf( st, "%02x%02x%02x%02x\n", (uint8_t)(j>>0), (uint8_t)(j>>8), (uint8_t)(j>>16), (uint8_t)(j>>24) );
uart0_sendStr( st );
}*/
for( i = 0; i < 32; i++ )
{
if( md5h2[i] != md52[i] )
{
uart0_sendStr( "File 2 MD5 mismatch\nActual:" );
uart0_sendStr( md5h2 );
uart0_sendStr( "\nExpected:" );
uart0_sendStr( md52 );
uart0_sendStr( "\n" );
return 5;
}
}
//Need to round sizes up.
size1 = ((size1-1)&(~0xfff))+1;
size2 = ((size2-1)&(~0xfff))+1;
ets_sprintf( st, "Copy 1: %08x to %08x, size %d\n", from1, to1, size1 );
uart0_sendStr( st );
ets_sprintf( st, "Copy 2: %08x to %08x, size %d\n", from2, to2, size2 );
uart0_sendStr( st );
//Everything checked out... Need to move the flashes.
ets_delay_us( 1000 );
//Disable all interrupts.
ets_intr_lock();
uart_tx_one_char( 'A' );
int j;
ipl = (size1/BLKSIZE)+1;
p = to1/BLKSIZE;
for( i = 0; i < ipl; i++ )
{
SPIEraseBlock( p++ );
for( j = 0; j < BLKSIZE/SRCSIZE; j++ )
{
SPIWrite( to1, (uint32_t*)(0x40200000 + from1), SRCSIZE );
to1 += SRCSIZE;
from1 += SRCSIZE;
}
}
uart_tx_one_char( 'B' );
ipl = (size2/BLKSIZE)+1;
p = to2/BLKSIZE;
for( i = 0; i < ipl; i++ )
{
SPIEraseBlock( p++ );
for( j = 0; j < BLKSIZE/SRCSIZE; j++ )
{
SPIWrite( to2, (uint32_t*)(0x40200000 + from2), SRCSIZE );
to2 += SRCSIZE;
from2 += SRCSIZE;
}
}
uart_tx_one_char( 'C' );
void(*rebootme)() = (void(*)())0x40000080;
rebootme();
// system_upgrade_reboot();
// software_reset(); //Doesn't seem to boot back in.
//Destinations are erased. Copy over the other part.
// for( i = 0; i < ; i++ )
/*Things I know:
flashchip->chip_size = 0x01000000;
SPIEraseSector( 1000000/4096 );
SPIWrite( 1000000, &t, 4 ); <<This looks right.
SPIRead( 1000000, &t, 4 ); <<Will read if we just wrote, but not from cache.
uint32_t * v = (uint32_t*)(0x40200000 + 1000000); //This will read, but from cache.
//Looks like you can copy this way...
// SPIWrite( 1000004, 0x40200000 + 1000000, 4 );
*/
/*
MD5Init( &c );
MD5Update( &c, "apple", 5 );
MD5Final( hash, &c );*/
//Once we hit this stage we cannot do too much, otherwise we'll cause major crashing.
}
int (*GlobalRewriteFlash)( char * command, int commandlen ) = MyRewriteFlash;

View file

@ -1,20 +0,0 @@
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
// ColorChord License. You Choose.
#ifndef _FLASH_REWRITER_H
#define _FLASH_REWRITER_H
//Unusual, but guarentees that the code resides in IRAM.
/*
Usage:
[from_address]:[to_address]:[size]:[MD5(key+data)]:[from_address]:[to_address]:[size]:[MD5(key+data)][extra byte required]
NOTE: YOU MUST USE 4096-byte-aligned boundaries.
Note: this will modify the text in "command"
*/
extern int (*GlobalRewriteFlash)( char * command, int commandlen );
#endif

View file

@ -1,625 +0,0 @@
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
// ColorChord License. You Choose.
#include "http.h"
#include "mystuff.h"
#include "esp8266_rom.h"
#define HTDEBUG( x... ) printf( x )
//#define ISKEEPALIVE "keep-alive"
#define ISKEEPALIVE "close"
struct HTTPConnection HTTPConnections[HTTP_CONNECTIONS];
struct HTTPConnection * curhttp;
uint8 * curdata;
uint16 curlen;
uint8 wsmask[4];
uint8 wsmaskplace;
ICACHE_FLASH_ATTR void InternalStartHTTP( );
ICACHE_FLASH_ATTR void HTTPHandleInternalCallback( );
ICACHE_FLASH_ATTR void HTTPClose( )
{
//This is dead code, but it is a testament to Charles.
//Do not do this here. Wait for the ESP to tell us the
//socket is successfully closed.
//curhttp->state = HTTP_STATE_NONE;
curhttp->state = HTTP_WAIT_CLOSE;
espconn_disconnect( curhttp->socket );
}
void ICACHE_FLASH_ATTR HTTPGotData( )
{
uint8 c;
curhttp->timeout = 0;
while( curlen-- )
{
c = HTTPPOP;
// sendhex2( h->state ); sendchr( ' ' );
switch( curhttp->state )
{
case HTTP_STATE_WAIT_METHOD:
if( c == ' ' )
{
curhttp->state = HTTP_STATE_WAIT_PATH;
curhttp->state_deets = 0;
}
break;
case HTTP_STATE_WAIT_PATH:
curhttp->pathbuffer[curhttp->state_deets++] = c;
if( curhttp->state_deets == MAX_PATHLEN )
{
curhttp->state_deets--;
}
if( c == ' ' )
{
//Tricky: If we're a websocket, we need the whole header.
curhttp->pathbuffer[curhttp->state_deets-1] = 0;
curhttp->state_deets = 0;
if( strncmp( (const char*)curhttp->pathbuffer, "/d/ws", 5 ) == 0 )
{
curhttp->state = HTTP_STATE_DATA_WEBSOCKET;
curhttp->state_deets = 0;
}
else
{
curhttp->state = HTTP_STATE_WAIT_PROTO;
}
}
break;
case HTTP_STATE_WAIT_PROTO:
if( c == '\n' )
{
curhttp->state = HTTP_STATE_WAIT_FLAG;
}
break;
case HTTP_STATE_WAIT_FLAG:
if( c == '\n' )
{
curhttp->state = HTTP_STATE_DATA_XFER;
InternalStartHTTP( );
}
else if( c != '\r' )
{
curhttp->state = HTTP_STATE_WAIT_INFLAG;
}
break;
case HTTP_STATE_WAIT_INFLAG:
if( c == '\n' )
{
curhttp->state = HTTP_STATE_WAIT_FLAG;
curhttp->state_deets = 0;
}
break;
case HTTP_STATE_DATA_XFER:
//Ignore any further data?
curlen = 0;
break;
case HTTP_STATE_DATA_WEBSOCKET:
WebSocketGotData( c );
break;
case HTTP_WAIT_CLOSE:
if( curhttp->keep_alive )
{
curhttp->state = HTTP_STATE_WAIT_METHOD;
}
else
{
HTTPClose( );
}
break;
default:
break;
};
}
}
static void DoHTTP( uint8_t timed )
{
switch( curhttp->state )
{
case HTTP_STATE_NONE: //do nothing if no state.
break;
case HTTP_STATE_DATA_XFER:
if( TCPCanSend( curhttp->socket, 1024 ) ) //TCPDoneSend
{
if( curhttp->is_dynamic )
{
HTTPCustomCallback( );
}
else
{
HTTPHandleInternalCallback( );
}
}
break;
case HTTP_WAIT_CLOSE:
if( TCPDoneSend( curhttp->socket ) )
{
if( curhttp->keep_alive )
{
curhttp->state = HTTP_STATE_WAIT_METHOD;
}
else
{
HTTPClose( );
}
}
break;
case HTTP_STATE_DATA_WEBSOCKET:
if( TCPCanSend( curhttp->socket, 1024 ) ) //TCPDoneSend
{
WebSocketTickInternal();
}
break;
default:
if( timed )
{
if( curhttp->timeout++ > HTTP_SERVER_TIMEOUT )
{
HTTPClose( );
}
}
}
}
void HTTPTick( uint8_t timed )
{
uint8_t i;
for( i = 0; i < HTTP_CONNECTIONS; i++ )
{
if( curhttp ) { printf( "Unexpected Race Condition\n" );}
curhttp = &HTTPConnections[i];
DoHTTP( timed );
curhttp = 0;
}
}
void ICACHE_FLASH_ATTR HTTPHandleInternalCallback( )
{
uint16_t i, bytestoread;
if( curhttp->isdone )
{
HTTPClose( );
return;
}
if( curhttp->is404 )
{
START_PACK
PushString("HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\nFile not found.");
EndTCPWrite( curhttp->socket );
curhttp->isdone = 1;
return;
}
if( curhttp->isfirst )
{
char stto[10];
uint8_t slen = os_strlen( curhttp->pathbuffer );
const char * k;
START_PACK;
//TODO: Content Length? MIME-Type?
PushString("HTTP/1.1 200 Ok\r\n");
if( curhttp->bytesleft < 0xfffffffe )
{
PushString("Connection: "ISKEEPALIVE"\r\nContent-Length: ");
Uint32To10Str( stto, curhttp->bytesleft );
PushBlob( stto, os_strlen( stto ) );
curhttp->keep_alive = 1;
}
else
{
PushString("Connection: close\r\n");
curhttp->keep_alive = 0;
}
PushString( "\r\nContent-Type: " );
//Content-Type?
while( slen && ( curhttp->pathbuffer[--slen] != '.' ) );
k = &curhttp->pathbuffer[slen+1];
if( strcmp( k, "mp3" ) == 0 )
{
PushString( "audio/mpeg3" );
}
else if( strcmp( k, "gz" ) == 0 )
{
PushString( "text/plain\r\nContent-Encoding: gzip\r\nCache-Control: public, max-age=3600" );
}
else if( curhttp->bytesleft == 0xfffffffe )
{
PushString( "text/plain" );
}
else
{
PushString( "text/html" );
}
PushString( "\r\n\r\n" );
EndTCPWrite( curhttp->socket );
curhttp->isfirst = 0;
return;
}
START_PACK
for( i = 0; i < 4 && curhttp->bytesleft; i++ )
{
int bpt = curhttp->bytesleft;
if( bpt > MFS_SECTOR ) bpt = MFS_SECTOR;
curhttp->bytesleft = MFSReadSector( generic_ptr, &curhttp->data.filedescriptor );
generic_ptr += bpt;
}
EndTCPWrite( curhttp->socket );