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

📄 bthid.cxx

📁 WinCE5.0部分核心源码
💻 CXX
📖 第 1 页 / 共 5 页
字号:
    SetEvent(gpState->hReconnectEvent);

    return pDev;
}

static DWORD WINAPI AuthenticateDevice (LPVOID lpArg) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request on hid device\n"));

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

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

    SCall *pCall = VerifyCall ((SCall *)lpArg);
    HidDevice *pDev = pCall ? FindDevice (&pCall->pLink->b) : NULL;

    if (! pDev) {
        IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: authentication request on nonexistent hid device\n"));
        gpState->Unlock ();

        return ERROR_SUCCESS;
    }

    int fAuth = pDev->fAuthenticate;
    int fEncr = pDev->fEncrypt;
    int fIncoming = pDev->fIncoming;

    unsigned char id = pCall->l2cap_id;
    unsigned short cid = pCall->pLink->cid;

    BD_ADDR b = pDev->b;
    BT_ADDR bt = SET_NAP_SAP (b.NAP, b.SAP);

    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request on hid device %04x%08x cid 0x%04x auth: %d, encr: %d, incoming: %d\n", b.NAP, b.SAP, fAuth, fEncr, fIncoming));

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

    gpState->Unlock ();

    if (fIncoming) {
        __try {
            pCallbackConnect (hL2CAP, NULL, &b, id, cid, 1, 1);
        } __except (1) {
        }
    }

    int iErr = ERROR_SUCCESS;
    if (fAuth)
        iErr = BthAuthenticate (&bt);

    if (fEncr && (iErr == ERROR_SUCCESS))
        iErr = BthSetEncryption (&bt, TRUE);

    gpState->Lock ();

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

    pDev = VerifyDevice (pDev);
    if (! pDev) {
        IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: authentication request : device disappeared enroute\n"));
        gpState->Unlock ();

        return ERROR_SUCCESS;
    }

    gpState->Unlock ();

    if (fIncoming) {
        unsigned short result = 0;

        if (iErr != ERROR_SUCCESS)
            result = 3;

        __try {
            pCallbackConnect (hL2CAP, NULL, &b, id, cid, result, 0);
        } __except (1) {
        }

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

        if (iErr != ERROR_SUCCESS)
            hiddev_lCallAborted (pCall, iErr);
    } else {
        if (iErr == ERROR_SUCCESS) {
            iErr = ERROR_INTERNAL_ERROR;
            __try {
                iErr = pCallbackConfig (hL2CAP, pCall, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
            } __except (1) {
            }
        } else
            HIDCloseCID_Int (cid);

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

    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: authentication request completes with status %d\n", iErr));

    return ERROR_SUCCESS;
}

static int WritePacket (void *lpHidDevice, BTHHIDPacket *pSource, int iTimeout, BTHHIDPacket **ppRes, int iChannel) {
    int iRes = ERROR_SUCCESS;

    for ( ; ; ) {
        if (! gpState)
            return ERROR_SERVICE_NOT_ACTIVE;

        gpState->Lock ();
        if (! gpState->fIsRunning) {
            gpState->Unlock ();

            return ERROR_SERVICE_NOT_ACTIVE;
        }

        HidDevice *pDev = VerifyDevice ((HidDevice *)lpHidDevice);
        if (! pDev) {
            gpState->Unlock ();

            return ERROR_SERVICE_NOT_ACTIVE;
        }

        HANDLE hevtComplete = pDev->hevtTransFree;

        if (pDev->fTrans) {    // We don't have the transaction
            gpState->Unlock ();

            if (iTimeout == 0)
                return ERROR_TIMEOUT;

            DWORD dwTicks = GetTickCount ();
            WaitForSingleObject (hevtComplete, iTimeout);
            if (iTimeout != INFINITE) {
                iTimeout -= GetTickCount () - dwTicks;
                if (iTimeout < 0)
                    iTimeout = 0;
            }

            continue;
        }

        Link *pLink = FindLink (&pDev->b, iChannel);
        if (! pLink) {
            gpState->Unlock ();

            return ERROR_NOT_FOUND;
        }

        BD_BUFFER *frags[BTH_MAX_FRAGMENTS];
        int cfrags = 0;

        pSource->SetMTU(pLink->mtu);

        for (cfrags = 0 ; cfrags < BTH_MAX_FRAGMENTS ; ++cfrags) {
            int cChunk = 0;
            pSource->GetPayloadChunk (NULL, 0, &cChunk);

            frags[cfrags] = HID_BufferAlloc (cChunk + gpState->cHeaders + gpState->cTrailers);
            if (! frags[cfrags]) {
                HID_BufferFreeArray (frags, cfrags);
                gpState->Unlock ();

                return ERROR_OUTOFMEMORY;
            }

            frags[cfrags]->cStart = gpState->cHeaders;
            frags[cfrags]->cEnd = frags[cfrags]->cSize - gpState->cTrailers;

            if (! pSource->GetPayloadChunk(frags[cfrags]->pBuffer + frags[cfrags]->cStart, cChunk, &cChunk))
                break;
        }

        if (cfrags == BTH_MAX_FRAGMENTS) {
            HID_BufferFreeArray (frags, cfrags);
            gpState->Unlock ();

            return ERROR_OUTOFMEMORY;
        }

        ++cfrags;

        HANDLE hL2CAP = gpState->hL2CAP;
        L2CA_DataDown_In pCallback = gpState->l2cap_if.l2ca_DataDown_In;

        unsigned short usCID = pLink->cid;
        HANDLE hevt = pDev->hevtTrans;

        pDev->fTrans = TRUE;    // We own the transaction
        ResetEvent (hevtComplete);

        gpState->Unlock ();

        iRes = ERROR_SUCCESS;
        int iSent = 0;
        __try {
            for (iSent = 0 ; iSent < cfrags ; ++iSent) {
                if (ERROR_SUCCESS != (iRes = pCallback (hL2CAP, NULL, usCID, frags[iSent])))
                    break;
            }
        } __except (1) {
            iRes = ERROR_EXCEPTION_IN_SERVICE;
        }

        if (iRes == ERROR_SUCCESS)
            WaitForSingleObject (hevt, iTimeout);

        if (! gpState) {
            SetEvent (hevtComplete);
            return ERROR_SERVICE_NOT_ACTIVE;
        }

        gpState->Lock ();

        if (iRes != ERROR_SUCCESS)
            HID_BufferFreeArray (frags + iSent, cfrags - iSent);

        SetEvent (hevtComplete);

        if (! gpState->fIsRunning) {
            gpState->Unlock ();

            return ERROR_SERVICE_NOT_ACTIVE;
        }

        if (! VerifyDevice (pDev)) {
            gpState->Unlock ();

            return ERROR_SERVICE_NOT_ACTIVE;
        }

        BTHHIDPacket *pPacket = pDev->pktTransResp;
        pDev->pktTransResp = NULL;
        pDev->fTrans = FALSE;    // Clear the transaction

        if (! pPacket) {
            gpState->Unlock ();

            return iRes == ERROR_SUCCESS ? ERROR_TIMEOUT : iRes;
        }

        if (ppRes)
            *ppRes = pPacket;
        else {
            pPacket->ReleasePayload ();
            delete pPacket;
        }

        gpState->Unlock ();

        break;
    }

    return iRes;
}

int HidDevice::FillPersistentParameters (int fIncoming) {
    DWORD dwDeviceFlags = 0;
    unsigned char *psdp = NULL;
    unsigned int csdp = 0;

    if (! GetDeviceConfig (&b, &dwDeviceFlags, &psdp, &csdp)) {
        IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - bonding does not exist\n", b.NAP, b.SAP));
        return FALSE;
    }

    if (fIncoming && ((dwDeviceFlags & HIDCONF_FLAGS_ACTIVE) == 0)) {
        IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - device is not activated\n", b.NAP, b.SAP));
        g_funcFree (psdp, g_pvFreeData);
        return FALSE;
    }

    if (dwDeviceFlags & HIDCONF_FLAGS_AUTH)
        fAuthenticate = TRUE;

    if (dwDeviceFlags & HIDCONF_FLAGS_ENCRYPT)
        fEncrypt = TRUE;

    BTHHIDSdpParser sdpParser;

    int iErr = sdpParser.Start (psdp, csdp);

    BOOL bb = FALSE;

    if (iErr == ERROR_SUCCESS)
        iErr = sdpParser.GetHIDReconnectInitiate(&bb);

    if (iErr == ERROR_SUCCESS) {
        fReconnectInitiate = bb;
        iErr = sdpParser.GetHIDNormallyConnectable(&bb);
        if (iErr == ERROR_SUCCESS)
            fNormallyConnectable = bb;
        iErr = ERROR_SUCCESS;
    }

    if (iErr == ERROR_SUCCESS) {
        iErr = sdpParser.GetHIDVirtualCable(&bb);
    }

    if (iErr == ERROR_SUCCESS) {
        fVirtualCable = bb;
        iErr = sdpParser.GetHIDReportDescriptor(&blobReportDescriptor);
    }

    if (iErr == ERROR_SUCCESS) {
        // Now we have the size. Allocate and requery.
        SVSUTIL_ASSERT(blobReportDescriptor.cbSize > 0);
        blobReportDescriptor.pBlobData = (unsigned char *)g_funcAlloc (blobReportDescriptor.cbSize, g_pvAllocData);
        iErr = sdpParser.GetHIDReportDescriptor(&blobReportDescriptor);
    }

    sdpParser.End ();

    if (iErr != ERROR_SUCCESS) {
        IFDBG(DebugOut (DEBUG_WARN, L"BTH HID: FillPersistentParameters %04x%08x - parsing SDP record failed\n", b.NAP, b.SAP));
    }

    g_funcFree (psdp, g_pvFreeData);

    return iErr == ERROR_SUCCESS;
}

static int ProcessHidPacket (BTHHIDPacket *pPacket, HidDevice *pDev) {
    if (pPacket->GetReportType () == BTHID_REPORT_INPUT) {
        BYTE* pPayload;
        int   cbPayload;

        if (pDev->pvNotifyParameter) {
            pPacket->GetPayload(&pPayload, &cbPayload);
            if (ERROR_SUCCESS != HidMdd_ProcessInterruptReport(pPayload, cbPayload, pDev->pvNotifyParameter)) {
                IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ProcessHidPacket : Error processing interrupt report - disconnecting device.\n"));
                DisconnectDevice (pDev, TRUE);    
            }
        }
    } else {
        if (pPacket->GetHeader() == gbUnplugHeader) {
            IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ReportHandler : virtual disconnect\n"));
            DisconnectDevice (pDev, FALSE);
        } else {
            if (! pDev->fTrans) {
                IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: protocol error - control packet w/o transaction. Aborting...\n"));
                DisconnectDevice (pDev, TRUE);
            } else {
                if (pDev->pktTransResp) {                        // Transaction violated
                    IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: protocol error - multiple control packets for transaction. Aborting...\n"));
                    DisconnectDevice (pDev, TRUE);
                } else {
                    pDev->pktTransResp = pPacket;
                    SetEvent (pDev->hevtTrans);
                    return FALSE;    // Don't destroy the packet
                }
            }
        }
    }

    return TRUE;
}

//
//    L2CAP stuff
//
static int hiddev_DataUpInd (void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Data up on channel 0x%04x %d bytes\n", cid, BufferTotal (pBuffer)));

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

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

    Link *pLink = FindLink (cid);
    HidDevice *pDev = pLink ? FindDevice (&pLink->b) : NULL;
    BTHHIDPacket *pPacket = pDev ? (pLink->psm == BTH_PSM_CONTROL ? pDev->pktControl : pDev->pktInterrupt) : NULL;

    if (pDev && (! pPacket)) {
        pPacket = new BTHHIDPacket;

        if (pPacket) {
            pPacket->SetMTU (pLink->mtu);
            pPacket->SetOwner (pDev);

            // Store this packet away.  In some cases, we will need to buffer up
            // several fragments before passing data up to HID layer.
            
            if (pLink->psm == BTH_PSM_CONTROL) {
                pPacket->SetReportType(BTHID_REPORT_FEATURE);
                pDev->pktControl = pPacket;
            } else {
                pPacket->SetReportType(BTHID_REPORT_INPUT);
                pDev->pktInterrupt = pPacket;
            }
        }
    }

#if defined (DEBUG) || defined (_DEBUG)
    if (pPacket) {
        SVSUTIL_ASSERT (pPacket->GetOwner() == pDev);
    } else {
        IFDBG(DebugOut (DEBUG_ERROR, L"BTH HID: Data up - no packet\n"));
    }
#endif

    if (pPacket) {
        // If this function returns 0 we can indicate the packet up to HID layer.  Otherwise, we have
        // to recv more data before indicating up.
        if (! pPacket->AddPayloadChunk(pBuffer->pBuffer + pBuffer->cStart, BufferTotal (pBuffer))) {
            if (pLink->psm == BTH_PSM_CONTROL)
                pDev->pktControl = NULL;
            else
                pDev->pktInterrupt = NULL;
                
#if defined (BTHHID_QUEUE)
            if (! gpState->qHidReports.Put (pPacket)) {
                pPacket->ReleasePayload();
                delete pPacket;
            }

            SetEvent (gpState->hevtReports);
#else
            int fRelease = ProcessHidPacket (pPacket, pDev);
            if (fRelease) {
                pPacket->ReleasePayload();
                delete pPacket;
            }
#endif
        }
    }

⌨️ 快捷键说明

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