diff --git a/embedded8266/0x00000.bin b/embedded8266/0x00000.bin deleted file mode 100644 index 78cc1cd..0000000 Binary files a/embedded8266/0x00000.bin and /dev/null differ diff --git a/embedded8266/0x40000.bin b/embedded8266/0x40000.bin deleted file mode 100644 index 27ace10..0000000 Binary files a/embedded8266/0x40000.bin and /dev/null differ diff --git a/embedded8266/LICENSE b/embedded8266/LICENSE index 5e01f6c..ca83dc1 100644 --- a/embedded8266/LICENSE +++ b/embedded8266/LICENSE @@ -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 diff --git a/embedded8266/Makefile b/embedded8266/Makefile index f551217..d574ae0 100644 --- a/embedded8266/Makefile +++ b/embedded8266/Makefile @@ -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) diff --git a/embedded8266/README.md b/embedded8266/README.md index e245930..dafa186 100644 --- a/embedded8266/README.md +++ b/embedded8266/README.md @@ -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: diff --git a/embedded8266/ccconfig.h b/embedded8266/ccconfig.h new file mode 100644 index 0000000..cf0c2de --- /dev/null +++ b/embedded8266/ccconfig.h @@ -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 + diff --git a/embedded8266/common/commonservices.c b/embedded8266/common/commonservices.c new file mode 100644 index 0000000..14ac1bf --- /dev/null +++ b/embedded8266/common/commonservices.c @@ -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); + } +} + diff --git a/embedded8266/common/commonservices.h b/embedded8266/common/commonservices.h new file mode 100644 index 0000000..2d6afbd --- /dev/null +++ b/embedded8266/common/commonservices.h @@ -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 + diff --git a/embedded8266/common/esp8266_rom.h b/embedded8266/common/esp8266_rom.h new file mode 100644 index 0000000..96d839b --- /dev/null +++ b/embedded8266/common/esp8266_rom.h @@ -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 +#include + +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 + + diff --git a/embedded8266/common/flash_rewriter.c b/embedded8266/common/flash_rewriter.c new file mode 100644 index 0000000..0af9225 --- /dev/null +++ b/embedded8266/common/flash_rewriter.c @@ -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 +#include +#include + +#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 ); << 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 diff --git a/embedded8266/common/http.c b/embedded8266/common/http.c new file mode 100644 index 0000000..2283b31 --- /dev/null +++ b/embedded8266/common/http.c @@ -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 ); +} + + diff --git a/embedded8266/common/http.h b/embedded8266/common/http.h new file mode 100644 index 0000000..4504344 --- /dev/null +++ b/embedded8266/common/http.h @@ -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 + diff --git a/embedded8266/common/http_custom.c b/embedded8266/common/http_custom.c new file mode 100644 index 0000000..9399fcb --- /dev/null +++ b/embedded8266/common/http_custom.c @@ -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() +{ +} + diff --git a/embedded8266/common/mfs.c b/embedded8266/common/mfs.c new file mode 100644 index 0000000..6b9f6d2 --- /dev/null +++ b/embedded8266/common/mfs.c @@ -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; +} + + + diff --git a/embedded8266/common/mfs.h b/embedded8266/common/mfs.h new file mode 100644 index 0000000..8f9d526 --- /dev/null +++ b/embedded8266/common/mfs.h @@ -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 + + diff --git a/embedded8266/common/mystuff.c b/embedded8266/common/mystuff.c new file mode 100644 index 0000000..145f464 --- /dev/null +++ b/embedded8266/common/mystuff.c @@ -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; +} + diff --git a/embedded8266/common/mystuff.h b/embedded8266/common/mystuff.h new file mode 100644 index 0000000..6ebc87b --- /dev/null +++ b/embedded8266/common/mystuff.h @@ -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 +#include +#include +#include +#include + +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 diff --git a/embedded8266/driver/adc.c b/embedded8266/driver/adc.c index 5a93c77..e03b8e2 100644 --- a/embedded8266/driver/adc.c +++ b/embedded8266/driver/adc.c @@ -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" diff --git a/embedded8266/driver/uart.c b/embedded8266/driver/uart.c index e6c043a..96c1422 100644 --- a/embedded8266/driver/uart.c +++ b/embedded8266/driver/uart.c @@ -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 #include diff --git a/embedded8266/image.elf b/embedded8266/image.elf index 66c23c4..7b0599d 100755 Binary files a/embedded8266/image.elf and b/embedded8266/image.elf differ diff --git a/embedded8266/include/stdint.h b/embedded8266/include/stdint.h index a48f79f..c185b36 100644 --- a/embedded8266/include/stdint.h +++ b/embedded8266/include/stdint.h @@ -1 +1,3 @@ +//This exists to make sure anything including stdint.h includes this instead. + #include "c_types.h" diff --git a/embedded8266/include/string.h b/embedded8266/include/string.h index bb97dcd..411d27f 100644 --- a/embedded8266/include/string.h +++ b/embedded8266/include/string.h @@ -1 +1 @@ -//Nothing here. +//Nothing here. Just a file to make things that include happy. diff --git a/embedded8266/user/colorchord.c b/embedded8266/user/colorchord.c deleted file mode 100644 index 9fd5152..0000000 --- a/embedded8266/user/colorchord.c +++ /dev/null @@ -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"); -} - -*/ diff --git a/embedded8266/user/colorchord.h b/embedded8266/user/colorchord.h deleted file mode 100644 index 714deb8..0000000 --- a/embedded8266/user/colorchord.h +++ /dev/null @@ -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 - - diff --git a/embedded8266/user/hpatimer.c b/embedded8266/user/hpatimer.c index 619a080..a2b0edc 100644 --- a/embedded8266/user/hpatimer.c +++ b/embedded8266/user/hpatimer.c @@ -1,3 +1,5 @@ +//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or +// ColorChord License. You Choose. #include "hpatimer.h" #include @@ -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(); +} + + + diff --git a/embedded8266/user/hpatimer.h b/embedded8266/user/hpatimer.h index 46503d9..306c501 100644 --- a/embedded8266/user/hpatimer.h +++ b/embedded8266/user/hpatimer.h @@ -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 +#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 diff --git a/embedded8266/user/mystuff.c b/embedded8266/user/mystuff.c deleted file mode 100644 index a4c024c..0000000 --- a/embedded8266/user/mystuff.c +++ /dev/null @@ -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 ); -} - - - diff --git a/embedded8266/user/mystuff.h b/embedded8266/user/mystuff.h deleted file mode 100644 index 76a3a6b..0000000 --- a/embedded8266/user/mystuff.h +++ /dev/null @@ -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 diff --git a/embedded8266/user/user_main.c b/embedded8266/user/user_main.c index 6277755..bc74b53 100644 --- a/embedded8266/user/user_main.c +++ b/embedded8266/user/user_main.c @@ -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 #include #include +#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(); +} + diff --git a/embedded8266/user/ws2812_i2s.c b/embedded8266/user/ws2812_i2s.c index d4c0edf..88f8eb7 100644 --- a/embedded8266/user/ws2812_i2s.c +++ b/embedded8266/user/ws2812_i2s.c @@ -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, diff --git a/embedded8266/user/ws2812_i2s.h b/embedded8266/user/ws2812_i2s.h index e20785f..fff35cc 100644 --- a/embedded8266/user/ws2812_i2s.h +++ b/embedded8266/user/ws2812_i2s.h @@ -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: diff --git a/embedded8266/web/Makefile b/embedded8266/web/Makefile new file mode 100644 index 0000000..bfeddb3 --- /dev/null +++ b/embedded8266/web/Makefile @@ -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 diff --git a/embedded8266/web/execute_reflash.c b/embedded8266/web/execute_reflash.c new file mode 100644 index 0000000..652ccc6 --- /dev/null +++ b/embedded8266/web/execute_reflash.c @@ -0,0 +1,266 @@ +//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or +// ColorChord License. You Choose. + +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} + + diff --git a/embedded8266/web/md5.c b/embedded8266/web/md5.c new file mode 100644 index 0000000..52d96ac --- /dev/null +++ b/embedded8266/web/md5.c @@ -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 + * + * 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 + +#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 diff --git a/embedded8266/web/md5.h b/embedded8266/web/md5.h new file mode 100644 index 0000000..2da44bf --- /dev/null +++ b/embedded8266/web/md5.h @@ -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 + * + * 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 +#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 diff --git a/embedded8266/web/mfsmaker.c b/embedded8266/web/mfsmaker.c new file mode 100644 index 0000000..ad67c7c --- /dev/null +++ b/embedded8266/web/mfsmaker.c @@ -0,0 +1,139 @@ + +//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or +// ColorChord License. You Choose. + +#include +#include +#include +#include +#include + +#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; +} + + diff --git a/embedded8266/web/page/index.html b/embedded8266/web/page/index.html new file mode 100644 index 0000000..c8d934f --- /dev/null +++ b/embedded8266/web/page/index.html @@ -0,0 +1,8 @@ + + +Hello! This is a test page.
+ + + + + diff --git a/embedded8266/web/page/test.txt b/embedded8266/web/page/test.txt new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/embedded8266/web/page/test.txt @@ -0,0 +1 @@ +test diff --git a/embedded8266/web/page/websocket.js b/embedded8266/web/page/websocket.js new file mode 100644 index 0000000..a73f78d --- /dev/null +++ b/embedded8266/web/page/websocket.js @@ -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('RESPONSE: ' + evt.data+''); + // websocket.close(); +} + +function onError(evt) +{ + writeToScreen('ERROR: ' + 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); + diff --git a/embedded8266/web/page/wstest.html b/embedded8266/web/page/wstest.html new file mode 100644 index 0000000..e14fa89 --- /dev/null +++ b/embedded8266/web/page/wstest.html @@ -0,0 +1,10 @@ + + +WebSocket Test + + + +

WebSocket Test

+
+ + diff --git a/embedded8266/web/pushtodev.c b/embedded8266/web/pushtodev.c new file mode 100644 index 0000000..615db44 --- /dev/null +++ b/embedded8266/web/pushtodev.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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; +}