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

📄 bthid.cxx

📁 WinCE5.0部分核心源码
💻 CXX
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/**
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.


Abstract:
    Windows CE Bluetooth stack layer sample

**/

#include <windows.h>

#include <svsutil.hxx>

#include <bt_debug.h>
#include <bt_os.h>
#include <bt_buffer.h>
#include <bt_ddi.h>
#include <bt_api.h>

#if defined (UNDER_CE)
#include <pkfuncs.h>
#endif

#include <bt_tdbg.h>

#include <hid.h>

#include "bthidpriv.h"
#include "hidpkt.h"
#include "hidsdp.h"
#include "bthid.h"
#include "hidconf.h"

#define DEBUG_LAYER_TRACE           0x00000040

DECLARE_DEBUG_VARS();

#define BTH_PSM_CONTROL             0x11
#define BTH_PSM_INTERRUPT           0x13
#define BTH_MTU_MIN                 48
#define BTH_MTU_MAX                 672

#define BTH_MAX_FRAGMENTS           256

#define BTH_PARSER_TIMEOUT          3600000
#define BTH_CONNECTION_TIMEOUT      120000
#define BTH_WIRE_TIMEOUT            5000

#define CALL_L2CAP_LINK_SETUP       0x11

#define NONE                        0x00
#define CONNECTED                   0x01
#define CONFIG_REQ_DONE             0x02
#define CONFIG_IND_DONE             0x04
#define UP                          0x07
#define LINK_ERROR                  0x80

#define HID_RECONNECT_INTERVAL      20000


#ifdef DEBUG

// Need this for hidmdd module
DBGPARAM dpCurSettings = {
    _T("BTHHID"), 
    {
        _T("Errors"), _T("Warnings"), _T("Init"), _T("Function"),
        _T("HID Data"), _T("Comments"), _T(""), _T(""),
        _T("Parsing"), _T(""), _T(""), _T(""),
        _T(""), _T(""), _T(""), _T("BTH Client") 
    },
    0x3 
};

#endif


struct Link {
    Link            *pNext;
    BD_ADDR         b;
    unsigned short  psm;
    unsigned short  cid;

    unsigned int    fStage;

    unsigned int    fIncoming : 1;

    unsigned short  mtu;
};

struct SCall {
    SCall           *pNext;
    Link            *pLink;

    HANDLE          hEvent;

    int             iResult;

    unsigned short  psm;

    unsigned int    fWhat            : 8;
    unsigned int    fComplete        : 1;
    unsigned int    fAutoClean       : 1;

    unsigned char   l2cap_id;

    BD_BUFFER       *pBuffer;
};

struct HidDevice : public IBTHHIDReportHandler {
    HidDevice        *pNext;
    BD_ADDR          b;

    union {
        struct {
            // BTH
            unsigned int    fEncrypt : 1;
            unsigned int    fAuthenticate : 1;
            unsigned int    fHaveControl : 1;
            unsigned int    fHaveInterrupt : 1;

            // HID
            unsigned int    fReconnectInitiate : 1;
            unsigned int    fNormallyConnectable : 1;
            unsigned int    fVirtualCable : 1;

            // Service
            unsigned int    fIncoming : 1;
            unsigned int    fAuthSpinned : 1;
            unsigned int    fTrans : 1;
        };

        unsigned int flags;
    };

    HANDLE          hevtTransFree;
    HANDLE          hevtTrans;
    int             cTransWait;
    BTHHIDPacket    *pktTransResp;

    BTHHIDPacket    *pktControl;
    BTHHIDPacket    *pktInterrupt;

    SVSCookie       ckDeviceTimeout;
    SVSCookie       ckConnectionTimeout;

    PVOID           pvNotifyParameter;
    BLOB            blobReportDescriptor;

    HidDevice (BD_ADDR *pba) {
        pNext = 0;
        b = *pba;

        flags = 0;

        hevtTrans = CreateEvent (NULL, FALSE, FALSE, NULL);
        hevtTransFree = CreateEvent (NULL, TRUE, FALSE, NULL);

        cTransWait = 0;
        pktTransResp = pktControl = pktInterrupt = NULL;
        ckDeviceTimeout = 0;
        ckConnectionTimeout = 0;
        pvNotifyParameter = NULL;
        
        memset(&blobReportDescriptor, 0, sizeof(BLOB));
    }

    ~HidDevice (void) {
        SetEvent (hevtTransFree);
        CloseHandle (hevtTransFree);
        SetEvent (hevtTrans);
        CloseHandle (hevtTrans);

        if (pvNotifyParameter)
            HidMdd_Notifications(HID_MDD_CLOSE_DEVICE, 0, pvNotifyParameter);

        if (pktTransResp) {
            pktTransResp->ReleasePayload ();
            delete pktTransResp;
        }

        if (pktControl) {
            pktControl->ReleasePayload ();
            delete pktControl;
        }

        if (pktInterrupt) {
            pktInterrupt->ReleasePayload ();
            delete pktInterrupt;
        }

        if (blobReportDescriptor.pBlobData)
            g_funcFree (blobReportDescriptor.pBlobData, g_pvFreeData);
    }

    void *operator new (size_t iSize);
    void operator delete(void *ptr);

    int FillPersistentParameters (int fIncoming);

    // IBTHHIDReportHandler overrides
    int  SetIdle(unsigned char bIdle);
    int  GetIdle(unsigned char* pbIdle);
    int  SetProtocol(E_BTHID_PROTOCOLS protocol);
    int  GetReport(int iReportID, E_BTHID_REPORT_TYPES type, PCHAR pBuffer, int cbBuffer, PDWORD pcbTransfered, int iTimeout);
    int  SetReport(E_BTHID_REPORT_TYPES type, PCHAR pBuffer, int cbBuffer, int iTimeout);
};

int hiddev_CloseDriverInstance (void);

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);
static int hiddev_ConnectInd (void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm);
static int hiddev_DataUpInd (void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer);
static int hiddev_DisconnectInd (void *pUserContext, unsigned short cid, int iError);
static int hiddev_lStackEvent (void *pUserContext, int iEvent, void *pEventContext);

static int hiddev_lCallAborted (void *pCallContext, int iError);
static int hiddev_ConfigReq_Out (void *pCallContext, unsigned short usResult, unsigned short usInMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **pExtendedOptions);
static int hiddev_ConfigResponse_Out (void *pCallContext, unsigned short result);
static int hiddev_ConnectReq_Out (void *pCallContext, unsigned short cid, unsigned short result, unsigned short status);
static int hiddev_ConnectResponse_Out (void *pCallContext, unsigned short result);
static int hiddev_DataDown_Out (void *pCallContext, unsigned short result);
static int hiddev_Ping_Out (void *pCallContext, BD_ADDR *pba, unsigned char *pOutBuffer, unsigned short size);
static int hiddev_Disconnect_Out (void *pCallContext, unsigned short result);

#if defined (BTHHID_QUEUE)
static DWORD WINAPI HidReportHandler (LPVOID lpNull);
#endif

static int WritePacket (void *lpHidDevice, BTHHIDPacket *pSource, int iTimeout, BTHHIDPacket **ppRes, int iChannel);
static int HIDConnect_Int(BD_ADDR *pba, unsigned short usPSM, unsigned short *pusCid);
static int HIDCloseCID_Int (unsigned short usCID);

class HIDDEV : public SVSSynch, public SVSRefObj {
public:
    Link            *pLinks;
    SCall           *pCalls;
    HidDevice       *pHIDs;

    unsigned int    fIsRunning : 1;
    unsigned int    fConnected : 1;

    HANDLE          hL2CAP;
    L2CAP_INTERFACE l2cap_if;

    int             cHeaders;
    int             cTrailers;

    FixedMemDescr   *pfmdLinks;
    FixedMemDescr   *pfmdCalls;
    FixedMemDescr   *pfmdHIDs;

#if defined (BTHHID_QUEUE)
    HANDLE          hthReports;
    SVSQueue        qHidReports;
    HANDLE          hevtReports;
#endif

    HANDLE          hthReconnect;
    HANDLE          hReconnectEvent;
    
    SVSThreadPool   *pSchedule;

    HIDDEV (void) {
        IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: new HIDDEV\n"));
        pLinks = NULL;
        pCalls = NULL;
        pHIDs  = NULL;

        cHeaders = 0;
        cTrailers = 0;

        fIsRunning = FALSE;
        fConnected = FALSE;

        hL2CAP = NULL;

        memset (&l2cap_if, 0, sizeof(l2cap_if));

        pfmdLinks = pfmdCalls = pfmdHIDs = NULL;
        pSchedule = NULL;

        if (! (hReconnectEvent = CreateEvent (NULL, FALSE, FALSE, NULL)))
            return;

#if defined (BTHHID_QUEUE)
        hthReports  = NULL;
        hevtReports = NULL;

        if (! qHidReports.IsQueueInitialized())
            return;

        if (! (hevtReports = CreateEvent (NULL, FALSE, FALSE, NULL)))
            return;
#endif

        if (! (pSchedule = new SVSThreadPool))
            return;

        if (! (pfmdLinks = svsutil_AllocFixedMemDescr (sizeof(Link), 10)))
            return;

        if (! (pfmdHIDs = svsutil_AllocFixedMemDescr (sizeof(HidDevice), 10)))
            return;

        if (! (pfmdCalls = svsutil_AllocFixedMemDescr (sizeof(SCall), 10)))
            return;

        L2CAP_EVENT_INDICATION lei;
        memset (&lei, 0, sizeof(lei));

        lei.l2ca_ConfigInd = hiddev_ConfigInd;
        lei.l2ca_ConnectInd = hiddev_ConnectInd;
        lei.l2ca_DataUpInd = hiddev_DataUpInd;
        lei.l2ca_DisconnectInd = hiddev_DisconnectInd;
        lei.l2ca_StackEvent = hiddev_lStackEvent;

        L2CAP_CALLBACKS lc;
        memset (&lc, 0, sizeof(lc));

        lc.l2ca_CallAborted = hiddev_lCallAborted;
        lc.l2ca_ConfigReq_Out = hiddev_ConfigReq_Out;
        lc.l2ca_ConfigResponse_Out = hiddev_ConfigResponse_Out;
        lc.l2ca_ConnectReq_Out = hiddev_ConnectReq_Out;
        lc.l2ca_ConnectResponse_Out = hiddev_ConnectResponse_Out;
        lc.l2ca_DataDown_Out = hiddev_DataDown_Out;
        lc.l2ca_Ping_Out = hiddev_Ping_Out;
        lc.l2ca_Disconnect_Out = hiddev_Disconnect_Out;

        if (ERROR_SUCCESS != L2CAP_EstablishDeviceContext (this, L2CAP_PSM_MULTIPLE, &lei, &lc, &l2cap_if, &cHeaders, &cTrailers, &hL2CAP))
            return;

        int iRes = ERROR_SUCCESS;

        __try {
            int iRet = 0;
            unsigned short usPSMin = BTH_PSM_CONTROL;

            iRes = l2cap_if.l2ca_ioctl (hL2CAP, BTH_STACK_IOCTL_RESERVE_PORT, sizeof(usPSMin), (char *)&usPSMin, 0, NULL, &iRet);
            if (iRes == ERROR_SUCCESS) {
                usPSMin = BTH_PSM_INTERRUPT;
                iRes = l2cap_if.l2ca_ioctl (hL2CAP, BTH_STACK_IOCTL_RESERVE_PORT, sizeof(usPSMin), (char *)&usPSMin, 0, NULL, &iRet);
            }
        } __except (1) {
            iRes = ERROR_EXCEPTION_IN_SERVICE;
        }


        if (iRes == ERROR_SUCCESS)
            fIsRunning = TRUE;

        IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: new HIDDEV successful\n"));
    }

    ~HIDDEV (void) {
        IFDBG(DebugOut (DEBUG_LAYER_TRACE, L"BTH HID: delete HIDDEV\n"));

        fIsRunning = FALSE;
        fConnected = FALSE;

#if defined (BTHHID_QUEUE)
        if (hevtReports) {
            HANDLE h = hevtReports;
            hevtReports = NULL;

            SetEvent (h);
            CloseHandle (h);
        }

        if (hthReports) {
            if (WAIT_OBJECT_0 != WaitForSingleObject (hthReports, 15000))
                TerminateThread (hthReports, 0);

            CloseHandle (hthReports);
        }
#endif

        CloseHandle (hReconnectEvent);

        if (pSchedule)
            delete pSchedule;

        if (hL2CAP)
            L2CAP_CloseDeviceContext (hL2CAP);

        if (pfmdHIDs)
            svsutil_ReleaseFixedNonEmpty (pfmdHIDs);

        if (pfmdLinks)
            svsutil_ReleaseFixedNonEmpty (pfmdLinks);

        if (pfmdCalls)
            svsutil_ReleaseFixedNonEmpty (pfmdCalls);
    }
};


static HIDDEV *gpState = NULL;
static BYTE gbUnplugHeader = 0;

//
//    Auxiliary code
//
void *HidDevice::operator new (size_t iSize) {
    SVSUTIL_ASSERT (iSize == sizeof(HidDevice));

    void *pRes = svsutil_GetFixed (gpState->pfmdHIDs);

    return pRes;
}

void HidDevice::operator delete(void *ptr) {
    svsutil_FreeFixed (ptr, gpState->pfmdHIDs);
}

static HIDDEV *CreateNewState (void) {
    return new HIDDEV;
}

static SCall *AllocCall (int fWhat, Link *pLink) {
    SCall *pCall = (SCall *)svsutil_GetFixed (gpState->pfmdCalls);
    if (! pCall)
        return NULL;

    memset (pCall, 0, sizeof(*pCall));

    pCall->pLink = pLink;
    pCall->fWhat = fWhat;
    
    pCall->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    if (NULL == pCall->hEvent) {
        svsutil_FreeFixed (pCall, gpState->pfmdCalls);
        return NULL;
    }        

    if (! gpState->pCalls)

⌨️ 快捷键说明

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