Implemented factory reset & split ansi_parser to parser and callbacks

pull/30/head
Ondřej Hruška 8 years ago
parent 46320ef4b9
commit def04042a7
  1. 251
      user/ansi_parser.c
  2. 7
      user/ansi_parser.h
  3. 209
      user/ansi_parser.rl
  4. 256
      user/ansi_parser_callbacks.c
  5. 11
      user/ansi_parser_callbacks.h

@ -1,208 +1,11 @@
/* #line 1 "user/ansi_parser.rl" */
#include <esp8266.h>
#include "screen.h"
#include "ansi_parser.h"
// Max nr of CSI parameters
#define CSI_N_MAX 3
/**
* \brief Handle fully received CSI ANSI sequence
* \param leadchar - private range leading character, 0 if none
* \param params - array of CSI_N_MAX ints holding the numeric arguments
* \param keychar - the char terminating the sequence
*/
void ICACHE_FLASH_ATTR
handle_CSI(char leadchar, int *params, char keychar)
{
/*
Implemented codes (from Wikipedia)
CSI n A CUU Cursor Up
CSI n B CUD Cursor Down
CSI n C CUF Cursor Forward
CSI n D CUB Cursor Back
CSI n E CNL Cursor Next Line
CSI n F CPL Cursor Previous Line
CSI n G CHA Cursor Horizontal Absolute
CSI n ; m H CUP Cursor Position
CSI n J ED Erase Display
CSI n K EL Erase in Line
CSI n S SU Scroll Up
CSI n T SD Scroll Down
CSI n ; m f HVP Horizontal and Vertical Position
CSI n m SGR Select Graphic Rendition (Implemented only some)
CSI 6n DSR Device Status Report NOT IMPL
CSI s SCP Save Cursor Position
CSI u RCP Restore Cursor Position
CSI ?25l DECTCEM Hides the cursor
CSI ?25h DECTCEM Shows the cursor
*/
int n1 = params[0];
int n2 = params[1];
// int n3 = params[2];
// defaults
switch (keychar) {
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'S':
case 'T':
if (n1 == 0) n1 = 1;
break;
case 'H':
case 'f':
if (n1 == 0) n1 = 1;
if (n2 == 0) n2 = 1;
break;
case 'J':
case 'K':
if (n1 > 2) n1 = 0;
break;
}
switch (keychar) {
// CUU CUD CUF CUB
case 'A': screen_cursor_move(0, -n1); break;
case 'B': screen_cursor_move(0, n1); break;
case 'C': screen_cursor_move(n1, 0); break;
case 'D': screen_cursor_move(-n1, 0); break;
case 'E': // CNL
screen_cursor_move(0, n1);
screen_cursor_set_x(0);
break;
case 'F': // CPL
screen_cursor_move(0, -n1);
screen_cursor_set_x(0);
break;
// CHA
case 'G':
screen_cursor_set_x(n1 - 1); break; // 1-based
// SU, SD
case 'S': screen_scroll_up(n1); break;
case 'T': screen_scroll_down(n1); break;
// CUP,HVP
case 'H':
case 'f':
screen_cursor_set(n2-1, n1-1); break; // 1-based
case 'J': // ED
if (n1 == 0) {
screen_clear(CLEAR_TO_CURSOR);
} else if (n1 == 1) {
screen_clear(CLEAR_FROM_CURSOR);
} else {
screen_clear(CLEAR_ALL);
screen_cursor_set(0, 0);
}
break;
case 'K': // EL
if (n1 == 0) {
screen_clear_line(CLEAR_TO_CURSOR);
} else if (n1 == 1) {
screen_clear_line(CLEAR_FROM_CURSOR);
} else {
screen_clear_line(CLEAR_ALL);
screen_cursor_set_x(0);
}
break;
// SCP, RCP
case 's': screen_cursor_save(); break;
case 'u': screen_cursor_restore(); break;
// DECTCEM cursor show hide
case 'l':
if (leadchar == '?' && n1 == 25) {
screen_cursor_enable(1);
}
break;
case 'h':
if (leadchar == '?' && n1 == 25) {
screen_cursor_enable(0);
}
break;
case 'm': // SGR
// iterate arguments
for (int i = 0; i < CSI_N_MAX; i++) {
int n = params[i];
if (i == 0 && n == 0) { // reset SGR
screen_set_fg(7);
screen_set_bg(0);
break; // cannot combine reset with others
}
else if (n >= 30 && n <= 37) screen_set_fg(n-30); // ANSI normal fg
else if (n >= 40 && n <= 47) screen_set_bg(n-40); // ANSI normal bg
else if (n == 39) screen_set_fg(7); // default fg
else if (n == 49) screen_set_bg(0); // default bg
else if (n == 7) screen_inverse(1); // inverse
else if (n == 27) screen_inverse(0); // positive
else if (n == 1) screen_set_bright_fg(); // ANSI bold = bright fg
else if (n >= 90 && n <= 97) screen_set_fg(n-90+8); // AIX bright fg
else if (n >= 100 && n <= 107) screen_set_bg(n-100+8); // AIX bright bg
}
break;
}
}
/**
* \brief Handle a request to reset the display device
*/
void ICACHE_FLASH_ATTR
handle_RESET_cmd(void)
{
screen_reset();
}
/**
* \brief Handle a received plain character
* \param c - the character
*/
void ICACHE_FLASH_ATTR
handle_plainchar(char c)
{
screen_putchar(c);
}
void ICACHE_FLASH_ATTR
handle_OSC_FactoryReset(void)
{
info("OSC: Factory reset");
warn("NOT IMPLEMENTED");
// TODO
}
void ICACHE_FLASH_ATTR
handle_OSC_SetScreenSize(int rows, int cols)
{
info("OSC: Set screen size to %d x %d", rows, cols);
screen_resize(rows, cols);
}
/* Ragel constants block */
/* #line 206 "user/ansi_parser.c" */
/* #line 9 "user/ansi_parser.c" */
static const char _ansi_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 6, 1,
@ -224,7 +27,7 @@ static const int ansi_en_OSC_body = 5;
static const int ansi_en_main = 1;
/* #line 205 "user/ansi_parser.rl" */
/* #line 8 "user/ansi_parser.rl" */
/**
@ -261,17 +64,17 @@ ansi_parser(const char *newdata, size_t len)
// Init Ragel on the first run
if (cs == -1) {
/* #line 265 "user/ansi_parser.c" */
/* #line 68 "user/ansi_parser.c" */
{
cs = ansi_start;
}
/* #line 241 "user/ansi_parser.rl" */
/* #line 44 "user/ansi_parser.rl" */
}
// The parser
/* #line 275 "user/ansi_parser.c" */
/* #line 78 "user/ansi_parser.c" */
{
const char *_acts;
unsigned int _nacts;
@ -419,13 +222,13 @@ execFuncs:
while ( _nacts-- > 0 ) {
switch ( *_acts++ ) {
case 0:
/* #line 251 "user/ansi_parser.rl" */
/* #line 54 "user/ansi_parser.rl" */
{
handle_plainchar((*p));
apars_handle_plainchar((*p));
}
break;
case 1:
/* #line 258 "user/ansi_parser.rl" */
/* #line 61 "user/ansi_parser.rl" */
{
/* Reset the CSI builder */
csi_leading = csi_char = 0;
@ -440,13 +243,13 @@ execFuncs:
}
break;
case 2:
/* #line 271 "user/ansi_parser.rl" */
/* #line 74 "user/ansi_parser.rl" */
{
csi_leading = (*p);
}
break;
case 3:
/* #line 275 "user/ansi_parser.rl" */
/* #line 78 "user/ansi_parser.rl" */
{
/* x10 + digit */
if (csi_ni < CSI_N_MAX) {
@ -455,30 +258,30 @@ execFuncs:
}
break;
case 4:
/* #line 282 "user/ansi_parser.rl" */
/* #line 85 "user/ansi_parser.rl" */
{
csi_ni++;
}
break;
case 5:
/* #line 286 "user/ansi_parser.rl" */
/* #line 89 "user/ansi_parser.rl" */
{
csi_char = (*p);
handle_CSI(csi_leading, csi_n, csi_char);
apars_handle_CSI(csi_leading, csi_n, csi_char);
{cs = 1; goto _again;}
}
break;
case 6:
/* #line 294 "user/ansi_parser.rl" */
/* #line 97 "user/ansi_parser.rl" */
{
warn("Invalid escape sequence discarded.");
apars_handle_badseq();
{cs = 1; goto _again;}
}
break;
case 7:
/* #line 311 "user/ansi_parser.rl" */
/* #line 114 "user/ansi_parser.rl" */
{
csi_ni = 0;
@ -491,29 +294,29 @@ execFuncs:
}
break;
case 8:
/* #line 322 "user/ansi_parser.rl" */
/* #line 125 "user/ansi_parser.rl" */
{
handle_OSC_FactoryReset();
apars_handle_OSC_FactoryReset();
{cs = 1; goto _again;}
}
break;
case 9:
/* #line 327 "user/ansi_parser.rl" */
/* #line 130 "user/ansi_parser.rl" */
{
handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
{cs = 1; goto _again;}
}
break;
case 10:
/* #line 338 "user/ansi_parser.rl" */
/* #line 141 "user/ansi_parser.rl" */
{
// Reset screen
handle_RESET_cmd();
apars_handle_RESET_cmd();
{cs = 1; goto _again;}
}
break;
/* #line 517 "user/ansi_parser.c" */
/* #line 320 "user/ansi_parser.c" */
}
}
goto _again;
@ -531,13 +334,13 @@ _again:
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 6:
/* #line 294 "user/ansi_parser.rl" */
/* #line 97 "user/ansi_parser.rl" */
{
warn("Invalid escape sequence discarded.");
apars_handle_badseq();
{cs = 1; goto _again;}
}
break;
/* #line 541 "user/ansi_parser.c" */
/* #line 344 "user/ansi_parser.c" */
}
}
}
@ -545,6 +348,6 @@ _again:
_out: {}
}
/* #line 356 "user/ansi_parser.rl" */
/* #line 159 "user/ansi_parser.rl" */
}

@ -6,6 +6,13 @@
// Max nr of CSI parameters
#define CSI_N_MAX 3
extern void apars_handle_badseq(void);
extern void apars_handle_CSI(char leadchar, int *params, char keychar);
extern void apars_handle_RESET_cmd(void);
extern void apars_handle_plainchar(char c);
extern void apars_handle_OSC_FactoryReset(void);
extern void apars_handle_OSC_SetScreenSize(int rows, int cols);
/**
* \brief Linear ANSI chars stream parser
*

@ -1,203 +1,6 @@
#include <esp8266.h>
#include "screen.h"
#include "ansi_parser.h"
// Max nr of CSI parameters
#define CSI_N_MAX 3
/**
* \brief Handle fully received CSI ANSI sequence
* \param leadchar - private range leading character, 0 if none
* \param params - array of CSI_N_MAX ints holding the numeric arguments
* \param keychar - the char terminating the sequence
*/
void ICACHE_FLASH_ATTR
handle_CSI(char leadchar, int *params, char keychar)
{
/*
Implemented codes (from Wikipedia)
CSI n A CUU – Cursor Up
CSI n B CUD – Cursor Down
CSI n C CUF – Cursor Forward
CSI n D CUB – Cursor Back
CSI n E CNL – Cursor Next Line
CSI n F CPL – Cursor Previous Line
CSI n G CHA – Cursor Horizontal Absolute
CSI n ; m H CUP – Cursor Position
CSI n J ED – Erase Display
CSI n K EL – Erase in Line
CSI n S SU – Scroll Up
CSI n T SD – Scroll Down
CSI n ; m f HVP – Horizontal and Vertical Position
CSI n m SGR – Select Graphic Rendition (Implemented only some)
CSI 6n DSR – Device Status Report NOT IMPL
CSI s SCP – Save Cursor Position
CSI u RCP – Restore Cursor Position
CSI ?25l DECTCEM Hides the cursor
CSI ?25h DECTCEM Shows the cursor
*/
int n1 = params[0];
int n2 = params[1];
// int n3 = params[2];
// defaults
switch (keychar) {
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'S':
case 'T':
if (n1 == 0) n1 = 1;
break;
case 'H':
case 'f':
if (n1 == 0) n1 = 1;
if (n2 == 0) n2 = 1;
break;
case 'J':
case 'K':
if (n1 > 2) n1 = 0;
break;
}
switch (keychar) {
// CUU CUD CUF CUB
case 'A': screen_cursor_move(0, -n1); break;
case 'B': screen_cursor_move(0, n1); break;
case 'C': screen_cursor_move(n1, 0); break;
case 'D': screen_cursor_move(-n1, 0); break;
case 'E': // CNL
screen_cursor_move(0, n1);
screen_cursor_set_x(0);
break;
case 'F': // CPL
screen_cursor_move(0, -n1);
screen_cursor_set_x(0);
break;
// CHA
case 'G':
screen_cursor_set_x(n1 - 1); break; // 1-based
// SU, SD
case 'S': screen_scroll_up(n1); break;
case 'T': screen_scroll_down(n1); break;
// CUP,HVP
case 'H':
case 'f':
screen_cursor_set(n2-1, n1-1); break; // 1-based
case 'J': // ED
if (n1 == 0) {
screen_clear(CLEAR_TO_CURSOR);
} else if (n1 == 1) {
screen_clear(CLEAR_FROM_CURSOR);
} else {
screen_clear(CLEAR_ALL);
screen_cursor_set(0, 0);
}
break;
case 'K': // EL
if (n1 == 0) {
screen_clear_line(CLEAR_TO_CURSOR);
} else if (n1 == 1) {
screen_clear_line(CLEAR_FROM_CURSOR);
} else {
screen_clear_line(CLEAR_ALL);
screen_cursor_set_x(0);
}
break;
// SCP, RCP
case 's': screen_cursor_save(); break;
case 'u': screen_cursor_restore(); break;
// DECTCEM cursor show hide
case 'l':
if (leadchar == '?' && n1 == 25) {
screen_cursor_enable(1);
}
break;
case 'h':
if (leadchar == '?' && n1 == 25) {
screen_cursor_enable(0);
}
break;
case 'm': // SGR
// iterate arguments
for (int i = 0; i < CSI_N_MAX; i++) {
int n = params[i];
if (i == 0 && n == 0) { // reset SGR
screen_set_fg(7);
screen_set_bg(0);
break; // cannot combine reset with others
}
else if (n >= 30 && n <= 37) screen_set_fg(n-30); // ANSI normal fg
else if (n >= 40 && n <= 47) screen_set_bg(n-40); // ANSI normal bg
else if (n == 39) screen_set_fg(7); // default fg
else if (n == 49) screen_set_bg(0); // default bg
else if (n == 7) screen_inverse(1); // inverse
else if (n == 27) screen_inverse(0); // positive
else if (n == 1) screen_set_bright_fg(); // ANSI bold = bright fg
else if (n >= 90 && n <= 97) screen_set_fg(n-90+8); // AIX bright fg
else if (n >= 100 && n <= 107) screen_set_bg(n-100+8); // AIX bright bg
}
break;
}
}
/**
* \brief Handle a request to reset the display device
*/
void ICACHE_FLASH_ATTR
handle_RESET_cmd(void)
{
screen_reset();
}
/**
* \brief Handle a received plain character
* \param c - the character
*/
void ICACHE_FLASH_ATTR
handle_plainchar(char c)
{
screen_putchar(c);
}
void ICACHE_FLASH_ATTR
handle_OSC_FactoryReset(void)
{
info("OSC: Factory reset");
warn("NOT IMPLEMENTED");
// TODO
}
void ICACHE_FLASH_ATTR
handle_OSC_SetScreenSize(int rows, int cols)
{
info("OSC: Set screen size to %d x %d", rows, cols);
screen_resize(rows, cols);
}
/* Ragel constants block */
%%{
machine ansi;
@ -249,7 +52,7 @@ ansi_parser(const char *newdata, size_t len)
# --- Regular characters to be printed ---
action plain_char {
handle_plainchar(fc);
apars_handle_plainchar(fc);
}
# --- CSI CSI commands (Select Graphic Rendition) ---
@ -286,13 +89,13 @@ ansi_parser(const char *newdata, size_t len)
action CSI_end {
csi_char = fc;
handle_CSI(csi_leading, csi_n, csi_char);
apars_handle_CSI(csi_leading, csi_n, csi_char);
fgoto main;
}
action errBadSeq {
warn("Invalid escape sequence discarded.");
apars_handle_badseq();
fgoto main;
}
@ -320,12 +123,12 @@ ansi_parser(const char *newdata, size_t len)
}
action OSC_fr {
handle_OSC_FactoryReset();
apars_handle_OSC_FactoryReset();
fgoto main;
}
action OSC_resize {
handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
fgoto main;
}
@ -337,7 +140,7 @@ ansi_parser(const char *newdata, size_t len)
action RESET_cmd {
// Reset screen
handle_RESET_cmd();
apars_handle_RESET_cmd();
fgoto main;
}

@ -0,0 +1,256 @@
/**
* ANSI code parser callbacks that do the actual work.
* Split from the parser itself for easier editing without
* having to deal with Ragel.
*/
#include <esp8266.h>
#include "ansi_parser_callbacks.h"
#include "screen.h"
#include "ansi_parser.h"
#include "uart_driver.h"
/**
* Handle a received plain character
*/
void ICACHE_FLASH_ATTR
apars_handle_plainchar(char c)
{
screen_putchar(c);
}
/**
* Bad sequence received, show warning
*/
void apars_handle_badseq(void)
{
warn("Invalid escape sequence discarded.");
}
/**
* \brief Handle fully received CSI ANSI sequence
* \param leadchar - private range leading character, 0 if none
* \param params - array of CSI_N_MAX ints holding the numeric arguments
* \param keychar - the char terminating the sequence
*/
void ICACHE_FLASH_ATTR
apars_handle_CSI(char leadchar, int *params, char keychar)
{
/*
Implemented codes (from Wikipedia)
CSI n A CUU Cursor Up
CSI n B CUD Cursor Down
CSI n C CUF Cursor Forward
CSI n D CUB Cursor Back
CSI n E CNL Cursor Next Line
CSI n F CPL Cursor Previous Line
CSI n G CHA Cursor Horizontal Absolute
CSI n ; m H CUP Cursor Position
CSI n J ED Erase Display
CSI n K EL Erase in Line
CSI n S SU Scroll Up
CSI n T SD Scroll Down
CSI n ; m f HVP Horizontal and Vertical Position
CSI n m SGR Select Graphic Rendition (Implemented only some)
CSI 6n DSR Device Status Report NOT IMPL
CSI s SCP Save Cursor Position
CSI u RCP Restore Cursor Position
CSI ?25l DECTCEM Hides the cursor
CSI ?25h DECTCEM Shows the cursor
*/
int n1 = params[0];
int n2 = params[1];
// int n3 = params[2];
// defaults
switch (keychar) {
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'S':
case 'T':
if (n1 == 0) n1 = 1;
break;
case 'H':
case 'f':
if (n1 == 0) n1 = 1;
if (n2 == 0) n2 = 1;
break;
case 'J':
case 'K':
if (n1 > 2) n1 = 0;
break;
}
switch (keychar) {
// CUU CUD CUF CUB
case 'A': screen_cursor_move(0, -n1); break;
case 'B': screen_cursor_move(0, n1); break;
case 'C': screen_cursor_move(n1, 0); break;
case 'D': screen_cursor_move(-n1, 0); break;
case 'E': // CNL
screen_cursor_move(0, n1);
screen_cursor_set_x(0);
break;
case 'F': // CPL
screen_cursor_move(0, -n1);
screen_cursor_set_x(0);
break;
// CHA
case 'G':
screen_cursor_set_x(n1 - 1); break; // 1-based
// SU, SD
case 'S': screen_scroll_up(n1); break;
case 'T': screen_scroll_down(n1); break;
// CUP,HVP
case 'H':
case 'f':
screen_cursor_set(n2-1, n1-1); break; // 1-based
case 'J': // ED
if (n1 == 0) {
screen_clear(CLEAR_TO_CURSOR);
} else if (n1 == 1) {
screen_clear(CLEAR_FROM_CURSOR);
} else {
screen_clear(CLEAR_ALL);
screen_cursor_set(0, 0);
}
break;
case 'K': // EL
if (n1 == 0) {
screen_clear_line(CLEAR_TO_CURSOR);
} else if (n1 == 1) {
screen_clear_line(CLEAR_FROM_CURSOR);
} else {
screen_clear_line(CLEAR_ALL);
screen_cursor_set_x(0);
}
break;
// SCP, RCP
case 's': screen_cursor_save(); break;
case 'u': screen_cursor_restore(); break;
// DECTCEM cursor show hide
case 'l':
if (leadchar == '?' && n1 == 25) {
screen_cursor_enable(1);
}
break;
case 'h':
if (leadchar == '?' && n1 == 25) {
screen_cursor_enable(0);
}
break;
case 'm': // SGR
// iterate arguments
for (int i = 0; i < CSI_N_MAX; i++) {
int n = params[i];
if (i == 0 && n == 0) { // reset SGR
screen_set_fg(7);
screen_set_bg(0);
break; // cannot combine reset with others
}
else if (n >= 30 && n <= 37) screen_set_fg(n-30); // ANSI normal fg
else if (n >= 40 && n <= 47) screen_set_bg(n-40); // ANSI normal bg
else if (n == 39) screen_set_fg(7); // default fg
else if (n == 49) screen_set_bg(0); // default bg
else if (n == 7) screen_inverse(1); // inverse
else if (n == 27) screen_inverse(0); // positive
else if (n == 1) screen_set_bright_fg(); // ANSI bold = bright fg
else if (n >= 90 && n <= 97) screen_set_fg(n-90+8); // AIX bright fg
else if (n >= 100 && n <= 107) screen_set_bg(n-100+8); // AIX bright bg
}
break;
}
}
/**
* \brief Handle a request to reset the display device
*/
void ICACHE_FLASH_ATTR
apars_handle_RESET_cmd(void)
{
// XXX maybe user wanted to reset the module instead?
screen_reset();
}
/**
* Handle a factory reset request
*/
void ICACHE_FLASH_ATTR
apars_handle_OSC_FactoryReset(void)
{
info("OSC: Factory reset");
// Send acknowledgement message to UART0
// User is performing this manually, so we can just print it as string
UART_WriteString(UART0, "\r\nFACTORY RESET\r\n", UART_TIMEOUT_US);
// Disconnect from AP if connected
int opmode = wifi_get_opmode();
if (opmode != SOFTAP_MODE) {
wifi_station_disconnect();
}
// Both must be enabled so we can manipulate their settings
wifi_set_opmode(STATIONAP_MODE);
// --- AP config ---
struct softap_config apconf;
wifi_softap_get_config(&apconf);
apconf.authmode=AUTH_OPEN; // Disable access protection
apconf.channel=1; // Reset channel; user may have set bad channel in the UI
// generate unique AP name
u8 mac[6];
wifi_get_macaddr(SOFTAP_IF, mac);
sprintf((char*)apconf.ssid, "TERM-%02X%02X%02X", mac[3], mac[4], mac[5]);
apconf.ssid_len = (u8)strlen((char*)apconf.ssid);
// --- Station ---
struct station_config staconf;
wifi_station_get_config(&staconf);
// clear info about SSID
staconf.ssid[0]=0;
staconf.bssid_set=0;
staconf.password[0]=0;
wifi_softap_set_config(&apconf);
wifi_station_set_config(&staconf);
UART_WriteString(UART0, "Factory Reset complete, device reset.\r\n\r\n", UART_TIMEOUT_US);
// Reboot to clean STA+AP mode with Channel 1 & reset AP SSID.
system_restart();
}
/**
* Handle a screen resize request
*/
void ICACHE_FLASH_ATTR
apars_handle_OSC_SetScreenSize(int rows, int cols)
{
info("OSC: Set screen size to %d x %d", rows, cols);
screen_resize(rows, cols);
}

@ -0,0 +1,11 @@
#ifndef ANSI_PARSER_CALLBACKS_H
#define ANSI_PARSER_CALLBACKS_H
void apars_handle_badseq(void);
void apars_handle_CSI(char leadchar, int *params, char keychar);
void apars_handle_RESET_cmd(void);
void apars_handle_plainchar(char c);
void apars_handle_OSC_FactoryReset(void);
void apars_handle_OSC_SetScreenSize(int rows, int cols);
#endif //ESP_VT100_FIRMWARE_ANSI_PARSER_CALLBACKS_H
Loading…
Cancel
Save