static int console_rx_char(void *arg, uint8_t data) { struct console_tty *ct = (struct console_tty *)arg; struct console_ring *tx = &ct->ct_tx; struct console_ring *rx = &ct->ct_rx; int tx_space; if (CONSOLE_HEAD_INC(&ct->ct_rx) == ct->ct_rx.cr_tail) { /* * RX queue full. Reader must drain this. */ if (ct->ct_rx_cb) { ct->ct_rx_cb(0); } return -1; } tx_space = console_buf_space(tx); /* echo */ switch (data) { case '\r': case '\n': /* * linefeed */ if (tx_space < 3) { console_tx_flush(ct, 3); } console_add_char(tx, '\n'); console_add_char(tx, '\r'); console_add_char(rx, '\n'); if (ct->ct_rx_cb) { ct->ct_rx_cb(1); } break; case '\b': /* * backspace */ if (tx_space < 3) { console_tx_flush(ct, 3); } console_add_char(tx, '\b'); console_add_char(tx, ' '); console_add_char(tx, '\b'); console_pull_char_head(rx); break; default: if (tx_space < 1) { console_tx_flush(ct, 1); } console_add_char(tx, data); console_add_char(rx, data); break; } hal_uart_start_tx(CONSOLE_UART); return 0; }
static void console_queue_char(char ch) { struct console_tty *ct = &console_tty; int sr; OS_ENTER_CRITICAL(sr); while (CONSOLE_HEAD_INC(&ct->ct_tx) == ct->ct_tx.cr_tail) { /* TX needs to drain */ hal_uart_start_tx(CONSOLE_UART); OS_EXIT_CRITICAL(sr); os_time_delay(1); OS_ENTER_CRITICAL(sr); } console_add_char(&ct->ct_tx, ch); OS_EXIT_CRITICAL(sr); }
static int console_hist_move(struct console_ring *rx, uint8_t *tx_buf, uint8_t direction) { struct console_hist *ch = &console_hist; uint8_t *str = NULL; int space = 0; int i; uint8_t limit = direction == CONSOLE_UP ? ch->ch_tail : ch->ch_head; /* no more history to return in this direction */ if (ch->ch_curr == limit) { return 0; } if (direction == CONSOLE_UP) { ch->ch_curr = (ch->ch_curr - 1) & (ch->ch_size - 1); } else { ch->ch_curr = (ch->ch_curr + 1) & (ch->ch_size - 1); } /* consume all chars */ while (console_pull_char_head(rx) == 0) { /* do nothing */ } str = ch->ch_buf[ch->ch_curr]; for (i = 0; i < MYNEWT_VAL(CONSOLE_RX_BUF_SIZE); ++i) { if (str[i] == '\0') { break; } tx_buf[i] = str[i]; console_add_char(rx, str[i]); space++; } return space; }
static int console_rx_char(void *arg, uint8_t data) { struct console_tty *ct = (struct console_tty *)arg; struct console_ring *tx = &ct->ct_tx; struct console_ring *rx = &ct->ct_rx; int tx_space; int i; int tx_buf[3]; if (CONSOLE_HEAD_INC(&ct->ct_rx) == ct->ct_rx.cr_tail) { /* * RX queue full. Reader must drain this. */ if (ct->ct_rx_cb) { ct->ct_rx_cb(); } return -1; } /* echo */ switch (data) { case '\r': case '\n': /* * linefeed */ tx_buf[0] = '\n'; tx_buf[1] = '\r'; tx_space = 2; console_add_char(rx, '\n'); if (ct->ct_rx_cb) { ct->ct_rx_cb(); } break; case CONSOLE_ESC: ct->ct_esc_seq = 1; goto out; case '[': if (ct->ct_esc_seq == 1) { ct->ct_esc_seq = 2; goto out; } else { goto queue_char; } break; case CONSOLE_LEFT: if (ct->ct_esc_seq == 2) { goto backspace; } else { goto queue_char; } break; case CONSOLE_UP: case CONSOLE_DOWN: if (ct->ct_esc_seq == 2) { /* * Do nothing. */ ct->ct_esc_seq = 0; goto out; } goto queue_char; case CONSOLE_RIGHT: if (ct->ct_esc_seq == 2) { data = ' '; /* add space */ } goto queue_char; case '\b': case CONSOLE_DEL: backspace: /* * backspace */ ct->ct_esc_seq = 0; if (console_pull_char_head(rx) == 0) { /* * Only wipe out char if we can pull stuff off from head. */ tx_buf[0] = '\b'; tx_buf[1] = ' '; tx_buf[2] = '\b'; tx_space = 3; } else { goto out; } break; default: queue_char: tx_buf[0] = data; tx_space = 1; ct->ct_esc_seq = 0; console_add_char(rx, data); break; } if (!ct->ct_echo_off) { if (console_buf_space(tx) < tx_space) { console_tx_flush(ct, tx_space); } for (i = 0; i < tx_space; i++) { console_add_char(tx, tx_buf[i]); } hal_uart_start_tx(CONSOLE_UART); } out: return 0; }
static int console_rx_char(void *arg, uint8_t data) { struct console_tty *ct = (struct console_tty *)arg; struct console_ring *tx = &ct->ct_tx; struct console_ring *rx = &ct->ct_rx; int tx_space = 0; int i; #if MYNEWT_VAL(CONSOLE_HIST_ENABLE) uint8_t tx_buf[MYNEWT_VAL(CONSOLE_RX_BUF_SIZE)]; #else uint8_t tx_buf[3]; #endif if (CONSOLE_HEAD_INC(&ct->ct_rx) == ct->ct_rx.cr_tail) { /* * RX queue full. Reader must drain this. */ if (ct->ct_rx_cb) { ct->ct_rx_cb(); } return -1; } /* echo */ switch (data) { case '\r': case '\n': /* * linefeed */ tx_buf[0] = '\n'; tx_buf[1] = '\r'; tx_space = 2; console_add_char(rx, '\n'); #if MYNEWT_VAL(CONSOLE_HIST_ENABLE) console_hist_add(rx); #endif if (ct->ct_rx_cb) { ct->ct_rx_cb(); } break; case CONSOLE_ESC: ct->ct_esc_seq = 1; goto out; case '[': if (ct->ct_esc_seq == 1) { ct->ct_esc_seq = 2; goto out; } else { goto queue_char; } break; case CONSOLE_LEFT: if (ct->ct_esc_seq == 2) { goto backspace; } else { goto queue_char; } break; case CONSOLE_UP: case CONSOLE_DOWN: if (ct->ct_esc_seq != 2) { goto queue_char; } #if MYNEWT_VAL(CONSOLE_HIST_ENABLE) tx_space = console_hist_move(rx, tx_buf, data); tx_buf[tx_space] = 0; ct->ct_esc_seq = 0; /* * when moving up, stop on oldest history entry * when moving down, let it delete input before leaving... */ if (data == CONSOLE_UP && tx_space == 0) { goto out; } if (!ct->ct_echo_off) { /* HACK: clean line by backspacing up to maximum possible space */ for (i = 0; i < MYNEWT_VAL(CONSOLE_TX_BUF_SIZE); i++) { if (console_buf_space(tx) < 3) { console_tx_flush(ct, 3); } console_add_char(tx, '\b'); console_add_char(tx, ' '); console_add_char(tx, '\b'); uart_start_tx(ct->ct_dev); } if (tx_space == 0) { goto out; } } else { goto queue_char; } break; #else ct->ct_esc_seq = 0; goto out; #endif case CONSOLE_RIGHT: if (ct->ct_esc_seq == 2) { data = ' '; /* add space */ } goto queue_char; case '\b': case CONSOLE_DEL: backspace: /* * backspace */ ct->ct_esc_seq = 0; if (console_pull_char_head(rx) == 0) { /* * Only wipe out char if we can pull stuff off from head. */ tx_buf[0] = '\b'; tx_buf[1] = ' '; tx_buf[2] = '\b'; tx_space = 3; } else { goto out; } break; default: queue_char: tx_buf[0] = data; tx_space = 1; ct->ct_esc_seq = 0; console_add_char(rx, data); break; } if (!ct->ct_echo_off) { if (console_buf_space(tx) < tx_space) { console_tx_flush(ct, tx_space); } for (i = 0; i < tx_space; i++) { console_add_char(tx, tx_buf[i]); } uart_start_tx(ct->ct_dev); } out: return 0; }