parser timeout, better checksum checking and struct stuffing, shaved some bytes off RAM

pull/111/merge
Ondřej Hruška 7 years ago
parent 4eaee9389d
commit f8c60b0668
  1. 2
      Makefile
  2. 6
      html_orig/_pages.php
  3. 10
      html_orig/lang/en.php
  4. 6
      html_orig/pages/cfg_term.php
  5. 2
      html_orig/pages/term.php
  6. 70
      user/ansi_parser.c
  7. 22
      user/ansi_parser.rl
  8. 6
      user/cgi_network.c
  9. 2
      user/cgi_persist.c
  10. 2
      user/cgi_sockets.c
  11. 2
      user/cgi_system.c
  12. 41
      user/cgi_term_cfg.c
  13. 4
      user/cgi_wifi.c
  14. 45
      user/persist.c
  15. 17
      user/persist.h
  16. 15
      user/screen.c
  17. 13
      user/screen.h
  18. 7
      user/syscfg.h
  19. 27
      user/wifimgr.h

@ -65,7 +65,7 @@ LIBS += esphttpd
# compiler flags using during compilation of source files # compiler flags using during compilation of source files
CFLAGS = -Os -ggdb -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ CFLAGS = -Os -ggdb -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \ -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
-Wno-address -Wno-unused -DHTTPD_MAX_BACKLOG_SIZE=8192 -DADMIN_PASSWORD=$(ADMIN_PASSWORD) -Wno-address -Wno-unused -DHTTPD_MAX_BACKLOG_SIZE=4096 -DADMIN_PASSWORD=$(ADMIN_PASSWORD)
# linker flags used to generate the main object file # linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static

@ -18,6 +18,9 @@ if (! function_exists('pg')) {
} }
} }
pg('cfg_term', 'cfg', 'terminal', '/cfg/term');
pg('term_set', 'api', '', '/cfg/term/set');
pg('cfg_wifi', 'cfg', 'wifi', '/cfg/wifi'); pg('cfg_wifi', 'cfg', 'wifi', '/cfg/wifi');
pg('cfg_wifi_conn', '', '', '/cfg/wifi/connecting'); pg('cfg_wifi_conn', '', '', '/cfg/wifi/connecting');
pg('wifi_connstatus', 'api', '', '/cfg/wifi/connstatus'); pg('wifi_connstatus', 'api', '', '/cfg/wifi/connstatus');
@ -27,9 +30,6 @@ pg('wifi_scan', 'api', '', '/cfg/wifi/scan');
pg('cfg_network', 'cfg', 'network', '/cfg/network'); pg('cfg_network', 'cfg', 'network', '/cfg/network');
pg('network_set', 'api', '', '/cfg/network/set'); pg('network_set', 'api', '', '/cfg/network/set');
pg('cfg_term', 'cfg', 'terminal', '/cfg/term');
pg('term_set', 'api', '', '/cfg/term/set');
pg('cfg_system', 'cfg', 'configure', '/cfg/system'); pg('cfg_system', 'cfg', 'configure', '/cfg/system');
pg('system_set', 'api', '', '/cfg/system/set'); pg('system_set', 'api', '', '/cfg/system/set');

@ -36,6 +36,7 @@ return [
'term.default_fg_bg' => 'Text / background', 'term.default_fg_bg' => 'Text / background',
'term.buttons' => 'Button labels', 'term.buttons' => 'Button labels',
'term.theme' => 'Color scheme', 'term.theme' => 'Color scheme',
'term.parser_tout_ms' => 'Parser timeout',
// terminal color labels // terminal color labels
'color.0' => 'Black', 'color.0' => 'Black',
@ -115,14 +116,13 @@ return [
'system.confirm_store_defaults' => 'system.confirm_store_defaults' =>
'Enter admin password to confirm you want to store the current settings as defaults.', 'Enter admin password to confirm you want to store the current settings as defaults.',
'system.password' => 'Admin password:', 'system.password' => 'Admin password:',
'system.restore_defaults' => 'Reset to default settings', 'system.restore_defaults' => 'Reset active settings to defaults',
'system.write_defaults' => 'Save current settings as default', 'system.write_defaults' => 'Save active settings as defaults',
'system.restore_hard' => 'Reset to firmware default settings', 'system.restore_hard' => 'Reset active settings to firmware defaults',
'system.explain_persist' => ' 'system.explain_persist' => '
ESPTerm contains two persistent memory banks, one for default and ESPTerm contains two persistent memory banks, one for default and
one for active settings. Active settings can be stored as defaults one for active settings. Active settings can be stored as defaults
by the administrator. Use the following button to revert all by the administrator (password required).
active settings to their stored default values.
', ',
'system.uart' => 'Serial Port', 'system.uart' => 'Serial Port',
'system.explain_uart' => ' 'system.explain_uart' => '

@ -104,6 +104,12 @@
<input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%"> <input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%">
</div> </div>
<div class="Row">
<label for="parser_tout_ms"><?= tr('term.parser_tout_ms') ?><span class="mq-phone">&nbsp;(ms)</span></label>
<input type="number" step=1 min=0 name="parser_tout_ms" id="parser_tout_ms" value="%parser_tout_ms%" required>
<span class="mq-no-phone">&nbsp;ms</span>
</div>
<div class="Row buttons"> <div class="Row buttons">
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a> <a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
</div> </div>

@ -26,7 +26,7 @@
<nav id="botnav"> <nav id="botnav">
<a href="#" onclick="toggleSoftKb(true); return false" class="icn-keyboard mq-tablet-max"></a><!-- <a href="#" onclick="toggleSoftKb(true); return false" class="icn-keyboard mq-tablet-max"></a><!--
--><a href="<?= url('cfg_wifi') ?>"><?= tr('menu.settings') ?></a><!-- --><a href="<?= url('cfg_term') ?>"><?= tr('menu.settings') ?></a><!--
--><a href="<?= url('help') ?>">Help</a><!-- --><a href="<?= url('help') ?>">Help</a><!--
--><a href="<?= url('about') ?>">About</a> --><a href="<?= url('about') ?>">About</a>
</nav> </nav>

@ -2,10 +2,11 @@
/* #line 1 "user/ansi_parser.rl" */ /* #line 1 "user/ansi_parser.rl" */
#include <esp8266.h> #include <esp8266.h>
#include "ansi_parser.h" #include "ansi_parser.h"
#include "screen.h"
/* Ragel constants block */ /* Ragel constants block */
/* #line 9 "user/ansi_parser.c" */ /* #line 10 "user/ansi_parser.c" */
static const char _ansi_actions[] = { static const char _ansi_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1, 0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 6, 1, 3, 1, 4, 1, 5, 1, 6, 1,
@ -30,9 +31,21 @@ static const int ansi_en_OSC_body = 5;
static const int ansi_en_main = 1; static const int ansi_en_main = 1;
/* #line 8 "user/ansi_parser.rl" */ /* #line 9 "user/ansi_parser.rl" */
static volatile int cs = -1;
static ETSTimer resetTim;
static void ICACHE_FLASH_ATTR
resetParserCb(void *arg) {
if (cs != ansi_start) {
cs = ansi_start;
warn("Parser timeout, state reset");
}
}
/** /**
* \brief Linear ANSI chars stream parser * \brief Linear ANSI chars stream parser
* *
@ -49,8 +62,6 @@ static const int ansi_en_main = 1;
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
ansi_parser(const char *newdata, size_t len) ansi_parser(const char *newdata, size_t len)
{ {
static int cs = -1;
// The CSI code is built here // The CSI code is built here
static char csi_leading; //!< Leading char, 0 if none static char csi_leading; //!< Leading char, 0 if none
static int csi_ni; //!< Number of the active digit static int csi_ni; //!< Number of the active digit
@ -69,17 +80,24 @@ ansi_parser(const char *newdata, size_t len)
// Init Ragel on the first run // Init Ragel on the first run
if (cs == -1) { if (cs == -1) {
/* #line 73 "user/ansi_parser.c" */ /* #line 84 "user/ansi_parser.c" */
{ {
cs = ansi_start; cs = ansi_start;
} }
/* #line 46 "user/ansi_parser.rl" */ /* #line 57 "user/ansi_parser.rl" */
}
// schedule state reset
if (termconf->parser_tout_ms > 0) {
os_timer_disarm(&resetTim);
os_timer_setfn(&resetTim, resetParserCb, NULL);
os_timer_arm(&resetTim, termconf->parser_tout_ms, 0);
} }
// The parser // The parser
/* #line 83 "user/ansi_parser.c" */ /* #line 101 "user/ansi_parser.c" */
{ {
const char *_acts; const char *_acts;
unsigned int _nacts; unsigned int _nacts;
@ -315,13 +333,13 @@ execFuncs:
while ( _nacts-- > 0 ) { while ( _nacts-- > 0 ) {
switch ( *_acts++ ) { switch ( *_acts++ ) {
case 0: case 0:
/* #line 58 "user/ansi_parser.rl" */ /* #line 76 "user/ansi_parser.rl" */
{ {
apars_handle_plainchar((*p)); apars_handle_plainchar((*p));
} }
break; break;
case 1: case 1:
/* #line 65 "user/ansi_parser.rl" */ /* #line 83 "user/ansi_parser.rl" */
{ {
// Reset the CSI builder // Reset the CSI builder
csi_leading = csi_char = 0; csi_leading = csi_char = 0;
@ -336,13 +354,13 @@ execFuncs:
} }
break; break;
case 2: case 2:
/* #line 78 "user/ansi_parser.rl" */ /* #line 96 "user/ansi_parser.rl" */
{ {
csi_leading = (*p); csi_leading = (*p);
} }
break; break;
case 3: case 3:
/* #line 82 "user/ansi_parser.rl" */ /* #line 100 "user/ansi_parser.rl" */
{ {
// x10 + digit // x10 + digit
if (csi_ni < CSI_N_MAX) { if (csi_ni < CSI_N_MAX) {
@ -351,13 +369,13 @@ execFuncs:
} }
break; break;
case 4: case 4:
/* #line 89 "user/ansi_parser.rl" */ /* #line 107 "user/ansi_parser.rl" */
{ {
csi_ni++; csi_ni++;
} }
break; break;
case 5: case 5:
/* #line 93 "user/ansi_parser.rl" */ /* #line 111 "user/ansi_parser.rl" */
{ {
csi_char = (*p); csi_char = (*p);
@ -367,14 +385,14 @@ execFuncs:
} }
break; break;
case 6: case 6:
/* #line 101 "user/ansi_parser.rl" */ /* #line 119 "user/ansi_parser.rl" */
{ {
apars_handle_badseq(); apars_handle_badseq();
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 7: case 7:
/* #line 118 "user/ansi_parser.rl" */ /* #line 136 "user/ansi_parser.rl" */
{ {
csi_ni = 0; csi_ni = 0;
@ -390,20 +408,20 @@ execFuncs:
} }
break; break;
case 8: case 8:
/* #line 132 "user/ansi_parser.rl" */ /* #line 150 "user/ansi_parser.rl" */
{ {
apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]); apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 9: case 9:
/* #line 137 "user/ansi_parser.rl" */ /* #line 155 "user/ansi_parser.rl" */
{ {
osc_buffer[osc_bi++] = (*p); osc_buffer[osc_bi++] = (*p);
} }
break; break;
case 10: case 10:
/* #line 141 "user/ansi_parser.rl" */ /* #line 159 "user/ansi_parser.rl" */
{ {
osc_buffer[osc_bi++] = '\0'; osc_buffer[osc_bi++] = '\0';
apars_handle_OSC_SetTitle(osc_buffer); apars_handle_OSC_SetTitle(osc_buffer);
@ -411,7 +429,7 @@ execFuncs:
} }
break; break;
case 11: case 11:
/* #line 147 "user/ansi_parser.rl" */ /* #line 165 "user/ansi_parser.rl" */
{ {
osc_buffer[osc_bi++] = '\0'; osc_buffer[osc_bi++] = '\0';
apars_handle_OSC_SetButton(csi_n[0], osc_buffer); apars_handle_OSC_SetButton(csi_n[0], osc_buffer);
@ -419,7 +437,7 @@ execFuncs:
} }
break; break;
case 12: case 12:
/* #line 159 "user/ansi_parser.rl" */ /* #line 177 "user/ansi_parser.rl" */
{ {
// Reset screen // Reset screen
apars_handle_RESET_cmd(); apars_handle_RESET_cmd();
@ -427,20 +445,20 @@ execFuncs:
} }
break; break;
case 13: case 13:
/* #line 165 "user/ansi_parser.rl" */ /* #line 183 "user/ansi_parser.rl" */
{ {
apars_handle_saveCursorAttrs(); apars_handle_saveCursorAttrs();
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 14: case 14:
/* #line 170 "user/ansi_parser.rl" */ /* #line 188 "user/ansi_parser.rl" */
{ {
apars_handle_restoreCursorAttrs(); apars_handle_restoreCursorAttrs();
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
/* #line 444 "user/ansi_parser.c" */ /* #line 462 "user/ansi_parser.c" */
} }
} }
goto _again; goto _again;
@ -458,7 +476,7 @@ _again:
while ( __nacts-- > 0 ) { while ( __nacts-- > 0 ) {
switch ( *__acts++ ) { switch ( *__acts++ ) {
case 6: case 6:
/* #line 101 "user/ansi_parser.rl" */ /* #line 119 "user/ansi_parser.rl" */
{ {
apars_handle_badseq(); apars_handle_badseq();
{cs = 1; if ( p == pe ) {cs = 1; if ( p == pe )
@ -466,7 +484,7 @@ _again:
goto _again;} goto _again;}
} }
break; break;
/* #line 470 "user/ansi_parser.c" */ /* #line 488 "user/ansi_parser.c" */
} }
} }
} }
@ -474,6 +492,6 @@ goto _again;}
_out: {} _out: {}
} }
/* #line 190 "user/ansi_parser.rl" */ /* #line 208 "user/ansi_parser.rl" */
} }

@ -1,5 +1,6 @@
#include <esp8266.h> #include <esp8266.h>
#include "ansi_parser.h" #include "ansi_parser.h"
#include "screen.h"
/* Ragel constants block */ /* Ragel constants block */
%%{ %%{
@ -7,6 +8,18 @@
write data; write data;
}%% }%%
static volatile int cs = -1;
static ETSTimer resetTim;
static void ICACHE_FLASH_ATTR
resetParserCb(void *arg) {
if (cs != ansi_start) {
cs = ansi_start;
warn("Parser timeout, state reset");
}
}
/** /**
* \brief Linear ANSI chars stream parser * \brief Linear ANSI chars stream parser
* *
@ -23,8 +36,6 @@
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
ansi_parser(const char *newdata, size_t len) ansi_parser(const char *newdata, size_t len)
{ {
static int cs = -1;
// The CSI code is built here // The CSI code is built here
static char csi_leading; //!< Leading char, 0 if none static char csi_leading; //!< Leading char, 0 if none
static int csi_ni; //!< Number of the active digit static int csi_ni; //!< Number of the active digit
@ -45,6 +56,13 @@ ansi_parser(const char *newdata, size_t len)
%% write init; %% write init;
} }
// schedule state reset
if (termconf->parser_tout_ms > 0) {
os_timer_disarm(&resetTim);
os_timer_setfn(&resetTim, resetParserCb, NULL);
os_timer_arm(&resetTim, termconf->parser_tout_ms, 0);
}
// The parser // The parser
%%{ %%{
#/* #/*

@ -28,9 +28,9 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData)
{ {
static ETSTimer timer; static ETSTimer timer;
char buff[50]; char buff[20];
char redir_url_buf[100];
char redir_url_buf[300];
char *redir_url = redir_url_buf; char *redir_url = redir_url_buf;
redir_url += sprintf(redir_url, SET_REDIR_ERR); redir_url += sprintf(redir_url, SET_REDIR_ERR);
// we'll test if anything was printed by looking for \0 in failed_keys_buf // we'll test if anything was printed by looking for \0 in failed_keys_buf
@ -201,7 +201,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData)
//Template code for the WLAN page. //Template code for the WLAN page.
httpd_cgi_state ICACHE_FLASH_ATTR tplNetwork(HttpdConnData *connData, char *token, void **arg) httpd_cgi_state ICACHE_FLASH_ATTR tplNetwork(HttpdConnData *connData, char *token, void **arg)
{ {
char buff[100]; char buff[20];
u8 mac[6]; u8 mac[6];
if (token == NULL) { if (token == NULL) {

@ -20,7 +20,7 @@ verify_admin_pw(const char *pw)
httpd_cgi_state ICACHE_FLASH_ATTR httpd_cgi_state ICACHE_FLASH_ATTR
cgiPersistWriteDefaults(HttpdConnData *connData) cgiPersistWriteDefaults(HttpdConnData *connData)
{ {
char buff[50]; char buff[PASSWORD_LEN];
if (connData->conn == NULL) { if (connData->conn == NULL) {
//Connection aborted. Clean up. //Connection aborted. Clean up.

@ -6,7 +6,7 @@
#include "uart_driver.h" #include "uart_driver.h"
#include "screen.h" #include "screen.h"
#define SOCK_BUF_LEN 2048 #define SOCK_BUF_LEN 1024
static char sock_buff[SOCK_BUF_LEN]; static char sock_buff[SOCK_BUF_LEN];
volatile bool notify_available = true; volatile bool notify_available = true;

@ -61,8 +61,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR
cgiSystemCfgSetParams(HttpdConnData *connData) cgiSystemCfgSetParams(HttpdConnData *connData)
{ {
char buff[50]; char buff[50];
char redir_url_buf[100];
char redir_url_buf[300];
char *redir_url = redir_url_buf; char *redir_url = redir_url_buf;
redir_url += sprintf(redir_url, SET_REDIR_ERR); redir_url += sprintf(redir_url, SET_REDIR_ERR);
// we'll test if anything was printed by looking for \0 in failed_keys_buf // we'll test if anything was printed by looking for \0 in failed_keys_buf

@ -19,8 +19,9 @@ httpd_cgi_state ICACHE_FLASH_ATTR
cgiTermCfgSetParams(HttpdConnData *connData) cgiTermCfgSetParams(HttpdConnData *connData)
{ {
char buff[50]; char buff[50];
char redir_url_buf[100];
int n, w, h;
char redir_url_buf[300];
char *redir_url = redir_url_buf; char *redir_url = redir_url_buf;
redir_url += sprintf(redir_url, SET_REDIR_ERR); redir_url += sprintf(redir_url, SET_REDIR_ERR);
// we'll test if anything was printed by looking for \0 in failed_keys_buf // we'll test if anything was printed by looking for \0 in failed_keys_buf
@ -33,11 +34,11 @@ cgiTermCfgSetParams(HttpdConnData *connData)
// width and height must always go together so we can do max size validation // width and height must always go together so we can do max size validation
if (GET_ARG("term_width")) { if (GET_ARG("term_width")) {
dbg("Default screen width: %s", buff); dbg("Default screen width: %s", buff);
int w = atoi(buff); w = atoi(buff);
if (w > 1) { if (w > 1) {
if (GET_ARG("term_height")) { if (GET_ARG("term_height")) {
dbg("Default screen height: %s", buff); dbg("Default screen height: %s", buff);
int h = atoi(buff); h = atoi(buff);
if (h > 1) { if (h > 1) {
if (w * h <= MAX_SCREEN_SIZE) { if (w * h <= MAX_SCREEN_SIZE) {
termconf->width = w; termconf->width = w;
@ -63,20 +64,31 @@ cgiTermCfgSetParams(HttpdConnData *connData)
if (GET_ARG("default_bg")) { if (GET_ARG("default_bg")) {
dbg("Screen default BG: %s", buff); dbg("Screen default BG: %s", buff);
int color = atoi(buff); n = atoi(buff);
if (color >= 0 && color < 16) { if (n >= 0 && n < 16) {
termconf->default_bg = (u8) color; termconf->default_bg = (u8) n;
} else { } else {
warn("Bad color %s", buff); warn("Bad color %s", buff);
redir_url += sprintf(redir_url, "default_bg,"); redir_url += sprintf(redir_url, "default_bg,");
} }
} }
if (GET_ARG("parser_tout_ms")) {
dbg("Parser timeout: %s ms", buff);
n = atoi(buff);
if (n >= 0) {
termconf->parser_tout_ms = (u8) n;
} else {
warn("Bad timeout %s", buff);
redir_url += sprintf(redir_url, "parser_tout_ms,");
}
}
if (GET_ARG("default_fg")) { if (GET_ARG("default_fg")) {
dbg("Screen default FG: %s", buff); dbg("Screen default FG: %s", buff);
int color = atoi(buff); n = atoi(buff);
if (color >= 0 && color < 16) { if (n >= 0 && n < 16) {
termconf->default_fg = (u8) color; termconf->default_fg = (u8) n;
} else { } else {
warn("Bad color %s", buff); warn("Bad color %s", buff);
redir_url += sprintf(redir_url, "default_fg,"); redir_url += sprintf(redir_url, "default_fg,");
@ -85,9 +97,9 @@ cgiTermCfgSetParams(HttpdConnData *connData)
if (GET_ARG("theme")) { if (GET_ARG("theme")) {
dbg("Screen color theme: %s", buff); dbg("Screen color theme: %s", buff);
int theme = atoi(buff); n = atoi(buff);
if (theme >= 0 && theme <= 5) { // ALWAYS ADJUST WHEN ADDING NEW THEME! if (n >= 0 && n <= 5) { // ALWAYS ADJUST WHEN ADDING NEW THEME!
termconf->theme = (u8) theme; termconf->theme = (u8) n;
} else { } else {
warn("Bad theme num: %s", buff); warn("Bad theme num: %s", buff);
redir_url += sprintf(redir_url, "theme,"); redir_url += sprintf(redir_url, "theme,");
@ -127,7 +139,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
httpd_cgi_state ICACHE_FLASH_ATTR httpd_cgi_state ICACHE_FLASH_ATTR
tplTermCfg(HttpdConnData *connData, char *token, void **arg) tplTermCfg(HttpdConnData *connData, char *token, void **arg)
{ {
#define BUFLEN 100 #define BUFLEN TERM_TITLE_LEN
char buff[BUFLEN]; char buff[BUFLEN];
char buff2[10]; char buff2[10];
@ -144,6 +156,9 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
else if (streq(token, "term_height")) { else if (streq(token, "term_height")) {
sprintf(buff, "%d", termconf->height); sprintf(buff, "%d", termconf->height);
} }
else if (streq(token, "parser_tout_ms")) {
sprintf(buff, "%d", termconf->parser_tout_ms);
}
else if (streq(token, "theme")) { else if (streq(token, "theme")) {
sprintf(buff, "%d", termconf->theme); sprintf(buff, "%d", termconf->theme);
} }

@ -325,8 +325,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData)
static ETSTimer timer; static ETSTimer timer;
char buff[50]; char buff[50];
char redir_url_buf[100]; // this is just barely enough - but it's split into two forms, so we never have error in all fields
char redir_url_buf[300];
char *redir_url = redir_url_buf; char *redir_url = redir_url_buf;
redir_url += sprintf(redir_url, SET_REDIR_ERR); redir_url += sprintf(redir_url, SET_REDIR_ERR);
// we'll test if anything was printed by looking for \0 in failed_keys_buf // we'll test if anything was printed by looking for \0 in failed_keys_buf
@ -507,7 +507,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData)
//Template code for the WLAN page. //Template code for the WLAN page.
httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg)
{ {
char buff[100]; char buff[PASSWORD_LEN];
int x; int x;
int connectStatus; int connectStatus;

@ -17,23 +17,45 @@ static void ICACHE_FLASH_ATTR
apply_live_settings(void) apply_live_settings(void)
{ {
dbg("[Persist] Applying live settings..."); dbg("[Persist] Applying live settings...");
terminal_apply_settings();
wifimgr_apply_settings(); dbg("[Persist] > system");
sysconf_apply_settings(); sysconf_apply_settings();
dbg("[Persist] > wifi");
wifimgr_apply_settings();
dbg("[Persist] > terminal");
terminal_apply_settings();
dbg("[Persist] Live settings applied.");
// ... // ...
} }
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
restore_live_settings_to_hard_defaults(void) restore_live_settings_to_hard_defaults(void)
{ {
dbg("[Persist] Restore to hard defaults...");
dbg("[Persist] > system");
sysconf_restore_defaults();
dbg("[Persist] > wifi");
wifimgr_restore_defaults(); wifimgr_restore_defaults();
dbg("[Persist] > terminal");
terminal_restore_defaults(); terminal_restore_defaults();
sysconf_restore_defaults();
dbg("[Persist] Restored to hard defaults.");
// ... // ...
} }
//endregion //endregion
const u32 wconf_at = (u32)&persist.defaults.wificonf - (u32)&persist.defaults;
const u32 tconf_at = (u32)&persist.defaults.termconf - (u32)&persist.defaults;
const u32 sconf_at = (u32)&persist.defaults.sysconf - (u32)&persist.defaults;
const u32 cksum_at = (u32)&persist.defaults.checksum - (u32)&persist.defaults;
/** /**
* Compute CRC32. Adapted from https://github.com/esp8266/Arduino * Compute CRC32. Adapted from https://github.com/esp8266/Arduino
* @param data * @param data
@ -43,7 +65,9 @@ restore_live_settings_to_hard_defaults(void)
static uint32_t ICACHE_FLASH_ATTR static uint32_t ICACHE_FLASH_ATTR
calculateCRC32(const uint8_t *data, size_t length) calculateCRC32(const uint8_t *data, size_t length)
{ {
uint32_t crc = 0xffffffff + CHECKSUM_SALT; // the salt here should ensure settings are wiped when the structure changes
// CHECKSUM_SALT can be adjusted manually to force a reset.
uint32_t crc = 0xffffffff + CHECKSUM_SALT + ((wconf_at << 16) ^ (tconf_at << 10) ^ (sconf_at << 5));
while (length--) { while (length--) {
uint8_t c = *data++; uint8_t c = *data++;
for (uint32_t i = 0x80; i > 0; i >>= 1) { for (uint32_t i = 0x80; i > 0; i >>= 1) {
@ -81,13 +105,12 @@ persist_load(void)
{ {
info("[Persist] Loading stored settings from FLASH..."); info("[Persist] Loading stored settings from FLASH...");
dbg("sizeof(AppConfigBundle) = %d bytes", sizeof(AppConfigBundle)); dbg("AppConfigBundle memory map:");
dbg("> sizeof(WiFiConfigBundle) = %d bytes", sizeof(WiFiConfigBundle)); dbg("> WiFiConfigBundle at %4d (error %2d)", wconf_at, wconf_at - 0);
dbg("> sizeof(TerminalConfigBundle) = %d bytes", sizeof(TerminalConfigBundle)); dbg("> SystemConfigBundle at %4d (error %2d)", sconf_at, sconf_at - WIFICONF_SIZE);
dbg("> sizeof(SystemConfigBundle) = %d bytes", sizeof(SystemConfigBundle)); dbg("> TerminalConfigBundle at %4d (error %2d)", tconf_at, tconf_at - WIFICONF_SIZE - SYSCONF_SIZE);
dbg("> sizeof(checksum) = %d bytes", sizeof(uint32_t)); dbg("> Checksum at %4d (error %2d)", cksum_at, cksum_at - (APPCONF_SIZE - 4));
dbg("> filler = %d bytes", dbg("> Total size = %d bytes (error %d)", sizeof(AppConfigBundle), APPCONF_SIZE - sizeof(AppConfigBundle));
sizeof(AppConfigBundle) - (sizeof(WiFiConfigBundle) + sizeof(TerminalConfigBundle) + sizeof(SystemConfigBundle)));
bool hard_reset = false; bool hard_reset = false;

@ -16,15 +16,20 @@
// Changing this could be used to force-erase the config area // Changing this could be used to force-erase the config area
// after a firmware upgrade // after a firmware upgrade
#define CHECKSUM_SALT 2 #define CHECKSUM_SALT 3
#define APPCONF_SIZE 2048 #define APPCONF_SIZE 2048
/** Struct for current or default settings */ /** Struct for current or default settings */
typedef struct { // the entire block should be 1024 bytes long (for compatibility across upgrades) typedef struct { // the entire block should be 1024 bytes long (for compatibility across upgrades)
WiFiConfigBundle wificonf; WiFiConfigBundle wificonf;
TerminalConfigBundle termconf; uint8_t _filler1[WIFICONF_SIZE - sizeof(WiFiConfigBundle)];
SystemConfigBundle sysconf; SystemConfigBundle sysconf;
uint8_t _filler3[SYSCONF_SIZE - sizeof(SystemConfigBundle)];
TerminalConfigBundle termconf;
uint8_t _filler2[TERMCONF_SIZE - sizeof(TerminalConfigBundle)];
// --- Space for future settings --- // --- Space for future settings ---
// The size must be appropriately reduced each time something is added, // The size must be appropriately reduced each time something is added,
@ -34,12 +39,12 @@ typedef struct { // the entire block should be 1024 bytes long (for compatibilit
// This ensures user settings are not lost each time they upgrade the firmware, // This ensures user settings are not lost each time they upgrade the firmware,
// which would lead to a checksum mismatch if the structure was changed and // which would lead to a checksum mismatch if the structure was changed and
// it grew to a different memory area. // it grew to a different memory area.
uint8_t filler[ uint8_t _filler_end[
APPCONF_SIZE APPCONF_SIZE
- sizeof(uint32_t) // checksum - sizeof(uint32_t) // checksum
- sizeof(WiFiConfigBundle) - WIFICONF_SIZE
- sizeof(TerminalConfigBundle) - SYSCONF_SIZE
- sizeof(SystemConfigBundle) - TERMCONF_SIZE
]; ];
uint32_t checksum; // computed before write and tested on load. If it doesn't match, values are reset to hard defaults. uint32_t checksum; // computed before write and tested on load. If it doesn't match, values are reset to hard defaults.

@ -8,6 +8,9 @@
TerminalConfigBundle * const termconf = &persist.current.termconf; TerminalConfigBundle * const termconf = &persist.current.termconf;
TerminalConfigBundle termconf_scratch; TerminalConfigBundle termconf_scratch;
#define W termconf_scratch.width
#define H termconf_scratch.height
/** /**
* Restore hard defaults * Restore hard defaults
*/ */
@ -17,6 +20,7 @@ void terminal_restore_defaults(void)
termconf->default_fg = 7; termconf->default_fg = 7;
termconf->width = 26; termconf->width = 26;
termconf->height = 10; termconf->height = 10;
termconf->parser_tout_ms = 10;
sprintf(termconf->title, "ESPTerm"); sprintf(termconf->title, "ESPTerm");
for(int i=1; i <= 5; i++) { for(int i=1; i <= 5; i++) {
sprintf(termconf->btn[i-1], "%d", i); sprintf(termconf->btn[i-1], "%d", i);
@ -29,12 +33,16 @@ void terminal_restore_defaults(void)
void terminal_apply_settings(void) void terminal_apply_settings(void)
{ {
memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle)); memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle));
if (W*H >= MAX_SCREEN_SIZE) {
error("BAD SCREEN SIZE: %d rows x %d cols", H, W);
error("reverting terminal settings to default");
terminal_restore_defaults();
persist_store();
memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle));
}
screen_init(); screen_init();
} }
#define W termconf_scratch.width
#define H termconf_scratch.height
/** /**
* Highest permissible value of the color attribute * Highest permissible value of the color attribute
*/ */
@ -105,6 +113,7 @@ static volatile int notifyLock = 0;
static inline void static inline void
clear_range(unsigned int from, unsigned int to) clear_range(unsigned int from, unsigned int to)
{ {
if (to >= W*H) to = W*H-1;
Color fg = cursor.inverse ? cursor.bg : cursor.fg; Color fg = cursor.inverse ? cursor.bg : cursor.fg;
Color bg = cursor.inverse ? cursor.fg : cursor.bg; Color bg = cursor.inverse ? cursor.fg : cursor.bg;
for (unsigned int i = from; i <= to; i++) { for (unsigned int i = from; i <= to; i++) {

@ -56,18 +56,7 @@ typedef struct {
char title[TERM_TITLE_LEN]; char title[TERM_TITLE_LEN];
char btn[5][TERM_BTN_LEN]; char btn[5][TERM_BTN_LEN];
u8 theme; u8 theme;
u32 parser_tout_ms;
u8 _filler[
TERMCONF_SIZE
- 4
- 4
- 1
- 1
- 1
- TERM_TITLE_LEN
- TERM_BTN_LEN * 5
];
} TerminalConfigBundle; } TerminalConfigBundle;
// Live config // Live config

@ -15,13 +15,6 @@ typedef struct {
u32 uart_baudrate; u32 uart_baudrate;
u8 uart_parity; u8 uart_parity;
u8 uart_stopbits; u8 uart_stopbits;
u8 _filler[
SYSCONF_SIZE
- 4
- 1
- 1
];
} SystemConfigBundle; } SystemConfigBundle;
extern SystemConfigBundle * const sysconf; extern SystemConfigBundle * const sysconf;

@ -27,42 +27,21 @@ typedef struct {
WIFI_MODE opmode : 8; WIFI_MODE opmode : 8;
u8 tpw; u8 tpw;
// --- AP config --- // AP config
u8 ap_channel; u8 ap_channel;
u8 ap_ssid[SSID_LEN]; u8 ap_ssid[SSID_LEN];
u8 ap_password[PASSWORD_LEN]; u8 ap_password[PASSWORD_LEN];
bool ap_hidden; bool ap_hidden;
//
u16 ap_dhcp_time; // in minutes u16 ap_dhcp_time; // in minutes
struct dhcps_lease ap_dhcp_range; struct dhcps_lease ap_dhcp_range;
struct ip_info ap_addr; struct ip_info ap_addr;
// --- Client config --- // Client config
u8 sta_ssid[SSID_LEN]; u8 sta_ssid[SSID_LEN];
u8 sta_password[PASSWORD_LEN]; u8 sta_password[PASSWORD_LEN];
bool sta_dhcp_enable; bool sta_dhcp_enable;
struct ip_info sta_addr; struct ip_info sta_addr;
u8 _filler[
WIFICONF_SIZE
- 1
- 1
- 1
- SSID_LEN
- PASSWORD_LEN
- 1
- 2
- sizeof(struct dhcps_lease)
- sizeof(struct ip_info)
- SSID_LEN
- PASSWORD_LEN
- 1
- sizeof(struct ip_info)
- 8 // padding?
];
} WiFiConfigBundle; } WiFiConfigBundle;
typedef struct { typedef struct {

Loading…
Cancel
Save