int
console_read(char *str, int cnt)
{
    struct console_tty *ct = &console_tty;
    struct console_ring *cr = &ct->ct_rx;
    int sr;
    int i;
    uint8_t ch;

    OS_ENTER_CRITICAL(sr);
    for (i = 0; i < cnt; i++) {
        if (cr->cr_head == cr->cr_tail) {
            i = -1;
            break;
        }
        ch = console_pull_char(cr);
        if (ch == '\n') {
            *str = '\0';
            break;
        }
        *str++ = ch;
    }
    OS_EXIT_CRITICAL(sr);
    if (i >= 0) {
        hal_uart_start_rx(CONSOLE_UART);
    }
    return i;
}
/*
 * Interrupts disabled when console_tx_char/console_rx_char are called.
 */
static int
console_tx_char(void *arg)
{
    struct console_tty *ct = (struct console_tty *)arg;
    struct console_ring *cr = &ct->ct_tx;

    if (cr->cr_head == cr->cr_tail) {
        /*
         * No more data.
         */
        return -1;
    }
    return console_pull_char(cr);
}
/*
 * Flush cnt characters from console output queue.
 */
static void
console_tx_flush(struct console_tty *ct, int cnt)
{
    int i;
    uint8_t byte;

    for (i = 0; i < cnt; i++) {
        if (ct->ct_tx.cr_head == ct->ct_tx.cr_tail) {
            /*
             * Queue is empty.
             */
            break;
        }
        byte = console_pull_char(&ct->ct_tx);
        console_blocking_tx(byte);
    }
}
int
console_read(char *str, int cnt, int *newline)
{
    struct console_tty *ct = &console_tty;
    struct console_ring *cr = &ct->ct_rx;
    int sr;
    int i;
    uint8_t ch;

    *newline = 0;
    OS_ENTER_CRITICAL(sr);
    for (i = 0; i < cnt; i++) {
        if (cr->cr_head == cr->cr_tail) {
            break;
        }

        if ((i & (CONSOLE_RX_CHUNK - 1)) == (CONSOLE_RX_CHUNK - 1)) {
            /*
             * Make a break from blocking interrupts during the copy.
             */
            OS_EXIT_CRITICAL(sr);
            OS_ENTER_CRITICAL(sr);
        }

        ch = console_pull_char(cr);
        if (ch == '\n') {
            *str = '\0';
            *newline = 1;
            break;
        }
        *str++ = ch;
    }
    OS_EXIT_CRITICAL(sr);
    if (i > 0 || *newline) {
        hal_uart_start_rx(CONSOLE_UART);
    }
    return i;
}