// File: /workspace/github_c_makefile_star2_O3/Carton32[P]quectel-CM/GobiNetCM.c
// Function: GobiNetThread
static void * GobiNetThread(void *pData) {
    PROFILE_T *profile = (PROFILE_T *)pData;
    const char *qcqmi = (const char *)profile->qmichannel;
    int wait_for_request_quit = 0;   
    
    qmiclientId[QMUX_TYPE_WDS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS);
    if (profile->enable_ipv6)
        qmiclientId[QMUX_TYPE_WDS_IPV6] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS);
    qmiclientId[QMUX_TYPE_DMS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_DMS);
    qmiclientId[QMUX_TYPE_NAS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_NAS);
    qmiclientId[QMUX_TYPE_UIM] = GobiNetGetClientID(qcqmi, QMUX_TYPE_UIM);
    if (profile->qmap_mode == 0 || profile->loopback_state) {//when QMAP enabled, set data format in GobiNet Driver
        qmiclientId[QMUX_TYPE_WDS_ADMIN] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS_ADMIN);
        profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN];
    }

    //donot check clientWDA, there is only one client for WDA, if quectel-CM is killed by SIGKILL, i cannot get client ID for WDA again!
    if (qmiclientId[QMUX_TYPE_WDS] == 0)  /*|| (clientWDA == -1)*/ {
        GobiNetDeInit();
        dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, qcqmi, errno, strerror(errno));
        qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
        pthread_exit(NULL);
        return NULL;
    }

    qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED);

    while (1) {
        struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}};
        int ne, ret, nevents = 1;
        unsigned int i;

        for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++)
        {
            if (qmiclientId[i] != 0)
            {
                pollfds[nevents].fd = qmiclientId[i];
                pollfds[nevents].events = POLLIN;
                pollfds[nevents].revents = 0;
                nevents++;
            }
        }

        do {
            ret = poll(pollfds, nevents, wait_for_request_quit ? 1000: -1);
         } while ((ret < 0) && (errno == EINTR));

	if (ret == 0 && wait_for_request_quit) {
    		QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI()
		continue;
	}

        if (ret <= 0) {
            dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
            break;
        }

        for (ne = 0; ne < nevents; ne++) {
            int fd = pollfds[ne].fd;
            short revents = pollfds[ne].revents;

            if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
                dbg_time("%s poll err/hup/inval", __func__);
                dbg_time("epoll fd = %d, events = 0x%04x", fd, revents);
                if (fd == qmidevice_control_fd[1]) {
                } else {
                }
                if (revents & (POLLERR | POLLHUP | POLLNVAL))
                    goto __GobiNetThread_quit;
            }

            if ((revents & POLLIN) == 0)
                continue;

            if (fd == qmidevice_control_fd[1]) {
                int triger_event;
                if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) {
                    //DBG("triger_event = 0x%x", triger_event);
                    switch (triger_event) {
                        case RIL_REQUEST_QUIT:
                            goto __GobiNetThread_quit;
                        break;
                        case SIG_EVENT_STOP:
                            wait_for_request_quit = 1;   
                        break;
                        default:
                        break;
                    }
                }
                continue;
            }

            {
                ssize_t nreads;
                PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf;

                nreads = read(fd, &pResponse->MUXMsg, sizeof(cm_recv_buf) - sizeof(QCQMI_HDR));
                if (nreads <= 0)
                {
                    dbg_time("%s read=%d errno: %d (%s)",  __func__, (int)nreads, errno, strerror(errno));
                    break;
                }

                for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++)
                {
                    if (qmiclientId[i] == fd)
                    {
                        pResponse->QMIHdr.QMIType = i;
                    }
                }

                pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
                pResponse->QMIHdr.Length = cpu_to_le16(nreads + sizeof(QCQMI_HDR)  - 1);
                pResponse->QMIHdr.CtlFlags = 0x00;
                pResponse->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pResponse->QMIHdr.QMIType;;

                QmiThreadRecvQMI(pResponse);
            }
        }
    }

__GobiNetThread_quit:
    GobiNetDeInit();
    qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
    QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI()
    dbg_time("%s exit", __func__);
    pthread_exit(NULL);
    return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %rdi, %r14
leaq 0x8a(%rdi), %rbx
movq %rbx, %rdi
movl $0x1, %esi
callq 0x6f7e
movl %eax, 0x239ae(%rip)     # 0x2a364
cmpb $0x0, 0x51(%r14)
je 0x69d0
movq %rbx, %rdi
movl $0x1, %esi
callq 0x6f7e
movl %eax, 0x239d4(%rip)     # 0x2a3a4
movq %rbx, %rdi
movl $0x2, %esi
callq 0x6f7e
movl %eax, 0x23985(%rip)     # 0x2a368
movq %rbx, %rdi
movl $0x3, %esi
callq 0x6f7e
movl %eax, 0x23976(%rip)     # 0x2a36c
movq %rbx, %rdi
movl $0xb, %esi
callq 0x6f7e
movl %eax, 0x23983(%rip)     # 0x2a38c
cmpl $0x0, 0x10a(%r14)
je 0x6a1d
cmpb $0x0, 0x215(%r14)
je 0x6a37
movq %rbx, %rdi
movl $0x1a, %esi
callq 0x6f7e
movl %eax, 0x23998(%rip)     # 0x2a3c8
movl %eax, 0x122(%r14)
cmpl $0x0, 0x23926(%rip)     # 0x2a364
jne 0x6b0a
xorl %r14d, %r14d
leaq 0x23912(%rip), %r15     # 0x2a360
movl (%r14,%r15), %edi
testl %edi, %edi
je 0x6a63
callq 0x5230
movl $0x0, (%r14,%r15)
addq $0x4, %r14
cmpq $0x6c, %r14
jne 0x6a4e
movq 0x2354c(%rip), %rax     # 0x29fc0
movq (%rax), %r15
callq 0xea3b
movq %rax, %r12
callq 0x5070
movq %rax, %r14
movl (%rax), %ebp
movl %ebp, %edi
callq 0x5530
movq %rax, (%rsp)
leaq 0x1768d(%rip), %rsi     # 0x1e128
leaq 0x178e6(%rip), %rcx     # 0x1e388
movq %r15, %rdi
movq %r12, %rdx
movq %rbx, %r8
movl %ebp, %r9d
xorl %eax, %eax
callq 0x52c0
leaq 0x241ec(%rip), %rax     # 0x2aca8
movq (%rax), %r15
testq %r15, %r15
je 0x6afb
callq 0xea3b
movq %rax, %r12
movl (%r14), %ebp
movl %ebp, %edi
callq 0x5530
movq %rax, (%rsp)
leaq 0x17647(%rip), %rsi     # 0x1e128
leaq 0x178a0(%rip), %rcx     # 0x1e388
movq %r15, %rdi
movq %r12, %rdx
movq %rbx, %r8
movl %ebp, %r9d
xorl %eax, %eax
callq 0x52c0
movl $0x1003, %edi           # imm = 0x1003
callq 0x7354
jmp 0x6f77
movl $0x1002, %edi           # imm = 0x1002
callq 0x7354
leaq 0x23845(%rip), %r12     # 0x2a360
leaq 0x2420e(%rip), %r15     # 0x2ad30
leaq 0x6(%r15), %rax
movq %rax, 0x28(%rsp)
movl $0x0, 0x14(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
movaps %xmm0, 0xa0(%rsp)
movaps %xmm0, 0x90(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
leaq 0x2386a(%rip), %rax     # 0x2a3d8
movl 0x4(%rax), %eax
movl %eax, 0x30(%rsp)
movw $0x1, 0x34(%rsp)
movl $0x1, %ebx
xorl %eax, %eax
movl (%rax,%r12), %ecx
testl %ecx, %ecx
je 0x6b9c
movslq %ebx, %rbx
movl %ecx, 0x30(%rsp,%rbx,8)
movl $0x1, 0x34(%rsp,%rbx,8)
incl %ebx
addq $0x4, %rax
cmpq $0x6c, %rax
jne 0x6b83
movslq %ebx, %r13
cmpl $0x1, 0x14(%rsp)
movl $0x0, %r14d
sbbl %r14d, %r14d
orl $0x3e8, %r14d           # imm = 0x3E8
leaq 0x30(%rsp), %rdi
movq %r13, %rsi
movl %r14d, %edx
callq 0x53c0
movl %eax, %ebp
testl %eax, %eax
jns 0x6be3
callq 0x5070
cmpl $0x4, (%rax)
je 0x6bbe
jmp 0x6d9d
cmpl $0x0, 0x14(%rsp)
je 0x6c02
testl %ebp, %ebp
jne 0x6c02
xorl %edi, %edi
callq 0xa3ae
movl $0x1, 0x14(%rsp)
jmp 0x6b33
testl %ebp, %ebp
je 0x6d9d
testl %ebx, %ebx
jle 0x6b33
movl %ebx, %r14d
xorl %ebx, %ebx
movl 0x30(%rsp,%rbx,8), %r13d
movswl 0x36(%rsp,%rbx,8), %ebp
testb $0x38, %bpl
jne 0x6e35
testb $0x1, %bpl
je 0x6cea
leaq 0x2379c(%rip), %rax     # 0x2a3d8
cmpl 0x4(%rax), %r13d
jne 0x6c7d
movl $0x4, %edx
movl %r13d, %edi
leaq 0x24(%rsp), %rsi
callq 0x5250
cmpq $0x4, %rax
jne 0x6ce2
movl $0x1, %eax
movl 0x24(%rsp), %ecx
cmpl $0x2, %ecx
je 0x6ce6
movl 0x14(%rsp), %eax
cmpl $0x1000, %ecx           # imm = 0x1000
jne 0x6ce6
jmp 0x6ee5
movl $0xffa, %edx            # imm = 0xFFA
movl %r13d, %edi
movq 0x28(%rsp), %rsi
callq 0x5250
movq %rax, %rbp
testq %rax, %rax
jle 0x6cfb
movq %r12, %rax
xorl %ecx, %ecx
cmpl %r13d, (%rax)
jne 0x6ca5
movb %cl, 0x4(%r15)
incq %rcx
addq $0x4, %rax
cmpq $0x1b, %rcx
jne 0x6c9c
movb $0x1, (%r15)
leal 0x5(%rbp), %eax
movzwl %ax, %edi
callq 0xee7e
movw %ax, 0x1(%r15)
movb $0x0, 0x3(%r15)
testb %r13b, %r13b
jne 0x6cd4
movl 0x4(%r15), %r13d
movb %r13b, 0x5(%r15)
movq %r15, %rdi
callq 0xa3ae
jmp 0x6cea
movl 0x14(%rsp), %eax
movl %eax, 0x14(%rsp)
incq %rbx
cmpq %r14, %rbx
jne 0x6c17
jmp 0x6b33
movq 0x232be(%rip), %rax     # 0x29fc0
movq (%rax), %rbx
callq 0xea3b
movq %rax, 0x18(%rsp)
callq 0x5070
movq %rax, %r13
movl (%rax), %r14d
movl %r14d, %edi
callq 0x5530
movq %rax, (%rsp)
movq %rbx, %rdi
leaq 0x174a8(%rip), %rsi     # 0x1e1d8
movq 0x18(%rsp), %rdx
leaq 0x1764c(%rip), %rbx     # 0x1e388
movq %rbx, %rcx
movl %ebp, %r8d
movl %r14d, %r9d
xorl %eax, %eax
callq 0x52c0
leaq 0x23f55(%rip), %rax     # 0x2aca8
movq (%rax), %r14
testq %r14, %r14
je 0x6b33
callq 0xea3b
movq %rax, 0x18(%rsp)
movl (%r13), %r13d
movl %r13d, %edi
callq 0x5530
movq %rax, (%rsp)
movq %r14, %rdi
leaq 0x17455(%rip), %rsi     # 0x1e1d8
movq 0x18(%rsp), %rdx
movq %rbx, %rcx
movl %ebp, %r8d
movl %r13d, %r9d
xorl %eax, %eax
callq 0x52c0
jmp 0x6b33
movq 0x2321c(%rip), %rax     # 0x29fc0
movq (%rax), %r14
callq 0xea3b
movq %rax, %r15
callq 0x5070
movq %rax, %rbx
movl (%rax), %r12d
movl %r12d, %edi
callq 0x5530
movq %rax, (%rsp)
leaq 0x173aa(%rip), %rsi     # 0x1e177
leaq 0x175b4(%rip), %rcx     # 0x1e388
movq %r14, %rdi
movq %r15, %rdx
movl %ebp, %r8d
movl %r12d, %r9d
xorl %eax, %eax
callq 0x52c0
leaq 0x23eba(%rip), %rax     # 0x2aca8
movq (%rax), %r14
testq %r14, %r14
je 0x6ee5
callq 0xea3b
movq %rax, %r15
movl (%rbx), %ebx
movl %ebx, %edi
callq 0x5530
movq %rax, (%rsp)
leaq 0x17361(%rip), %rsi     # 0x1e177
leaq 0x1756b(%rip), %rcx     # 0x1e388
movq %r14, %rdi
movq %r15, %rdx
movl %ebp, %r8d
movl %ebx, %r9d
xorl %eax, %eax
callq 0x52c0
jmp 0x6ee5
movq 0x23184(%rip), %rax     # 0x29fc0
movq (%rax), %rbx
callq 0xea3b
leaq 0x1734d(%rip), %rsi     # 0x1e198
leaq 0x17536(%rip), %rcx     # 0x1e388
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x52c0
leaq 0x23e42(%rip), %rax     # 0x2aca8
movq (%rax), %rbx
testq %rbx, %rbx
je 0x6e8e
callq 0xea3b
leaq 0x1731e(%rip), %rsi     # 0x1e198
leaq 0x17507(%rip), %rcx     # 0x1e388
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x52c0
movq 0x2312b(%rip), %rax     # 0x29fc0
movq (%rax), %rbx
callq 0xea3b
leaq 0x174f2(%rip), %rsi     # 0x1e396
movq %rbx, %rdi
movq %rax, %rdx
movl %r13d, %ecx
movl %ebp, %r8d
xorl %eax, %eax
callq 0x52c0
leaq 0x23dea(%rip), %rax     # 0x2aca8
movq (%rax), %rbx
testq %rbx, %rbx
je 0x6ee5
callq 0xea3b
leaq 0x174c4(%rip), %rsi     # 0x1e396
movq %rbx, %rdi
movq %rax, %rdx
movl %r13d, %ecx
movl %ebp, %r8d
xorl %eax, %eax
callq 0x52c0
xorl %ebx, %ebx
leaq 0x23472(%rip), %r14     # 0x2a360
movl (%rbx,%r14), %edi
testl %edi, %edi
je 0x6f03
callq 0x5230
movl $0x0, (%rbx,%r14)
addq $0x4, %rbx
cmpq $0x6c, %rbx
jne 0x6eee
movl $0x1003, %edi           # imm = 0x1003
callq 0x7354
xorl %edi, %edi
callq 0xa3ae
movq 0x2309b(%rip), %rax     # 0x29fc0
movq (%rax), %rbx
callq 0xea3b
leaq 0x172f4(%rip), %rsi     # 0x1e228
leaq 0x1744d(%rip), %rcx     # 0x1e388
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x52c0
leaq 0x23d59(%rip), %rax     # 0x2aca8
movq (%rax), %rbx
testq %rbx, %rbx
je 0x6f77
callq 0xea3b
leaq 0x172c5(%rip), %rsi     # 0x1e228
leaq 0x1741e(%rip), %rcx     # 0x1e388
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x52c0
xorl %edi, %edi
callq 0x5350