// File: AndreRenaud[P]simple_uart/simple_uart_term.c
// Function: main
int main(int argc, char *argv[])
{
    const char *port = NULL;
    int baudrate;
    const char *flags = "8N1";
    int opt;

    while ((opt = getopt(argc, argv, "p:b:f:lh")) != -1) {
        switch (opt) {
        case 'p': port = optarg; break;
        case 'b': baudrate = atoi(optarg); break;
        case 'f': flags = optarg; break;
        case 'l': {
            char **names;
            ssize_t nuarts = simple_uart_list(&names);
            printf("Found %zd ports\n", nuarts);
            for (ssize_t i = 0; i < nuarts; i++) {
                printf("Port %zd: %s\n", i, names[i]);
            }

            for (ssize_t i = 0; i < nuarts; i++) {
                if (names[i])
                    free(names[i]);
            }
            free(names);
            exit(0);
        }
        default:
        case 'h': print_usage(argv[0]); exit(1);
        }
    }

    if (!port) {
        print_usage(argv[0]);
        exit(1);
    }

    struct simple_uart *uart;

    uart = simple_uart_open(port, baudrate, flags);
    if (!uart) {
        fprintf(stderr, "Unable to open %s:%d:%s\n", port, baudrate, flags);
        exit(1);
    }

    /* Disable buffering on stdin */
    struct termios term;

    if (tcgetattr(STDIN_FILENO, &term)) {
        fprintf(stderr, "tcgetattr\n");
        exit(-1);
    }

    term.c_lflag &= ~(ICANON | ECHO);
    term.c_cc[VMIN] = 0;
    term.c_cc[VTIME] = 0;

    if (tcsetattr(STDIN_FILENO, TCSANOW, &term)) {
        fprintf(stderr, "tcsetattr\n");
        exit(-1);
    }

    while (1) {
        fd_set fds;
        int nfds = STDIN_FILENO;
        struct timeval tv = {1, 0};
        char buffer[128];

        /* Wait for bytes on either serial port or stdin */
        FD_ZERO(&fds);
        FD_SET(STDIN_FILENO, &fds);
        FD_SET(simple_uart_get_fd(uart), &fds);
        if (simple_uart_get_fd(uart) > nfds)
            nfds = simple_uart_get_fd(uart);

        select(nfds + 1, &fds, NULL, NULL, &tv);

        /* Move bytes from one to the other */
        if (FD_ISSET(STDIN_FILENO, &fds)) {
            int len = read(STDIN_FILENO, buffer, sizeof(buffer));
            if (len > 0)
                simple_uart_write(uart, buffer, len);
        }
        if (FD_ISSET(simple_uart_get_fd(uart), &fds)) {
            int len = simple_uart_read(uart, buffer, sizeof(buffer));
            if (len > 0)
                write(STDOUT_FILENO, buffer, len);
        }
    }

    simple_uart_close(uart);
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
leaq 0x2c38(%rip), %rax      # 0x5040
movq %rax, -0x28(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x2c2a(%rip), %rdx      # 0x5044
callq 0x2260
movl %eax, -0x2c(%rbp)
cmpl $-0x1, %eax
je 0x2563
movl -0x2c(%rbp), %eax
addl $-0x62, %eax
movl %eax, %ecx
movq %rcx, -0x1d0(%rbp)
subl $0xe, %eax
ja 0x2546
movq -0x1d0(%rbp), %rax
leaq 0x2bb3(%rip), %rcx      # 0x5004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x4b77(%rip), %rax      # 0x6fd8
movq (%rax), %rax
movq %rax, -0x18(%rbp)
jmp 0x255e
movq 0x4b64(%rip), %rax      # 0x6fd8
movq (%rax), %rdi
callq 0x2270
movl %eax, -0x1c(%rbp)
jmp 0x255e
movq 0x4b4d(%rip), %rax      # 0x6fd8
movq (%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x255e
leaq -0x38(%rbp), %rdi
callq 0x3650
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rsi
leaq 0x2b9e(%rip), %rdi      # 0x504d
movb $0x0, %al
callq 0x2120
movq $0x0, -0x48(%rbp)
movq -0x48(%rbp), %rax
cmpq -0x40(%rbp), %rax
jge 0x24f4
movq -0x48(%rbp), %rsi
movq -0x38(%rbp), %rax
movq -0x48(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
leaq 0x2b7f(%rip), %rdi      # 0x505e
movb $0x0, %al
callq 0x2120
movq -0x48(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x48(%rbp)
jmp 0x24be
movq $0x0, -0x50(%rbp)
movq -0x50(%rbp), %rax
cmpq -0x40(%rbp), %rax
jge 0x2536
movq -0x38(%rbp), %rax
movq -0x50(%rbp), %rcx
cmpq $0x0, (%rax,%rcx,8)
je 0x2526
movq -0x38(%rbp), %rax
movq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x2040
jmp 0x2528
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x50(%rbp)
jmp 0x24fc
movq -0x38(%rbp), %rdi
callq 0x2040
xorl %edi, %edi
callq 0x2290
jmp 0x2548
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2850
movl $0x1, %edi
callq 0x2290
jmp 0x240c
cmpq $0x0, -0x18(%rbp)
jne 0x2580
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2850
movl $0x1, %edi
callq 0x2290
movq -0x18(%rbp), %rdi
movl -0x1c(%rbp), %esi
movq -0x28(%rbp), %rdx
callq 0x2d10
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
jne 0x25c8
movq 0x4a56(%rip), %rax      # 0x6ff8
movq (%rax), %rdi
movq -0x18(%rbp), %rdx
movl -0x1c(%rbp), %ecx
movq -0x28(%rbp), %r8
leaq 0x2ab5(%rip), %rsi      # 0x506c
movb $0x0, %al
callq 0x21a0
movl $0x1, %edi
callq 0x2290
xorl %edi, %edi
leaq -0x94(%rbp), %rsi
callq 0x2210
cmpl $0x0, %eax
je 0x25fd
movq 0x4a16(%rip), %rax      # 0x6ff8
movq (%rax), %rdi
leaq 0x2a99(%rip), %rsi      # 0x5085
movb $0x0, %al
callq 0x21a0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2290
movl -0x88(%rbp), %eax
andl $-0xb, %eax
movl %eax, -0x88(%rbp)
movb $0x0, -0x7d(%rbp)
movb $0x0, -0x7e(%rbp)
xorl %esi, %esi
leaq -0x94(%rbp), %rdx
movl %esi, %edi
callq 0x2220
cmpl $0x0, %eax
je 0x264b
movq 0x49c8(%rip), %rax      # 0x6ff8
movq (%rax), %rdi
leaq 0x2a56(%rip), %rsi      # 0x5090
movb $0x0, %al
callq 0x21a0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2290
jmp 0x264d
movl $0x0, -0x11c(%rbp)
movq 0x2a6a(%rip), %rax      # 0x50c8
movq %rax, -0x130(%rbp)
movq 0x2a64(%rip), %rax      # 0x50d0
movq %rax, -0x128(%rbp)
leaq -0x118(%rbp), %rax
movq %rax, -0x1c0(%rbp)
movl $0x0, -0x1b4(%rbp)
movl -0x1b4(%rbp), %eax
cmpq $0x10, %rax
jae 0x26bd
movq -0x1c0(%rbp), %rax
movl -0x1b4(%rbp), %ecx
movq $0x0, (%rax,%rcx,8)
movl -0x1b4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1b4(%rbp)
jmp 0x268b
jmp 0x26bf
movq -0x118(%rbp), %rax
orq $0x1, %rax
movq %rax, -0x118(%rbp)
movq -0x58(%rbp), %rdi
callq 0x4370
movl $0x40, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, -0x1d8(%rbp)
movq -0x58(%rbp), %rdi
callq 0x4370
movq -0x1d8(%rbp), %rcx
movl $0x40, %esi
cltd
idivl %esi
cltq
orq -0x118(%rbp,%rax,8), %rcx
movq %rcx, -0x118(%rbp,%rax,8)
movq -0x58(%rbp), %rdi
callq 0x4370
cmpl -0x11c(%rbp), %eax
jle 0x273f
movq -0x58(%rbp), %rdi
callq 0x4370
movl %eax, -0x11c(%rbp)
movl -0x11c(%rbp), %edi
addl $0x1, %edi
leaq -0x118(%rbp), %rsi
xorl %eax, %eax
movl %eax, %ecx
leaq -0x130(%rbp), %r8
movq %rcx, %rdx
callq 0x21d0
movq -0x118(%rbp), %rax
andq $0x1, %rax
cmpq $0x0, %rax
je 0x27ae
leaq -0x1b0(%rbp), %rsi
xorl %edi, %edi
movl $0x80, %edx
callq 0x2160
movl %eax, -0x1c4(%rbp)
cmpl $0x0, -0x1c4(%rbp)
jle 0x27ac
movq -0x58(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
movslq -0x1c4(%rbp), %rdx
callq 0x2b30
jmp 0x27ae
movq -0x58(%rbp), %rdi
callq 0x4370
movl $0x40, %ecx
cltd
idivl %ecx
cltq
movq -0x118(%rbp,%rax,8), %rax
movq %rax, -0x1e0(%rbp)
movq -0x58(%rbp), %rdi
callq 0x4370
movl $0x40, %ecx
cltd
idivl %ecx
movq -0x1e0(%rbp), %rax
movl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
je 0x283c
movq -0x58(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
movl $0x80, %edx
callq 0x2880
movl %eax, -0x1c8(%rbp)
cmpl $0x0, -0x1c8(%rbp)
jle 0x283a
leaq -0x1b0(%rbp), %rsi
movslq -0x1c8(%rbp), %rdx
movl $0x1, %edi
callq 0x20b0
jmp 0x283c
jmp 0x264d
nopw %cs:(%rax,%rax)