// File: exrok[P]evdoublebind/./src/evdoublebind.c
// Function: map_events
void map_events(char *input_path){
    struct input_event buf[INPUT_BUF_LEN];
    u_int32_t previous_scancode = 0, current_scancode = 0;
    int fd = open_input(input_path);

#if KEY_TIMEOUT_CONFIG != 0
    time_t last_sec = 0;
    suseconds_t last_usec = 0;
#endif
    while(1) {
        int rd = read(fd, buf, sizeof(buf));
        if (rd == -1) {
            close(fd);
            //Wait for device initialization
            for (int i = 0; i < 20; i++) { //Try acessing the path for 2s
                if (access(input_path, F_OK) != -1) break;
                usleep(100000);
            }
            int fd = open_input(input_path); //Try again maybe device reset.
            rd = read(fd, buf, sizeof(buf));
            if (rd != -1) {
                perror("Error: Opening Keyboard");
                exit(1);
            }
        }
        struct input_event *end = buf + (rd / sizeof(struct input_event));
        int after_scancode = 0;
        for(const struct input_event *curr = buf; curr < end; curr++){
            if (curr->type == EV_MSC && curr->code == MSC_SCAN) {
                current_scancode = curr->value;
                after_scancode = 1;
                continue;
            }

            if (curr->type != EV_KEY || !after_scancode || curr->value == V_KEY_REPEAT) continue;
            after_scancode = 0;

            if (curr->value == V_KEY_DOWN) {
#if KEY_TIMEOUT_CONFIG != 0
                last_sec = curr->time.tv_sec;
                last_usec = curr->time.tv_usec;
#endif
                previous_scancode = current_scancode;
            } else if (current_scancode == previous_scancode) {
#if KEY_TIMEOUT_CONFIG != 0
                long sec_diff = curr->time.tv_sec - last_sec;
                if (sec_diff > 1) continue;
                if (curr->time.tv_usec - last_usec + (sec_diff * 1000000)  > KEY_TIMEOUT_CONFIG)
                    continue;
#endif
                const KeyBind *index = find_keybind(curr->code);
                if (!index) continue;
                if (index->tap_modifier)
                    tap_mod_key(index->tap_key,index->tap_modifier, fd);
                else
                    tap_key(index->tap_key, fd);

            }
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1f0, %rsp            # imm = 0x1F0
movq %rdi, -0x8(%rbp)
movl $0x0, -0x194(%rbp)
movl $0x0, -0x198(%rbp)
movq -0x8(%rbp), %rdi
callq 0x1510
movl %eax, -0x19c(%rbp)
movq $0x0, -0x1a8(%rbp)
movq $0x0, -0x1b0(%rbp)
movl -0x19c(%rbp), %edi
leaq -0x190(%rbp), %rsi
movl $0x180, %edx            # imm = 0x180
callq 0x1070
movl %eax, -0x1b4(%rbp)
cmpl $-0x1, -0x1b4(%rbp)
jne 0x168a
movl -0x19c(%rbp), %edi
callq 0x1060
movl $0x0, -0x1b8(%rbp)
cmpl $0x14, -0x1b8(%rbp)
jge 0x163d
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x10a0
cmpl $-0x1, %eax
je 0x1622
jmp 0x163d
movl $0x186a0, %edi          # imm = 0x186A0
callq 0x10c0
movl -0x1b8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1b8(%rbp)
jmp 0x1607
movq -0x8(%rbp), %rdi
callq 0x1510
movl %eax, -0x1bc(%rbp)
movl -0x1bc(%rbp), %edi
leaq -0x190(%rbp), %rsi
movl $0x180, %edx            # imm = 0x180
callq 0x1070
movl %eax, -0x1b4(%rbp)
cmpl $-0x1, -0x1b4(%rbp)
je 0x1688
leaq 0x98b(%rip), %rdi       # 0x2004
callq 0x1350
movl $0x1, %edi
callq 0x10b0
jmp 0x168a
leaq -0x190(%rbp), %rax
movq %rax, -0x1f0(%rbp)
movslq -0x1b4(%rbp), %rax
movl $0x18, %ecx
xorl %edx, %edx
divq %rcx
movq %rax, %rcx
movq -0x1f0(%rbp), %rax
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x1c8(%rbp)
movl $0x0, -0x1cc(%rbp)
leaq -0x190(%rbp), %rax
movq %rax, -0x1d8(%rbp)
movq -0x1d8(%rbp), %rax
cmpq -0x1c8(%rbp), %rax
jae 0x1895
movq -0x1d8(%rbp), %rax
movzwl 0x10(%rax), %eax
cmpl $0x4, %eax
jne 0x172c
movq -0x1d8(%rbp), %rax
movzwl 0x12(%rax), %eax
cmpl $0x4, %eax
jne 0x172c
movq -0x1d8(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0x198(%rbp)
movl $0x1, -0x1cc(%rbp)
jmp 0x187e
movq -0x1d8(%rbp), %rax
movzwl 0x10(%rax), %eax
cmpl $0x1, %eax
jne 0x1752
cmpl $0x0, -0x1cc(%rbp)
je 0x1752
movq -0x1d8(%rbp), %rax
cmpl $0x2, 0x14(%rax)
jne 0x1757
jmp 0x187e
movl $0x0, -0x1cc(%rbp)
movq -0x1d8(%rbp), %rax
cmpl $0x1, 0x14(%rax)
jne 0x17a2
movq -0x1d8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x1a8(%rbp)
movq -0x1d8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x1b0(%rbp)
movl -0x198(%rbp), %eax
movl %eax, -0x194(%rbp)
jmp 0x187c
movl -0x198(%rbp), %eax
cmpl -0x194(%rbp), %eax
jne 0x187a
movq -0x1d8(%rbp), %rax
movq (%rax), %rax
subq -0x1a8(%rbp), %rax
movq %rax, -0x1e0(%rbp)
cmpq $0x1, -0x1e0(%rbp)
jle 0x17db
jmp 0x187e
movq -0x1d8(%rbp), %rax
movq 0x8(%rax), %rax
subq -0x1b0(%rbp), %rax
imulq $0xf4240, -0x1e0(%rbp), %rcx # imm = 0xF4240
addq %rcx, %rax
cmpq $0x35b60, %rax          # imm = 0x35B60
jle 0x1805
jmp 0x187e
movq -0x1d8(%rbp), %rax
movzwl 0x12(%rax), %edi
callq 0x14a0
movq %rax, -0x1e8(%rbp)
cmpq $0x0, -0x1e8(%rbp)
jne 0x1828
jmp 0x187e
movq -0x1e8(%rbp), %rax
cmpw $0x0, 0x4(%rax)
je 0x185f
movq -0x1e8(%rbp), %rax
movw 0x2(%rax), %cx
movq -0x1e8(%rbp), %rax
movw 0x4(%rax), %ax
movl -0x19c(%rbp), %edx
movzwl %cx, %edi
movzwl %ax, %esi
callq 0x13b0
jmp 0x1878
movq -0x1e8(%rbp), %rax
movw 0x2(%rax), %ax
movl -0x19c(%rbp), %esi
movzwl %ax, %edi
callq 0x1440
jmp 0x187a
jmp 0x187c
jmp 0x187e
movq -0x1d8(%rbp), %rax
addq $0x18, %rax
movq %rax, -0x1d8(%rbp)
jmp 0x16d9
jmp 0x15c8
nopw (%rax,%rax)