Update ESP8266 version

This commit is contained in:
cnlohr 2015-07-29 01:54:49 -04:00
parent 102219f9a7
commit ff2cd22d9a
42 changed files with 3035 additions and 213 deletions

Binary file not shown.

Binary file not shown.

View file

@ -1,7 +1,8 @@
*Note if you use the ESP8266 port, you are bound to this license as well as *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 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 and the other is a MIT-based license, but this is not really a problem for
people want) the ESP8266 as long as you follow the ColorChord license and only use it on
the ESP8266)
ESPRSSIF MIT License ESPRSSIF MIT License

View file

@ -6,14 +6,19 @@ TARGET_OUT:=image.elf
SRCS:=driver/uart.c \ 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/ws2812_i2s.c \
user/hpatimer.c \ user/hpatimer.c \
driver/adc.c \ driver/adc.c \
../embeddedcommon/DFT32.c \ ../embeddedcommon/DFT32.c \
../embeddedcommon/embeddednf.c \ ../embeddedcommon/embeddednf.c \
../embeddedcommon/embeddedout.c \ ../embeddedcommon/embeddedout.c \
user/user_main.c user/user_main.c \
common/commonservices.c
GCC_FOLDER:=~/esp8266/esp-open-sdk/xtensa-lx106-elf GCC_FOLDER:=~/esp8266/esp-open-sdk/xtensa-lx106-elf
ESPTOOL_PY:=~/esp8266/esptool/esptool.py ESPTOOL_PY:=~/esp8266/esptool/esptool.py
@ -28,28 +33,32 @@ FOLDERPREFIX:=$(GCC_FOLDER)/bin
PREFIX:=$(FOLDERPREFIX)/xtensa-lx106-elf- PREFIX:=$(FOLDERPREFIX)/xtensa-lx106-elf-
CC:=$(PREFIX)gcc CC:=$(PREFIX)gcc
CFLAGS:=-mlongcalls -I$(SDK)/include -Imyclib -Iinclude -Iuser -Os -I$(SDK)/include/ -I../embeddedcommon -Dmemcpy=ets_memcpy -Dmemset=ets_memset \ CFLAGS:=-mlongcalls -I$(SDK)/include -Imyclib -Iinclude -Iuser -Os -I$(SDK)/include/ -I../embeddedcommon -I. -Icommon -DICACHE_FLASH
-DDFREQ=16000 -DCCEMBEDDED -DNUM_LIN_LEDS=24
#-DFREQ==12500 seems to work well. #-DFREQ==12500 seems to work well.
LDFLAGS_CORE:=\ LDFLAGS_CORE:=\
-nostdlib \ -nostdlib \
-Wl,--relax -Wl,--gc-sections \
-L$(XTLIB) \ -L$(XTLIB) \
-L$(XTGCCLIB) \ -L$(XTGCCLIB) \
$(SDK)/lib/libmain.a \
$(SDK)/lib/liblwip.a \ $(SDK)/lib/liblwip.a \
$(SDK)/lib/libssl.a \ $(SDK)/lib/libssl.a \
$(SDK)/lib/libupgrade.a \ $(SDK)/lib/libupgrade.a \
$(SDK)/lib/libnet80211.a \ $(SDK)/lib/libnet80211.a \
$(SDK)/lib/liblwip.a \
$(SDK)/lib/libwpa.a \ $(SDK)/lib/libwpa.a \
$(SDK)/lib/libnet80211.a \ $(SDK)/lib/libnet80211.a \
$(SDK)/lib/libphy.a \ $(SDK)/lib/libphy.a \
$(SDK)/lib/libmain.a \ $(SDK)/lib/liblwip.a \
$(SDK)/lib/libpp.a \ $(SDK)/lib/libpp.a \
$(SDK)/lib/libmain.a \
$(XTGCCLIB) \ $(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:= \ LINKFLAGS:= \
$(LDFLAGS_CORE) \ $(LDFLAGS_CORE) \
@ -59,7 +68,7 @@ LINKFLAGS:= \
# $(PREFIX)ld $^ $(LDFLAGS) -o $@ # $(PREFIX)ld $^ $(LDFLAGS) -o $@
$(TARGET_OUT) : $(SRCS) $(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 $@" @echo "FW $@"
$(FW_TOOL) -eo $(TARGET_OUT) -es .irom0.text $@ -ec $(FW_TOOL) -eo $(TARGET_OUT) -es .irom0.text $@ -ec
IP?=192.168.4.1
burn : $(FW_FILE_1) $(FW_FILE_2) burn : $(FW_FILE_1) $(FW_FILE_2)
($(ESPTOOL_PY) --port $(PORT) write_flash 0x00000 0x00000.bin 0x40000 0x40000.bin)||(true) ($(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 : clean :
rm -rf user/*.o driver/*.o $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) rm -rf user/*.o driver/*.o $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2)

View file

@ -1,5 +1,7 @@
#ESP8266 ColorChord #ESP8266 ColorChord
## WARNING THIS IS UNDER CONSTRUCTION
(based off of ESP8266 I2S WS2812 Driver) (based off of ESP8266 I2S WS2812 Driver)
This project is based off of the I2S interface for the mp3 player found here: This project is based off of the I2S interface for the mp3 player found here:

13
embedded8266/ccconfig.h Normal file
View 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

View 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);
}
}

View 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

View 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

View 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;

View 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
View 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 );
}

View 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

View 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
View 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
View 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

View 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;
}

View 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

View file

@ -1,4 +1,7 @@
//I did not write this file, but I don't know where it came from. //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 "ets_sys.h"
#include "osapi.h" #include "osapi.h"

View file

@ -8,6 +8,7 @@
* *
* Modification history: * Modification history:
* 2014/3/12, v1.0 create this file. * 2014/3/12, v1.0 create this file.
* [various] Not released, Modified by Charles Lohr to change the RX behavior
*******************************************************************************/ *******************************************************************************/
#include <osapi.h> #include <osapi.h>
#include <ets_sys.h> #include <ets_sys.h>

Binary file not shown.

View file

@ -1 +1,3 @@
//This exists to make sure anything including stdint.h includes this instead.
#include "c_types.h" #include "c_types.h"

View file

@ -1 +1 @@
//Nothing here. //Nothing here. Just a file to make things that include <string.h> happy.

View file

@ -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");
}
*/

View file

@ -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

View file

@ -1,3 +1,5 @@
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
// ColorChord License. You Choose.
#include "hpatimer.h" #include "hpatimer.h"
#include <driver/adc.h> #include <driver/adc.h>
@ -56,3 +58,20 @@ void ICACHE_FLASH_ATTR StartHPATimer()
hs_adc_start(); 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();
}

View file

@ -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 #ifndef _HPATIMER_H
#define _HPATIMER_H #define _HPATIMER_H
#include <c_types.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... //Using a system timer on the ESP to poll the ADC in at a regular interval...
//BUFFSIZE must be a power-of-two //BUFFSIZE must be a power-of-two
@ -11,6 +19,9 @@ extern volatile uint16_t soundhead;
void StartHPATimer(); void StartHPATimer();
void ICACHE_FLASH_ATTR ContinueHPATimer();
void ICACHE_FLASH_ATTR PauseHPATimer();
#endif #endif

View file

@ -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 );
}

View file

@ -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

View file

@ -1,3 +1,6 @@
//Copyright 2015 <>< Charles Lohr Under the MIT/x11 License, NewBSD License or
// ColorChord License. You Choose.
#include "mem.h" #include "mem.h"
#include "c_types.h" #include "c_types.h"
#include "user_interface.h" #include "user_interface.h"
@ -11,7 +14,10 @@
#include <DFT32.h> #include <DFT32.h>
#include <embeddednf.h> #include <embeddednf.h>
#include <embeddedout.h> #include <embeddedout.h>
#include "ets_sys.h"
#include "gpio.h"
//#define PROFILE
#define PORT 7777 #define PORT 7777
#define SERVER_TIMEOUT 1500 #define SERVER_TIMEOUT 1500
@ -30,6 +36,9 @@ extern volatile uint8_t sounddata[HPABUFFSIZE];
extern volatile uint16_t soundhead; extern volatile uint16_t soundhead;
uint16_t soundtail; uint16_t soundtail;
void user_rf_pre_init()
{
}
//Call this once we've stacked together one full colorchord frame. //Call this once we've stacked together one full colorchord frame.
static void NewFrame() static void NewFrame()
@ -54,8 +63,12 @@ static void procTask(os_event_t *events)
{ {
system_os_post(procTaskPrio, 0, 0 ); 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 ) while( soundtail != soundhead )
{ {
int16_t samp = sounddata[soundtail]; int16_t samp = sounddata[soundtail];
@ -70,6 +83,9 @@ static void procTask(os_event_t *events)
wf = 0; wf = 0;
} }
} }
#ifdef PROFILE
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(0), 0 );
#endif
if( events->sig == 0 && events->par == 0 ) if( events->sig == 0 && events->par == 0 )
{ {
@ -109,6 +125,7 @@ static void procTask(os_event_t *events)
//Timer event. //Timer event.
static void myTimer(void *arg) static void myTimer(void *arg)
{ {
CSTick( 1 );
// uart0_sendStr("."); // uart0_sendStr(".");
// printf( "%d/%d\n",soundtail,soundhead ); // printf( "%d/%d\n",soundtail,soundhead );
// 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. //Called when new packet comes in.
static void ICACHE_FLASH_ATTR static void udpserver_recv(void *arg, char *pusrdata, unsigned short len)
udpserver_recv(void *arg, char *pusrdata, unsigned short len)
{ {
struct espconn *pespconn = (struct espconn *)arg; struct espconn *pespconn = (struct espconn *)arg;
// uint8_t buffer[MAX_FRAME]; // uint8_t buffer[MAX_FRAME];
// uint8_t ledout[] = { 0x00, 0xff, 0xaa, 0x00, 0xff, 0xaa, }; // uint8_t ledout[] = { 0x00, 0xff, 0xaa, 0x00, 0xff, 0xaa, };
uart0_sendStr("X"); uart0_sendStr("X");
// ws2812_push( pusrdata, len ); ws2812_push( pusrdata, len );
} }
void ICACHE_FLASH_ATTR charrx( uint8_t c ) 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); uart_init(BIT_RATE_115200, BIT_RATE_115200);
int wifiMode = wifi_get_opmode(); int wifiMode = wifi_get_opmode();
uart0_sendStr("\r\nCustom Server\r\n"); 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. 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" ); } while(1) { uart0_sendStr( "\r\nFAULT\r\n" ); }
} }
CSInit();
//Add a process //Add a process
system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen); 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_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL);
os_timer_arm(&some_timer, 100, 1); os_timer_arm(&some_timer, 100, 1);
Init(); //Init colorchord InitColorChord(); //Init colorchord
StartHPATimer(); //Init the high speed ADC timer. StartHPATimer(); //Init the high speed ADC timer.
@ -187,4 +208,16 @@ void user_init(void)
system_os_post(procTaskPrio, 0, 0 ); system_os_post(procTaskPrio, 0, 0 );
} }
void EnterCritical()
{
PauseHPATimer();
//ets_intr_lock();
}
void ExitCritical()
{
//ets_intr_unlock();
ContinueHPATimer();
}

View file

@ -1,5 +1,6 @@
/****************************************************************************** /******************************************************************************
* Copyright 2013-2015 Espressif Systems * Copyright 2013-2015 Espressif Systems
* 2015 <>< Charles Lohr
* *
* FileName: i2s_freertos.c * 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 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. 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. //Tricky, send out WS2812 bits with coded pulses, one nibble, then the other.
static const uint16_t bitpatterns[16] = { static const uint16_t bitpatterns[16] = {
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110, 0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,

View file

@ -1,5 +1,8 @@
#ifndef _I2S_TEST //Copyright 2015 <>< Charles Lohr, See LICENSE file.
#define _I2S_TEST //WS2812 sender that abuses the I2S interface on the WS2812.
#ifndef _WS2812I2S_TEST
#define _WS2812I2S_TEST
//Stuff that should be for the header: //Stuff that should be for the header:

19
embedded8266/web/Makefile Normal file
View 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

View 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
View 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
View 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
View 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;
}

View file

@ -0,0 +1,8 @@
<HTML>
<BODY>
Hello! This is a test page.<BR>
<IMG SRC=dsc.jpg>
</BODY>
</HTML>

View file

@ -0,0 +1 @@
test

View 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);

View 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>

View 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;
}