Removed buffer allocation for telnet escaping of IAC bytes. Baudrate setting is now correctly reported on the web page.

pull/140/head
Christophe Duparquet 9 years ago
parent 076391bb62
commit b61eb276e2
  1. 161
      serial/serbridge.c

@ -24,7 +24,9 @@
* RESET (#1) -> ESP pin GPIO5 (#14)
* RXTX (#2) -> ESP pin GPIO13 (#5)
*
* Command: diabolo -t rfc2217://192.168.1.78:23
* Commands (using pyserial-3.0):
* python -m serial.tools.miniterm rfc2217://192.168.1.78:23
* diabolo -t rfc2217://192.168.1.78:23 --keep-txd-low 0.1 --read-flash
*/
#include "esp8266.h"
@ -41,14 +43,20 @@
#define SKIP_AT_RESET
/* ESP8266
/* ESP8266 hardware registers
*/
#define IROM ICACHE_FLASH_ATTR
#define REG_BRR (*(volatile uint32_t*)0x60000014)
#define REG_CONF0 (*(volatile uint32_t*)0x60000020)
#define REG_CONF1 (*(volatile uint32_t*)0x60000024)
#ifdef SERBR_DBG
# define DBG(...) do { os_printf(__VA_ARGS__); }while(0)
#else
# define DBG(...) do{}while(0)
#endif
static struct espconn serbridgeConn1; // plain bridging port
static struct espconn serbridgeConn2; // programming port
static esp_tcp serbridgeTcp1, serbridgeTcp2;
@ -61,8 +69,8 @@ void (*programmingCB)(char *buffer, short length) = NULL;
// Connection pool
serbridgeConnData connData[MAX_CONN];
static sint8 IROM espbuffsend(serbridgeConnData *conn, const char *data, uint16 len) ;
static sint8 IROM espbuffsend_tn(serbridgeConnData *conn, const char *data, uint16 len) ;
static sint8 ICACHE_FLASH_ATTR espbuffsend(serbridgeConnData *conn, const char *data, uint16 len) ;
static sint8 ICACHE_FLASH_ATTR espbuffsend_tn(serbridgeConnData *conn, const char *data, uint16 len) ;
// Telnet protocol (RFC854) characters
@ -88,13 +96,6 @@ static sint8 IROM espbuffsend_tn(serbridgeConnData *conn, const char *data, uint
#define PURGE_DATA 12 // suboption "PURGE"
#ifdef SERBR_DBG
# define dbgf(...) do { os_printf(__VA_ARGS__); }while(0)
#else
# define dbgf(...) do{}while(0)
#endif
/* Telnet state machine states
*/
enum {
@ -115,7 +116,8 @@ enum {
/* Telnet state machine: process one byte comming from a telnet connection
*/
static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
static void ICACHE_FLASH_ATTR
telnet_process_char ( serbridgeConnData *conn, char c )
{
#define state conn->tn_state
#define opt conn->tn_opt
@ -167,7 +169,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
}
if ( state == ST_NEGO ) {
dbgf("TELNET: IAC NEGO (%02X)", c);
DBG("TELNET: IAC NEGO (%02X)", c);
if ( c == BINARY ||
c == ECHO ||
c == SUPPRESS_GO_AHEAD ||
@ -175,7 +177,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/*
* Acknowledge positive requests for known options
*/
dbgf(": OK\n");
DBG(": OK\n");
if ( opt == DO )
opt = WILL ;
else if ( opt == WILL )
@ -185,7 +187,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/*
* Deny positive requests for unknown options
*/
dbgf(": REJECTED\n");
DBG(": REJECTED\n");
if ( opt == DO )
opt = WONT ;
else if ( opt == WILL )
@ -215,26 +217,26 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
if ( state == ST_COMPORT ) {
if ( c == SET_BAUDRATE ) {
dbgf(" BAUDRATE:");
DBG(" BAUDRATE:");
vlen = 0 ;
state = ST_BAUDRATE ;
} else if ( c == SET_DATASIZE ) {
dbgf(" DATASIZE:");
DBG(" DATASIZE:");
state = ST_DATASIZE ;
} else if ( c == SET_PARITY ) {
dbgf(" PARITY:");
DBG(" PARITY:");
state = ST_PARITY ;
} else if ( c == SET_STOPSIZE ) {
dbgf(" STOPSIZE:");
DBG(" STOPSIZE:");
state = ST_STOPSIZE ;
} else if ( c == SET_CONTROL ) {
dbgf(" CONTROL:");
DBG(" CONTROL:");
state = ST_CONTROL ;
} else if ( c == PURGE_DATA ) {
dbgf(" PURGE:");
DBG(" PURGE:");
state = ST_PURGE ;
} else {
dbgf("UNKNOWN: %02X\n", c);
DBG("UNKNOWN: %02X\n", c);
state = ST_WAIT_IAC ;
}
return ;
@ -244,7 +246,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/*
* Get 4 bytes of baudrate (MSB first)
*/
dbgf(" %02X", c);
DBG(" %02X", c);
value <<= 8 ;
value += c ;
@ -258,18 +260,22 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
*/
if ( value == 0 )
/*
* Get actual baudrate
* Get baudrate
*/
value = (int)(0.5 + 80e6/REG_BRR);
//value = (int)(0.5 + 80e6/REG_BRR);
value = flashConfig.baud_rate ;
else
/*
* Set baudrate
*/
REG_BRR = (int)(0.5 + 80e6/value);
//REG_BRR = (int)(0.5 + 80e6/value);
//UART_SetBaudrate(0,value); /* Not supported? */
flashConfig.baud_rate = value ;
uart0_baud( value );
/* Acknowledge
*/
dbgf(" = %ld\n", value);
DBG(" = %ld\n", value);
char v0 = value ;
char v1 = value >> 8 ;
char v2 = value >> 16 ;
@ -286,8 +292,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
if ( state == ST_DATASIZE ) {
if ( c >= 5 && c <= 8 ) {
/*
* Set data size
* Store databits in bits 3..2 of register conf0
* Set data size: CONF0 bits 3..2
*/
REG_CONF0 = (REG_CONF0 & ~0xC) | ((c-5)<<2) ;
}
@ -300,7 +305,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/* Acknowledge datasize
*/
dbgf(" %d\n", c );
DBG(" %d\n", c );
espbuffsend( conn, (char[]){IAC,SB,COM_PORT_OPTION,100+SET_DATASIZE,c,IAC,SE},7 );
state = ST_WAIT_IAC ;
return ;
@ -345,7 +350,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/* Acknowledge parity
*/
dbgf(" %d\n", c );
DBG(" %d\n", c );
espbuffsend( conn, (char[]){IAC,SB,COM_PORT_OPTION,100+SET_PARITY,c,IAC,SE},7 );
state = ST_WAIT_IAC ;
return ;
@ -386,7 +391,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/* Acknowledge stop bits
*/
dbgf(" %d\n", c );
DBG(" %d\n", c );
espbuffsend( conn, (char[]){IAC,SB,COM_PORT_OPTION,100+SET_STOPSIZE,c,IAC,SE},7 );
state = ST_WAIT_IAC ;
return ;
@ -418,84 +423,68 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
else if ( c == 8 ) {
#ifdef USE_UART_CONTROL_LINES
/*
* Set DTR Signal State ON
*
* Assert DTR: CONF0 bit 7
* Set DTR Signal State ON: CONF0 bit 7 = 1
*/
REG_CONF0 |= (1ULL<<7) ;
#else
/*
* Set DTR Signal State ON
*
* Drive MCU reset LOW
* Set DTR Signal State ON: drive MCU reset LOW
*/
if (mcu_reset_pin >= 0) {
dbgf("MCU reset gpio%d\n", mcu_reset_pin);
DBG("MCU reset gpio%d\n", mcu_reset_pin);
GPIO_OUTPUT_SET(mcu_reset_pin, 0);
}
else
dbgf("MCU reset: no pin\n");
DBG("MCU reset: no pin\n");
#endif
}
else if ( c == 9 ) {
#ifdef USE_UART_CONTROL_LINES
/*
* Set DTR Signal State OFF
*
* Assert DTR: CONF0 bit 7
* Set DTR Signal State OFF: CONF0 bit 7 = 0
*/
REG_CONF0 &= ~(1ULL<<7) ;
#else
/*
* Set DTR Signal State OFF
*
* Drive MCU reset HIGH
* Set DTR Signal State OFF: drive MCU reset HIGH
*/
if (mcu_reset_pin >= 0) {
dbgf("MCU reset gpio%d\n", mcu_reset_pin);
DBG("MCU reset gpio%d\n", mcu_reset_pin);
GPIO_OUTPUT_SET(mcu_reset_pin, 1);
}
else
dbgf("MCU reset: no pin\n");
DBG("MCU reset: no pin\n");
#endif
}
else if ( c == 11 ) {
#ifdef USE_UART_CONTROL_LINES
/*
* Set RTS Signal State ON
*
* Assert RTS: CONF0 bit 6 = 1
* Set RTS Signal State ON: CONF0 bit 6 = 1
*/
REG_CONF0 |= (1ULL<<6) ;
#else
/*
* Set RTS Signal State ON
*
* Drive MCU ISP pin LOW
* Set RTS Signal State ON: drive MCU ISP pin LOW
*/
if (mcu_isp_pin >= 0) {
dbgf("MCU ISP gpio%d\n", mcu_isp_pin);
DBG("MCU ISP gpio%d\n", mcu_isp_pin);
GPIO_OUTPUT_SET(mcu_isp_pin, 0);
os_delay_us(100L);
}
else
dbgf("MCU isp: no pin\n");
DBG("MCU isp: no pin\n");
slip_disabled++;
#endif
}
else if ( c == 12 ) {
#ifdef USE_UART_CONTROL_LINES
/*
* Set RTS Signal State OFF
*
* Assert RTS: CONF0 bit 6 = 0
* Set RTS Signal State OFF: CONF0 bit 6 = 0
*/
REG_CONF0 &= ~(1ULL<<6) ;
#else
/*
* Set RTS Signal State OFF
*
* Drive MCU ISP pin HIGH
* Set RTS Signal State OFF: drive MCU ISP pin HIGH
*/
if (mcu_isp_pin >= 0) {
GPIO_OUTPUT_SET(mcu_isp_pin, 1);
@ -514,7 +503,7 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/* Acknowledge control
*/
dbgf(" %d\n", c );
DBG(" %d\n", c );
espbuffsend( conn, (char[]){IAC,SB,COM_PORT_OPTION,100+SET_CONTROL,c,IAC,SE},7 );
state = ST_WAIT_IAC ;
return ;
@ -544,15 +533,13 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/* Acknowledge purge
*/
dbgf(" %d\n", c );
DBG(" %d\n", c );
espbuffsend( conn, (char[]){IAC,SB,COM_PORT_OPTION,100+PURGE_DATA,c,IAC,SE},7 );
state = ST_WAIT_IAC ;
return ;
}
/* Unexpected char
*/
state = ST_WAIT_IAC ;
/* Unknown state */
#undef state
#undef opt
@ -563,7 +550,8 @@ static void IROM telnet_process_char ( serbridgeConnData *conn, char c )
/* Process bytes comming from a telnet connection
*/
static void IROM telnet_process_buf ( serbridgeConnData *conn, uint8_t *buf, int len )
static void ICACHE_FLASH_ATTR
telnet_process_buf ( serbridgeConnData *conn, uint8_t *buf, int len )
{
#ifdef SERBR_DBG
os_printf("TELNET:");
@ -714,37 +702,16 @@ sendtxbuffer(serbridgeConnData *conn)
static sint8 ICACHE_FLASH_ATTR
espbuffsend_tn ( serbridgeConnData *conn, const char *data, uint16 len )
{
// How many bytes for the new buffer?
//
int n = 0 ;
for ( int i=0 ; i<len ; i++ )
if ( data[i] == 0xFF )
n++ ;
// Allocate and populate new buffer if necessary
//
if ( n ) {
char *tnbuf = os_zalloc(len+n);
if ( tnbuf == NULL ) {
os_printf("espbuffsend: could not allocate buffer for telnet escape\n");
return -128;
}
n = 0 ;
for ( int i=0 ; i<len ; i++ ) {
tnbuf[n++] = data[i] ;
if ( data[i] == 0xFF )
tnbuf[n++] = 0xFF ;
}
sint8 r ;
// Send buffer
//
sint8 result = espbuffsend( conn, tnbuf, n );
os_free( tnbuf );
return result ;
for ( char const *p=data ; p<data+len ; p++ ) {
if ( (r = espbuffsend( conn, p, 1 )) != 0 )
return r ;
if ( *p == '\xFF' && (r = espbuffsend( conn, p, 1 )) != 0 )
return r ;
}
return espbuffsend( conn, data, len );
return 0;
}

Loading…
Cancel
Save