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

📄 bthid.cxx

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

    if (result) {
        if (result != 1) {
            pCall->fComplete = TRUE;
            pCall->iResult = ERROR_CONNECTION_REFUSED;
            SetEvent (pCall->hEvent);
        }
        gpState->Unlock ();
        return ERROR_SUCCESS;
    }

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

    if (! pDev) {
        pCall->fComplete = TRUE;
        pCall->iResult = ERROR_CONNECTION_REFUSED;
        SetEvent (pCall->hEvent);
        gpState->Unlock ();

        HIDCloseCID_Int (cid);
        return ERROR_SUCCESS;
    }

    Link *pLink = pCall->pLink;

    SVSUTIL_ASSERT (pLink->fStage == NONE);
    SVSUTIL_ASSERT (! pLink->cid);
    SVSUTIL_ASSERT (pLink->psm);

    pLink->fStage = CONNECTED;
    pLink->cid = cid;

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

        gpState->Unlock ();
        
        return ERROR_SUCCESS;
    }

    HANDLE hL2CAP = gpState->hL2CAP;
    L2CA_ConfigReq_In pCallback = gpState->l2cap_if.l2ca_ConfigReq_In;
    gpState->Unlock ();

    int iRes = ERROR_INTERNAL_ERROR;
    __try {
        iRes = pCallback (hL2CAP, pCallContext, cid, BTH_MTU_MAX, 0xffff, NULL, 0, NULL);
    } __except (1) {
    }

    if (iRes != ERROR_SUCCESS)
        hiddev_lCallAborted (pCallContext, iRes);

    return ERROR_SUCCESS;
}

static int hiddev_DataDown_Out (void *pCallContext, unsigned short result) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: Data down call 0x%08x result %d\n", pCallContext, result));
    return ERROR_SUCCESS;
}

static int hiddev_Ping_Out (void *pCallContext, BD_ADDR *pba, unsigned char *pOutBuffer, unsigned short size) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: hiddev_Ping_Out call 0x%08x result %d\n", pCallContext));
    return ERROR_SUCCESS;
}

// These are just stubs - they do nothing
static int hiddev_ConfigResponse_Out (void *pCallContext, unsigned short result) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: ConfigResponse out call 0x%08x, result %d\n", pCallContext, result));
    return ERROR_SUCCESS;
}

static int hiddev_ConnectResponse_Out (void *pCallContext, unsigned short result) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: ConnectResponse out call 0x%08x, result %d\n", pCallContext, result));
    return ERROR_SUCCESS;
}

static int hiddev_Disconnect_Out (void *pCallContext, unsigned short result) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: disconnect out call 0x%08x, result %d\n", pCallContext, result));
    return ERROR_SUCCESS;
}

//
//    Init stuff
//
static int hiddev_CreateDriverInstance (void) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+hiddev_CreateDriverInstance\n"));

    if (gpState) {
        IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_ALREADY_INITIALIZED\n"));
        return ERROR_ALREADY_INITIALIZED;
    }

    if (! BthPktInitAllocator ())
        return ERROR_OUTOFMEMORY;

    BTHID_Header_Parameter  packetVirtualUnplug;
    packetVirtualUnplug.bRawHeader = 0;

    packetVirtualUnplug.control_p.bControlOp = BTHID_CONTROL_VIRTUAL_CABLE_UNPLUG;
    gbUnplugHeader = (BTHID_HID_CONTROL << 4) | packetVirtualUnplug.bRawHeader;

    gpState = CreateNewState ();

    if ((! gpState) || (! gpState->fIsRunning)) {
        IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_OUTOFMEMORY\n"));
        if (gpState)
            delete gpState;
        gpState = NULL;
        return ERROR_OUTOFMEMORY;
    }

#if defined (BTHHID_QUEUE)
    gpState->hthReports = CreateThread (NULL, 0, HidReportHandler, NULL, 0, NULL);
    if (gpState->hthReports)
        SetThreadPriority (gpState->hthReports, THREAD_PRIORITY_HIGHEST);
#endif

    gpState->hthReconnect = CreateThread (NULL, 0, HidReconnectThread, NULL, 0, NULL);
    if (! gpState->hthReconnect) {
        IFDBG(DebugOut (DEBUG_ERROR, L"-hiddev_CreateDriverInstance : Failed to create reconnect thread.\n"));
    }

    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CreateDriverInstance : ERROR_SUCCESS\n"));
    return ERROR_SUCCESS;
}


static int hiddev_CloseDriverInstance (void) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"+hiddev_CloseDriverInstance\n"));

    if (! gpState) {
        IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
        return ERROR_SERVICE_NOT_ACTIVE;
    }

    gpState->Lock ();
    if (! gpState->fIsRunning) {
        IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CloseDriverInstance : ERROR_SERVICE_NOT_ACTIVE\n"));
        gpState->Unlock ();

        return ERROR_SERVICE_NOT_ACTIVE;
    }

    gpState->fIsRunning = FALSE;
    
    SetEvent(gpState->hReconnectEvent);    

    while (gpState->GetRefCount () > 1) {
        IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"Waiting for ref count in hiddev_CloseDriverInstance\n"));
        gpState->Unlock ();
        Sleep (200);
        gpState->Lock ();
    }

    while (gpState->pCalls) {
        SetEvent (gpState->pCalls->hEvent);
        gpState->pCalls->iResult = ERROR_CANCELLED;
        gpState->pCalls = gpState->pCalls->pNext;
    }

    while (gpState->pLinks) {
        unsigned short cid = gpState->pLinks->cid;

        gpState->Unlock ();
        gpState->l2cap_if.l2ca_Disconnect_In (gpState->hL2CAP, NULL, cid);
        gpState->Lock ();

        gpState->pLinks = gpState->pLinks->pNext;
    }

    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"-hiddev_CloseDriverInstance : ERROR_SUCCESS\n"));

    if (gpState->hthReconnect)
        CloseHandle (gpState->hthReconnect);

    gpState->Unlock ();
    delete gpState;
    gpState = NULL;

    BthPktFreeAllocator ();

    return ERROR_SUCCESS;
}

#if defined (BTHHID_QUEUE)
//
//    HID reports processing
//
static DWORD WINAPI HidReportHandler (LPVOID lpNull) {
    IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID ReportHandler : started\n"));

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

        gpState->Lock ();

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

        HANDLE hEvent = gpState->hevtReports;

        gpState->Unlock ();

        WaitForSingleObject (hEvent, INFINITE);

        gpState->Lock ();

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

        while (! gpState->qHidReports.IsEmpty()) {
            BTHHIDPacket *pPacket = (BTHHIDPacket *)gpState->qHidReports.Get ();
            HidDevice *pDev = VerifyDevice ((HidDevice *)pPacket->GetOwner());
            int fRelease = TRUE;
            if (pDev)
                fRelease = ProcessHidPacket (pPacket, pDev);
            else {
                IFDBG(DebugOut (DEBUG_ERROR, L"BTH Device: Device not found for a packet...\n"));
            }

            if (fRelease) {
                pPacket->ReleasePayload();
                delete pPacket;
            }
        }
        gpState->Unlock ();
    }
    return 0;
}
#endif

//
//    Internal API section
//

static int HIDConnect_Int
(
BD_ADDR            *pba,
unsigned short  usPSM,
unsigned short  *pusCid
) {
    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

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

        return ERROR_SERVICE_NOT_ACTIVE;
    }

    Link *pLink = (Link *)svsutil_GetFixed (gpState->pfmdLinks);
    memset (pLink, 0, sizeof (*pLink));
    pLink->cid = 0;
    pLink->b = *pba;
    pLink->fStage = NONE;
    pLink->fIncoming = FALSE;
    pLink->psm = usPSM;

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

    SCall *pCall = AllocCall (CALL_L2CAP_LINK_SETUP, pLink);
    if (! pCall) {
        gpState->Unlock ();
        return ERROR_OUTOFMEMORY;
    }
    
    HANDLE hEvent = pCall->hEvent;
    HANDLE hL2CAP = gpState->hL2CAP;
    L2CA_ConnectReq_In pCallbackConnect = gpState->l2cap_if.l2ca_ConnectReq_In;
    L2CA_ConfigReq_In pCallbackConfig = gpState->l2cap_if.l2ca_ConfigReq_In;
    int iRes = ERROR_INTERNAL_ERROR;
    gpState->Unlock ();
    __try {
        iRes = pCallbackConnect (hL2CAP, pCall, usPSM, pba);
    } __except (1) {
    }

    if (iRes == ERROR_SUCCESS)
        WaitForSingleObject (hEvent, INFINITE);

    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

    gpState->Lock ();

    if (gpState->fIsRunning) {
        pCall = VerifyCall (pCall);
        pLink = VerifyLink (pLink);
    } else {
        pCall = NULL;
        pLink = NULL;
        iRes = ERROR_SERVICE_NOT_ACTIVE;
    }

    if (iRes == ERROR_SUCCESS) {
        if (pCall && pCall->fComplete)
            iRes = pCall->iResult;
        else
            iRes = ERROR_TIMEOUT;
    }

    if (pCall)
        DeleteCall (pCall);
    else
        iRes = ERROR_INTERNAL_ERROR;

    if ((! pLink) || (pLink->fStage & LINK_ERROR) || (iRes != ERROR_SUCCESS) || (pLink->fStage != UP)) {
        unsigned short cid_disconnect = 0;

        if (pLink) {
            if ((iRes == ERROR_SUCCESS) && (pLink->fStage != UP))
                iRes = ERROR_INTERNAL_ERROR;

            cid_disconnect = pLink->cid;
        } else
            iRes = ERROR_INTERNAL_ERROR;

        gpState->Unlock ();

        if (cid_disconnect)
            HIDCloseCID_Int (cid_disconnect);

        return iRes;
    }

    *pusCid = pLink->cid;

    gpState->Unlock ();
    return ERROR_SUCCESS;
}

static int HIDCloseCID_Int (unsigned short usCID) {
    if (! gpState)
        return ERROR_SERVICE_NOT_ACTIVE;

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

        return ERROR_SERVICE_NOT_ACTIVE;
    }

    Link *pLink = FindLink (usCID);
    if (! pLink) {
        gpState->Unlock ();

        return ERROR_NOT_FOUND;
    }

    unsigned short cid = pLink->cid;
    DeleteLink (pLink);
    HANDLE hL2CAP = gpState->hL2CAP;
    L2CA_Disconnect_In pCallback = gpState->l2cap_if.l2ca_Disconnect_In;

    gpState->Unlock ();

    __try {
        pCallback (hL2CAP, NULL, cid);
    } __except (1) {
    }

    return ERROR_SUCCESS;
}

//
//    Hid parser interface
//
//
//    Parser interface
//
int HidDevice::SetIdle(unsigned char bIdle) {
    // Initialize the packets
    BTHHIDPacket requestPacket;
    requestPacket.SetHeader(BTHID_SET_IDLE << 4);
    requestPacket.SetPayload(&bIdle, sizeof(bIdle));

    return WritePacket (this, &requestPacket, BTH_WIRE_TIMEOUT, NULL, BTH_PSM_CONTROL);
}

int HidDevice::GetIdle(unsigned char* pbIdle) {
    BTHHIDPacket requestPacket;
    requestPacket.SetHeader(BTHID_GET_IDLE << 4);

    BTHHIDPacket *pPacket = NULL;
    int iErr = WritePacket (this, &requestPacket, BTH_WIRE_TIMEOUT, &pPacket, BTH_PSM_CONTROL);

    if (iErr == ERROR_SUCCESS) {
        // Check if the request succeeded
        BYTE bHeader = pPacket->GetHeader();
        if ((bHeader >> 4) == BTHID_DATA) {
            // Request succeeded, get the payload to the caller
            BYTE *pPacketPayload;
            int   cbPacketPayload;

            pPacket->GetPayload(&pPacketPayload, &cbPacketPayload);
            if (cbPacketPayload == 1) {
                *pbIdle = *pPacketPayload;
            } else
                iErr = ERROR_INVALID_DATA;
        } else
            iErr = ERROR_INVALID_DATA;

        pPacket->ReleasePayload ();
        delete pPacket;
    }

    return iErr;
}

int HidDevice::SetProtocol(E_BTHID_PROTOCOLS protocol) {
    // Initialize the packets
    BTHHIDPacket requestPacket;
    BTHID_Header_Parameter param;

    // Initialize the packets
    param.bRawHeader = 0;
    param.setprotocol_p.bProtocol = protocol;
    requestPacket.SetHeader((BTHID_SET_PROTOCOL << 4) | param.bRawHeader);

    return WritePacket (this, &requestPacket, BTH_WIRE_TIMEOUT, NULL, BTH_PSM_CONTROL);
}

int HidDevice::SetReport(E_BTHID_REPORT_TYPES type, PCHAR pBuffer, int cbBuffer, int iTimeout) {
    // Initialize the packets
    BTHHIDPacket requestPacket;
    BTHID_Header_Parameter SetReport_param;

    // Initialize the packets
    SetReport_param.bRawHeader = 0;
    SetReport_param.setreport_p.bReportType = type;

    // Start by sending BTHIDSetReport_Request down the pipe.
    requestPacket.SetHeader((BTHID_SET_REPORT << 4) | SetReport_param.bR

⌨️ 快捷键说明

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