// File: /workspace/github_c_makefile_star2_O2/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
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x6e70
movl %eax, 0x22a67(%rip)     # 0x29364
cmpb $0x0, 0x51(%r14)
je 0x6915
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x6e70
movl %eax, 0x22a8f(%rip)     # 0x293a4
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x6e70
movl %eax, 0x22a42(%rip)     # 0x29368
pushq $0x3
popq %rsi
movq %rbx, %rdi
callq 0x6e70
movl %eax, 0x22a35(%rip)     # 0x2936c
pushq $0xb
popq %rsi
movq %rbx, %rdi
callq 0x6e70
movl %eax, 0x22a44(%rip)     # 0x2938c
cmpl $0x0, 0x10a(%r14)
je 0x695c
cmpb $0x0, 0x215(%r14)
je 0x6974
pushq $0x1a
popq %rsi
movq %rbx, %rdi
callq 0x6e70
movl %eax, 0x22a5b(%rip)     # 0x293c8
movl %eax, 0x122(%r14)
cmpl $0x0, 0x229e9(%rip)     # 0x29364
jne 0x6a23
callq 0x6734
movq 0x2262b(%rip), %rax     # 0x28fb8
movq (%rax), %r15
callq 0xe343
movq %rax, %r12
callq 0x5070
movq %rax, %r14
movl (%rax), %ebp
movl %ebp, %edi
callq 0x5540
movq %rax, (%rsp)
leaq 0x15774(%rip), %rsi     # 0x1c128
leaq 0x159cd(%rip), %rcx     # 0x1c388
movq %r15, %rdi
movq %r12, %rdx
movq %rbx, %r8
movl %ebp, %r9d
xorl %eax, %eax
callq 0x52c0
leaq 0x232d3(%rip), %rax     # 0x29ca8
movq (%rax), %r15
testq %r15, %r15
je 0x6a14
callq 0xe343
movq %rax, %r12
movl (%r14), %ebp
movl %ebp, %edi
callq 0x5540
movq %rax, (%rsp)
leaq 0x1572e(%rip), %rsi     # 0x1c128
leaq 0x15987(%rip), %rcx     # 0x1c388
movq %r15, %rdi
movq %r12, %rdx
movq %rbx, %r8
movl %ebp, %r9d
xorl %eax, %eax
callq 0x52c0
movl $0x1003, %edi           # imm = 0x1003
callq 0x7244
jmp 0x6e69
movl $0x1002, %edi           # imm = 0x1002
callq 0x7244
leaq 0x232fc(%rip), %r13     # 0x29d30
leaq 0x6(%r13), %rax
movq %rax, 0x28(%rsp)
leaq 0x2291c(%rip), %rbp     # 0x29360
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 0x22951(%rip), %rax     # 0x293d8
movl 0x4(%rax), %eax
movl %eax, 0x30(%rsp)
movw $0x1, 0x34(%rsp)
xorl %eax, %eax
pushq $0x1
popq %rcx
movl %ecx, %r14d
movslq %r14d, %r15
cmpq $0x6c, %rax
je 0x6ac7
movl (%rax,%rbp), %ecx
testl %ecx, %ecx
je 0x6ac1
movl %ecx, 0x30(%rsp,%r15,8)
movl $0x1, 0x34(%rsp,%r15,8)
incl %r15d
movl %r15d, %r14d
addq $0x4, %rax
jmp 0x6a9d
cmpl $0x1, 0x14(%rsp)
movl $0x0, %r12d
sbbl %r12d, %r12d
orl $0x3e8, %r12d           # imm = 0x3E8
leaq 0x30(%rsp), %rdi
movq %r15, %rsi
movl %r12d, %edx
callq 0x53d0
movl %eax, %ebx
testl %eax, %eax
jns 0x6b01
callq 0x5070
cmpl $0x4, (%rax)
je 0x6adc
jmp 0x6cb5
cmpl $0x0, 0x14(%rsp)
je 0x6b1f
testl %ebx, %ebx
jne 0x6b1f
xorl %edi, %edi
callq 0x9fbb
pushq $0x1
popq %rax
movl %eax, 0x14(%rsp)
jmp 0x6a4c
testl %ebx, %ebx
je 0x6cb5
testl %r14d, %r14d
movl $0x0, %eax
cmovlel %eax, %r14d
xorl %r12d, %r12d
cmpq %r14, %r12
je 0x6a4c
movl 0x30(%rsp,%r12,8), %ebx
movswl 0x36(%rsp,%r12,8), %r15d
testb $0x38, %r15b
jne 0x6d4c
testb $0x1, %r15b
je 0x6c0e
leaq 0x22873(%rip), %rax     # 0x293d8
cmpl 0x4(%rax), %ebx
jne 0x6ba0
movl %ebx, %edi
leaq 0x24(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0x5250
cmpq $0x4, %rax
jne 0x6c06
movl 0x24(%rsp), %ecx
pushq $0x1
popq %rax
cmpl $0x2, %ecx
je 0x6c0a
movl 0x14(%rsp), %eax
cmpl $0x1000, %ecx           # imm = 0x1000
jne 0x6c0a
jmp 0x6dfa
movl $0xffa, %edx            # imm = 0xFFA
movl %ebx, %edi
movq 0x28(%rsp), %rsi
callq 0x5250
movq %rax, %r15
testq %rax, %rax
jle 0x6c16
movq %rbp, %rax
xorl %ecx, %ecx
cmpq $0x1b, %rcx
je 0x6bd5
cmpl %ebx, (%rax)
jne 0x6bcc
movb %cl, 0x4(%r13)
incq %rcx
addq $0x4, %rax
jmp 0x6bbe
movb $0x1, (%r13)
leal 0x5(%r15), %eax
movzwl %ax, %edi
callq 0xe749
movw %ax, 0x1(%r13)
movb $0x0, 0x3(%r13)
testb %bl, %bl
jne 0x6bf8
movl 0x4(%r13), %ebx
movb %bl, 0x5(%r13)
movq %r13, %rdi
callq 0x9fbb
jmp 0x6c0e
movl 0x14(%rsp), %eax
movl %eax, 0x14(%rsp)
incq %r12
jmp 0x6b36
movq 0x2239b(%rip), %rax     # 0x28fb8
movq (%rax), %r14
callq 0xe343
movq %rax, 0x18(%rsp)
callq 0x5070
movq %rax, %rbx
movl (%rax), %r12d
movl %r12d, %edi
callq 0x5540
movq %rax, (%rsp)
movq %r14, %rdi
leaq 0x1558d(%rip), %rsi     # 0x1c1d8
movq 0x18(%rsp), %rdx
leaq 0x15731(%rip), %r14     # 0x1c388
movq %r14, %rcx
movl %r15d, %r8d
movl %r12d, %r9d
xorl %eax, %eax
callq 0x52c0
leaq 0x2303a(%rip), %rax     # 0x29ca8
movq (%rax), %r12
testq %r12, %r12
je 0x6a4c
callq 0xe343
movq %rax, 0x18(%rsp)
movl (%rbx), %ebx
movl %ebx, %edi
callq 0x5540
movq %rax, (%rsp)
movq %r12, %rdi
leaq 0x1553d(%rip), %rsi     # 0x1c1d8
movq 0x18(%rsp), %rdx
movq %r14, %rcx
movl %r15d, %r8d
movl %ebx, %r9d
xorl %eax, %eax
callq 0x52c0
jmp 0x6a4c
movq 0x222fc(%rip), %rax     # 0x28fb8
movq (%rax), %r15
callq 0xe343
movq %rax, %r12
callq 0x5070
movq %rax, %r14
movl (%rax), %ebp
movl %ebp, %edi
callq 0x5540
movq %rax, (%rsp)
leaq 0x15494(%rip), %rsi     # 0x1c177
leaq 0x1569e(%rip), %rcx     # 0x1c388
movq %r15, %rdi
movq %r12, %rdx
movl %ebx, %r8d
movl %ebp, %r9d
xorl %eax, %eax
callq 0x52c0
leaq 0x22fa4(%rip), %rax     # 0x29ca8
movq (%rax), %r15
testq %r15, %r15
je 0x6dfa
callq 0xe343
movq %rax, %r12
movl (%r14), %ebp
movl %ebp, %edi
callq 0x5540
movq %rax, (%rsp)
leaq 0x1544a(%rip), %rsi     # 0x1c177
leaq 0x15654(%rip), %rcx     # 0x1c388
movq %r15, %rdi
movq %r12, %rdx
movl %ebx, %r8d
movl %ebp, %r9d
xorl %eax, %eax
callq 0x52c0
jmp 0x6dfa
movq 0x22265(%rip), %rax     # 0x28fb8
movq (%rax), %r14
callq 0xe343
leaq 0x15436(%rip), %rsi     # 0x1c198
leaq 0x1561f(%rip), %rcx     # 0x1c388
movq %r14, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x52c0
leaq 0x22f2b(%rip), %rax     # 0x29ca8
movq (%rax), %r14
testq %r14, %r14
je 0x6da5
callq 0xe343
leaq 0x15407(%rip), %rsi     # 0x1c198
leaq 0x155f0(%rip), %rcx     # 0x1c388
movq %r14, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x52c0
movq 0x2220c(%rip), %rax     # 0x28fb8
movq (%rax), %r14
callq 0xe343
leaq 0x155db(%rip), %rsi     # 0x1c396
movq %r14, %rdi
movq %rax, %rdx
movl %ebx, %ecx
movl %r15d, %r8d
xorl %eax, %eax
callq 0x52c0
leaq 0x22ed4(%rip), %rax     # 0x29ca8
movq (%rax), %r14
testq %r14, %r14
je 0x6dfa
callq 0xe343
leaq 0x155ae(%rip), %rsi     # 0x1c396
movq %r14, %rdi
movq %rax, %rdx
movl %ebx, %ecx
movl %r15d, %r8d
xorl %eax, %eax
callq 0x52c0
callq 0x6734
movl $0x1003, %edi           # imm = 0x1003
callq 0x7244
xorl %edi, %edi
callq 0x9fbb
movq 0x221a1(%rip), %rax     # 0x28fb8
movq (%rax), %rbx
callq 0xe343
leaq 0x15402(%rip), %rsi     # 0x1c228
leaq 0x1555b(%rip), %rcx     # 0x1c388
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x52c0
leaq 0x22e67(%rip), %rax     # 0x29ca8
movq (%rax), %rbx
testq %rbx, %rbx
je 0x6e69
callq 0xe343
leaq 0x153d3(%rip), %rsi     # 0x1c228
leaq 0x1552c(%rip), %rcx     # 0x1c388
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x52c0
xorl %edi, %edi
callq 0x5350