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

View file

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

View file

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

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

View file

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

Binary file not shown.

View file

@ -1 +1,3 @@
//This exists to make sure anything including stdint.h includes this instead.
#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 <driver/adc.h>
@ -56,3 +58,20 @@ void ICACHE_FLASH_ATTR StartHPATimer()
hs_adc_start();
}
void ICACHE_FLASH_ATTR PauseHPATimer()
{
TM1_EDGE_INT_DISABLE();
ETS_FRC1_INTR_DISABLE();
system_timer_reinit();
}
void ICACHE_FLASH_ATTR ContinueHPATimer()
{
TM1_EDGE_INT_ENABLE();
ETS_FRC1_INTR_ENABLE();
system_timer_reinit();
hs_adc_start();
}

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

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 "c_types.h"
#include "user_interface.h"
@ -11,7 +14,10 @@
#include <DFT32.h>
#include <embeddednf.h>
#include <embeddedout.h>
#include "ets_sys.h"
#include "gpio.h"
//#define PROFILE
#define PORT 7777
#define SERVER_TIMEOUT 1500
@ -30,6 +36,9 @@ extern volatile uint8_t sounddata[HPABUFFSIZE];
extern volatile uint16_t soundhead;
uint16_t soundtail;
void user_rf_pre_init()
{
}
//Call this once we've stacked together one full colorchord frame.
static void NewFrame()
@ -54,8 +63,12 @@ static void procTask(os_event_t *events)
{
system_os_post(procTaskPrio, 0, 0 );
// printf( "%d\n", sounddata[soundtail] );
CSTick( 0 );
//For profiling so we can see how much CPU is spent in this loop.
#ifdef PROFILE
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(0), 1 );
#endif
while( soundtail != soundhead )
{
int16_t samp = sounddata[soundtail];
@ -70,6 +83,9 @@ static void procTask(os_event_t *events)
wf = 0;
}
}
#ifdef PROFILE
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(0), 0 );
#endif
if( events->sig == 0 && events->par == 0 )
{
@ -109,6 +125,7 @@ static void procTask(os_event_t *events)
//Timer event.
static void myTimer(void *arg)
{
CSTick( 1 );
// uart0_sendStr(".");
// printf( "%d/%d\n",soundtail,soundhead );
// printf( "%d/%d\n",soundtail,soundhead );
@ -118,15 +135,14 @@ static void myTimer(void *arg)
//Called when new packet comes in.
static void ICACHE_FLASH_ATTR
udpserver_recv(void *arg, char *pusrdata, unsigned short len)
static void udpserver_recv(void *arg, char *pusrdata, unsigned short len)
{
struct espconn *pespconn = (struct espconn *)arg;
// uint8_t buffer[MAX_FRAME];
// uint8_t ledout[] = { 0x00, 0xff, 0xaa, 0x00, 0xff, 0xaa, };
uart0_sendStr("X");
// ws2812_push( pusrdata, len );
ws2812_push( pusrdata, len );
}
void ICACHE_FLASH_ATTR charrx( uint8_t c )
@ -135,13 +151,16 @@ void ICACHE_FLASH_ATTR charrx( uint8_t c )
}
void user_init(void)
void ICACHE_FLASH_ATTR user_init(void)
{
uart_init(BIT_RATE_115200, BIT_RATE_115200);
int wifiMode = wifi_get_opmode();
uart0_sendStr("\r\nCustom Server\r\n");
#ifdef PROFILE
GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0);
#endif
wifi_set_opmode( 2 ); //We broadcast our ESSID, wait for peopel to join.
@ -170,6 +189,8 @@ void user_init(void)
while(1) { uart0_sendStr( "\r\nFAULT\r\n" ); }
}
CSInit();
//Add a process
system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen);
@ -178,7 +199,7 @@ void user_init(void)
os_timer_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL);
os_timer_arm(&some_timer, 100, 1);
Init(); //Init colorchord
InitColorChord(); //Init colorchord
StartHPATimer(); //Init the high speed ADC timer.
@ -187,4 +208,16 @@ void user_init(void)
system_os_post(procTaskPrio, 0, 0 );
}
void EnterCritical()
{
PauseHPATimer();
//ets_intr_lock();
}
void ExitCritical()
{
//ets_intr_unlock();
ContinueHPATimer();
}

View file

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

View file

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

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