⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bthid.cxx

📁 WinCE5.0部分核心源码
💻 CXX
📖 第 1 页 / 共 5 页
字号:


    if (pBuffer->pFree)
        pBuffer->pFree (pBuffer);

    gpState->Unlock ();
    return ERROR_SUCCESS;
}

static int hiddev_DisconnectInd (void *pUserContext, unsigned short cid, int iError) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Disconnect indicator on channel 0x%04x\n", cid));

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

    if (! gpState->fIsRunning) {
        gpState->Unlock ();
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    Link *pLink = FindLink (cid);
    if (! pLink) {
        gpState->Unlock ();
        return ERROR_NOT_FOUND;
    }

    SCall *pC = gpState->pCalls;
    while (pC) {
        if (pC->pLink == pLink) {
            if (pC->fAutoClean) {
                DeleteCall (pC);
                pC = gpState->pCalls;
                continue;
            } else if (! pC->fComplete) {
                pC->fComplete = TRUE;
                pC->iResult = ERROR_CONNECTION_UNAVAIL;
                SetEvent (pC->hEvent);
            }
        }

        pC = pC->pNext;
    }

    DeleteLink (pLink);

    gpState->Unlock ();
    return ERROR_SUCCESS;
}

static int hiddev_lStackEvent (void *pUserContext, int iEvent, void *pEventContext) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Stack event (L2CAP) %d\n", iEvent));

    if (! gpState)
        return ERROR_SUCCESS;

    gpState->Lock ();

    if (! gpState->fIsRunning) {
        gpState->Unlock ();
        return ERROR_SUCCESS;
    }

    LPTHREAD_START_ROUTINE p = NULL;

    if (iEvent == BTH_STACK_DISCONNECT)
        hiddev_CloseDriverInstance ();
    else if (iEvent == BTH_STACK_DOWN)
        p = StackDown;
    else if (iEvent == BTH_STACK_UP)
        p = StackUp;

    HANDLE h = p ? CreateThread (NULL, 0, p, NULL, 0, NULL) : NULL;

    if (h) {
        CloseHandle (h);
        gpState->AddRef ();
    }

    gpState->Unlock ();

    return ERROR_SUCCESS;
}

static int hiddev_lCallAborted (void *pCallContext, int iError) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Aborted call 0x%08x error %d\n", pCallContext, iError));

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

    if (! gpState->fIsRunning) {
        gpState->Unlock ();
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    SCall *pCall = VerifyCall ((SCall *)pCallContext);
    if (! pCall) {
        IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: Aborted call not found!\n"));
        gpState->Unlock ();
        return ERROR_NOT_FOUND;
    }

    SVSUTIL_ASSERT (! pCall->fComplete);
    SVSUTIL_ASSERT (! pCall->pBuffer);

    Link *pLink = pCall->pLink;

    if (pCall->fAutoClean)
        DeleteCall (pCall);
    else {
        pCall->iResult = iError;
        pCall->fComplete = TRUE;
        pCall->pLink = NULL;
        SetEvent (pCall->hEvent);
    }

    unsigned short disconnect_cid = 0;

    if (pLink) {
        if ((pLink->fStage & UP) != UP) {
            if (pLink->fStage & CONNECTED)
                disconnect_cid = pLink->cid;
            else 
                DeleteLink (pLink);
        } else {
            disconnect_cid = pLink->cid;
            pLink->fStage |= LINK_ERROR;
        }
    }

    gpState->Unlock ();

    if (disconnect_cid)
        HIDCloseCID_Int (disconnect_cid);

    return ERROR_SUCCESS;
}

static int hiddev_ConfigInd (void *pUserContext, unsigned char id, unsigned short cid, unsigned short usOutMTU, unsigned short usInFlushTO, struct btFLOWSPEC *pInFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Config request indicator on ch 0x%04x id %d MTU %d flush 0x%04x, flow: %s\n", cid, id, usOutMTU, usInFlushTO, pInFlow ? L"yes" : L"no"));

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

    if (! gpState->fIsRunning) {
        gpState->Unlock ();
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    Link *pLink = FindLink (cid);
    SCall *pCall = pLink ? FindCall (pLink, CALL_L2CAP_LINK_SETUP) : NULL;

    if ((! pCall) || pCall->fComplete)  {
        IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: config setup call not found!\n"));
        gpState->Unlock ();
        return ERROR_NOT_FOUND;
    }

    pCall->l2cap_id = id;

    SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_LINK_SETUP);
    SVSUTIL_ASSERT (! pCall->fComplete);
    SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
    SVSUTIL_ASSERT (! pCall->pBuffer);

    int fAccept = FALSE;

//    if ((usInFlushTO == 0xffff) && (! pInFlow)) {
        pCall->iResult = ERROR_SUCCESS;
        pCall->pLink->fStage |= CONFIG_IND_DONE;
        pCall->pLink->mtu = usOutMTU ? usOutMTU : L2CAP_MTU;
        fAccept = TRUE;

        if (pLink->fStage == UP) {
            pCall->fComplete = TRUE;
            pCall->iResult = ERROR_SUCCESS;
            SetEvent (pCall->hEvent);

            if (pCall->fAutoClean)
                DeleteCall (pCall);

            HidDevice *pDev = FindDevice (&pLink->b);

            if (pDev) {
                if (pLink->psm == BTH_PSM_CONTROL)
                    pDev->fHaveControl = TRUE;
                else
                    pDev->fHaveInterrupt = TRUE;

                if (pDev->fHaveControl && pDev->fHaveInterrupt) {
                    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: device %04x%08x connected!\n", pDev->b.NAP, pDev->b.SAP));

                    if (pDev->ckConnectionTimeout) {
                        gpState->pSchedule->UnScheduleEvent (pDev->ckConnectionTimeout);
                        pDev->ckConnectionTimeout = 0;
                    }
                } else if (! pDev->ckConnectionTimeout)
                    pDev->ckConnectionTimeout = gpState->pSchedule->ScheduleEvent (ConnectionTimeout, pDev, BTH_CONNECTION_TIMEOUT);
            } else {
                IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: could not find HID device - connection not accepted!\n"));
                fAccept = FALSE;
            }
        }
//    } else {
//        IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: not accepting config because of flow control parameters.\n"));
//    }

    HANDLE hL2CAP = gpState->hL2CAP;
    L2CA_ConfigResponse_In pCallback = gpState->l2cap_if.l2ca_ConfigResponse_In;
    gpState->Unlock ();

    __try {
        pCallback (hL2CAP, NULL, id, cid, fAccept ? 0 : 2, usOutMTU, 0xffff, NULL, 0, NULL);
    } __except (1) {
    }

    if (! fAccept)
        hiddev_lCallAborted (pCall, ERROR_CONNECTION_ABORTED);

    return ERROR_SUCCESS;
}

static int hiddev_ConfigReq_Out (void *pCallContext, unsigned short usResult, unsigned short usOutMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Config req out for call 0x%08x result 0x%04x mtu %d flush 0x%04x, flow %s\n", pCallContext, usResult, usOutMTU, usOutFlushTO, pOutFlow ? L"yes" : L"no" ));

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

    if (! gpState->fIsRunning) {
        gpState->Unlock ();
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    SCall *pCall = VerifyCall ((SCall *)pCallContext);
    if ((! pCall) || pCall->fComplete)  {
        IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: config setup call not found!\n"));
        gpState->Unlock ();
        return ERROR_NOT_FOUND;
    }

    SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_LINK_SETUP);
    SVSUTIL_ASSERT (! pCall->fComplete);
    SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
    SVSUTIL_ASSERT (! pCall->pBuffer);

    if (usResult == 0) {
        Link *pLink = pCall->pLink;
        SVSUTIL_ASSERT (! (pLink->fStage & CONFIG_REQ_DONE));
        SVSUTIL_ASSERT (pLink->fStage & CONNECTED);
        SVSUTIL_ASSERT (pLink->cid);
        SVSUTIL_ASSERT (pLink->psm);

        pLink->fStage |= CONFIG_REQ_DONE;
		if (usOutMTU) 
			pLink->mtu = usOutMTU;

        if (pLink->fStage == UP) {
            pCall->fComplete = TRUE;
            pCall->iResult = ERROR_SUCCESS;
            SetEvent (pCall->hEvent);

            if (pCall->fAutoClean)
                DeleteCall (pCall);

            HidDevice *pDev = FindDevice (&pLink->b);

            if (pDev) {
                if (pLink->psm == BTH_PSM_CONTROL)
                    pDev->fHaveControl = TRUE;
                else
                    pDev->fHaveInterrupt = TRUE;

                if (pDev->fHaveControl && pDev->fHaveInterrupt) {
                    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: device %04x%08x connected!\n", pDev->b.NAP, pDev->b.SAP));

                    if (pDev->ckConnectionTimeout) {
                        gpState->pSchedule->UnScheduleEvent (pDev->ckConnectionTimeout);
                        pDev->ckConnectionTimeout = 0;
                    }
                } else if (! pDev->ckConnectionTimeout)
                    pDev->ckConnectionTimeout = gpState->pSchedule->ScheduleEvent (ConnectionTimeout, pDev, BTH_CONNECTION_TIMEOUT);
            } else {
                IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: could not find HID device - connection not accepted!\n"));

                gpState->Unlock ();

                hiddev_lCallAborted (pCallContext, ERROR_CONNECTION_ABORTED);

                return ERROR_SUCCESS;
            }
        }

        gpState->Unlock ();
        return ERROR_SUCCESS;
    }

    gpState->Unlock ();

    hiddev_lCallAborted (pCallContext, ERROR_CONNECTION_ABORTED);

    return ERROR_SUCCESS;
}

static int hiddev_ConnectInd (void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Connect indicator from %04x%08x ch 0x%04x id %d psm 0x%04x\n", pba->NAP, pba->SAP, cid, id, psm));

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

    if (! gpState->fIsRunning) {
        gpState->Unlock ();
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    unsigned short    result = 0;
    unsigned short    status = 0;

    HidDevice *pDev = FindDevice (pba);

    if (! pDev) {
        pDev = MakeNewDevice (pba, TRUE);

        if (pDev) {
            DWORD cbMaxInputReport;
            
            // Pass the report descriptor off to the MDD
            if ((NULL == pDev->pvNotifyParameter) && 
                (HidMdd_Attach(
                        (HID_PDD_HANDLE) pDev,
                        pDev->blobReportDescriptor.pBlobData,
                        pDev->blobReportDescriptor.cbSize,
                        0,
                        0,
                        0,
                        0,
                        &pDev->pvNotifyParameter,
                        &cbMaxInputReport) == FALSE)) {
                IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: Failed to initialize HID Mdd\n"));
                return ERROR_NOT_CONNECTED;
            }
        }
    }

    if (! pDev) {
        IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: connect indication: could not make device\n"));
        result = 4;
    } else if (pDev->ckDeviceTimeout) {
        gpState->pSchedule->UnScheduleEvent (pDev->ckDeviceTimeout);
        pDev->ckDeviceTimeout = 0;
    }

    SCall *pCall = NULL;

    if (pDev) {
        Link *pLink = (Link *)svsutil_GetFixed (gpState->pfmdLinks);
        pCall = pLink ? AllocCall (CALL_L2CAP_LINK_SETUP, pLink) : NULL;
        if (pCall) {
            pCall->fAutoClean = TRUE;
            pCall->l2cap_id = id;

            pLink->b = *pba;
            pLink->cid = cid;
            pLink->fStage = CONNECTED;
            pLink->mtu = 0;
            pLink->psm = psm;
            pLink->fIncoming = TRUE;

            pLink->pNext = gpState->pLinks;
            gpState->pLinks = pLink;

            result = 0;
        } else {
            if (pLink)
                svsutil_FreeFixed (pLink, gpState->pfmdLinks);
            result = 4;
        }
    } else {
        if (result == 0)
            result = 2;
    }

    if ((result == 0) && (pDev->fEncrypt || pDev->fAuthenticate) && (! pDev->fAuthSpinned)) {
        pDev->fAuthSpinned = TRUE;
        gpState->pSchedule->ScheduleEvent (AuthenticateDevice, pCall, 0);

        gpState->Unlock ();
        
        return ERROR_SUCCESS;
       }

    HANDLE hL2CAP = gpState->hL2CAP;
    L2CA_ConnectResponse_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectResponse_In;
    L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
    gpState->Unlock ();

    __try {
        pCallbackConnect (hL2CAP, NULL, pba, id, cid, result, status);
    } __except (1) {
    }

    if (result == 0) {
        int iRes = ERROR_INTERNAL_ERROR;
        __try {
            iRes = pCallbackConfig (hL2CAP, pCall, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
        } __except (1) {
        }

        if (iRes != ERROR_SUCCESS)
            hiddev_lCallAborted (pCall, iRes);
    }

    return ERROR_SUCCESS;
}

static int hiddev_ConnectReq_Out (void *pCallContext, unsigned short cid, unsigned short result, unsigned short status) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Connect out for call 0x%08x ch 0x%04x result = 0x%04x status 0x%04x\n", pCallContext, cid, result, status));

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

    if (! gpState->fIsRunning) {
        gpState->Unlock ();
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    SCall *pCall = VerifyCall ((SCall *)pCallContext);
    if ((! pCall) || pCall->fComplete) {
        gpState->Unlock ();
        return ERROR_NOT_FOUND;
    }

    SVSUTIL_ASSERT (pCall->fWhat == CALL_L2CAP_LINK_SETUP);
    SVSUTIL_ASSERT (! pCall->fComplete);
    SVSUTIL_ASSERT (VerifyLink (pCall->pLink));
    SVSUTIL_ASSERT (! pCall->pBuffer);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -