serbridge.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. // Copyright 2015 by Thorsten von Eicken, see LICENSE.txt
  2. #include "esp8266.h"
  3. #include "uart.h"
  4. #include "crc16.h"
  5. #include "serbridge.h"
  6. #include "serled.h"
  7. #include "config.h"
  8. #include "console.h"
  9. #include "slip.h"
  10. #ifdef SYSLOG
  11. #include "syslog.h"
  12. #else
  13. #define syslog(X1...)
  14. #endif
  15. static struct espconn serbridgeConn1; // plain bridging port
  16. static struct espconn serbridgeConn2; // programming port
  17. static esp_tcp serbridgeTcp1, serbridgeTcp2;
  18. static int8_t mcu_reset_pin, mcu_isp_pin;
  19. uint8_t in_mcu_flashing; // for disabling slip during MCU flashing
  20. void (*programmingCB)(char *buffer, short length) = NULL;
  21. static sint8 espbuffsend(serbridgeConnData *conn, const char *data, uint16 len);
  22. // Connection pool
  23. serbridgeConnData connData[MAX_CONN];
  24. //===== TCP -> UART
  25. // Telnet protocol characters
  26. #define IAC 255 // escape
  27. #define DONT 254 // negotiation
  28. #define DO 253 // negotiation
  29. #define WILL 251 // negotiation
  30. #define SB 250 // subnegotiation begin
  31. #define SE 240 // subnegotiation end
  32. #define ComPortOpt 44 // COM port options
  33. #define SetBaud 1 // Set baud rate
  34. #define SetDataSize 2 // Set data size
  35. #define SetParity 3 // Set parity
  36. #define SetControl 5 // Set control lines
  37. #define PurgeData 12 // Flush FIFO buffer(s)
  38. #define PURGE_TX 2
  39. #define BRK_REQ 4 // request current BREAK state
  40. #define BRK_ON 5 // set BREAK (TX-line to LOW)
  41. #define BRK_OFF 6 // reset BREAK
  42. #define DTR_ON 8 // used here to reset microcontroller
  43. #define DTR_OFF 9
  44. #define RTS_ON 11 // used here to signal ISP (in-system-programming) to uC
  45. #define RTS_OFF 12
  46. // telnet state machine states
  47. enum { TN_normal, TN_iac, TN_will, TN_start, TN_end, TN_comPort, TN_setControl, TN_setBaud,
  48. TN_setDataSize, TN_setParity, TN_purgeData };
  49. static char tn_baudCnt;
  50. static uint32_t tn_baud; // shared across all sockets, thus possible race condition
  51. static uint8_t tn_break = 0; // 0=BREAK-OFF, 1=BREAK-ON
  52. // process a buffer-full on a telnet connection
  53. static void ICACHE_FLASH_ATTR
  54. telnetUnwrap(serbridgeConnData *conn, uint8_t *inBuf, int len)
  55. {
  56. uint8_t state = conn->telnet_state;
  57. for (int i=0; i<len; i++) {
  58. uint8_t c = inBuf[i];
  59. switch (state) {
  60. default:
  61. case TN_normal:
  62. if (c == IAC) state = TN_iac; // escape char: see what's next
  63. else uart0_write_char(c); // regular char
  64. break;
  65. case TN_iac:
  66. //os_printf("Telnet: IAC + %d\n", c);
  67. switch (c) {
  68. case IAC: // second escape -> write one to outbuf and go normal again
  69. state = TN_normal;
  70. uart0_write_char(c);
  71. break;
  72. case WILL: // negotiation
  73. state = TN_will;
  74. break;
  75. case SB: // command sequence begin
  76. state = TN_start;
  77. break;
  78. case SE: // command sequence end
  79. state = TN_normal;
  80. break;
  81. default: // not sure... let's ignore
  82. uart0_write_char(IAC);
  83. uart0_write_char(c);
  84. }
  85. break;
  86. case TN_will: { // client announcing it will send telnet cmds, try to respond
  87. char respBuf[3] = {IAC, DONT, c};
  88. if (c == ComPortOpt) respBuf[1] = DO;
  89. else os_printf("Telnet: rejecting WILL %d\n", c);
  90. espbuffsend(conn, respBuf, 3);
  91. state = TN_normal; // go back to normal
  92. break; }
  93. case TN_start: // in command seq, now comes the type of cmd
  94. if (c == ComPortOpt) state = TN_comPort;
  95. else state = TN_end; // an option we don't know, skip 'til the end seq
  96. break;
  97. case TN_end: // wait for end seq
  98. if (c == IAC) state = TN_iac; // simple wait to accept end or next escape seq
  99. break;
  100. case TN_comPort:
  101. switch (c) {
  102. case SetControl: state = TN_setControl; break;
  103. case SetDataSize: state = TN_setDataSize; break;
  104. case SetParity: state = TN_setParity; break;
  105. case SetBaud: state = TN_setBaud; tn_baudCnt = 0; tn_baud = 0; break;
  106. case PurgeData: state = TN_purgeData; break;
  107. default: state = TN_end; break;
  108. }
  109. break;
  110. case TN_purgeData: // purge FIFO-buffers
  111. switch (c) {
  112. case PURGE_TX:
  113. // TODO: flush TX buffer
  114. break;
  115. }
  116. state = TN_end;
  117. break;
  118. case TN_setControl: // switch control line and delay a tad
  119. switch (c) {
  120. case DTR_ON:
  121. if (mcu_reset_pin >= 0) {
  122. #ifdef SERBR_DBG
  123. os_printf("Telnet: reset gpio%d\n", mcu_reset_pin);
  124. #endif
  125. GPIO_OUTPUT_SET(mcu_reset_pin, 0);
  126. os_delay_us(100L);
  127. }
  128. #ifdef SERBR_DBG
  129. else { os_printf("Telnet: reset: no pin\n"); }
  130. #endif
  131. break;
  132. case DTR_OFF:
  133. if (mcu_reset_pin >= 0) {
  134. GPIO_OUTPUT_SET(mcu_reset_pin, 1);
  135. os_delay_us(100L);
  136. }
  137. break;
  138. case RTS_ON:
  139. if (mcu_isp_pin >= 0) {
  140. #ifdef SERBR_DBG
  141. os_printf("Telnet: ISP gpio%d LOW\n", mcu_isp_pin);
  142. #endif
  143. GPIO_OUTPUT_SET(mcu_isp_pin, 0);
  144. os_delay_us(100L);
  145. }
  146. #ifdef SERBR_DBG
  147. else { os_printf("Telnet: isp: no pin\n"); }
  148. #endif
  149. in_mcu_flashing++;
  150. break;
  151. case RTS_OFF:
  152. if (mcu_isp_pin >= 0) {
  153. #ifdef SERBR_DBG
  154. os_printf("Telnet: ISP gpio%d HIGH\n", mcu_isp_pin);
  155. #endif
  156. GPIO_OUTPUT_SET(mcu_isp_pin, 1);
  157. os_delay_us(100L);
  158. }
  159. if (in_mcu_flashing > 0) in_mcu_flashing--;
  160. break;
  161. case BRK_REQ: {
  162. char respBuf[7] = { IAC, SB, ComPortOpt, SetControl, tn_break, IAC, SE };
  163. espbuffsend(conn, respBuf, 7);
  164. #ifdef SERBR_DBG
  165. os_printf("Telnet: BREAK state requested: state = %d)\n", tn_break);
  166. #endif
  167. break; }
  168. case BRK_ON:
  169. if (((READ_PERI_REG(UART_STATUS(UART0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT) == 0) { // TX-FIFO of UART0 must be empty
  170. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1);
  171. GPIO_OUTPUT_SET(1, 0);
  172. tn_break = 1;
  173. #ifdef SERBR_DBG
  174. os_printf("Telnet: BREAK ON: set TX to LOW\n");
  175. #endif
  176. }
  177. break;
  178. case BRK_OFF:
  179. if (tn_break == 1) {
  180. GPIO_OUTPUT_SET(1, 1);
  181. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
  182. tn_break = 0;
  183. #ifdef SERBR_DBG
  184. os_printf("Telnet: BREAK OFF: set TX to HIGH\n");
  185. #endif
  186. }
  187. break;
  188. }
  189. state = TN_end;
  190. break;
  191. case TN_setDataSize:
  192. if (c >= 5 && c <= 8) {
  193. flashConfig.data_bits = c - 5 + FIVE_BITS;
  194. uart0_config(flashConfig.data_bits, flashConfig.parity, flashConfig.stop_bits);
  195. configSave();
  196. os_printf("Telnet: %d bits/char\n", c);
  197. } else if (c == 0) {
  198. // data size of zero means we need to send the current data size
  199. char respBuf[7] = { IAC, SB, ComPortOpt, SetDataSize,
  200. flashConfig.data_bits-FIVE_BITS+5, IAC, SE };
  201. espbuffsend(conn, respBuf, 7);
  202. }
  203. state = TN_end;
  204. break;
  205. case TN_setBaud:
  206. tn_baud |= ((uint32_t)c) << (24-8*tn_baudCnt);
  207. tn_baudCnt++;
  208. if (tn_baudCnt == 4) {
  209. // we got all four baud rate bytes (big endian)
  210. if (tn_baud >= 300 && tn_baud <= 1000000) {
  211. uart0_baud(tn_baud);
  212. flashConfig.baud_rate = tn_baud;
  213. configSave();
  214. os_printf("Telnet: %d baud\n", tn_baud);
  215. } else if (tn_baud == 0) {
  216. // baud rate of zero means we need to send the baud rate
  217. uint32_t b = flashConfig.baud_rate;
  218. char respBuf[10] = { IAC, SB, ComPortOpt, SetDataSize, b>>24, b>>16, b>>8, b, IAC, SE };
  219. espbuffsend(conn, respBuf, 10);
  220. }
  221. state = TN_end;
  222. }
  223. break;
  224. case TN_setParity:
  225. if (c == 0) {
  226. // parity of zero means we need to send the parity info
  227. char respBuf[7] = { IAC, SB, ComPortOpt, SetDataSize, 1/*none*/, IAC, SE };
  228. if (flashConfig.parity == ODD_BITS) respBuf[4] = 2;
  229. if (flashConfig.parity == EVEN_BITS) respBuf[4] = 3;
  230. espbuffsend(conn, respBuf, 7);
  231. state = TN_end;
  232. break;
  233. }
  234. uint8_t parity = NONE_BITS;
  235. if (c == 2) parity = ODD_BITS;
  236. if (c == 3) parity = EVEN_BITS;
  237. flashConfig.parity = parity;
  238. //uart0_config(flashConfig.data_bits, flashConfig.parity, flashConfig.stop_bits);
  239. configSave();
  240. os_printf("Telnet: parity %s\n", c==2?"odd":c==3?"even":"none");
  241. state = TN_end;
  242. break;
  243. }
  244. }
  245. conn->telnet_state = state;
  246. }
  247. // Generate a reset pulse for the attached microcontroller
  248. void ICACHE_FLASH_ATTR
  249. serbridgeReset()
  250. {
  251. if (mcu_reset_pin >= 0) {
  252. #ifdef SERBR_DBG
  253. os_printf("MCU reset gpio%d\n", mcu_reset_pin);
  254. #endif
  255. GPIO_OUTPUT_SET(mcu_reset_pin, 0);
  256. os_delay_us(2000L); // esp8266 needs at least 1ms reset pulse, it seems...
  257. GPIO_OUTPUT_SET(mcu_reset_pin, 1);
  258. }
  259. #ifdef SERBR_DBG
  260. else { os_printf("MCU reset: no pin\n"); }
  261. #endif
  262. }
  263. // Receive callback
  264. static void ICACHE_FLASH_ATTR
  265. serbridgeRecvCb(void *arg, char *data, unsigned short len)
  266. {
  267. serbridgeConnData *conn = ((struct espconn*)arg)->reverse;
  268. //os_printf("Receive callback on conn %p\n", conn);
  269. if (conn == NULL) return;
  270. bool startPGM = false;
  271. // At the start of a connection on the primary port we're in cmInit mode and we wait
  272. // for the first few characters to arrive in order to decide what type of connection this is..
  273. // The following if statements do this dispatch.
  274. // An issue here is that we assume that the first few characters all arrive
  275. // in the same TCP packet, which is true if the sender is a program, but not necessarily
  276. // if the sender is a person typing (although in that case the line-oriented TTY input seems
  277. // to make it work too). If this becomes a problem we need to buffer the first few chars...
  278. if (conn->conn_mode == cmInit) {
  279. // If the connection starts with the Arduino or ARM reset sequence we perform a RESET
  280. if ((len == 2 && strncmp(data, "0 ", 2) == 0) ||
  281. (len == 2 && strncmp(data, "?\n", 2) == 0) ||
  282. (len == 3 && strncmp(data, "?\r\n", 3) == 0)) {
  283. startPGM = true;
  284. conn->conn_mode = cmPGM;
  285. // If the connection starts with a telnet negotiation we will do telnet
  286. } else if (len >= 2 && data[0] == IAC && (data[1]==WILL||data[1]==DO)) {
  287. conn->conn_mode = cmTelnet;
  288. conn->telnet_state = TN_normal;
  289. // note that the three negotiation chars will be gobbled-up by telnetUnwrap
  290. #ifdef SERBR_DBG
  291. os_printf("telnet mode\n");
  292. #endif
  293. // Looks like a plain-vanilla connection!
  294. } else {
  295. conn->conn_mode = cmTransparent;
  296. }
  297. // if we start out in cmPGM mode due to a connection to the second port we need to do the
  298. // reset dance right away
  299. } else if (conn->conn_mode == cmPGMInit) {
  300. conn->conn_mode = cmPGM;
  301. startPGM = true;
  302. }
  303. // do the programming reset dance
  304. if (startPGM) {
  305. #ifdef SERBR_DBG
  306. os_printf("MCU Reset=gpio%d ISP=gpio%d\n", mcu_reset_pin, mcu_isp_pin);
  307. os_delay_us(2*1000L); // time for os_printf to happen
  308. #endif
  309. // send reset to arduino/ARM, send "ISP" signal for the duration of the programming
  310. if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 0);
  311. os_delay_us(100L);
  312. if (mcu_isp_pin >= 0) GPIO_OUTPUT_SET(mcu_isp_pin, 0);
  313. os_delay_us(2000L);
  314. if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 1);
  315. //os_delay_us(100L);
  316. //if (mcu_isp_pin >= 0) GPIO_OUTPUT_SET(mcu_isp_pin, 1);
  317. os_delay_us(1000L); // wait a millisecond before writing to the UART below
  318. conn->conn_mode = cmPGM;
  319. in_mcu_flashing++; // disable SLIP so it doesn't interfere with flashing
  320. serledFlash(50); // short blink on serial LED
  321. return;
  322. }
  323. // write the buffer to the uart
  324. if (conn->conn_mode == cmTelnet) {
  325. telnetUnwrap(conn, (uint8_t *)data, len);
  326. } else {
  327. uart0_tx_buffer(data, len);
  328. }
  329. serledFlash(50); // short blink on serial LED
  330. }
  331. //===== UART -> TCP
  332. // Send all data in conn->txbuffer
  333. // returns result from espconn_sent if data in buffer or ESPCONN_OK (0)
  334. // Use only internally from espbuffsend and serbridgeSentCb
  335. static sint8 ICACHE_FLASH_ATTR
  336. sendtxbuffer(serbridgeConnData *conn)
  337. {
  338. sint8 result = ESPCONN_OK;
  339. if (conn->txbufferlen != 0) {
  340. //os_printf("TX %p %d\n", conn, conn->txbufferlen);
  341. conn->readytosend = false;
  342. result = espconn_sent(conn->conn, (uint8_t*)conn->txbuffer, conn->txbufferlen);
  343. conn->txbufferlen = 0;
  344. if (result != ESPCONN_OK) {
  345. os_printf("sendtxbuffer: espconn_sent error %d on conn %p\n", result, conn);
  346. conn->txbufferlen = 0;
  347. if (!conn->txoverflow_at) conn->txoverflow_at = system_get_time();
  348. } else {
  349. conn->sentbuffer = conn->txbuffer;
  350. conn->txbuffer = NULL;
  351. conn->txbufferlen = 0;
  352. }
  353. }
  354. return result;
  355. }
  356. // espbuffsend adds data to the send buffer. If the previous send was completed it calls
  357. // sendtxbuffer and espconn_sent.
  358. // Returns ESPCONN_OK (0) for success, -128 if buffer is full or error from espconn_sent
  359. // Use espbuffsend instead of espconn_sent as it solves the problem that espconn_sent must
  360. // only be called *after* receiving an espconn_sent_callback for the previous packet.
  361. static sint8 ICACHE_FLASH_ATTR
  362. espbuffsend(serbridgeConnData *conn, const char *data, uint16 len)
  363. {
  364. if (conn->txbufferlen >= MAX_TXBUFFER) goto overflow;
  365. // make sure we indeed have a buffer
  366. if (conn->txbuffer == NULL) conn->txbuffer = os_zalloc(MAX_TXBUFFER);
  367. if (conn->txbuffer == NULL) {
  368. os_printf("espbuffsend: cannot alloc tx buffer\n");
  369. return -128;
  370. }
  371. // add to send buffer
  372. uint16_t avail = conn->txbufferlen+len > MAX_TXBUFFER ? MAX_TXBUFFER-conn->txbufferlen : len;
  373. os_memcpy(conn->txbuffer + conn->txbufferlen, data, avail);
  374. conn->txbufferlen += avail;
  375. // try to send
  376. sint8 result = ESPCONN_OK;
  377. if (conn->readytosend) result = sendtxbuffer(conn);
  378. if (avail < len) {
  379. // some data didn't fit into the buffer
  380. if (conn->txbufferlen == 0) {
  381. // we sent the prior buffer, so try again
  382. return espbuffsend(conn, data+avail, len-avail);
  383. }
  384. goto overflow;
  385. }
  386. return result;
  387. overflow:
  388. if (conn->txoverflow_at) {
  389. // we've already been overflowing
  390. if (system_get_time() - conn->txoverflow_at > 10*1000*1000) {
  391. // no progress in 10 seconds, kill the connection
  392. os_printf("serbridge: killing overlowing stuck conn %p\n", conn);
  393. espconn_disconnect(conn->conn);
  394. }
  395. // else be silent, we already printed an error
  396. } else {
  397. // print 1-time message and take timestamp
  398. os_printf("serbridge: txbuffer full, conn %p\n", conn);
  399. conn->txoverflow_at = system_get_time();
  400. }
  401. return -128;
  402. }
  403. //callback after the data are sent
  404. static void ICACHE_FLASH_ATTR
  405. serbridgeSentCb(void *arg)
  406. {
  407. serbridgeConnData *conn = ((struct espconn*)arg)->reverse;
  408. //os_printf("Sent CB %p\n", conn);
  409. if (conn == NULL) return;
  410. //os_printf("%d ST\n", system_get_time());
  411. if (conn->sentbuffer != NULL) os_free(conn->sentbuffer);
  412. conn->sentbuffer = NULL;
  413. conn->readytosend = true;
  414. conn->txoverflow_at = 0;
  415. sendtxbuffer(conn); // send possible new data in txbuffer
  416. }
  417. void ICACHE_FLASH_ATTR
  418. console_process(char *buf, short len)
  419. {
  420. // push buffer into web-console
  421. for (short i=0; i<len; i++)
  422. console_write_char(buf[i]);
  423. // push the buffer into each open connection
  424. for (short i=0; i<MAX_CONN; i++) {
  425. if (connData[i].conn) {
  426. espbuffsend(&connData[i], buf, len);
  427. }
  428. }
  429. }
  430. // callback with a buffer of characters that have arrived on the uart
  431. void ICACHE_FLASH_ATTR
  432. serbridgeUartCb(char *buf, short length)
  433. {
  434. if (programmingCB) {
  435. programmingCB(buf, length);
  436. } else if (!flashConfig.slip_enable || in_mcu_flashing > 0) {
  437. //os_printf("SLIP: disabled got %d\n", length);
  438. console_process(buf, length);
  439. } else {
  440. slip_parse_buf(buf, length);
  441. }
  442. serledFlash(50); // short blink on serial LED
  443. }
  444. //===== Connect / disconnect
  445. // Disconnection callback
  446. static void ICACHE_FLASH_ATTR
  447. serbridgeDisconCb(void *arg)
  448. {
  449. serbridgeConnData *conn = ((struct espconn*)arg)->reverse;
  450. if (conn == NULL) return;
  451. // Free buffers
  452. if (conn->sentbuffer != NULL) os_free(conn->sentbuffer);
  453. conn->sentbuffer = NULL;
  454. if (conn->txbuffer != NULL) os_free(conn->txbuffer);
  455. conn->txbuffer = NULL;
  456. conn->txbufferlen = 0;
  457. // Send reset to attached uC if it was in programming mode
  458. if (conn->conn_mode == cmPGM && mcu_reset_pin >= 0) {
  459. if (mcu_isp_pin >= 0) GPIO_OUTPUT_SET(mcu_isp_pin, 1);
  460. os_delay_us(100L);
  461. GPIO_OUTPUT_SET(mcu_reset_pin, 0);
  462. os_delay_us(100L);
  463. GPIO_OUTPUT_SET(mcu_reset_pin, 1);
  464. }
  465. conn->conn = NULL;
  466. }
  467. // Connection reset callback (note that there will be no DisconCb)
  468. static void ICACHE_FLASH_ATTR
  469. serbridgeResetCb(void *arg, sint8 err)
  470. {
  471. os_printf("serbridge: connection reset err=%d\n", err);
  472. serbridgeDisconCb(arg);
  473. }
  474. // New connection callback, use one of the connection descriptors, if we have one left.
  475. static void ICACHE_FLASH_ATTR
  476. serbridgeConnectCb(void *arg)
  477. {
  478. struct espconn *conn = arg;
  479. // Find empty conndata in pool
  480. int i;
  481. for (i=0; i<MAX_CONN; i++) if (connData[i].conn==NULL) break;
  482. #ifdef SERBR_DBG
  483. os_printf("Accept port %d, conn=%p, pool slot %d\n", conn->proto.tcp->local_port, conn, i);
  484. #endif
  485. syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_NOTICE, "meta-id", "Accept port %d, conn=%p, pool slot %d\n",
  486. conn->proto.tcp->local_port, conn, i);
  487. if (i==MAX_CONN) {
  488. #ifdef SERBR_DBG
  489. os_printf("Aiee, conn pool overflow!\n");
  490. #endif
  491. syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_WARNING, "meta-id", "Aiee, conn pool overflow!\n");
  492. espconn_disconnect(conn);
  493. return;
  494. }
  495. os_memset(connData+i, 0, sizeof(struct serbridgeConnData));
  496. connData[i].conn = conn;
  497. conn->reverse = connData+i;
  498. connData[i].readytosend = true;
  499. connData[i].conn_mode = cmInit;
  500. // if it's the second port we start out in programming mode
  501. if (conn->proto.tcp->local_port == serbridgeConn2.proto.tcp->local_port)
  502. connData[i].conn_mode = cmPGMInit;
  503. espconn_regist_recvcb(conn, serbridgeRecvCb);
  504. espconn_regist_disconcb(conn, serbridgeDisconCb);
  505. espconn_regist_reconcb(conn, serbridgeResetCb);
  506. espconn_regist_sentcb(conn, serbridgeSentCb);
  507. espconn_set_opt(conn, ESPCONN_REUSEADDR|ESPCONN_NODELAY);
  508. }
  509. //===== Initialization
  510. void ICACHE_FLASH_ATTR
  511. serbridgeInitPins()
  512. {
  513. mcu_reset_pin = flashConfig.reset_pin;
  514. mcu_isp_pin = flashConfig.isp_pin;
  515. #ifdef SERBR_DBG
  516. os_printf("Serbridge pins: reset=%d isp=%d swap=%d\n",
  517. mcu_reset_pin, mcu_isp_pin, flashConfig.swap_uart);
  518. #endif
  519. if (flashConfig.swap_uart) {
  520. PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 4); // RX
  521. PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 4); // TX
  522. PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U);
  523. if (flashConfig.rx_pullup) PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U);
  524. else PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U);
  525. system_uart_swap();
  526. } else {
  527. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, 0);
  528. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, 0);
  529. PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
  530. if (flashConfig.rx_pullup) PIN_PULLUP_EN(PERIPHS_IO_MUX_U0RXD_U);
  531. else PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0RXD_U);
  532. system_uart_de_swap();
  533. }
  534. // set both pins to 1 before turning them on so we don't cause a reset
  535. if (mcu_isp_pin >= 0) GPIO_OUTPUT_SET(mcu_isp_pin, 1);
  536. if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 1);
  537. // switch pin mux to make these pins GPIO pins
  538. if (mcu_reset_pin >= 0) makeGpio(mcu_reset_pin);
  539. if (mcu_isp_pin >= 0) makeGpio(mcu_isp_pin);
  540. }
  541. // Start transparent serial bridge TCP server on specified port (typ. 23)
  542. void ICACHE_FLASH_ATTR
  543. serbridgeInit(int port1, int port2)
  544. {
  545. serbridgeInitPins();
  546. os_memset(connData, 0, sizeof(connData));
  547. os_memset(&serbridgeTcp1, 0, sizeof(serbridgeTcp1));
  548. os_memset(&serbridgeTcp2, 0, sizeof(serbridgeTcp2));
  549. // set-up the primary port for plain bridging
  550. serbridgeConn1.type = ESPCONN_TCP;
  551. serbridgeConn1.state = ESPCONN_NONE;
  552. serbridgeTcp1.local_port = port1;
  553. serbridgeConn1.proto.tcp = &serbridgeTcp1;
  554. espconn_regist_connectcb(&serbridgeConn1, serbridgeConnectCb);
  555. espconn_accept(&serbridgeConn1);
  556. espconn_tcp_set_max_con_allow(&serbridgeConn1, MAX_CONN);
  557. espconn_regist_time(&serbridgeConn1, SER_BRIDGE_TIMEOUT, 0);
  558. // set-up the secondary port for programming
  559. serbridgeConn2.type = ESPCONN_TCP;
  560. serbridgeConn2.state = ESPCONN_NONE;
  561. serbridgeTcp2.local_port = port2;
  562. serbridgeConn2.proto.tcp = &serbridgeTcp2;
  563. espconn_regist_connectcb(&serbridgeConn2, serbridgeConnectCb);
  564. espconn_accept(&serbridgeConn2);
  565. espconn_tcp_set_max_con_allow(&serbridgeConn2, MAX_CONN);
  566. espconn_regist_time(&serbridgeConn2, SER_BRIDGE_TIMEOUT, 0);
  567. }
  568. int ICACHE_FLASH_ATTR serbridgeInMCUFlashing()
  569. {
  570. return in_mcu_flashing;
  571. }