// File: fgheng[P]keysound/src/DeviceDetect.cc
// Function: device_detect(Audio*, Mixer*)
void device_detect(Audio *audio, Mixer *mixer) {
    // 首先启动已有的设备	Start the existing equipment first
    start_exists_device(audio, mixer);
    fd_set fds;
    struct timeval tv;

    int sock_fd = init_socket();
    if (sock_fd < 0) {
        std::cout << "init error" << std::endl;
        return;
    }

    char buf[UEVENT_BUFFER_SIZE];

    // while的条件要更改，本身监控是一个线程，所以要安全退出
    // The condition of while needs to be changed, the monitoring itself is a thread,
    // so it is necessary to exit safely
    while (detect) {
        FD_ZERO(&fds);
        FD_SET(sock_fd, &fds);
        tv.tv_sec = 0;
        tv.tv_usec = 100 * 1000;

        int ret = select(sock_fd + 1, &fds, NULL, NULL, &tv);
        if (ret < 0) continue;
        if (!(ret > 0 && FD_ISSET(sock_fd, &fds))) continue;

        std::memset(buf, '\0', UEVENT_BUFFER_SIZE);
        if (recv(sock_fd, buf, UEVENT_BUFFER_SIZE, 0) > 0) {
            std::string str_event_id = get_event_id(buf);
            // int int_event_id = atoi(str_event_id.c_str());

            // 判断状态，增加设备还是删除设备
	    // Determine the status, add or delete equipment
            int state = device_state(buf);
            switch (state) {
                case 1:
                {
                    // 若是增加设备		If you add equipment
                    // 判断设备线程是否已经存在 Determine whether the device thread already exists
                    if (event_id_exists(str_event_id)) break;
                    else {
                        // 判断是不是键盘设备	Determine if it is a keyboard device
                        if (is_keyboard(str_event_id)) {
                            // 新建线程		Create new thread
                            all_threads.push_back(std::thread(key_detect, str_event_id, audio, mixer));
                        }
                    }
                    break;
                }
                case -1:
                {
                    // 删除					Delete
                    // 判断是否已经存在于key_detect_threads中	Determine whether it already exists in key_detect_threads
                    if (event_id_exists(str_event_id)) {
                        del_event_id(str_event_id);
                    }
                    break;
                }
                default:
                    break;

            }
        }
    }

    clear_all_key_detect_threads();
    if (sock_fd > 0) close(sock_fd);

    // 等待子线程结束	Wait for the child thread
    for (auto &th: all_threads) {
        th.join();
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x400, %rsp            # imm = 0x400
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0xb540
callq 0xb760
movl %eax, -0xa4(%rbp)
cmpl $0x0, -0xa4(%rbp)
jge 0xafbb
movq 0x1401d(%rip), %rdi     # 0x1efb8
leaq 0xb702(%rip), %rsi      # 0x166a4
callq 0x43a0
movq %rax, %rdi
movq 0x13fd7(%rip), %rsi     # 0x1ef88
callq 0x4400
jmp 0xb522
jmp 0xafbd
testb $0x1, 0x143e4(%rip)     # 0x1f3a8
je 0xb48f
jmp 0xafcc
leaq -0x90(%rbp), %rax
movq %rax, -0x2c0(%rbp)
movl $0x0, -0x2b4(%rbp)
movl -0x2b4(%rbp), %eax
cmpq $0x10, %rax
jae 0xb016
movq -0x2c0(%rbp), %rax
movl -0x2b4(%rbp), %ecx
movq $0x0, (%rax,%rcx,8)
movl -0x2b4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2b4(%rbp)
jmp 0xafe4
jmp 0xb018
movl -0xa4(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, %rcx
movl -0xa4(%rbp), %eax
movl $0x40, %esi
cltd
idivl %esi
cltq
orq -0x90(%rbp,%rax,8), %rcx
movq %rcx, -0x90(%rbp,%rax,8)
movq $0x0, -0xa0(%rbp)
movq $0x186a0, -0x98(%rbp) # imm = 0x186A0
movl -0xa4(%rbp), %edi
addl $0x1, %edi
leaq -0x90(%rbp), %rsi
xorl %eax, %eax
movl %eax, %ecx
leaq -0xa0(%rbp), %r8
movq %rcx, %rdx
callq 0x4360
movl %eax, -0x2c4(%rbp)
cmpl $0x0, -0x2c4(%rbp)
jge 0xb0a2
jmp 0xafbd
cmpl $0x0, -0x2c4(%rbp)
jle 0xb0f5
movl -0xa4(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
cltq
movq -0x90(%rbp,%rax,8), %rax
movq %rax, -0x3d8(%rbp)
movl -0xa4(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movq -0x3d8(%rbp), %rax
movl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
jne 0xb0fa
jmp 0xafbd
leaq -0x2b0(%rbp), %rdi
xorl %esi, %esi
movl $0x200, %edx            # imm = 0x200
callq 0x41d0
movl -0xa4(%rbp), %edi
leaq -0x2b0(%rbp), %rsi
movl $0x200, %edx            # imm = 0x200
xorl %ecx, %ecx
callq 0x4120
cmpq $0x0, %rax
jle 0xb48a
leaq -0x309(%rbp), %rdi
movq %rdi, -0x3e0(%rbp)
callq 0x4680
movq -0x3e0(%rbp), %rdx
leaq -0x308(%rbp), %rdi
leaq -0x2b0(%rbp), %rsi
callq 0x93e0
jmp 0xb15f
leaq -0x2e8(%rbp), %rdi
leaq -0x308(%rbp), %rsi
callq 0xb840
jmp 0xb174
leaq -0x308(%rbp), %rdi
callq 0x4728
leaq -0x309(%rbp), %rdi
callq 0x4420
leaq -0x341(%rbp), %rdi
movq %rdi, -0x3e8(%rbp)
callq 0x4680
movq -0x3e8(%rbp), %rdx
leaq -0x340(%rbp), %rdi
leaq -0x2b0(%rbp), %rsi
callq 0x93e0
jmp 0xb1bb
leaq -0x340(%rbp), %rdi
callq 0xb940
movl %eax, -0x3ec(%rbp)
jmp 0xb1cf
leaq -0x340(%rbp), %rdi
callq 0x4728
leaq -0x341(%rbp), %rdi
callq 0x4420
movl -0x3ec(%rbp), %eax
movl %eax, -0x320(%rbp)
movl -0x320(%rbp), %eax
movl %eax, -0x3f0(%rbp)
subl $-0x1, %eax
je 0xb3b5
jmp 0xb20a
movl -0x3f0(%rbp), %eax
subl $0x1, %eax
je 0xb2a4
jmp 0xb469
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
jmp 0xb250
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
leaq -0x308(%rbp), %rdi
callq 0x4728
leaq -0x309(%rbp), %rdi
callq 0x4420
jmp 0xb52b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
jmp 0xb293
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
leaq -0x340(%rbp), %rdi
callq 0x4728
leaq -0x341(%rbp), %rdi
callq 0x4420
jmp 0xb479
leaq -0x368(%rbp), %rdi
leaq -0x2e8(%rbp), %rsi
callq 0x4180
jmp 0xb2b9
leaq -0x368(%rbp), %rdi
callq 0x14230
movb %al, -0x3f1(%rbp)
jmp 0xb2cd
leaq -0x368(%rbp), %rdi
callq 0x4728
movb -0x3f1(%rbp), %al
testb $0x1, %al
jne 0xb2e5
jmp 0xb324
jmp 0xb46b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
jmp 0xb479
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
leaq -0x368(%rbp), %rdi
callq 0x4728
jmp 0xb479
leaq -0x2e8(%rbp), %rdi
callq 0xb9b0
movb %al, -0x3f2(%rbp)
jmp 0xb338
movb -0x3f2(%rbp), %al
testb $0x1, %al
jne 0xb344
jmp 0xb3ae
leaq 0x2115(%rip), %rsi      # 0xd460
leaq -0x370(%rbp), %rdi
leaq -0x2e8(%rbp), %rdx
leaq -0x8(%rbp), %rcx
leaq -0x10(%rbp), %r8
callq 0xbb60
jmp 0xb368
leaq 0x168b1(%rip), %rdi     # 0x21c20
leaq -0x370(%rbp), %rsi
callq 0xbb30
jmp 0xb37d
leaq -0x370(%rbp), %rdi
callq 0xbc30
jmp 0xb3ae
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
leaq -0x370(%rbp), %rdi
callq 0xbc30
jmp 0xb479
jmp 0xb3b0
jmp 0xb46b
leaq -0x390(%rbp), %rdi
leaq -0x2e8(%rbp), %rsi
callq 0x4180
jmp 0xb3ca
leaq -0x390(%rbp), %rdi
callq 0x14230
movb %al, -0x3f3(%rbp)
jmp 0xb3de
leaq -0x390(%rbp), %rdi
callq 0x4728
movb -0x3f3(%rbp), %al
testb $0x1, %al
jne 0xb3f6
jmp 0xb467
leaq -0x3b0(%rbp), %rdi
leaq -0x2e8(%rbp), %rsi
callq 0x4180
jmp 0xb40b
leaq -0x3b0(%rbp), %rdi
callq 0x141f0
jmp 0xb419
leaq -0x3b0(%rbp), %rdi
callq 0x4728
jmp 0xb467
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
leaq -0x390(%rbp), %rdi
callq 0x4728
jmp 0xb479
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x318(%rbp)
movl %eax, -0x31c(%rbp)
leaq -0x3b0(%rbp), %rdi
callq 0x4728
jmp 0xb479
jmp 0xb46b
jmp 0xb46b
leaq -0x2e8(%rbp), %rdi
callq 0x4728
jmp 0xb48a
leaq -0x2e8(%rbp), %rdi
callq 0x4728
jmp 0xb52b
jmp 0xafbd
callq 0x143e0
cmpl $0x0, -0xa4(%rbp)
jle 0xb4a8
movl -0xa4(%rbp), %edi
callq 0x46f0
leaq 0x16771(%rip), %rax     # 0x21c20
movq %rax, -0x3b8(%rbp)
leaq 0x16763(%rip), %rdi     # 0x21c20
callq 0xbc60
movq %rax, -0x3c0(%rbp)
leaq 0x16750(%rip), %rdi     # 0x21c20
callq 0xbc90
movq %rax, -0x3c8(%rbp)
leaq -0x3c0(%rbp), %rdi
leaq -0x3c8(%rbp), %rsi
callq 0xbcc0
testb $0x1, %al
jne 0xb4f5
jmp 0xb522
leaq -0x3c0(%rbp), %rdi
callq 0xbd00
movq %rax, -0x3d0(%rbp)
movq -0x3d0(%rbp), %rdi
callq 0x4650
leaq -0x3c0(%rbp), %rdi
callq 0xbd20
jmp 0xb4dc
addq $0x400, %rsp            # imm = 0x400
popq %rbp
retq
movq -0x318(%rbp), %rdi
callq 0x4670
nopw (%rax,%rax)