// File: hzeller[P]gcode-cli/machine-connection.cc
// Function: SetTTYParams(int, std::basic_string_view<char, std::char_traits<char>>)
static bool SetTTYParams(int fd, std::string_view parameters) {
    tty_termios_t tty;

#ifdef USE_TERMIOS
    if (tcgetattr(fd, &tty) < 0) {
        perror("tcgetattr() failed. Is this a tty ?");
        return false;
    }
#else
    if (ioctl(fd, TCGETS2, &tty)) {
        perror("ioctl(TCGETS2) failed. Is this a tty ?");
        return false;
    }
#endif

    // Some generic settings, possibly overridden later
    tty.c_cflag |= (CLOCAL | CREAD);  // no modem controls
    tty.c_cflag &= ~CSIZE;            // Reset size as we want to choose ..
    tty.c_cflag |= CS8;               // 8 .. bits
    tty.c_cflag &= ~PARENB;           // N
    tty.c_cflag &= ~CSTOPB;           // 1
    tty.c_cflag |= CRTSCTS;           // Hardware flow-control

    // Terminal magic. Non-canonical mode
    tty.c_iflag &=
        ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_oflag &= ~OPOST;

    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 1;

    SetTTYSpeed(fd, &tty, 115200);
    while (!parameters.empty()) {
        const auto pos = parameters.find(',');
        const auto part_len =
            (pos != std::string_view::npos) ? pos + 1 : parameters.size();
        std::string_view param = parameters.substr(0, part_len);
        parameters.remove_prefix(part_len);

        if (param[0] == 'b' || param[0] == 'B') {
            int s;
            if (auto r = std::from_chars(param.begin() + 1, param.end(), s);
                r.ec == std::errc()) {
                if (!SetTTYSpeed(fd, &tty, s)) return false;
            }
            continue;
        }

        // Flags can be with optional positive or negative prefix.
        bool flag_positive = true;
        if (param[0] == '+') {
            param = param.substr(1);
        } else if (param[0] == '-') {
            flag_positive = false;
            param = param.substr(1);
        }

        if (param == "crtscts") {
            if (flag_positive) {
                tty.c_cflag |= CRTSCTS;
            } else {
                tty.c_cflag &= ~CRTSCTS;
            }
        } else {
            fprintf(stderr, "Unknown option %.*s\n", (int)param.size(),
                    param.data());
            return false;
        }
    }

#ifdef USE_TERMIOS
    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        printf("Error from tcsetattr: %s\n", strerror(errno));
        return false;
    }
#else
    if (ioctl(fd, TCSETS2, &tty)) {
        printf("ioctl(TCSETS2) failed: %s\n", strerror(errno));
        return false;
    }
#endif
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rsi, -0x18(%rbp)
movq %rdx, -0x10(%rbp)
movl %edi, -0x1c(%rbp)
movl -0x1c(%rbp), %edi
movl $0x802c542a, %esi       # imm = 0x802C542A
leaq -0x48(%rbp), %rdx
movb $0x0, %al
callq 0x2350
cmpl $0x0, %eax
je 0x4983
leaq 0x32b1(%rip), %rdi      # 0x7c26
callq 0x2200
movb $0x0, -0x1(%rbp)
jmp 0x4cbb
movl -0x40(%rbp), %eax
orl $0x880, %eax            # imm = 0x880
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
andl $-0x31, %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
orl $0x30, %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
andl $0xfffffeff, %eax       # imm = 0xFFFFFEFF
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
andl $-0x41, %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
orl $0x80000000, %eax       # imm = 0x80000000
movl %eax, -0x40(%rbp)
movl -0x48(%rbp), %eax
andl $0xfffffa14, %eax       # imm = 0xFFFFFA14
movl %eax, -0x48(%rbp)
movl -0x3c(%rbp), %eax
andl $0xffff7fb4, %eax       # imm = 0xFFFF7FB4
movl %eax, -0x3c(%rbp)
movl -0x44(%rbp), %eax
andl $-0x2, %eax
movl %eax, -0x44(%rbp)
movb $0x1, -0x31(%rbp)
movb $0x1, -0x32(%rbp)
movl -0x1c(%rbp), %edi
leaq -0x48(%rbp), %rsi
movl $0x1c200, %edx          # imm = 0x1C200
callq 0x4cd0
leaq -0x18(%rbp), %rdi
callq 0x3690
xorb $-0x1, %al
testb $0x1, %al
jne 0x4a0b
jmp 0x4c7c
leaq -0x18(%rbp), %rdi
movl $0x2c, %esi
xorl %eax, %eax
movl %eax, %edx
callq 0x4d70
movq %rax, -0x50(%rbp)
cmpq $-0x1, -0x50(%rbp)
je 0x4a39
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xd0(%rbp)
jmp 0x4a49
leaq -0x18(%rbp), %rdi
callq 0x3650
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rdx
leaq -0x18(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4e10
movq %rax, -0x68(%rbp)
movq %rdx, -0x60(%rbp)
movq -0x58(%rbp), %rsi
leaq -0x18(%rbp), %rdi
callq 0x5090
leaq -0x68(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x50d0
movsbl (%rax), %eax
cmpl $0x62, %eax
je 0x4aa4
leaq -0x68(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x50d0
movsbl (%rax), %eax
cmpl $0x42, %eax
jne 0x4b09
leaq -0x68(%rbp), %rdi
callq 0x5260
addq $0x1, %rax
movq %rax, -0xd8(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x36b0
movq -0xd8(%rbp), %rdi
movq %rax, %rsi
leaq -0x6c(%rbp), %rdx
movl $0xa, %ecx
callq 0x5100
movq %rax, -0x80(%rbp)
movl %edx, -0x78(%rbp)
cmpl $0x0, -0x78(%rbp)
jne 0x4b04
movl -0x1c(%rbp), %edi
movl -0x6c(%rbp), %edx
leaq -0x48(%rbp), %rsi
callq 0x4cd0
testb $0x1, %al
jne 0x4b02
movb $0x0, -0x1(%rbp)
jmp 0x4cbb
jmp 0x4b04
jmp 0x49f7
movb $0x1, -0x81(%rbp)
leaq -0x68(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x50d0
movsbl (%rax), %eax
cmpl $0x2b, %eax
jne 0x4b60
leaq -0x68(%rbp), %rdi
movl $0x1, %esi
movq $-0x1, %rdx
callq 0x4e10
movq %rax, -0x98(%rbp)
movq %rdx, -0x90(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x60(%rbp)
jmp 0x4bb7
leaq -0x68(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x50d0
movsbl (%rax), %eax
cmpl $0x2d, %eax
jne 0x4bb5
movb $0x0, -0x81(%rbp)
leaq -0x68(%rbp), %rdi
movl $0x1, %esi
movq $-0x1, %rdx
callq 0x4e10
movq %rax, -0xa8(%rbp)
movq %rdx, -0xa0(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0xa0(%rbp), %rax
movq %rax, -0x60(%rbp)
jmp 0x4bb7
movq -0x68(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0xc8(%rbp), %rdi
leaq 0x3072(%rip), %rsi      # 0x7c4d
callq 0x3900
movq -0xb8(%rbp), %rdi
movq -0xb0(%rbp), %rsi
movq -0xc8(%rbp), %rdx
movq -0xc0(%rbp), %rcx
callq 0x5280
testb $0x1, %al
jne 0x4c07
jmp 0x4c2a
testb $0x1, -0x81(%rbp)
je 0x4c1d
movl -0x40(%rbp), %eax
orl $0x80000000, %eax       # imm = 0x80000000
movl %eax, -0x40(%rbp)
jmp 0x4c28
movl -0x40(%rbp), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movl %eax, -0x40(%rbp)
jmp 0x4c77
movq 0x63a7(%rip), %rax      # 0xafd8
movq (%rax), %rax
movq %rax, -0xe8(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x3650
movl %eax, -0xdc(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x3670
movq -0xe8(%rbp), %rdi
movl -0xdc(%rbp), %edx
movq %rax, %rcx
leaq 0x2feb(%rip), %rsi      # 0x7c55
movb $0x0, %al
callq 0x2360
movb $0x0, -0x1(%rbp)
jmp 0x4cbb
jmp 0x49f7
movl -0x1c(%rbp), %edi
movl $0x402c542b, %esi       # imm = 0x402C542B
leaq -0x48(%rbp), %rdx
movb $0x0, %al
callq 0x2350
cmpl $0x0, %eax
je 0x4cb7
callq 0x2040
movl (%rax), %edi
callq 0x20c0
movq %rax, %rsi
leaq 0x2fc0(%rip), %rdi      # 0x7c6a
movb $0x0, %al
callq 0x2050
movb $0x0, -0x1(%rbp)
jmp 0x4cbb
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xf0, %rsp
popq %rbp
retq
nopl (%rax)