Update ESP8266 version
This commit is contained in:
parent
102219f9a7
commit
ff2cd22d9a
Binary file not shown.
Binary file not shown.
|
@ -1,7 +1,8 @@
|
|||
*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 and will consider resolving this if
|
||||
people want)
|
||||
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
|
||||
|
|
|
@ -6,14 +6,19 @@ TARGET_OUT:=image.elf
|
|||
|
||||
|
||||
SRCS:=driver/uart.c \
|
||||
user/mystuff.c \
|
||||
common/mystuff.c \
|
||||
common/flash_rewriter.c \
|
||||
common/http.c \
|
||||
common/http_custom.c \
|
||||
common/mfs.c \
|
||||
user/ws2812_i2s.c \
|
||||
user/hpatimer.c \
|
||||
driver/adc.c \
|
||||
../embeddedcommon/DFT32.c \
|
||||
../embeddedcommon/embeddednf.c \
|
||||
../embeddedcommon/embeddedout.c \
|
||||
user/user_main.c
|
||||
user/user_main.c \
|
||||
common/commonservices.c
|
||||
|
||||
GCC_FOLDER:=~/esp8266/esp-open-sdk/xtensa-lx106-elf
|
||||
ESPTOOL_PY:=~/esp8266/esptool/esptool.py
|
||||
|
@ -28,28 +33,32 @@ FOLDERPREFIX:=$(GCC_FOLDER)/bin
|
|||
PREFIX:=$(FOLDERPREFIX)/xtensa-lx106-elf-
|
||||
CC:=$(PREFIX)gcc
|
||||
|
||||
CFLAGS:=-mlongcalls -I$(SDK)/include -Imyclib -Iinclude -Iuser -Os -I$(SDK)/include/ -I../embeddedcommon -Dmemcpy=ets_memcpy -Dmemset=ets_memset \
|
||||
-DDFREQ=16000 -DCCEMBEDDED -DNUM_LIN_LEDS=24
|
||||
CFLAGS:=-mlongcalls -I$(SDK)/include -Imyclib -Iinclude -Iuser -Os -I$(SDK)/include/ -I../embeddedcommon -I. -Icommon -DICACHE_FLASH
|
||||
|
||||
#-DFREQ==12500 seems to work well.
|
||||
|
||||
|
||||
LDFLAGS_CORE:=\
|
||||
-nostdlib \
|
||||
-Wl,--relax -Wl,--gc-sections \
|
||||
-L$(XTLIB) \
|
||||
-L$(XTGCCLIB) \
|
||||
$(SDK)/lib/libmain.a \
|
||||
$(SDK)/lib/liblwip.a \
|
||||
$(SDK)/lib/libssl.a \
|
||||
$(SDK)/lib/libupgrade.a \
|
||||
$(SDK)/lib/libnet80211.a \
|
||||
$(SDK)/lib/liblwip.a \
|
||||
$(SDK)/lib/libwpa.a \
|
||||
$(SDK)/lib/libnet80211.a \
|
||||
$(SDK)/lib/libphy.a \
|
||||
$(SDK)/lib/libmain.a \
|
||||
$(SDK)/lib/liblwip.a \
|
||||
$(SDK)/lib/libpp.a \
|
||||
$(SDK)/lib/libmain.a \
|
||||
$(XTGCCLIB) \
|
||||
-T $(SDK)/ld/eagle.app.v6.ld
|
||||
-T $(SDK)/ld/eagle.app.v6.ld \
|
||||
-Wl,-Map,output.map \
|
||||
|
||||
# -flto -Wl,--relax -Wl,--gc-sections
|
||||
|
||||
|
||||
LINKFLAGS:= \
|
||||
$(LDFLAGS_CORE) \
|
||||
|
@ -59,7 +68,7 @@ LINKFLAGS:= \
|
|||
# $(PREFIX)ld $^ $(LDFLAGS) -o $@
|
||||
|
||||
$(TARGET_OUT) : $(SRCS)
|
||||
$(PREFIX)gcc $(CFLAGS) $^ -flto $(LINKFLAGS) -o $@
|
||||
$(PREFIX)gcc $(CFLAGS) $^ $(LINKFLAGS) -o $@
|
||||
|
||||
|
||||
|
||||
|
@ -71,10 +80,17 @@ $(FW_FILE_2): $(TARGET_OUT)
|
|||
@echo "FW $@"
|
||||
$(FW_TOOL) -eo $(TARGET_OUT) -es .irom0.text $@ -ec
|
||||
|
||||
|
||||
IP?=192.168.4.1
|
||||
|
||||
burn : $(FW_FILE_1) $(FW_FILE_2)
|
||||
($(ESPTOOL_PY) --port $(PORT) write_flash 0x00000 0x00000.bin 0x40000 0x40000.bin)||(true)
|
||||
|
||||
|
||||
|
||||
netburn : image.elf $(FW_FILE_1) $(FW_FILE_2)
|
||||
web/execute_reflash $(IP) 0x00000.bin 0x40000.bin
|
||||
|
||||
clean :
|
||||
rm -rf user/*.o driver/*.o $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2)
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#ESP8266 ColorChord
|
||||
|
||||
## WARNING THIS IS UNDER CONSTRUCTION
|
||||
|
||||
(based off of ESP8266 I2S WS2812 Driver)
|
||||
|
||||
This project is based off of the I2S interface for the mp3 player found here:
|
||||
|
|
13
embedded8266/ccconfig.h
Normal file
13
embedded8266/ccconfig.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef _CCCONFIG_H
|
||||
#define _CCCONFIG_H
|
||||
|
||||
#define CCEMBEDDED
|
||||
#define NUM_LIN_LEDS 24
|
||||
#define USE_NUM_LIN_LEDS 24
|
||||
#define DFREQ 16000
|
||||
|
||||
#define memcpy ets_memcpy
|
||||
#define memset ets_memset
|
||||
|
||||
#endif
|
||||
|
350
embedded8266/common/commonservices.c
Normal file
350
embedded8266/common/commonservices.c
Normal file
|
@ -0,0 +1,350 @@
|
|||
//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 "flash_rewriter.h"
|
||||
|
||||
static struct espconn *pUdpServer;
|
||||
static struct espconn *pHTTPServer;
|
||||
struct espconn *pespconn;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR issue_command(void *arg, char *pusrdata, unsigned short len)
|
||||
{
|
||||
pespconn = (struct espconn *)arg;
|
||||
//We accept commands on this.
|
||||
|
||||
switch( pusrdata[0] )
|
||||
{
|
||||
case 'f': case 'F': //Flashing commands (F_)
|
||||
{
|
||||
flashchip->chip_size = 0x01000000;
|
||||
// ets_printf( "PC%p\n", &pusrdata[2] );
|
||||
const char * colon = (const char *) ets_strstr( (char*)&pusrdata[2], ":" );
|
||||
int nr = my_atoi( &pusrdata[2] );
|
||||
|
||||
switch (pusrdata[1])
|
||||
{
|
||||
case 'e': case 'E': //(FE#\n) <- # = sector.
|
||||
{
|
||||
char __attribute__ ((aligned (16))) buffer[50];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
|
||||
EnterCritical();
|
||||
spi_flash_erase_sector( nr ); //SPI_FLASH_SEC_SIZE 4096
|
||||
ExitCritical();
|
||||
|
||||
buffend += ets_sprintf(buffend, "FE%d\r\n", nr );
|
||||
espconn_sent( pespconn, buffer, ets_strlen( buffer ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case 'b': case 'B': //(FE#\n) <- # = sector.
|
||||
{
|
||||
char __attribute__ ((aligned (16))) buffer[50];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
//spi_flash_erase_sector( nr ); //SPI_FLASH_SEC_SIZE 4096
|
||||
|
||||
EnterCritical();
|
||||
SPIEraseBlock( nr );
|
||||
ExitCritical();
|
||||
|
||||
buffend += ets_sprintf(buffend, "FB%d\r\n", nr );
|
||||
espconn_sent( pespconn, buffer, ets_strlen( buffer ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case 'm': case 'M': //Execute the flash re-writer
|
||||
{
|
||||
char ret[128];
|
||||
int n = ets_sprintf( ret, "FM" );
|
||||
espconn_sent( pespconn, ret, n );
|
||||
int r = (*GlobalRewriteFlash)( &pusrdata[2], len-2 );
|
||||
n = ets_sprintf( ret, "!FM%d", r );
|
||||
espconn_sent( pespconn, ret, n );
|
||||
}
|
||||
case 'w': case 'W': //Flash Write (FW#\n) <- # = byte pos.
|
||||
if( colon )
|
||||
{
|
||||
char __attribute__ ((aligned (32))) buffer[1300];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
buffer[0] = 0;
|
||||
colon++;
|
||||
const char * colon2 = (const char *) ets_strstr( (char*)colon, ":" );
|
||||
if( colon2 )
|
||||
{
|
||||
colon2++;
|
||||
int datlen = (int)len - (colon2 - pusrdata);
|
||||
ets_memcpy( buffer, colon2, datlen );
|
||||
|
||||
EnterCritical();
|
||||
spi_flash_write( nr, (uint32*)buffer, (datlen/4)*4 );
|
||||
ExitCritical();
|
||||
|
||||
//SPIWrite( nr, (uint32_t*)buffer, (datlen/4)*4 );
|
||||
|
||||
buffend = buffer;
|
||||
buffend += ets_sprintf(buffend, "FW%d\r\n", nr );
|
||||
if( ets_strlen( buffer ) )
|
||||
espconn_sent( pespconn, buffer, ets_strlen( buffer ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'r': case 'R': //Flash Read (FR#\n) <- # = sector.
|
||||
if( colon )
|
||||
{
|
||||
char __attribute__ ((aligned (16))) buffer[1300];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
buffer[0] = 0;
|
||||
colon++;
|
||||
int datlen = my_atoi( colon );
|
||||
if( datlen <= 1280 )
|
||||
{
|
||||
buffend += ets_sprintf(buffend, "FR%08d:%04d:", nr, datlen );
|
||||
int frontlen = buffend - buffer;
|
||||
spi_flash_read( nr, (uint32*)buffend, (datlen/4)*4 );
|
||||
espconn_sent( pespconn, buffer, frontlen + datlen );
|
||||
buffer[0] = 0;
|
||||
if( ets_strlen( buffer ) )
|
||||
espconn_sent( pespconn, buffer, ets_strlen( buffer ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
flashchip->chip_size = 0x00080000;
|
||||
break;
|
||||
}
|
||||
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.
|
||||
{
|
||||
char * colon = (char *) ets_strstr( (char*)&pusrdata[2], ":" );
|
||||
char * colon2 = (colon)?((char *)ets_strstr( (char*)(colon+1), ":" )):0;
|
||||
char * extra = colon2;
|
||||
char __attribute__ ((aligned (16))) buffer[1300];
|
||||
char * buffend;
|
||||
buffend = buffer;
|
||||
buffer[0] = 0;
|
||||
|
||||
if( extra )
|
||||
{
|
||||
for( ; *extra; extra++ )
|
||||
{
|
||||
if( *extra < 32 )
|
||||
{
|
||||
*extra = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (pusrdata[1])
|
||||
{
|
||||
case '1': //Station mode
|
||||
if( colon && colon2 )
|
||||
{
|
||||
int c1l = 0;
|
||||
int c2l = 0;
|
||||
struct station_config stationConf;
|
||||
*colon = 0; colon++;
|
||||
*colon2 = 0; colon2++;
|
||||
c1l = ets_strlen( colon );
|
||||
c2l = ets_strlen( colon2 );
|
||||
if( c1l > 32 ) c1l = 32;
|
||||
if( c2l > 32 ) c2l = 32;
|
||||
os_bzero( &stationConf, sizeof( stationConf ) );
|
||||
|
||||
printf( "Switching to: \"%s\"/\"%s\".\n", colon, colon2 );
|
||||
|
||||
os_memcpy(&stationConf.ssid, colon, c1l);
|
||||
os_memcpy(&stationConf.password, colon2, c2l);
|
||||
|
||||
wifi_set_opmode( 1 );
|
||||
wifi_station_set_config(&stationConf);
|
||||
wifi_station_connect();
|
||||
espconn_sent( pespconn, "W1\r\n", 4 );
|
||||
|
||||
printf( "Switching.\n" );
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
{
|
||||
wifi_set_opmode_current( 1 );
|
||||
wifi_set_opmode( 2 );
|
||||
espconn_sent( pespconn, "W2\r\n", 4 );
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
{
|
||||
struct station_config sc;
|
||||
int mode = wifi_get_opmode();
|
||||
char buffer[200];
|
||||
char * buffend = &buffer[0];
|
||||
|
||||
buffend += ets_sprintf( buffend, "WI%d", mode );
|
||||
|
||||
wifi_station_get_config( &sc );
|
||||
|
||||
buffend += ets_sprintf( buffend, ":%s:%s", sc.ssid, sc.password );
|
||||
|
||||
espconn_sent( pespconn, buffer, buffend - buffer );
|
||||
}
|
||||
break;
|
||||
case 'S': case 's':
|
||||
{
|
||||
char buffer[1024];
|
||||
char * buffend = &buffer[0];
|
||||
int i, r;
|
||||
|
||||
scanplace = 0;
|
||||
|
||||
if( wifi_get_opmode() == SOFTAP_MODE )
|
||||
{
|
||||
wifi_set_opmode_current( STATION_MODE );
|
||||
need_to_switch_back_to_soft_ap = 1;
|
||||
r = wifi_station_scan(0, scandone );
|
||||
}
|
||||
else
|
||||
{
|
||||
r = wifi_station_scan(0, scandone );
|
||||
}
|
||||
|
||||
buffend += ets_sprintf( buffend, "WS%d\n", r );
|
||||
uart0_sendStr(buffer);
|
||||
|
||||
espconn_sent( pespconn, buffer, buffend - buffer );
|
||||
|
||||
}
|
||||
break;
|
||||
case 'R': case 'r':
|
||||
{
|
||||
char buffer[1024];
|
||||
char * buffend = &buffer[0];
|
||||
int i, r;
|
||||
|
||||
buffend += ets_sprintf( buffend, "WR%d\n", scanplace );
|
||||
|
||||
for( i = 0; i < scanplace; 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] );
|
||||
}
|
||||
|
||||
espconn_sent( pespconn, buffer, buffend - buffer );
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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 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;
|
||||
wifi_set_opmode_current( SOFTAP_MODE );
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
18
embedded8266/common/commonservices.h
Normal file
18
embedded8266/common/commonservices.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
//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"
|
||||
|
||||
//Includes UDP Control + HTTP Interfaces
|
||||
void ICACHE_FLASH_ATTR CSInit();
|
||||
void ICACHE_FLASH_ATTR CSTick( int slowtick );
|
||||
|
||||
//You must provide:
|
||||
void EnterCritical();
|
||||
void ExitCritical();
|
||||
|
||||
#endif
|
||||
|
92
embedded8266/common/esp8266_rom.h
Normal file
92
embedded8266/common/esp8266_rom.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
#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); //Doesn't work?
|
||||
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
|
||||
|
||||
|
292
embedded8266/common/flash_rewriter.c
Normal file
292
embedded8266/common/flash_rewriter.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
//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
|
||||
|
||||
|
||||
static const char * key = "";
|
||||
static int keylen = 0;
|
||||
|
||||
void SafeMD5Update( MD5_CTX * md5ctx, uint8_t*from, uint32_t size1 )
|
||||
{
|
||||
char __attribute__ ((aligned (32))) buffer[32];
|
||||
|
||||
|
||||
while( size1 > 32 )
|
||||
{
|
||||
ets_memcpy( buffer, from, 32 );
|
||||
MD5Update( md5ctx, buffer, 32 );
|
||||
size1-=32;
|
||||
from+=32;
|
||||
}
|
||||
ets_memcpy( buffer, from, 32 );
|
||||
MD5Update( md5ctx, buffer, size1 );
|
||||
}
|
||||
|
||||
|
||||
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]:[to_address]:[size]:[MD5(key+data)]:[from_address]:[to_address]:[size]:[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] == ':' )
|
||||
{
|
||||
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();
|
||||
|
||||
ipl = (size1/SRCSIZE)+1;
|
||||
p = to1/SRCSIZE;
|
||||
for( i = 0; i < ipl; i++ )
|
||||
{
|
||||
SPIEraseSector( p++ );
|
||||
SPIWrite( to1, (uint32_t*)(0x40200000 + from1), SRCSIZE );
|
||||
to1 += SRCSIZE;
|
||||
from1 += SRCSIZE;
|
||||
}
|
||||
|
||||
uart_tx_one_char( 'B' );
|
||||
|
||||
ipl = (size2/SRCSIZE)+1;
|
||||
p = to2/SRCSIZE;
|
||||
for( i = 0; i < ipl; i++ )
|
||||
{
|
||||
SPIEraseSector( p++ );
|
||||
SPIWrite( to2, (uint32_t*)(0x40200000 + from2), SRCSIZE );
|
||||
to2 += SRCSIZE;
|
||||
from2 += SRCSIZE;
|
||||
|
||||
}
|
||||
|
||||
uart_tx_one_char( 'R' );
|
||||
|
||||
|
||||
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;
|
20
embedded8266/common/flash_rewriter.h
Normal file
20
embedded8266/common/flash_rewriter.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
//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
|
560
embedded8266/common/http.c
Normal file
560
embedded8266/common/http.c
Normal file
|
@ -0,0 +1,560 @@
|
|||
//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 )
|
||||
|
||||
struct HTTPConnection HTTPConnections[HTTP_CONNECTIONS];
|
||||
struct HTTPConnection * curhttp;
|
||||
uint8 * curdata;
|
||||
uint16 curlen;
|
||||
|
||||
ICACHE_FLASH_ATTR void InternalStartHTTP( );
|
||||
ICACHE_FLASH_ATTR void HTTPHandleInternalCallback( );
|
||||
|
||||
ICACHE_FLASH_ATTR void HTTPClose( )
|
||||
{
|
||||
curhttp->state = HTTP_STATE_NONE;
|
||||
espconn_disconnect( curhttp->socket );
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR HTTPGotData( )
|
||||
{
|
||||
uint8 c;
|
||||
curhttp->timeout = 0;
|
||||
|
||||
while( curlen-- )
|
||||
{
|
||||
c = POP;
|
||||
// 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:
|
||||
//printf( "__HTTPCLose1\n" );
|
||||
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 ) )
|
||||
{
|
||||
//printf( "HTTPCLose2\n");
|
||||
HTTPClose( );
|
||||
}
|
||||
break;
|
||||
case HTTP_STATE_DATA_WEBSOCKET:
|
||||
if( TCPCanSend( curhttp->socket, 1024 ) ) //TCPDoneSend
|
||||
{
|
||||
WebSocketTickInternal();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if( timed )
|
||||
{
|
||||
if( curhttp->timeout++ > HTTP_SERVER_TIMEOUT )
|
||||
{
|
||||
//printf( "HTTPClose3\n" );
|
||||
HTTPClose( );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPTick( uint8_t timed )
|
||||
{
|
||||
uint8_t i;
|
||||
for( i = 0; i < HTTP_CONNECTIONS; i++ )
|
||||
{
|
||||
curhttp = &HTTPConnections[i];
|
||||
DoHTTP( timed );
|
||||
}
|
||||
}
|
||||
|
||||
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\nConnection: close");
|
||||
|
||||
if( curhttp->bytesleft < 0xfffffffe )
|
||||
{
|
||||
PushString("\r\nContent-Length: ");
|
||||
Uint32To10Str( stto, curhttp->bytesleft );
|
||||
PushBlob( stto, os_strlen( stto ) );
|
||||
}
|
||||
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( 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 );
|
||||
|
||||
if( !curhttp->bytesleft )
|
||||
curhttp->isdone = 1;
|
||||
}
|
||||
|
||||
void InternalStartHTTP( )
|
||||
{
|
||||
int32_t clusterno;
|
||||
int8_t i;
|
||||
const char * path = &curhttp->pathbuffer[0];
|
||||
|
||||
if( curhttp->pathbuffer[0] == '/' )
|
||||
path++;
|
||||
|
||||
if( path[0] == 'd' && path[1] == '/' )
|
||||
{
|
||||
curhttp->is_dynamic = 1;
|
||||
curhttp->isfirst = 1;
|
||||
curhttp->isdone = 0;
|
||||
curhttp->is404 = 0;
|
||||
HTTPCustomStart();
|
||||
return;
|
||||
}
|
||||
|
||||
if( !path[0] )
|
||||
{
|
||||
path = "index.html";
|
||||
}
|
||||
|
||||
i = MFSOpenFile( path, &curhttp->data.filedescriptor );
|
||||
curhttp->bytessofar = 0;
|
||||
|
||||
if( i < 0 )
|
||||
{
|
||||
HTDEBUG( "404(%s)\n", path );
|
||||
curhttp->is404 = 1;
|
||||
curhttp->isfirst = 1;
|
||||
curhttp->isdone = 0;
|
||||
curhttp->is_dynamic = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
curhttp->isfirst = 1;
|
||||
curhttp->isdone = 0;
|
||||
curhttp->is404 = 0;
|
||||
curhttp->is_dynamic = 0;
|
||||
curhttp->bytesleft = curhttp->data.filedescriptor.filelen;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LOCAL void ICACHE_FLASH_ATTR
|
||||
http_disconnetcb(void *arg) {
|
||||
struct espconn *pespconn = (struct espconn *) arg;
|
||||
curhttp = (struct HTTPConnection * )pespconn->reverse;
|
||||
curhttp->state = 0;
|
||||
}
|
||||
|
||||
LOCAL void ICACHE_FLASH_ATTR
|
||||
http_recvcb(void *arg, char *pusrdata, unsigned short length)
|
||||
{
|
||||
struct espconn *pespconn = (struct espconn *) arg;
|
||||
|
||||
ets_intr_lock();
|
||||
curhttp = (struct HTTPConnection * )pespconn->reverse;
|
||||
curdata = (uint8*)pusrdata;
|
||||
curlen = length;
|
||||
HTTPGotData();
|
||||
ets_intr_unlock();
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
httpserver_connectcb(void *arg)
|
||||
{
|
||||
int i;
|
||||
struct espconn *pespconn = (struct espconn *)arg;
|
||||
|
||||
for( i = 0; i < HTTP_CONNECTIONS; i++ )
|
||||
{
|
||||
if( HTTPConnections[i].state == 0 )
|
||||
{
|
||||
pespconn->reverse = &HTTPConnections[i];
|
||||
HTTPConnections[i].socket = pespconn;
|
||||
HTTPConnections[i].state = HTTP_STATE_WAIT_METHOD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( i == HTTP_CONNECTIONS )
|
||||
{
|
||||
espconn_disconnect( pespconn );
|
||||
return;
|
||||
}
|
||||
|
||||
// espconn_set_opt(pespconn, ESPCONN_NODELAY);
|
||||
// espconn_set_opt(pespconn, ESPCONN_COPY);
|
||||
|
||||
espconn_regist_recvcb( pespconn, http_recvcb );
|
||||
espconn_regist_disconcb( pespconn, http_disconnetcb );
|
||||
|
||||
}
|
||||
|
||||
|
||||
int ICACHE_FLASH_ATTR URLDecode( char * decodeinto, int maxlen, const char * buf )
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for( ; buf && *buf; buf++ )
|
||||
{
|
||||
char c = *buf;
|
||||
if( c == '+' )
|
||||
{
|
||||
decodeinto[i++] = ' ';
|
||||
}
|
||||
else if( c == '?' || c == '&' )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if( c == '%' )
|
||||
{
|
||||
if( *(buf+1) && *(buf+2) )
|
||||
{
|
||||
decodeinto[i++] = hex2byte( buf+1 );
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decodeinto[i++] = c;
|
||||
}
|
||||
if( i >= maxlen -1 ) break;
|
||||
|
||||
}
|
||||
decodeinto[i] = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketGotData( uint8_t c )
|
||||
{
|
||||
switch( curhttp->state_deets )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
int i = 0;
|
||||
char inkey[120];
|
||||
unsigned char hash[SHA1_HASH_LEN];
|
||||
SHA1_CTX c;
|
||||
int inkeylen = 0;
|
||||
|
||||
curhttp->is_dynamic = 1;
|
||||
while( curlen > 20 )
|
||||
{
|
||||
curdata++; curlen--;
|
||||
if( strncmp( curdata, "Sec-WebSocket-Key: ", 19 ) == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( curlen <= 21 )
|
||||
{
|
||||
HTDEBUG( "No websocket key found.\n" );
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
curdata+= 19;
|
||||
curlen -= 19;
|
||||
|
||||
|
||||
#define WS_KEY_LEN 36
|
||||
#define WS_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
|
||||
while( curlen > 1 )
|
||||
{
|
||||
uint8_t lc = *(curdata++);
|
||||
inkey[i] = lc;
|
||||
curlen--;
|
||||
if( lc == '\r' )
|
||||
{
|
||||
inkey[i] = 0;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
if( i >= sizeof( inkey ) - WS_KEY_LEN - 5 )
|
||||
{
|
||||
HTDEBUG( "Websocket key too big.\n" );
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( curlen <= 1 )
|
||||
{
|
||||
HTDEBUG( "Invalid websocket key found.\n" );
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if( i + WS_KEY_LEN + 1 >= sizeof( inkey ) )
|
||||
{
|
||||
HTDEBUG( "WSKEY Too Big.\n" );
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
ets_memcpy( &inkey[i], WS_KEY, WS_KEY_LEN + 1 );
|
||||
i += WS_KEY_LEN;
|
||||
SHA1_Init( &c );
|
||||
SHA1_Update( &c, inkey, i );
|
||||
SHA1_Final( hash, &c );
|
||||
|
||||
if( SHA1_HASH_LEN * 2 > MAX_PATHLEN )
|
||||
{
|
||||
HTDEBUG( "Pathlen too short.\n" );
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
my_base64_encode( hash, SHA1_HASH_LEN, curhttp->pathbuffer );
|
||||
|
||||
//Respond...
|
||||
curhttp->state_deets = 1;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
if( c == '\n' ) curhttp->state_deets = 2;
|
||||
break;
|
||||
case 2:
|
||||
if( c == '\r' ) curhttp->state_deets = 3;
|
||||
else curhttp->state_deets = 1;
|
||||
break;
|
||||
case 3:
|
||||
if( c == '\n' ) curhttp->state_deets = 4;
|
||||
else curhttp->state_deets = 1;
|
||||
break;
|
||||
case 5: //Established connection.
|
||||
{
|
||||
if( curlen < 5 ) //Can't interpret packet.
|
||||
break;
|
||||
|
||||
uint8_t fin = c & 1;
|
||||
uint8_t opcode = c << 4;
|
||||
uint32_t payloadlen = *(curdata++);
|
||||
curlen--;
|
||||
if( !(payloadlen & 0x80) )
|
||||
{
|
||||
HTDEBUG( "Unmasked packet.\n" );
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if( payloadlen == 127 )
|
||||
{
|
||||
//Very long payload.
|
||||
//Not supported.
|
||||
HTDEBUG( "Unsupported payload packet.\n" );
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
break;
|
||||
}
|
||||
else if( payloadlen == 126 )
|
||||
{
|
||||
payloadlen = (curdata[0] << 8) | curdata[1];
|
||||
curdata += 2;
|
||||
curlen -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
payloadlen &= 0x7f;
|
||||
}
|
||||
WebSocketData( curdata, payloadlen );
|
||||
curlen -= payloadlen;
|
||||
curdata += payloadlen;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketTickInternal()
|
||||
{
|
||||
switch( curhttp->state_deets )
|
||||
{
|
||||
case 4: //Has key full HTTP header, etc. wants response.
|
||||
START_PACK;
|
||||
PushString( "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " );
|
||||
PushString( curhttp->pathbuffer );
|
||||
PushString( "\r\n\r\n" );
|
||||
EndTCPWrite( curhttp->socket );
|
||||
curhttp->state_deets = 5;
|
||||
curhttp->bytessofar = 0;
|
||||
curhttp->bytesleft = 0;
|
||||
NewWebSocket();
|
||||
break;
|
||||
case 5:
|
||||
WebSocketTick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketSend( uint8_t * data, int size )
|
||||
{
|
||||
START_PACK;
|
||||
PushByte( 0x81 );
|
||||
if( size > 126 )
|
||||
{
|
||||
PushByte( 0x00 | 126 );
|
||||
PushByte( size>>8 );
|
||||
PushByte( size&0xff );
|
||||
}
|
||||
else
|
||||
{
|
||||
PushByte( 0x00 | size );
|
||||
}
|
||||
PushBlob( data, size );
|
||||
EndTCPWrite( curhttp->socket );
|
||||
}
|
||||
|
||||
|
91
embedded8266/common/http.h
Normal file
91
embedded8266/common/http.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#ifndef _HTTP_H
|
||||
#define _HTTP_H
|
||||
|
||||
#include "mem.h"
|
||||
#include "c_types.h"
|
||||
#include "user_interface.h"
|
||||
#include "ets_sys.h"
|
||||
#include "driver/uart.h"
|
||||
#include "osapi.h"
|
||||
#include "espconn.h"
|
||||
#include "mfs.h"
|
||||
#include "mystuff.h"
|
||||
|
||||
#define HTTP_SERVER_TIMEOUT 500
|
||||
#define HTTP_CONNECTIONS 8
|
||||
#define MAX_PATHLEN 80
|
||||
|
||||
//You must provide:
|
||||
void ICACHE_FLASH_ATTR HTTPCustomStart( );
|
||||
void ICACHE_FLASH_ATTR HTTPCustomCallback( ); //called when we can send more data
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketData( uint8_t * data, int len );
|
||||
void ICACHE_FLASH_ATTR WebSocketTick( );
|
||||
void ICACHE_FLASH_ATTR WebSocketNew();
|
||||
|
||||
extern struct HTTPConnection * curhttp;
|
||||
extern uint8 * curdata;
|
||||
extern uint16 curlen;
|
||||
|
||||
#define POP (*curdata++)
|
||||
|
||||
#define HTTP_STATE_NONE 0
|
||||
#define HTTP_STATE_WAIT_METHOD 1
|
||||
#define HTTP_STATE_WAIT_PATH 2
|
||||
#define HTTP_STATE_WAIT_PROTO 3
|
||||
|
||||
#define HTTP_STATE_WAIT_FLAG 4
|
||||
#define HTTP_STATE_WAIT_INFLAG 5
|
||||
#define HTTP_STATE_DATA_XFER 7
|
||||
#define HTTP_STATE_DATA_WEBSOCKET 8
|
||||
|
||||
#define HTTP_WAIT_CLOSE 15
|
||||
|
||||
|
||||
struct HTTPConnection
|
||||
{
|
||||
uint8_t state:4;
|
||||
uint8_t state_deets;
|
||||
uint8_t pathbuffer[MAX_PATHLEN]; //Also used for temporary and handshake information when using websockets.
|
||||
uint8_t is_dynamic:1;
|
||||
uint16_t timeout;
|
||||
|
||||
union data_t
|
||||
{
|
||||
struct MFSFileInfo filedescriptor;
|
||||
struct UserData { uint16_t a, b, c; } user;
|
||||
} data;
|
||||
|
||||
void * rcb;
|
||||
|
||||
uint32_t bytesleft;
|
||||
uint32_t bytessofar;
|
||||
|
||||
uint8_t is404:1;
|
||||
uint8_t isdone:1;
|
||||
uint8_t isfirst:1;
|
||||
uint8_t need_resend:1;
|
||||
|
||||
struct espconn * socket;
|
||||
} HTTPConnections[HTTP_CONNECTIONS];
|
||||
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR httpserver_connectcb(void *arg);
|
||||
|
||||
void HTTPTick( uint8_t timedtick );
|
||||
//you can call this a LOT if you want fast transfers, but be sure only to call it with a 1 at the update tick rate.
|
||||
|
||||
int ICACHE_FLASH_ATTR URLDecode( char * decodeinto, int maxlen, const char * buf );
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketGotData( uint8_t c );
|
||||
void ICACHE_FLASH_ATTR WebSocketTickInternal();
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketSend( uint8_t * data, int size );
|
||||
|
||||
|
||||
#endif
|
||||
|
97
embedded8266/common/http_custom.c
Normal file
97
embedded8266/common/http_custom.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#include "http.h"
|
||||
#include "mystuff.h"
|
||||
#include "commonservices.h"
|
||||
|
||||
static ICACHE_FLASH_ATTR void huge()
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
START_PACK;
|
||||
do
|
||||
{
|
||||
PushByte( 0 );
|
||||
PushByte( i );
|
||||
} while( ++i ); //Tricky: this will roll-over to 0, and thus only execute 256 times.
|
||||
|
||||
EndTCPWrite( curhttp->socket );
|
||||
}
|
||||
|
||||
|
||||
static ICACHE_FLASH_ATTR void echo()
|
||||
{
|
||||
char mydat[128];
|
||||
int len = URLDecode( mydat, 128, curhttp->pathbuffer+8 );
|
||||
|
||||
START_PACK;
|
||||
PushBlob( mydat, len );
|
||||
EndTCPWrite( curhttp->socket );
|
||||
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
}
|
||||
|
||||
static ICACHE_FLASH_ATTR void issue()
|
||||
{
|
||||
char mydat[512];
|
||||
int len = URLDecode( mydat, 512, curhttp->pathbuffer+9 );
|
||||
|
||||
issue_command(curhttp->socket, mydat, len );
|
||||
|
||||
curhttp->state = HTTP_WAIT_CLOSE;
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR HTTPCustomStart( )
|
||||
{
|
||||
if( strncmp( (const char*)curhttp->pathbuffer, "/d/huge", 7 ) == 0 )
|
||||
{
|
||||
curhttp->rcb = (void(*)())&huge;
|
||||
curhttp->bytesleft = 0xffffffff;
|
||||
}
|
||||
else
|
||||
if( strncmp( (const char*)curhttp->pathbuffer, "/d/echo?", 8 ) == 0 )
|
||||
{
|
||||
curhttp->rcb = (void(*)())&echo;
|
||||
curhttp->bytesleft = 0xfffffffe;
|
||||
}
|
||||
else
|
||||
if( strncmp( (const char*)curhttp->pathbuffer, "/d/issue?", 9 ) == 0 )
|
||||
{
|
||||
curhttp->rcb = (void(*)())&issue;
|
||||
curhttp->bytesleft = 0xfffffffe;
|
||||
}
|
||||
else
|
||||
{
|
||||
curhttp->rcb = 0;
|
||||
curhttp->bytesleft = 0;
|
||||
}
|
||||
curhttp->isfirst = 1;
|
||||
HTTPHandleInternalCallback();
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR HTTPCustomCallback( )
|
||||
{
|
||||
if( curhttp->rcb )
|
||||
((void(*)())curhttp->rcb)();
|
||||
else
|
||||
curhttp->isdone = 1;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketTick()
|
||||
{
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR WebSocketData( uint8_t * data, int len )
|
||||
{
|
||||
char stout[128];
|
||||
int stl = ets_sprintf( stout, "output.innerHTML = %d; doSend('x' );\n", curhttp->bytessofar++ );
|
||||
WebSocketSend( stout, stl );
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR NewWebSocket()
|
||||
{
|
||||
}
|
||||
|
64
embedded8266/common/mfs.c
Normal file
64
embedded8266/common/mfs.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#include "mystuff.h"
|
||||
#include "mfs.h"
|
||||
#include "spi_flash.h"
|
||||
#include "ets_sys.h"
|
||||
|
||||
extern SpiFlashChip * flashchip;
|
||||
|
||||
//Returns 0 on succses.
|
||||
//Returns size of file if non-empty
|
||||
//If positive, populates mfi.
|
||||
//Returns -1 if can't find file or reached end of file list.
|
||||
int8_t MFSOpenFile( const char * fname, struct MFSFileInfo * mfi )
|
||||
{
|
||||
EnterCritical();
|
||||
flashchip->chip_size = 0x01000000;
|
||||
uint32 ptr = MFS_START;
|
||||
struct MFSFileEntry e;
|
||||
while(1)
|
||||
{
|
||||
spi_flash_read( ptr, (uint32*)&e, sizeof( e ) );
|
||||
ptr += sizeof(e);
|
||||
if( e.name[0] == 0xff || ets_strlen( e.name ) == 0 ) break;
|
||||
|
||||
if( ets_strcmp( e.name, fname ) == 0 )
|
||||
{
|
||||
mfi->offset = e.start;
|
||||
mfi->filelen = e.len;
|
||||
flashchip->chip_size = 0x00080000;
|
||||
ExitCritical();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
flashchip->chip_size = 0x00080000;
|
||||
ExitCritical();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t MFSReadSector( uint8_t* data, struct MFSFileInfo * mfi )
|
||||
{
|
||||
//returns # of bytes left tin file.
|
||||
if( !mfi->filelen )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toread = mfi->filelen;
|
||||
if( toread > MFS_SECTOR ) toread = MFS_SECTOR;
|
||||
|
||||
EnterCritical();
|
||||
flashchip->chip_size = 0x01000000;
|
||||
spi_flash_read( MFS_START+mfi->offset, (uint32*)data, MFS_SECTOR );
|
||||
flashchip->chip_size = 0x00080000;
|
||||
ExitCritical();
|
||||
|
||||
mfi->offset += toread;
|
||||
mfi->filelen -= toread;
|
||||
return mfi->filelen;
|
||||
}
|
||||
|
||||
|
||||
|
51
embedded8266/common/mfs.h
Normal file
51
embedded8266/common/mfs.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
//Not to be confused with MFS for the AVR.
|
||||
|
||||
#ifndef _MFS_H
|
||||
#define _MFS_H
|
||||
|
||||
#include "mem.h"
|
||||
#include "c_types.h"
|
||||
#include "mystuff.h"
|
||||
|
||||
//SPI_FLASH_SEC_SIZE 4096
|
||||
#define MFS_STARTFLASHSECTOR 0x100
|
||||
#define MFS_START (MFS_STARTFLASHSECTOR*SPI_FLASH_SEC_SIZE)
|
||||
#define MFS_SECTOR 256
|
||||
|
||||
|
||||
#define MFS_FILENAMELEN 32-8
|
||||
|
||||
//Format:
|
||||
// [FILE NAME (24)] [Start (4)] [Len (4)]
|
||||
// NOTE: Filename must be null-terminated within the 24.
|
||||
struct MFSFileEntry
|
||||
{
|
||||
char name[MFS_FILENAMELEN];
|
||||
uint32 start; //From beginning of mfs thing.
|
||||
uint32 len;
|
||||
};
|
||||
|
||||
|
||||
struct MFSFileInfo
|
||||
{
|
||||
uint32 offset;
|
||||
uint32 filelen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//Returns 0 on succses.
|
||||
//Returns size of file if non-empty
|
||||
//If positive, populates mfi.
|
||||
//Returns -1 if can't find file or reached end of file list.
|
||||
ICACHE_FLASH_ATTR int8_t MFSOpenFile( const char * fname, struct MFSFileInfo * mfi );
|
||||
ICACHE_FLASH_ATTR int32_t MFSReadSector( uint8_t* data, struct MFSFileInfo * mfi ); //returns # of bytes left in file.
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
169
embedded8266/common/mystuff.c
Normal file
169
embedded8266/common/mystuff.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
//Unless what else is individually marked, all code in this file is
|
||||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#include "mystuff.h"
|
||||
|
||||
const char * enctypes[6] = { "open", "wep", "wpa", "wpa2", "wpa_wpa2", "max" };
|
||||
|
||||
char generic_print_buffer[384];
|
||||
char generic_buffer[1500];
|
||||
char * generic_ptr;
|
||||
|
||||
int32 my_atoi( const char * in )
|
||||
{
|
||||
int positive = 1; //1 if negative.
|
||||
int hit = 0;
|
||||
int val = 0;
|
||||
while( *in && hit < 11 )
|
||||
{
|
||||
if( *in == '-' )
|
||||
{
|
||||
if( positive == -1 ) return val*positive;
|
||||
positive = -1;
|
||||
} else if( *in >= '0' && *in <= '9' )
|
||||
{
|
||||
val *= 10;
|
||||
val += *in - '0';
|
||||
hit++;
|
||||
} else if (!hit && ( *in == ' ' || *in == '\t' ) )
|
||||
{
|
||||
//okay
|
||||
} else
|
||||
{
|
||||
//bad.
|
||||
return val*positive;
|
||||
}
|
||||
in++;
|
||||
}
|
||||
return val*positive;
|
||||
}
|
||||
|
||||
void Uint32To10Str( char * out, uint32 dat )
|
||||
{
|
||||
int tens = 1000000000;
|
||||
int val;
|
||||
int place = 0;
|
||||
|
||||
while( tens > 1 )
|
||||
{
|
||||
if( dat/tens ) break;
|
||||
tens/=10;
|
||||
}
|
||||
|
||||
while( tens )
|
||||
{
|
||||
val = dat/tens;
|
||||
dat -= val*tens;
|
||||
tens /= 10;
|
||||
out[place++] = val + '0';
|
||||
}
|
||||
|
||||
out[place] = 0;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR EndTCPWrite( struct espconn * conn )
|
||||
{
|
||||
if(generic_ptr!=generic_buffer)
|
||||
espconn_sent(conn,generic_buffer,generic_ptr-generic_buffer);
|
||||
}
|
||||
|
||||
|
||||
void PushString( const char * buffer )
|
||||
{
|
||||
char c;
|
||||
while( c = *(buffer++) )
|
||||
PushByte( c );
|
||||
}
|
||||
|
||||
void PushBlob( const uint8 * buffer, int len )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < len; i++ )
|
||||
PushByte( buffer[i] );
|
||||
}
|
||||
|
||||
|
||||
int8_t TCPCanSend( struct espconn * conn, int size )
|
||||
{
|
||||
struct espconn_packet infoarg;
|
||||
sint8 r = espconn_get_packet_info(conn, &infoarg);
|
||||
|
||||
if( infoarg.snd_buf_size >= size && infoarg.snd_queuelen > 0 )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ICACHE_FLASH_ATTR TCPDoneSend( struct espconn * conn )
|
||||
{
|
||||
return conn->state == ESPCONN_CONNECT;
|
||||
}
|
||||
|
||||
const char * ICACHE_FLASH_ATTR my_strchr( const char * st, char c )
|
||||
{
|
||||
while( *st && *st != c ) st++;
|
||||
if( !*st ) return 0;
|
||||
return st;
|
||||
}
|
||||
|
||||
int ICACHE_FLASH_ATTR ColonsToInts( const char * str, int32_t * vals, int max_quantity )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < max_quantity; i++ )
|
||||
{
|
||||
const char * colon = my_strchr( str, ':' );
|
||||
vals[i] = my_atoi( str );
|
||||
if( !colon ) break;
|
||||
str = colon+1;
|
||||
}
|
||||
return i+1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//from http://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c
|
||||
static const char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'};
|
||||
|
||||
static const int mod_table[] = {0, 2, 1};
|
||||
|
||||
void ICACHE_FLASH_ATTR my_base64_encode(const unsigned char *data, size_t input_length, uint8_t * encoded_data )
|
||||
{
|
||||
|
||||
int i, j;
|
||||
int output_length = 4 * ((input_length + 2) / 3);
|
||||
|
||||
if( !encoded_data ) return;
|
||||
if( !data ) { encoded_data[0] = '='; encoded_data[1] = 0; return; }
|
||||
|
||||
for (i = 0, j = 0; i < input_length; ) {
|
||||
|
||||
uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
|
||||
uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
|
||||
uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
|
||||
|
||||
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
||||
|
||||
encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
|
||||
encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
|
||||
encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
|
||||
encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
|
||||
}
|
||||
|
||||
for (i = 0; i < mod_table[input_length % 3]; i++)
|
||||
encoded_data[output_length - 1 - i] = '=';
|
||||
|
||||
encoded_data[j] = 0;
|
||||
}
|
||||
|
43
embedded8266/common/mystuff.h
Normal file
43
embedded8266/common/mystuff.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
//Unless what else is individually marked, all code in this file is
|
||||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#ifndef _MYSTUFF_H
|
||||
#define _MYSTUFF_H
|
||||
|
||||
#include <mem.h>
|
||||
#include <c_types.h>
|
||||
#include <user_interface.h>
|
||||
#include <ets_sys.h>
|
||||
#include <espconn.h>
|
||||
|
||||
extern char generic_print_buffer[384];
|
||||
|
||||
extern const char * enctypes[6];// = { "open", "wep", "wpa", "wpa2", "wpa_wpa2", "max" };
|
||||
|
||||
#define printf( ... ) ets_sprintf( generic_print_buffer, __VA_ARGS__ ); uart0_sendStr( generic_print_buffer );
|
||||
|
||||
int32 my_atoi( const char * in );
|
||||
void Uint32To10Str( char * out, uint32 dat );
|
||||
|
||||
//For holding TX packet buffers
|
||||
extern char generic_buffer[1500];
|
||||
extern char * generic_ptr;
|
||||
int8_t ICACHE_FLASH_ATTR TCPCanSend( struct espconn * conn, int size );
|
||||
int8_t ICACHE_FLASH_ATTR TCPDoneSend( struct espconn * conn );
|
||||
void ICACHE_FLASH_ATTR EndTCPWrite( struct espconn * conn );
|
||||
|
||||
#define PushByte( c ) { *(generic_ptr++) = c; }
|
||||
|
||||
void PushString( const char * buffer );
|
||||
void PushBlob( const uint8 * buffer, int len );
|
||||
#define START_PACK {generic_ptr=generic_buffer;}
|
||||
#define PACK_LENGTH (generic_ptr-&generic_buffer[0]}
|
||||
|
||||
int ICACHE_FLASH_ATTR ColonsToInts( const char * str, int32_t * vals, int max_quantity );
|
||||
|
||||
//As much as it pains me, we shouldn't be using the esp8266's base64_encode() function
|
||||
//as it does stuff with dynamic memory.
|
||||
void ICACHE_FLASH_ATTR my_base64_encode(const unsigned char *data, size_t input_length, uint8_t * encoded_data );
|
||||
|
||||
#endif
|
|
@ -1,4 +1,7 @@
|
|||
//I did not write this file, but I don't know where it came from.
|
||||
//It was also heavily modified by me, Charles Lohr. I personally
|
||||
//renounce any copyright over this file, so all of my modifications
|
||||
//are hereby placed into the public domain.
|
||||
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*
|
||||
* Modification history:
|
||||
* 2014/3/12, v1.0 create this file.
|
||||
* [various] Not released, Modified by Charles Lohr to change the RX behavior
|
||||
*******************************************************************************/
|
||||
#include <osapi.h>
|
||||
#include <ets_sys.h>
|
||||
|
|
Binary file not shown.
|
@ -1 +1,3 @@
|
|||
//This exists to make sure anything including stdint.h includes this instead.
|
||||
|
||||
#include "c_types.h"
|
||||
|
|
|
@ -1 +1 @@
|
|||
//Nothing here.
|
||||
//Nothing here. Just a file to make things that include <string.h> happy.
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
#include "colorchord.h"
|
||||
|
||||
static uint8_t donefirstrun;
|
||||
static int8_t sintable[512]; //Actually [sin][cos] pairs.
|
||||
|
||||
//LDD instruction on AVR can read with constant offset. We can set Y to be the place in the buffer, and read with offset.
|
||||
static uint16_t datspace[bins*4]; //(advances,places,isses,icses)
|
||||
|
||||
//
|
||||
void HandleProgressiveInt( int8_t sample1, int8_t sample2 )
|
||||
{
|
||||
int i;
|
||||
uint16_t startpl = 0;
|
||||
int16_t ts, tc;
|
||||
int16_t tmp1;
|
||||
int8_t s1, c1;
|
||||
uint16_t ipl, localipl, adv;
|
||||
|
||||
|
||||
//startpl maps to 'Y'
|
||||
//
|
||||
|
||||
|
||||
//Estimated 68 minimum instructions... So for two pairs each... just under 5ksps, theoretical.
|
||||
//Running overall at ~2kHz.
|
||||
for( i = 0; i < bins; i++ ) //Loop, fixed size = 3 + 2 cycles 5
|
||||
{
|
||||
//12 cycles MIN
|
||||
adv = datspace[startpl++]; //Read, indirect from RAM (and increment) 2+2 cycles 4
|
||||
ipl = datspace[startpl++]; //Read, indirect from RAM (and increment) 2+2 cycles 4
|
||||
|
||||
//13 cycles MIN
|
||||
ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2
|
||||
localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1
|
||||
|
||||
// need to load Z with 'sintable' and add localipl 2
|
||||
s1 = sintable[localipl++]; //Read s1 component out of table. 2+2 cycles 2
|
||||
c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2
|
||||
|
||||
ts = (s1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB ts 2
|
||||
tc = (c1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB tc 2
|
||||
|
||||
|
||||
//15 cycles MIN
|
||||
ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2
|
||||
localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1
|
||||
|
||||
// need to load Z with 'sintable' and add localipl 2
|
||||
s1 = sintable[localipl++]; //Read s1 component out of table. 2 cycles 2
|
||||
c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2
|
||||
|
||||
ts += (s1 * sample2); // 8 x 8 multiply signed + add R1 out. 3
|
||||
tc += (c1 * sample2); // 8 x 8 multiply signed + add R1 out. 3
|
||||
|
||||
|
||||
//Add TS and TC to the datspace stuff. (24 instructions)
|
||||
tmp1 = datspace[startpl]; //Read out, sin component. 4
|
||||
tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2
|
||||
tmp1 += ts>>6; //Add MSBs with carry 2
|
||||
|
||||
datspace[startpl++] = tmp1; //Store values back 4
|
||||
|
||||
tmp1 = datspace[startpl]; //Read out, sin component. 4
|
||||
tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2
|
||||
tmp1 += tc>>6; //Add MSBs with carry 2
|
||||
|
||||
datspace[startpl++] = tmp1; //Store values back 4
|
||||
|
||||
datspace[startpl-3] = ipl; //Store values back 4
|
||||
}
|
||||
}
|
||||
|
||||
void SetupConstants()
|
||||
{
|
||||
int i;
|
||||
static int last_place;
|
||||
|
||||
if( !donefirstrun )
|
||||
{
|
||||
donefirstrun = 1;
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
sintable[i*2+0] = i;//(int8_t)((sin( i / 256.0 * 6.283 ) * 127.0));
|
||||
sintable[i*2+1] = i+1;//(int8_t)((cos( i / 256.0 * 6.283 ) * 127.0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for( i = 0; i < bins; i++ )
|
||||
{
|
||||
float freq = i;//frequencies[i];
|
||||
datspace[i*4] = 65536.0/freq;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup )
|
||||
{
|
||||
int i;
|
||||
static int last_place;
|
||||
|
||||
if( !donefirstrun )
|
||||
{
|
||||
donefirstrun = 1;
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
sintable[i*2+0] = (int8_t)((sinf( i / 256.0 * 6.283 ) * 127.0));
|
||||
sintable[i*2+1] = (int8_t)((cosf( i / 256.0 * 6.283 ) * 127.0));
|
||||
}
|
||||
}
|
||||
|
||||
if( gbins != bins )
|
||||
{
|
||||
gbins = bins;
|
||||
if( datspace ) free( datspace );
|
||||
datspace = malloc( bins * 2 * 4 );
|
||||
}
|
||||
|
||||
|
||||
for( i = 0; i < bins; i++ )
|
||||
{
|
||||
float freq = frequencies[i];
|
||||
datspace[i*4] = 65536.0/freq;
|
||||
}
|
||||
|
||||
|
||||
for( i = last_place; i != ( place_in_data_buffer&0xffffe ); i = (i+2)%size_of_data_buffer )
|
||||
{
|
||||
int8_t ifr1 = (int8_t)( ((databuffer[i+0]) ) * 127 );
|
||||
int8_t ifr2 = (int8_t)( ((databuffer[i+1]) ) * 127 );
|
||||
// printf( "%d %d\n", i, place_in_data_buffer&0xffffe );
|
||||
HandleProgressiveInt( ifr1, ifr2 );
|
||||
}
|
||||
|
||||
last_place = place_in_data_buffer&0xfffe;
|
||||
|
||||
//Extract bins.
|
||||
for( i = 0; i < bins; i++ )
|
||||
{
|
||||
int16_t isps = datspace[i*4+2];
|
||||
int16_t ispc = datspace[i*4+3];
|
||||
int16_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256));
|
||||
// printf( "%d (%d %d)\n", mux, isps, ispc );
|
||||
outbins[i] = sqrt( mux )/100.0;
|
||||
}
|
||||
// printf( "\n");
|
||||
}
|
||||
|
||||
*/
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef _COLORCHORD_H
|
||||
#define _COLORCHORD_H
|
||||
|
||||
#include "mem.h"
|
||||
#include "c_types.h"
|
||||
#include "user_interface.h"
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
|
||||
#define bins 120
|
||||
|
||||
void HandleProgressiveInt( int8_t sample1, int8_t sample2 );
|
||||
void SetupConstants();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#include "hpatimer.h"
|
||||
#include <driver/adc.h>
|
||||
|
@ -56,3 +58,20 @@ void ICACHE_FLASH_ATTR StartHPATimer()
|
|||
hs_adc_start();
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR PauseHPATimer()
|
||||
{
|
||||
TM1_EDGE_INT_DISABLE();
|
||||
ETS_FRC1_INTR_DISABLE();
|
||||
system_timer_reinit();
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR ContinueHPATimer()
|
||||
{
|
||||
TM1_EDGE_INT_ENABLE();
|
||||
ETS_FRC1_INTR_ENABLE();
|
||||
system_timer_reinit();
|
||||
hs_adc_start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
//This is a tool to make the ESP8266 run its ADC and pipe the samples into
|
||||
//the sounddata fifo.
|
||||
|
||||
#ifndef _HPATIMER_H
|
||||
#define _HPATIMER_H
|
||||
|
||||
#include <c_types.h>
|
||||
#include "ccconfig.h" //For DFREQ
|
||||
|
||||
//Using a system timer on the ESP to poll the ADC in at a regular interval...
|
||||
|
||||
//BUFFSIZE must be a power-of-two
|
||||
|
@ -11,6 +19,9 @@ extern volatile uint16_t soundhead;
|
|||
|
||||
void StartHPATimer();
|
||||
|
||||
void ICACHE_FLASH_ATTR ContinueHPATimer();
|
||||
void ICACHE_FLASH_ATTR PauseHPATimer();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#include "mystuff.h"
|
||||
|
||||
char generic_print_buffer[384];
|
||||
|
||||
|
||||
void user_rf_pre_init(void)
|
||||
{
|
||||
//nothing.
|
||||
}
|
||||
|
||||
|
||||
char * strcat( char * dest, char * src )
|
||||
{
|
||||
return strcat(dest, src );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef _MYSTUFF_H
|
||||
#define _MYSTUFF_H
|
||||
|
||||
extern char generic_print_buffer[384];
|
||||
|
||||
#define printf( ... ) ets_sprintf( generic_print_buffer, __VA_ARGS__ ); uart0_sendStr( generic_print_buffer );
|
||||
|
||||
#endif
|
|
@ -1,3 +1,6 @@
|
|||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#include "mem.h"
|
||||
#include "c_types.h"
|
||||
#include "user_interface.h"
|
||||
|
@ -11,7 +14,10 @@
|
|||
#include <DFT32.h>
|
||||
#include <embeddednf.h>
|
||||
#include <embeddedout.h>
|
||||
#include "ets_sys.h"
|
||||
#include "gpio.h"
|
||||
|
||||
//#define PROFILE
|
||||
|
||||
#define PORT 7777
|
||||
#define SERVER_TIMEOUT 1500
|
||||
|
@ -30,6 +36,9 @@ extern volatile uint8_t sounddata[HPABUFFSIZE];
|
|||
extern volatile uint16_t soundhead;
|
||||
uint16_t soundtail;
|
||||
|
||||
void user_rf_pre_init()
|
||||
{
|
||||
}
|
||||
|
||||
//Call this once we've stacked together one full colorchord frame.
|
||||
static void NewFrame()
|
||||
|
@ -54,8 +63,12 @@ static void procTask(os_event_t *events)
|
|||
{
|
||||
system_os_post(procTaskPrio, 0, 0 );
|
||||
|
||||
// printf( "%d\n", sounddata[soundtail] );
|
||||
CSTick( 0 );
|
||||
|
||||
//For profiling so we can see how much CPU is spent in this loop.
|
||||
#ifdef PROFILE
|
||||
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(0), 1 );
|
||||
#endif
|
||||
while( soundtail != soundhead )
|
||||
{
|
||||
int16_t samp = sounddata[soundtail];
|
||||
|
@ -70,6 +83,9 @@ static void procTask(os_event_t *events)
|
|||
wf = 0;
|
||||
}
|
||||
}
|
||||
#ifdef PROFILE
|
||||
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(0), 0 );
|
||||
#endif
|
||||
|
||||
if( events->sig == 0 && events->par == 0 )
|
||||
{
|
||||
|
@ -109,6 +125,7 @@ static void procTask(os_event_t *events)
|
|||
//Timer event.
|
||||
static void myTimer(void *arg)
|
||||
{
|
||||
CSTick( 1 );
|
||||
// uart0_sendStr(".");
|
||||
// printf( "%d/%d\n",soundtail,soundhead );
|
||||
// printf( "%d/%d\n",soundtail,soundhead );
|
||||
|
@ -118,15 +135,14 @@ static void myTimer(void *arg)
|
|||
|
||||
|
||||
//Called when new packet comes in.
|
||||
static void ICACHE_FLASH_ATTR
|
||||
udpserver_recv(void *arg, char *pusrdata, unsigned short len)
|
||||
static void udpserver_recv(void *arg, char *pusrdata, unsigned short len)
|
||||
{
|
||||
struct espconn *pespconn = (struct espconn *)arg;
|
||||
// uint8_t buffer[MAX_FRAME];
|
||||
|
||||
// uint8_t ledout[] = { 0x00, 0xff, 0xaa, 0x00, 0xff, 0xaa, };
|
||||
uart0_sendStr("X");
|
||||
// ws2812_push( pusrdata, len );
|
||||
ws2812_push( pusrdata, len );
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR charrx( uint8_t c )
|
||||
|
@ -135,13 +151,16 @@ void ICACHE_FLASH_ATTR charrx( uint8_t c )
|
|||
}
|
||||
|
||||
|
||||
void user_init(void)
|
||||
void ICACHE_FLASH_ATTR user_init(void)
|
||||
{
|
||||
uart_init(BIT_RATE_115200, BIT_RATE_115200);
|
||||
int wifiMode = wifi_get_opmode();
|
||||
|
||||
uart0_sendStr("\r\nCustom Server\r\n");
|
||||
|
||||
#ifdef PROFILE
|
||||
GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0);
|
||||
#endif
|
||||
|
||||
wifi_set_opmode( 2 ); //We broadcast our ESSID, wait for peopel to join.
|
||||
|
||||
|
@ -170,6 +189,8 @@ void user_init(void)
|
|||
while(1) { uart0_sendStr( "\r\nFAULT\r\n" ); }
|
||||
}
|
||||
|
||||
CSInit();
|
||||
|
||||
//Add a process
|
||||
system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen);
|
||||
|
||||
|
@ -178,7 +199,7 @@ void user_init(void)
|
|||
os_timer_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL);
|
||||
os_timer_arm(&some_timer, 100, 1);
|
||||
|
||||
Init(); //Init colorchord
|
||||
InitColorChord(); //Init colorchord
|
||||
|
||||
StartHPATimer(); //Init the high speed ADC timer.
|
||||
|
||||
|
@ -187,4 +208,16 @@ void user_init(void)
|
|||
system_os_post(procTaskPrio, 0, 0 );
|
||||
}
|
||||
|
||||
void EnterCritical()
|
||||
{
|
||||
PauseHPATimer();
|
||||
//ets_intr_lock();
|
||||
}
|
||||
|
||||
void ExitCritical()
|
||||
{
|
||||
//ets_intr_unlock();
|
||||
ContinueHPATimer();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/******************************************************************************
|
||||
* Copyright 2013-2015 Espressif Systems
|
||||
* 2015 <>< Charles Lohr
|
||||
*
|
||||
* FileName: i2s_freertos.c
|
||||
*
|
||||
|
@ -27,6 +28,10 @@ Notes:
|
|||
The way it works right now is to keep the DMA running forever and just update
|
||||
the data in the buffer so it continues sending the frame.
|
||||
|
||||
Extra copyright info:
|
||||
Actually not much of this file is Copyright Espressif, comparativly little
|
||||
mostly just the stuff to make the I2S bus go.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
|
@ -392,6 +397,10 @@ void ICACHE_FLASH_ATTR ws2812_init()
|
|||
}
|
||||
|
||||
|
||||
//All functions below this line are Public Domain 2015 Charles Lohr.
|
||||
//this code may be used by anyone in any way without restriction or limitation.
|
||||
|
||||
|
||||
//Tricky, send out WS2812 bits with coded pulses, one nibble, then the other.
|
||||
static const uint16_t bitpatterns[16] = {
|
||||
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#ifndef _I2S_TEST
|
||||
#define _I2S_TEST
|
||||
//Copyright 2015 <>< Charles Lohr, See LICENSE file.
|
||||
//WS2812 sender that abuses the I2S interface on the WS2812.
|
||||
|
||||
#ifndef _WS2812I2S_TEST
|
||||
#define _WS2812I2S_TEST
|
||||
|
||||
//Stuff that should be for the header:
|
||||
|
||||
|
|
19
embedded8266/web/Makefile
Normal file
19
embedded8266/web/Makefile
Normal file
|
@ -0,0 +1,19 @@
|
|||
all : execute_reflash page.dat push
|
||||
|
||||
mfsmaker : mfsmaker.c
|
||||
gcc -o $@ $^
|
||||
|
||||
page.dat : mfsmaker page
|
||||
./mfsmaker page page.dat
|
||||
|
||||
pushtodev : pushtodev.c
|
||||
gcc -o $@ $^
|
||||
|
||||
execute_reflash : execute_reflash.c md5.c
|
||||
gcc -o $@ $^
|
||||
|
||||
push : pushtodev page.dat
|
||||
./pushtodev 192.168.4.1 1048576 page.dat
|
||||
|
||||
clean :
|
||||
rm -rf mfsmaker page.dat pushtodev execute_reflash
|
266
embedded8266/web/execute_reflash.c
Normal file
266
embedded8266/web/execute_reflash.c
Normal file
|
@ -0,0 +1,266 @@
|
|||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "md5.h"
|
||||
|
||||
#define BLOCK_SIZE 65536
|
||||
#define SECTOR_SIZE 4096
|
||||
#define PADDING 1024
|
||||
int sockfd;
|
||||
struct sockaddr_in servaddr,cliaddr;
|
||||
|
||||
int PushMatch( const char * match )
|
||||
{
|
||||
struct timeval tva, tvb;
|
||||
gettimeofday( &tva, 0 );
|
||||
gettimeofday( &tvb, 0 );
|
||||
while( tvb.tv_sec - tva.tv_sec < 3 )
|
||||
{
|
||||
struct pollfd ufds;
|
||||
ufds.fd = sockfd;
|
||||
ufds.events = POLLIN;
|
||||
int rv = poll(&ufds, 1, 100);
|
||||
if( rv > 0 )
|
||||
{
|
||||
char recvline[10000];
|
||||
int n=recvfrom(sockfd,recvline,10000,0,NULL,NULL);
|
||||
// printf( "%s === %s\n", recvline, match );
|
||||
if( strncmp( recvline, match, strlen( match ) ) == 0 )
|
||||
{
|
||||
printf( "Ok - " ); fflush( stdout );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
gettimeofday( &tvb, 0 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t Push( uint32_t offset, const char * file )
|
||||
{
|
||||
char sendline[1000];
|
||||
char recvline[1000];
|
||||
|
||||
if( offset <= 0 )
|
||||
{
|
||||
fprintf( stderr, "Error: Cannot write to address 0 or before.\n" );
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
FILE * f = fopen( file, "rb" );
|
||||
if( !f || feof( f ) )
|
||||
{
|
||||
fprintf( stderr, "Error: cannot open file.\n" );
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int devo = 0;
|
||||
int lastblock = -1;
|
||||
|
||||
while( !feof( f ) )
|
||||
{
|
||||
int tries;
|
||||
int thissuccess;
|
||||
char buffer[PADDING];
|
||||
char bufferout[2000];
|
||||
|
||||
int reads = fread( buffer, 1, PADDING, f );
|
||||
int sendplace = offset + devo;
|
||||
int sendsize = PADDING;//reads;
|
||||
int block = sendplace / BLOCK_SIZE;
|
||||
|
||||
memset( buffer + reads, 0, sendsize-reads );
|
||||
|
||||
if( block != lastblock )
|
||||
{
|
||||
char se[64];
|
||||
int sel = sprintf( se, "FB%d\r\n", block );
|
||||
|
||||
thissuccess = 0;
|
||||
for( tries = 0; tries < 10; tries++ )
|
||||
{
|
||||
char match[75];
|
||||
printf( "Erase: %d\n", block );
|
||||
sendto( sockfd, se, sel, MSG_NOSIGNAL, (struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
sprintf( match, "FB%d", block );
|
||||
|
||||
if( PushMatch(match) == 0 ) { thissuccess = 1; break; }
|
||||
printf( "Retry.\n" );
|
||||
}
|
||||
if( !thissuccess )
|
||||
{
|
||||
fprintf( stderr, "Error: Timeout in communications.\n" );
|
||||
exit( -6 );
|
||||
}
|
||||
|
||||
lastblock = block;
|
||||
}
|
||||
|
||||
|
||||
int r = sprintf( bufferout, "FW%d:%d:", sendplace, sendsize );
|
||||
memcpy( bufferout + r, buffer, sendsize );
|
||||
|
||||
printf( "bufferout: %d %d\n", sendplace, sendsize );
|
||||
|
||||
thissuccess = 0;
|
||||
for( tries = 0; tries < 10; tries++ )
|
||||
{
|
||||
char match[75];
|
||||
sendto( sockfd, bufferout, sendsize + r, MSG_NOSIGNAL, (struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
sprintf( match, "FW%d", sendplace );
|
||||
|
||||
if( PushMatch(match) == 0 ) { thissuccess = 1; break; }
|
||||
printf( "Retry.\n" );
|
||||
}
|
||||
if( !thissuccess )
|
||||
{
|
||||
fprintf( stderr, "Error: Timeout in communications.\n" );
|
||||
exit( -6 );
|
||||
}
|
||||
devo += sendsize;
|
||||
}
|
||||
|
||||
return devo;
|
||||
}
|
||||
|
||||
void ComputeMD5WithKey( char * md5retText, const char * filename, const char * key )
|
||||
{
|
||||
uint8_t retmd5[16];
|
||||
MD5_CTX ctx;
|
||||
FILE * f = fopen( filename, "rb" );
|
||||
if( !f )
|
||||
{
|
||||
fprintf( stderr, "Error opening %s\n", filename );
|
||||
exit( -9 );
|
||||
}
|
||||
|
||||
fseek( f, 0, SEEK_END );
|
||||
int l = ftell( f );
|
||||
printf("MD5 Size: %d\n", l );
|
||||
int padl = ((l-1) / PADDING)*PADDING+PADDING;
|
||||
printf("MD5 Pad: %d\n", padl );
|
||||
fseek( f, 0, SEEK_SET );
|
||||
uint8_t data[padl];
|
||||
fread( data, l, 1, f );
|
||||
fclose( f );
|
||||
|
||||
memset( data+l, 0, padl-l );
|
||||
MD5_Init( &ctx );
|
||||
if( !strlen(key) )
|
||||
MD5_Update( &ctx, key, strlen( key ) );
|
||||
MD5_Update( &ctx, data, padl );
|
||||
MD5_Final( retmd5, &ctx );
|
||||
|
||||
for( l = 0; l < 16; l++ )
|
||||
{
|
||||
sprintf( md5retText + l*2, "%02x", retmd5[l] );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t roundup( uint32_t r )
|
||||
{
|
||||
return ((r-1)&(~0xFFF))+0x1000;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
int n;
|
||||
|
||||
char sendline[1000];
|
||||
char recvline[1000];
|
||||
|
||||
char md5_f1[48];
|
||||
char md5_f2[48];
|
||||
|
||||
if (argc < 4 )
|
||||
{
|
||||
printf("usage: pushtodev [IP address] [file_lower] [file_upper] [key (optional)]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
const char * file1 = argv[2];
|
||||
const char * file2 = argv[3];
|
||||
|
||||
|
||||
|
||||
sockfd=socket(AF_INET,SOCK_DGRAM,0);
|
||||
|
||||
bzero(&servaddr,sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr=inet_addr(argv[1]);
|
||||
servaddr.sin_port=htons(7878);
|
||||
|
||||
uint32_t fs1 = Push( 0x080000, file1 );
|
||||
uint32_t fs2 = Push( 0x0c0000, file2 );
|
||||
|
||||
if( !fs1 || !fs2 )
|
||||
{
|
||||
fprintf( stderr, "Error: File size not acceptable.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char * dat = "";
|
||||
if( argc == 5 )
|
||||
{
|
||||
dat = argv[4];
|
||||
}
|
||||
|
||||
ComputeMD5WithKey( md5_f1, file1, dat );
|
||||
ComputeMD5WithKey( md5_f2, file2, dat );
|
||||
|
||||
printf( "%s %s\n", md5_f1, md5_f2 );
|
||||
|
||||
//FM[from_address]:[to_address]:[size]:[MD5(key+data)]:[from_address]:[to_address]:[size]:[MD5(key+data)]
|
||||
|
||||
char cmd[1024];
|
||||
|
||||
sprintf( cmd, "FM%d:%d:%d:%s:%d:%d:%d:%s\n",
|
||||
0x080000,
|
||||
0x000000,
|
||||
fs1, //roundup( fs1 ),
|
||||
md5_f1,
|
||||
0x0C0000,
|
||||
0x040000,
|
||||
fs2, //roundup( fs2 ),
|
||||
md5_f2 );
|
||||
|
||||
printf( "Issuing: %s\n", cmd );
|
||||
sendto( sockfd, cmd, strlen(cmd), MSG_NOSIGNAL, (struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
usleep(10000);
|
||||
sendto( sockfd, cmd, strlen(cmd), MSG_NOSIGNAL, (struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
|
||||
struct pollfd ufds;
|
||||
ufds.fd = sockfd;
|
||||
ufds.events = POLLIN;
|
||||
int rv = poll(&ufds, 1, 100);
|
||||
if( rv > 0 )
|
||||
{
|
||||
char recvline[10000];
|
||||
int n=recvfrom(sockfd,recvline,10000,0,NULL,NULL);
|
||||
|
||||
printf( "Response: %s\n",recvline );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Timeout. Good? Maybe?\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
296
embedded8266/web/md5.c
Normal file
296
embedded8266/web/md5.c
Normal file
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_OPENSSL
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
* The basic MD5 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1321 definitions for
|
||||
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
|
||||
* implementation.
|
||||
*/
|
||||
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
|
||||
#define H(x, y, z) (((x) ^ (y)) ^ (z))
|
||||
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
|
||||
/*
|
||||
* The MD5 transformation for all four rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, t, s) \
|
||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
|
||||
(a) += (b);
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them
|
||||
* in a properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned
|
||||
* memory accesses is just an optimization. Nothing will break if it
|
||||
* doesn't work.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) \
|
||||
(*(MD5_u32plus *)&ptr[(n) * 4])
|
||||
#define GET(n) \
|
||||
SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = \
|
||||
(MD5_u32plus)ptr[(n) * 4] | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
|
||||
#define GET(n) \
|
||||
(ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update
|
||||
* the bit counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
const unsigned char *ptr;
|
||||
MD5_u32plus a, b, c, d;
|
||||
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
|
||||
|
||||
ptr = (const unsigned char *)data;
|
||||
|
||||
a = ctx->a;
|
||||
b = ctx->b;
|
||||
c = ctx->c;
|
||||
d = ctx->d;
|
||||
|
||||
do {
|
||||
saved_a = a;
|
||||
saved_b = b;
|
||||
saved_c = c;
|
||||
saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
||||
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
||||
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
||||
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
||||
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
||||
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
||||
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
||||
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
||||
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
||||
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
||||
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
||||
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
||||
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
||||
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
||||
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
||||
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
||||
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
||||
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
||||
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
||||
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
||||
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
||||
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
||||
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
||||
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
||||
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
||||
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
||||
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
||||
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
||||
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
||||
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
||||
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
||||
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
|
||||
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
||||
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
|
||||
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
||||
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
||||
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
||||
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
||||
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
||||
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
||||
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
||||
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
|
||||
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
||||
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
||||
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
||||
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
||||
|
||||
/* Round 4 */
|
||||
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
||||
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
||||
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
||||
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
||||
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
||||
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
||||
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
||||
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
||||
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
||||
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
||||
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
||||
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
||||
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
||||
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
||||
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
||||
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void MD5_Init(MD5_CTX *ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
MD5_u32plus saved_lo;
|
||||
unsigned long used, available;
|
||||
|
||||
saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
used = saved_lo & 0x3f;
|
||||
|
||||
if (used) {
|
||||
available = 64 - used;
|
||||
|
||||
if (size < available) {
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char *)data + available;
|
||||
size -= available;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64) {
|
||||
data = body(ctx, data, size & ~(unsigned long)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
||||
{
|
||||
unsigned long used, available;
|
||||
|
||||
used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
available = 64 - used;
|
||||
|
||||
if (available < 8) {
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
ctx->buffer[56] = ctx->lo;
|
||||
ctx->buffer[57] = ctx->lo >> 8;
|
||||
ctx->buffer[58] = ctx->lo >> 16;
|
||||
ctx->buffer[59] = ctx->lo >> 24;
|
||||
ctx->buffer[60] = ctx->hi;
|
||||
ctx->buffer[61] = ctx->hi >> 8;
|
||||
ctx->buffer[62] = ctx->hi >> 16;
|
||||
ctx->buffer[63] = ctx->hi >> 24;
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
result[0] = ctx->a;
|
||||
result[1] = ctx->a >> 8;
|
||||
result[2] = ctx->a >> 16;
|
||||
result[3] = ctx->a >> 24;
|
||||
result[4] = ctx->b;
|
||||
result[5] = ctx->b >> 8;
|
||||
result[6] = ctx->b >> 16;
|
||||
result[7] = ctx->b >> 24;
|
||||
result[8] = ctx->c;
|
||||
result[9] = ctx->c >> 8;
|
||||
result[10] = ctx->c >> 16;
|
||||
result[11] = ctx->c >> 24;
|
||||
result[12] = ctx->d;
|
||||
result[13] = ctx->d >> 8;
|
||||
result[14] = ctx->d >> 16;
|
||||
result[15] = ctx->d >> 24;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#endif
|
45
embedded8266/web/md5.h
Normal file
45
embedded8266/web/md5.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md5.c for more information.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/md5.h>
|
||||
#elif !defined(_MD5_H)
|
||||
#define _MD5_H
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef unsigned int MD5_u32plus;
|
||||
|
||||
typedef struct {
|
||||
MD5_u32plus lo, hi;
|
||||
MD5_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
MD5_u32plus block[16];
|
||||
} MD5_CTX;
|
||||
|
||||
extern void MD5_Init(MD5_CTX *ctx);
|
||||
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
|
||||
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
|
||||
|
||||
#endif
|
139
embedded8266/web/mfsmaker.c
Normal file
139
embedded8266/web/mfsmaker.c
Normal file
|
@ -0,0 +1,139 @@
|
|||
|
||||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPI_FLASH_SEC_SIZE 4096
|
||||
#define MFS_STARTFLASHSECTOR 0x100
|
||||
#define MFS_START (MFS_STARTFLASHSECTOR*SPI_FLASH_SEC_SIZE)
|
||||
#define MFS_SECTOR 256
|
||||
#define MFS_FILENAMELEN 32-8
|
||||
#define ENTRIES 8192
|
||||
|
||||
#define ENDIAN(x) x//htonl
|
||||
|
||||
struct MFSFileEntry
|
||||
{
|
||||
char name[MFS_FILENAMELEN];
|
||||
uint32_t start; //From beginning of mfs thing.
|
||||
uint32_t len;
|
||||
} mfsfat[ENTRIES];
|
||||
|
||||
unsigned char mfsdata[131072*8];
|
||||
|
||||
unsigned long fatpointer = 0;
|
||||
unsigned long datapointer = 0;
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
int i;
|
||||
DIR *d;
|
||||
struct dirent *dir;
|
||||
|
||||
if( argc != 3 )
|
||||
{
|
||||
fprintf( stderr, "Error: [tool] [directory to pack] [output packed .dat file]\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
d = opendir( argv[1] );
|
||||
|
||||
if (!d)
|
||||
{
|
||||
fprintf( stderr, "Error: cannot open folder for packing.\n" );
|
||||
return -2;
|
||||
}
|
||||
|
||||
while ((dir = readdir(d)) != NULL)
|
||||
{
|
||||
if( dir->d_type & DT_REG )
|
||||
{
|
||||
char thisfile[1024];
|
||||
struct stat buf;
|
||||
int dlen = strlen( dir->d_name );
|
||||
int sprret = snprintf( thisfile, 1023, "%s/%s", argv[1], dir->d_name );
|
||||
|
||||
if( sprret > 1023 || sprret < 1 )
|
||||
{
|
||||
fprintf( stderr, "Error processing \"%s\" (snprintf)\n", dir->d_name );
|
||||
continue;
|
||||
}
|
||||
|
||||
int statret = stat( thisfile, &buf );
|
||||
|
||||
if( statret )
|
||||
{
|
||||
fprintf( stderr, "Error processing \"%s\" (stat)\n", dir->d_name );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( dlen >= MFS_FILENAMELEN )
|
||||
{
|
||||
fprintf( stderr, "Warning: Fle \"%s\" too long.\n", dir->d_name );
|
||||
continue;
|
||||
}
|
||||
if( fatpointer > ENTRIES )
|
||||
{
|
||||
fprintf( stderr, "Warning: Not enough entries to fit \"%s\".\n", dir->d_name );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( buf.st_size + datapointer > sizeof( mfsdata ) )
|
||||
{
|
||||
fprintf( stderr, "Error: no space left.\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy( mfsfat[fatpointer].name, dir->d_name, dlen );
|
||||
mfsfat[fatpointer].start = datapointer;
|
||||
mfsfat[fatpointer].len = ENDIAN( buf.st_size );
|
||||
fatpointer++;
|
||||
|
||||
if( buf.st_size )
|
||||
{
|
||||
FILE * f = fopen( thisfile, "rb" );
|
||||
if( !f )
|
||||
{
|
||||
fprintf( stderr, "Error: cannot open \"%s\" for reading.\n", dir->d_name );
|
||||
return -9;
|
||||
}
|
||||
fread( &mfsdata[datapointer], 1, buf.st_size, f );
|
||||
fclose( f );
|
||||
int rs = buf.st_size;
|
||||
rs = (rs+1+MFS_SECTOR)&(~(MFS_SECTOR-1));
|
||||
datapointer += rs;
|
||||
printf( "%s: %d (%d)\n", thisfile, rs, datapointer );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
int rs = (fatpointer+1)*sizeof(struct MFSFileEntry);
|
||||
rs = (rs+1+MFS_SECTOR)&(~(MFS_SECTOR-1));
|
||||
for( i = 0; i < fatpointer; i++ )
|
||||
{
|
||||
mfsfat[i].start = ENDIAN(mfsfat[i].start + rs );
|
||||
}
|
||||
|
||||
printf( "%d %d\n", rs, datapointer );
|
||||
|
||||
FILE * f = fopen( argv[2], "w" );
|
||||
|
||||
if( !f || ferror( f ) )
|
||||
{
|
||||
fprintf( stderr, "Error: cannot open \"%s\" for writing.\n", argv[2] );
|
||||
}
|
||||
fwrite( mfsfat, rs, 1, f );
|
||||
fwrite( mfsdata, datapointer, 1, f );
|
||||
fclose( f );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
8
embedded8266/web/page/index.html
Normal file
8
embedded8266/web/page/index.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<HTML>
|
||||
<BODY>
|
||||
Hello! This is a test page.<BR>
|
||||
|
||||
<IMG SRC=dsc.jpg>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
1
embedded8266/web/page/test.txt
Normal file
1
embedded8266/web/page/test.txt
Normal file
|
@ -0,0 +1 @@
|
|||
test
|
69
embedded8266/web/page/websocket.js
Normal file
69
embedded8266/web/page/websocket.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
var wsUri = "ws://" + location.host + "/d/ws";
|
||||
|
||||
var output;
|
||||
|
||||
function init()
|
||||
{
|
||||
output = document.getElementById("output");
|
||||
console.log( wsUri );
|
||||
testWebSocket();
|
||||
}
|
||||
|
||||
function testWebSocket()
|
||||
{
|
||||
websocket = new WebSocket(wsUri);
|
||||
websocket.onopen = function(evt) { onOpen(evt) };
|
||||
websocket.onclose = function(evt) { onClose(evt) };
|
||||
websocket.onmessage = function(evt) { onMessage(evt) };
|
||||
websocket.onerror = function(evt) { onError(evt) };
|
||||
}
|
||||
|
||||
function repeatsend()
|
||||
{
|
||||
doSend('Hello!' );
|
||||
setTimeout( repeatsend, 1000 );
|
||||
}
|
||||
|
||||
function onOpen(evt)
|
||||
{
|
||||
writeToScreen("CONNECTED");
|
||||
doSend('Hello.' );
|
||||
//repeatsend();
|
||||
// doSend('{"args": ["entity", 1000], "kwargs": {}, "op": "ClientUpdater__requestUpdates", "seq": 1, "context": ["ClientUpdater", 0]}');
|
||||
}
|
||||
|
||||
function onClose(evt)
|
||||
{
|
||||
writeToScreen("DISCONNECTED");
|
||||
}
|
||||
|
||||
function onMessage(evt)
|
||||
{
|
||||
eval( evt.data );
|
||||
// obj = JSON.parse(evt.data);
|
||||
// console.log( obj );
|
||||
// writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
|
||||
// websocket.close();
|
||||
}
|
||||
|
||||
function onError(evt)
|
||||
{
|
||||
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
|
||||
}
|
||||
|
||||
function doSend(message)
|
||||
{
|
||||
writeToScreen("SENT: " + message);
|
||||
websocket.send(message);
|
||||
}
|
||||
|
||||
function writeToScreen(message)
|
||||
{
|
||||
var pre = document.createElement("p");
|
||||
pre.style.wordWrap = "break-word";
|
||||
pre.innerHTML = message;
|
||||
output.appendChild(pre);
|
||||
}
|
||||
|
||||
window.addEventListener("load", init, false);
|
||||
|
10
embedded8266/web/page/wstest.html
Normal file
10
embedded8266/web/page/wstest.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<title>WebSocket Test</title>
|
||||
<script language="javascript" type="text/javascript" src=websocket.js></script>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<h2>WebSocket Test</h2>
|
||||
<div id="output"></div>
|
||||
</BODY>
|
||||
</HTML>
|
202
embedded8266/web/pushtodev.c
Normal file
202
embedded8266/web/pushtodev.c
Normal file
|
@ -0,0 +1,202 @@
|
|||
//Unless what else is individually marked, all code in this file is
|
||||
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
|
||||
// ColorChord License. You Choose.
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define sector_SIZE 4096
|
||||
int sockfd;
|
||||
char recvline[10000];
|
||||
|
||||
|
||||
int PushMatch( const char * match )
|
||||
{
|
||||
struct timeval tva, tvb;
|
||||
gettimeofday( &tva, 0 );
|
||||
gettimeofday( &tvb, 0 );
|
||||
while( tvb.tv_sec - tva.tv_sec < 3 ) //3 second timeout.
|
||||
{
|
||||
struct pollfd ufds;
|
||||
ufds.fd = sockfd;
|
||||
ufds.events = POLLIN;
|
||||
int rv = poll(&ufds, 1, 500);
|
||||
if( rv > 0 )
|
||||
{
|
||||
// tbuf = recvline;
|
||||
int n=recvfrom(sockfd,recvline,10000,0,NULL,NULL);
|
||||
// printf( "!!%d ->%s\n", n,recvline );
|
||||
// printf( "%s === %s\n", recvline, match );
|
||||
if( strncmp( recvline, match, strlen( match ) ) == 0 )
|
||||
{
|
||||
// printf( "Ok\n" ); fflush( stdout );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
gettimeofday( &tvb, 0 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
int n;
|
||||
struct sockaddr_in servaddr,cliaddr;
|
||||
char sendline[1000];
|
||||
// char recvline[1000];
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
printf("usage: pushtodev [IP address] [address offset] [file]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int offset = atoi( argv[2] );
|
||||
const char * file = argv[3];
|
||||
|
||||
if( offset <= 0 )
|
||||
{
|
||||
fprintf( stderr, "Error: Cannot write to address 0 or before.\n" );
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
FILE * f = fopen( file, "rb" );
|
||||
if( !f || feof( f ) )
|
||||
{
|
||||
fprintf( stderr, "Error: cannot open file.\n" );
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
sockfd=socket(AF_INET,SOCK_DGRAM,0);
|
||||
|
||||
bzero(&servaddr,sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr=inet_addr(argv[1]);
|
||||
servaddr.sin_port=htons(7878);
|
||||
|
||||
int devo = 0;
|
||||
int lastsector = -1;
|
||||
int resend_times = 0;
|
||||
int r;
|
||||
while( !feof( f ) )
|
||||
{
|
||||
int tries;
|
||||
int thissuccess;
|
||||
char buffer[1024];
|
||||
char bufferout[1600];
|
||||
int reads = fread( buffer, 1, 1024, f );
|
||||
int sendplace = offset + devo;
|
||||
int sendsize = reads;
|
||||
int sector = sendplace / sector_SIZE;
|
||||
|
||||
if( sector != lastsector )
|
||||
{
|
||||
char se[64];
|
||||
int sel = sprintf( se, "FE%d\r\n", sector );
|
||||
|
||||
thissuccess = 0;
|
||||
for( tries = 0; tries < 10; tries++ )
|
||||
{
|
||||
char match[75];
|
||||
printf( "Erase: %d\n", sector );
|
||||
sendto( sockfd, se, sel, MSG_NOSIGNAL, (struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
sprintf( match, "FE%d", sector );
|
||||
|
||||
if( PushMatch(match) == 0 ) { thissuccess = 1; break; }
|
||||
printf( "Retry.\n" );
|
||||
}
|
||||
if( !thissuccess )
|
||||
{
|
||||
fprintf( stderr, "Error: Timeout in communications.\n" );
|
||||
exit( -6 );
|
||||
}
|
||||
|
||||
lastsector = sector;
|
||||
}
|
||||
|
||||
resend_times = 0;
|
||||
resend:
|
||||
r = sprintf( bufferout, "FW%d:%d:", sendplace, sendsize );
|
||||
printf( "bufferout: %d %d %s\n", sendplace, sendsize, bufferout );
|
||||
memcpy( bufferout + r, buffer, sendsize );
|
||||
|
||||
|
||||
thissuccess = 0;
|
||||
for( tries = 0; tries < 10; tries++ )
|
||||
{
|
||||
char match[75];
|
||||
sendto( sockfd, bufferout, reads + r, MSG_NOSIGNAL, (struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
|
||||
sprintf( match, "FW%d", sendplace );
|
||||
|
||||
if( PushMatch(match) == 0 ) { thissuccess = 1; break; }
|
||||
printf( "Retry.\n" );
|
||||
}
|
||||
if( !thissuccess )
|
||||
{
|
||||
fprintf( stderr, "Error: Timeout in communications.\n" );
|
||||
exit( -6 );
|
||||
}
|
||||
|
||||
/*
|
||||
printf( "Verifying..." );
|
||||
fflush( stdout );
|
||||
|
||||
int r = sprintf( bufferout, "FR%d:%d", sendplace, sendsize );
|
||||
bufferout[r] = 0;
|
||||
|
||||
thissuccess = 0;
|
||||
for( tries = 0; tries < 10; tries++ )
|
||||
{
|
||||
char match[1600];
|
||||
sendto( sockfd, bufferout, r, MSG_NOSIGNAL, (struct sockaddr *)&servaddr,sizeof(servaddr));
|
||||
devo += reads;
|
||||
sprintf( match, "FR%08d", sendplace );
|
||||
|
||||
if( PushMatch(match) == 0 ) {
|
||||
|
||||
//Check data...
|
||||
//printf( "RR:%s\n", recvline );
|
||||
char * colon1 = strchr( recvline, ':' );
|
||||
char * colon2 = (colon1)?strchr( colon1+1, ':' ):0;
|
||||
//printf( "::%p %p \"%s\"\n", colon1, colon2,recvline );
|
||||
if( colon2 )
|
||||
{
|
||||
if( memcmp( colon2+1, buffer, sendsize ) == 0 )
|
||||
thissuccess = 1;
|
||||
}
|
||||
|
||||
if( !thissuccess )
|
||||
{
|
||||
if( resend_times > 2 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
resend_times++;
|
||||
goto resend;
|
||||
}
|
||||
break;
|
||||
}
|
||||
printf( "Retry.\n" );
|
||||
}
|
||||
if( !thissuccess )
|
||||
{
|
||||
fprintf( stderr, "Error: Fault verifying.\n" );
|
||||
exit( -6 );
|
||||
}
|
||||
*/
|
||||
devo += reads;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue