@ -9,24 +9,27 @@
# include "gpio.h"
# include "uart.h"
# include "crc16.h"
# include "serbridge.h"
# include "serled.h"
# include "config.h"
# include "console.h"
# include "tcpclient .h"
# include "cmd .h"
static struct espconn serbridgeConn ;
static esp_tcp serbridgeTcp ;
static int8_t mcu_reset_pin , mcu_isp_pin ;
extern uint8_t slip_disabled ; // disable slip to allow flashing of attached MCU
static sint8 ICACHE_FLASH_ATTR espbuffsend ( serbridgeConnData * conn , const char * data , uint16 len ) ;
// Connection pool
serbridgeConnData connData [ MAX_CONN ] ;
// Given a pointer to an espconn struct find the connection that correcponds to it
static serbridgeConnData ICACHE_FLASH_ATTR * serbridgeFindConnData ( void * arg ) {
struct espconn * conn = arg ;
return arg = = NULL ? NULL : ( serbridgeConnData * ) conn - > reverse ;
struct espconn * conn = arg ;
return arg = = NULL ? NULL : ( serbridgeConnData * ) conn - > reverse ;
}
//===== TCP -> UART
@ -50,149 +53,152 @@ enum { TN_normal, TN_iac, TN_will, TN_start, TN_end, TN_comPort, TN_setControl }
static uint8_t ICACHE_FLASH_ATTR
telnetUnwrap ( uint8_t * inBuf , int len , uint8_t state )
{
for ( int i = 0 ; i < len ; i + + ) {
uint8_t c = inBuf [ i ] ;
switch ( state ) {
default :
case TN_normal :
if ( c = = IAC ) state = TN_iac ; // escape char: see what's next
else uart0_write_char ( c ) ; // regular char
break ;
case TN_iac :
switch ( c ) {
case IAC : // second escape -> write one to outbuf and go normal again
state = TN_normal ;
uart0_write_char ( c ) ;
break ;
case WILL : // negotiation
state = TN_will ;
break ;
case SB : // command sequence begin
state = TN_start ;
break ;
case SE : // command sequence end
state = TN_normal ;
break ;
default : // not sure... let's ignore
uart0_write_char ( IAC ) ;
uart0_write_char ( c ) ;
}
break ;
case TN_will :
state = TN_normal ; // yes, we do COM port options, let's go back to normal
break ;
case TN_start : // in command seq, now comes the type of cmd
if ( c = = ComPortOpt ) state = TN_comPort ;
else state = TN_end ; // an option we don't know, skip 'til the end seq
break ;
case TN_end : // wait for end seq
if ( c = = IAC ) state = TN_iac ; // simple wait to accept end or next escape seq
break ;
case TN_comPort :
if ( c = = SetControl ) state = TN_setControl ;
else state = TN_end ;
break ;
case TN_setControl : // switch control line and delay a tad
switch ( c ) {
case DTR_ON :
if ( mcu_reset_pin > = 0 ) {
os_printf ( " MCU reset gpio%d \n " , mcu_reset_pin ) ;
GPIO_OUTPUT_SET ( mcu_reset_pin , 0 ) ;
os_delay_us ( 100L ) ;
} else os_printf ( " MCU reset: no pin \n " ) ;
break ;
case DTR_OFF :
if ( mcu_reset_pin > = 0 ) {
GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
os_delay_us ( 100L ) ;
}
break ;
case RTS_ON :
if ( mcu_isp_pin > = 0 ) {
os_printf ( " MCU ISP gpio%d \n " , mcu_isp_pin ) ;
GPIO_OUTPUT_SET ( mcu_isp_pin , 0 ) ;
os_delay_us ( 100L ) ;
} else os_printf ( " MCU isp: no pin \n " ) ;
break ;
case RTS_OFF :
if ( mcu_isp_pin > = 0 ) {
GPIO_OUTPUT_SET ( mcu_isp_pin , 1 ) ;
os_delay_us ( 100L ) ;
}
break ;
}
state = TN_end ;
break ;
}
}
return state ;
for ( int i = 0 ; i < len ; i + + ) {
uint8_t c = inBuf [ i ] ;
switch ( state ) {
default :
case TN_normal :
if ( c = = IAC ) state = TN_iac ; // escape char: see what's next
else uart0_write_char ( c ) ; // regular char
break ;
case TN_iac :
switch ( c ) {
case IAC : // second escape -> write one to outbuf and go normal again
state = TN_normal ;
uart0_write_char ( c ) ;
break ;
case WILL : // negotiation
state = TN_will ;
break ;
case SB : // command sequence begin
state = TN_start ;
break ;
case SE : // command sequence end
state = TN_normal ;
break ;
default : // not sure... let's ignore
uart0_write_char ( IAC ) ;
uart0_write_char ( c ) ;
}
break ;
case TN_will :
state = TN_normal ; // yes, we do COM port options, let's go back to normal
break ;
case TN_start : // in command seq, now comes the type of cmd
if ( c = = ComPortOpt ) state = TN_comPort ;
else state = TN_end ; // an option we don't know, skip 'til the end seq
break ;
case TN_end : // wait for end seq
if ( c = = IAC ) state = TN_iac ; // simple wait to accept end or next escape seq
break ;
case TN_comPort :
if ( c = = SetControl ) state = TN_setControl ;
else state = TN_end ;
break ;
case TN_setControl : // switch control line and delay a tad
switch ( c ) {
case DTR_ON :
if ( mcu_reset_pin > = 0 ) {
os_printf ( " MCU reset gpio%d \n " , mcu_reset_pin ) ;
GPIO_OUTPUT_SET ( mcu_reset_pin , 0 ) ;
os_delay_us ( 100L ) ;
} else os_printf ( " MCU reset: no pin \n " ) ;
break ;
case DTR_OFF :
if ( mcu_reset_pin > = 0 ) {
GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
os_delay_us ( 100L ) ;
}
break ;
case RTS_ON :
if ( mcu_isp_pin > = 0 ) {
os_printf ( " MCU ISP gpio%d \n " , mcu_isp_pin ) ;
GPIO_OUTPUT_SET ( mcu_isp_pin , 0 ) ;
os_delay_us ( 100L ) ;
} else os_printf ( " MCU isp: no pin \n " ) ;
slip_disabled + + ;
break ;
case RTS_OFF :
if ( mcu_isp_pin > = 0 ) {
GPIO_OUTPUT_SET ( mcu_isp_pin , 1 ) ;
os_delay_us ( 100L ) ;
}
if ( slip_disabled > 0 ) slip_disabled - - ;
break ;
}
state = TN_end ;
break ;
}
}
return state ;
}
// Generate a reset pulse for the attached microcontroller
void ICACHE_FLASH_ATTR serbridgeReset ( ) {
if ( mcu_reset_pin > = 0 ) {
os_printf ( " MCU reset gpio%d \n " , mcu_reset_pin ) ;
GPIO_OUTPUT_SET ( mcu_reset_pin , 0 ) ;
os_delay_us ( 100L ) ;
GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
} else os_printf ( " MCU reset: no pin \n " ) ;
if ( mcu_reset_pin > = 0 ) {
os_printf ( " MCU reset gpio%d \n " , mcu_reset_pin ) ;
GPIO_OUTPUT_SET ( mcu_reset_pin , 0 ) ;
os_delay_us ( 100L ) ;
GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
} else os_printf ( " MCU reset: no pin \n " ) ;
}
// Receive callback
static void ICACHE_FLASH_ATTR serbridgeRecvCb ( void * arg , char * data , unsigned short len ) {
serbridgeConnData * conn = serbridgeFindConnData ( arg ) ;
//os_printf("Receive callback on conn %p\n", conn);
if ( conn = = NULL ) return ;
// at the start of a connection we're in cmInit mode and we wait for the first few characters
// to arrive in order to decide what type of connection this is.. The following if statements
// do this dispatch. An issue here is that we assume that the first few characters all arrive
// in the same TCP packet, which is true if the sender is a program, but not necessarily
// if the sender is a person typing (although in that case the line-oriented TTY input seems
// to make it work too). If this becomes a problem we need to buffer the first few chars...
if ( conn - > conn_mode = = cmInit ) {
// If the connection starts with the Arduino or ARM reset sequence we perform a RESET
if ( ( len = = 2 & & strncmp ( data , " 0 " , 2 ) = = 0 ) | |
( len = = 2 & & strncmp ( data , " ? \n " , 2 ) = = 0 ) | |
( len = = 3 & & strncmp ( data , " ? \r \n " , 3 ) = = 0 ) ) {
os_printf ( " MCU Reset=%d ISP=%d \n " , mcu_reset_pin , mcu_isp_pin ) ;
os_delay_us ( 2 * 1000L ) ; // time for os_printf to happen
// send reset to arduino/ARM
if ( mcu_reset_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_reset_pin , 0 ) ;
os_delay_us ( 100L ) ;
if ( mcu_isp_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_isp_pin , 0 ) ;
os_delay_us ( 100L ) ;
if ( mcu_reset_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
os_delay_us ( 100L ) ;
if ( mcu_isp_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_isp_pin , 1 ) ;
os_delay_us ( 1000L ) ;
conn - > conn_mode = cmAVR ;
// If the connection starts with a telnet negotiation we will do telnet
} else if ( len > = 3 & & strncmp ( data , ( char [ ] ) { IAC , WILL , ComPortOpt } , 3 ) = = 0 ) {
conn - > conn_mode = cmTelnet ;
conn - > telnet_state = TN_normal ;
// note that the three negotiation chars will be gobbled-up by telnetUnwrap
os_printf ( " telnet mode \n " ) ;
// looks like a plain-vanilla connection!
} else {
conn - > conn_mode = cmTransparent ;
}
// Process return data on TCP client connections
} else if ( conn - > conn_mode = = cmTcpClient ) {
}
// write the buffer to the uart
if ( conn - > conn_mode = = cmTelnet ) {
conn - > telnet_state = telnetUnwrap ( ( uint8_t * ) data , len , conn - > telnet_state ) ;
} else {
uart0_tx_buffer ( data , len ) ;
}
serledFlash ( 50 ) ; // short blink on serial LED
serbridgeConnData * conn = serbridgeFindConnData ( arg ) ;
//os_printf("Receive callback on conn %p\n", conn);
if ( conn = = NULL ) return ;
// at the start of a connection we're in cmInit mode and we wait for the first few characters
// to arrive in order to decide what type of connection this is.. The following if statements
// do this dispatch. An issue here is that we assume that the first few characters all arrive
// in the same TCP packet, which is true if the sender is a program, but not necessarily
// if the sender is a person typing (although in that case the line-oriented TTY input seems
// to make it work too). If this becomes a problem we need to buffer the first few chars...
if ( conn - > conn_mode = = cmInit ) {
// If the connection starts with the Arduino or ARM reset sequence we perform a RESET
if ( ( len = = 2 & & strncmp ( data , " 0 " , 2 ) = = 0 ) | |
( len = = 2 & & strncmp ( data , " ? \n " , 2 ) = = 0 ) | |
( len = = 3 & & strncmp ( data , " ? \r \n " , 3 ) = = 0 ) ) {
os_printf ( " MCU Reset=gpio %d ISP=gpio %d \n " , mcu_reset_pin , mcu_isp_pin ) ;
os_delay_us ( 2 * 1000L ) ; // time for os_printf to happen
// send reset to arduino/ARM
if ( mcu_reset_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_reset_pin , 0 ) ;
os_delay_us ( 100L ) ;
if ( mcu_isp_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_isp_pin , 0 ) ;
os_delay_us ( 100L ) ;
if ( mcu_reset_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
os_delay_us ( 100L ) ;
if ( mcu_isp_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_isp_pin , 1 ) ;
os_delay_us ( 1000L ) ;
conn - > conn_mode = cmAVR ;
slip_disabled + + ; // disable SLIP so it doesn't interfere with flashing
// If the connection starts with a telnet negotiation we will do telnet
} else if ( len > = 3 & & strncmp ( data , ( char [ ] ) { IAC , WILL , ComPortOpt } , 3 ) = = 0 ) {
conn - > conn_mode = cmTelnet ;
conn - > telnet_state = TN_normal ;
// note that the three negotiation chars will be gobbled-up by telnetUnwrap
os_printf ( " telnet mode \n " ) ;
// looks like a plain-vanilla connection!
} else {
conn - > conn_mode = cmTransparent ;
}
// Process return data on TCP client connections
} else if ( conn - > conn_mode = = cmTcpClient ) {
}
// write the buffer to the uart
if ( conn - > conn_mode = = cmTelnet ) {
conn - > telnet_state = telnetUnwrap ( ( uint8_t * ) data , len , conn - > telnet_state ) ;
} else {
uart0_tx_buffer ( data , len ) ;
}
serledFlash ( 50 ) ; // short blink on serial LED
}
//===== UART -> TCP
@ -203,18 +209,19 @@ static char txbuffer[MAX_CONN][MAX_TXBUFFER];
// Send all data in conn->txbuffer
// returns result from espconn_sent if data in buffer or ESPCONN_OK (0)
// Use only internally from espbuffsend and serbridgeSentCb
static sint8 ICACHE_FLASH_ATTR sendtxbuffer ( serbridgeConnData * conn ) {
sint8 result = ESPCONN_OK ;
if ( conn - > txbufferlen ! = 0 ) {
//os_printf("%d TX %d\n", system_get_time(), conn->txbufferlen);
conn - > readytosend = false ;
result = espconn_sent ( conn - > conn , ( uint8_t * ) conn - > txbuffer , conn - > txbufferlen ) ;
conn - > txbufferlen = 0 ;
if ( result ! = ESPCONN_OK ) {
os_printf ( " sendtxbuffer: espconn_sent error %d on conn %p \n " , result , conn ) ;
}
}
return result ;
static sint8 ICACHE_FLASH_ATTR
sendtxbuffer ( serbridgeConnData * conn ) {
sint8 result = ESPCONN_OK ;
if ( conn - > txbufferlen ! = 0 ) {
//os_printf("%d TX %d\n", system_get_time(), conn->txbufferlen);
conn - > readytosend = false ;
result = espconn_sent ( conn - > conn , ( uint8_t * ) conn - > txbuffer , conn - > txbufferlen ) ;
conn - > txbufferlen = 0 ;
if ( result ! = ESPCONN_OK ) {
os_printf ( " sendtxbuffer: espconn_sent error %d on conn %p \n " , result , conn ) ;
}
}
return result ;
}
// espbuffsend adds data to the send buffer. If the previous send was completed it calls
@ -222,173 +229,44 @@ static sint8 ICACHE_FLASH_ATTR sendtxbuffer(serbridgeConnData *conn) {
// Returns ESPCONN_OK (0) for success, -128 if buffer is full or error from espconn_sent
// Use espbuffsend instead of espconn_sent as it solves the problem that espconn_sent must
// only be called *after* receiving an espconn_sent_callback for the previous packet.
static sint8 ICACHE_FLASH_ATTR espbuffsend ( serbridgeConnData * conn , const char * data , uint16 len ) {
if ( conn - > txbufferlen + len > MAX_TXBUFFER ) {
os_printf ( " espbuffsend: txbuffer full on conn %p \n " , conn ) ;
return - 128 ;
}
os_memcpy ( conn - > txbuffer + conn - > txbufferlen , data , len ) ;
conn - > txbufferlen + = len ;
if ( conn - > readytosend ) {
return sendtxbuffer ( conn ) ;
} else {
//os_printf("%d QU %d\n", system_get_time(), conn->txbufferlen);
}
return ESPCONN_OK ;
static sint8 ICACHE_FLASH_ATTR
espbuffsend ( serbridgeConnData * conn , const char * data , uint16 len ) {
if ( conn - > txbufferlen + len > MAX_TXBUFFER ) {
os_printf ( " espbuffsend: txbuffer full on conn %p \n " , conn ) ;
return - 128 ;
}
os_memcpy ( conn - > txbuffer + conn - > txbufferlen , data , len ) ;
conn - > txbufferlen + = len ;
if ( conn - > readytosend ) {
return sendtxbuffer ( conn ) ;
} else {
//os_printf("%d QU %d\n", system_get_time(), conn->txbufferlen);
}
return ESPCONN_OK ;
}
void ICACHE_FLASH_ATTR
console_process ( char * buf , short len ) {
// push buffer into web-console
for ( short i = 0 ; i < len ; i + + )
console_write_char ( buf [ i ] ) ;
// push the buffer into each open connection
for ( short i = 0 ; i < MAX_CONN ; i + + ) {
if ( connData [ i ] . conn & & connData [ i ] . conn_mode ! = cmTcpClient ) {
espbuffsend ( & connData [ i ] , buf , len ) ;
}
}
}
//callback after the data are sent
static void ICACHE_FLASH_ATTR
serbridgeSentCb ( void * arg ) {
serbridgeConnData * conn = serbridgeFindConnData ( arg ) ;
//os_printf("Sent callback on conn %p\n", conn);
if ( conn = = NULL ) return ;
//os_printf("%d ST\n", system_get_time());
conn - > readytosend = true ;
sendtxbuffer ( conn ) ; // send possible new data in txbuffer
}
// TCP client connection state machine
// This processes commands from the attached uC to open outboud TCP connections
enum {
TC_idle , // in-between commands
TC_newline , // newline seen
TC_start , // start character (~) seen
TC_cmd , // command start (@) seen
TC_cmdChar , // command character seen
TC_cmdLine , // accumulating command
TC_tdchan , // saw data channel character
TC_tdlen1 , // saw first data length character
TC_tdata0 , // accumulate data, zero-terminated
TC_tdataN , // accumulate data, length-terminated
} ;
static uint8_t tcState = TC_newline ;
static uint8_t tcChan ; // channel for current command (index into tcConn)
# define CMD_MAX 256
static char tcCmdBuf [ CMD_MAX ] ;
static short tcCmdBufLen = 0 ;
static char tcCmdChar ;
static short tcLen ;
// scan a buffer for tcp client commands
static int ICACHE_FLASH_ATTR
tcpClientProcess ( char * buf , int len )
{
char * in = buf , * out = buf ;
for ( short i = 0 ; i < len ; i + + ) {
char c = * in + + ;
//os_printf("tcState=%d c=%c\n", tcState, c);
switch ( tcState ) {
case TC_idle :
if ( c = = ' \n ' ) tcState = TC_newline ;
break ;
case TC_newline : // saw newline, expect ~
if ( c = = ' ~ ' ) {
tcState = TC_start ;
continue ; // gobble up the ~
} else {
break ;
}
case TC_start : // saw ~, expect channel number
if ( c = = ' @ ' ) {
tcState = TC_cmd ;
continue ;
} else if ( c > = ' 0 ' & & c < = ' 9 ' ) {
tcChan = c - ' 0 ' ;
tcState = TC_tdchan ;
continue ;
}
* out + + = ' ~ ' ; // make up for '~' we skipped
break ;
case TC_cmd : // saw control char (@), expect channel char
if ( c > = ' 0 ' & & c < = ' 9 ' ) {
tcChan = c - ' 0 ' ;
tcState = TC_cmdChar ;
continue ;
} else {
* out + + = ' ~ ' ; // make up for '~' we skipped
* out + + = ' @ ' ; // make up for '@' we skipped
break ;
}
case TC_cmdChar : // saw channel number, expect command char
tcCmdChar = c ; // save command character
tcCmdBufLen = 0 ; // empty the command buffer
tcState = TC_cmdLine ;
continue ;
case TC_cmdLine : // accumulating command in buffer
if ( c ! = ' \n ' ) {
if ( tcCmdBufLen < CMD_MAX ) tcCmdBuf [ tcCmdBufLen + + ] = c ;
} else {
tcpClientCommand ( tcChan , tcCmdChar , tcCmdBuf ) ;
tcState = TC_newline ;
}
continue ;
case TC_tdchan : // saw channel number, getting first length char
if ( c > = ' 0 ' & & c < = ' 9 ' ) {
tcLen = c - ' 0 ' ;
} else if ( c > = ' A ' & & c < = ' F ' ) {
tcLen = c - ' A ' + 10 ;
} else {
* out + + = ' ~ ' ; // make up for '~' we skipped
* out + + = ' 0 ' + tcChan ;
break ;
}
tcState = TC_tdlen1 ;
continue ;
case TC_tdlen1 : // saw first length char, get second
tcLen * = 16 ;
if ( c > = ' 0 ' & & c < = ' 9 ' ) {
tcLen + = c - ' 0 ' ;
} else if ( c > = ' A ' & & c < = ' F ' ) {
tcLen + = c - ' A ' + 10 ;
} else {
* out + + = ' ~ ' ; // make up for '~' we skipped
* out + + = ' 0 ' + tcChan ;
break ;
}
tcState = tcLen = = 0 ? TC_tdata0 : TC_tdataN ;
continue ;
case TC_tdata0 : // saw data length, getting data characters zero-terminated
if ( c ! = 0 ) {
tcpClientSendChar ( tcChan , c ) ;
} else {
tcpClientSendPush ( tcChan ) ;
tcState = TC_idle ;
}
continue ;
case TC_tdataN : // saw data length, getting data characters length-terminated
tcpClientSendChar ( tcChan , c ) ;
tcLen - - ;
if ( tcLen = = 0 ) {
tcpClientSendPush ( tcChan ) ;
tcState = TC_idle ;
}
continue ;
}
* out + + = c ;
}
//if (tcState != TC_idle) os_printf("tcState=%d\n", tcState);
return out - buf ;
}
// callback with a buffer of characters that have arrived on the uart
void ICACHE_FLASH_ATTR
serbridgeUartCb ( char * buf , int length ) {
// push the buffer into the microcontroller console
for ( int i = 0 ; i < length ; i + + )
console_write_char ( buf [ i ] ) ;
// parse the buffer for TCP commands, this may remove characters from the buffer
length = tcpClientProcess ( buf , length ) ;
// push the buffer into each open connection
if ( length > 0 ) {
for ( int i = 0 ; i < MAX_CONN ; i + + ) {
if ( connData [ i ] . conn & & connData [ i ] . conn_mode ! = cmTcpClient ) {
espbuffsend ( & connData [ i ] , buf , length ) ;
}
}
}
serledFlash ( 50 ) ; // short blink on serial LED
serbridgeConnData * conn = serbridgeFindConnData ( arg ) ;
//os_printf("Sent callback on conn %p\n", conn);
if ( conn = = NULL ) return ;
//os_printf("%d ST\n", system_get_time());
conn - > readytosend = true ;
sendtxbuffer ( conn ) ; // send possible new data in txbuffer
}
//===== Connect / disconnect
@ -396,101 +274,107 @@ serbridgeUartCb(char *buf, int length) {
// Error callback (it's really poorly named, it's not a "connection reconnected" callback,
// it's really a "connection broken, please reconnect" callback)
static void ICACHE_FLASH_ATTR serbridgeReconCb ( void * arg , sint8 err ) {
serbridgeConnData * sbConn = serbridgeFindConnData ( arg ) ;
if ( sbConn = = NULL ) return ;
// Close the connection
espconn_disconnect ( sbConn - > conn ) ;
// free connection slot
sbConn - > conn = NULL ;
serbridgeConnData * sbConn = serbridgeFindConnData ( arg ) ;
if ( sbConn = = NULL ) return ;
if ( sbConn - > conn_mode = = cmAVR ) {
if ( slip_disabled > 0 ) slip_disabled - - ;
}
// Close the connection
espconn_disconnect ( sbConn - > conn ) ;
// free connection slot
sbConn - > conn = NULL ;
}
// Disconnection callback
static void ICACHE_FLASH_ATTR serbridgeDisconCb ( void * arg ) {
serbridgeConnData * sbConn = serbridgeFindConnData ( arg ) ;
if ( sbConn = = NULL ) return ;
// send reset to arduino/ARM
if ( sbConn - > conn_mode = = cmAVR & & mcu_reset_pin > = 0 ) {
GPIO_OUTPUT_SET ( mcu_reset_pin , 0 ) ;
os_delay_us ( 100L ) ;
GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
}
// free connection slot
sbConn - > conn = NULL ;
serbridgeConnData * sbConn = serbridgeFindConnData ( arg ) ;
if ( sbConn = = NULL ) return ;
// send reset to arduino/ARM
if ( sbConn - > conn_mode = = cmAVR ) {
if ( slip_disabled > 0 ) slip_disabled - - ;
if ( mcu_reset_pin > = 0 ) {
GPIO_OUTPUT_SET ( mcu_reset_pin , 0 ) ;
os_delay_us ( 100L ) ;
GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
}
}
// free connection slot
sbConn - > conn = NULL ;
}
// New connection callback, use one of the connection descriptors, if we have one left.
static void ICACHE_FLASH_ATTR serbridgeConnectCb ( void * arg ) {
struct espconn * conn = arg ;
// Find empty conndata in pool
int i ;
for ( i = 0 ; i < MAX_CONN ; i + + ) if ( connData [ i ] . conn = = NULL ) break ;
os_printf ( " Accept port 23, conn=%p, pool slot %d \n " , conn , i ) ;
if ( i = = MAX_CONN ) {
os_printf ( " Aiee, conn pool overflow! \n " ) ;
espconn_disconnect ( conn ) ;
return ;
}
conn - > reverse = connData + i ;
connData [ i ] . conn = conn ;
connData [ i ] . txbufferlen = 0 ;
connData [ i ] . readytosend = true ;
connData [ i ] . telnet_state = 0 ;
connData [ i ] . conn_mode = cmInit ;
espconn_regist_recvcb ( conn , serbridgeRecvCb ) ;
espconn_regist_reconcb ( conn , serbridgeReconCb ) ;
espconn_regist_disconcb ( conn , serbridgeDisconCb ) ;
espconn_regist_sentcb ( conn , serbridgeSentCb ) ;
espconn_set_opt ( conn , ESPCONN_REUSEADDR | ESPCONN_NODELAY ) ;
struct espconn * conn = arg ;
// Find empty conndata in pool
int i ;
for ( i = 0 ; i < MAX_CONN ; i + + ) if ( connData [ i ] . conn = = NULL ) break ;
os_printf ( " Accept port 23, conn=%p, pool slot %d \n " , conn , i ) ;
if ( i = = MAX_CONN ) {
os_printf ( " Aiee, conn pool overflow! \n " ) ;
espconn_disconnect ( conn ) ;
return ;
}
conn - > reverse = connData + i ;
connData [ i ] . conn = conn ;
connData [ i ] . txbufferlen = 0 ;
connData [ i ] . readytosend = true ;
connData [ i ] . telnet_state = 0 ;
connData [ i ] . conn_mode = cmInit ;
espconn_regist_recvcb ( conn , serbridgeRecvCb ) ;
espconn_regist_reconcb ( conn , serbridgeReconCb ) ;
espconn_regist_disconcb ( conn , serbridgeDisconCb ) ;
espconn_regist_sentcb ( conn , serbridgeSentCb ) ;
espconn_set_opt ( conn , ESPCONN_REUSEADDR | ESPCONN_NODELAY ) ;
}
//===== Initialization
void ICACHE_FLASH_ATTR serbridgeInitPins ( ) {
mcu_reset_pin = flashConfig . reset_pin ;
mcu_isp_pin = flashConfig . isp_pin ;
os_printf ( " Serbridge pins: reset=%d isp=%d swap=%d \n " ,
mcu_reset_pin , mcu_isp_pin , flashConfig . swap_uart ) ;
if ( flashConfig . swap_uart ) {
PIN_FUNC_SELECT ( PERIPHS_IO_MUX_MTCK_U , 4 ) ;
PIN_FUNC_SELECT ( PERIPHS_IO_MUX_MTDO_U , 4 ) ;
PIN_PULLUP_DIS ( PERIPHS_IO_MUX_MTCK_U ) ;
PIN_PULLUP_DIS ( PERIPHS_IO_MUX_MTDO_U ) ;
system_uart_swap ( ) ;
} else {
PIN_FUNC_SELECT ( PERIPHS_IO_MUX_U0TXD_U , 0 ) ;
PIN_FUNC_SELECT ( PERIPHS_IO_MUX_U0RXD_U , 0 ) ;
system_uart_de_swap ( ) ;
}
// set both pins to 1 before turning them on so we don't cause a reset
if ( mcu_isp_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_isp_pin , 1 ) ;
if ( mcu_reset_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
// switch pin mux to make these pins GPIO pins
if ( mcu_reset_pin > = 0 ) makeGpio ( mcu_reset_pin ) ;
if ( mcu_isp_pin > = 0 ) makeGpio ( mcu_isp_pin ) ;
mcu_reset_pin = flashConfig . reset_pin ;
mcu_isp_pin = flashConfig . isp_pin ;
os_printf ( " Serbridge pins: reset=%d isp=%d swap=%d \n " ,
mcu_reset_pin , mcu_isp_pin , flashConfig . swap_uart ) ;
if ( flashConfig . swap_uart ) {
PIN_FUNC_SELECT ( PERIPHS_IO_MUX_MTCK_U , 4 ) ;
PIN_FUNC_SELECT ( PERIPHS_IO_MUX_MTDO_U , 4 ) ;
PIN_PULLUP_DIS ( PERIPHS_IO_MUX_MTCK_U ) ;
PIN_PULLUP_DIS ( PERIPHS_IO_MUX_MTDO_U ) ;
system_uart_swap ( ) ;
} else {
PIN_FUNC_SELECT ( PERIPHS_IO_MUX_U0TXD_U , 0 ) ;
PIN_FUNC_SELECT ( PERIPHS_IO_MUX_U0RXD_U , 0 ) ;
system_uart_de_swap ( ) ;
}
// set both pins to 1 before turning them on so we don't cause a reset
if ( mcu_isp_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_isp_pin , 1 ) ;
if ( mcu_reset_pin > = 0 ) GPIO_OUTPUT_SET ( mcu_reset_pin , 1 ) ;
// switch pin mux to make these pins GPIO pins
if ( mcu_reset_pin > = 0 ) makeGpio ( mcu_reset_pin ) ;
if ( mcu_isp_pin > = 0 ) makeGpio ( mcu_isp_pin ) ;
}
// Start transparent serial bridge TCP server on specified port (typ. 23)
void ICACHE_FLASH_ATTR serbridgeInit ( int port ) {
serbridgeInitPins ( ) ;
int i ;
for ( i = 0 ; i < MAX_CONN ; i + + ) {
connData [ i ] . conn = NULL ;
connData [ i ] . txbuffer = txbuffer [ i ] ;
}
serbridgeConn . type = ESPCONN_TCP ;
serbridgeConn . state = ESPCONN_NONE ;
serbridgeTcp . local_port = port ;
serbridgeConn . proto . tcp = & serbridgeTcp ;
espconn_regist_connectcb ( & serbridgeConn , serbridgeConnectCb ) ;
espconn_accept ( & serbridgeConn ) ;
espconn_tcp_set_max_con_allow ( & serbridgeConn , MAX_CONN ) ;
espconn_regist_time ( & serbridgeConn , SER_BRIDGE_TIMEOUT , 0 ) ;
serbridgeInitPins ( ) ;
int i ;
for ( i = 0 ; i < MAX_CONN ; i + + ) {
connData [ i ] . conn = NULL ;
connData [ i ] . txbuffer = txbuffer [ i ] ;
}
serbridgeConn . type = ESPCONN_TCP ;
serbridgeConn . state = ESPCONN_NONE ;
serbridgeTcp . local_port = port ;
serbridgeConn . proto . tcp = & serbridgeTcp ;
espconn_regist_connectcb ( & serbridgeConn , serbridgeConnectCb ) ;
espconn_accept ( & serbridgeConn ) ;
espconn_tcp_set_max_con_allow ( & serbridgeConn , MAX_CONN ) ;
espconn_regist_time ( & serbridgeConn , SER_BRIDGE_TIMEOUT , 0 ) ;
}