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

📄 hidparser.cxx

📁 wince4.2 bluetooth sdk
💻 CXX
📖 第 1 页 / 共 3 页
字号:
//
// 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.
//
#include <windows.h>
#include <pkfuncs.h>
#include <hidpddi.h>

#include "../base/bthidpar.h"
#include "usbhid.h"

#ifdef DEBUG

DBGPARAM dpCurSettings = {
        TEXT("BTHHID"), {
        TEXT("Errors"), TEXT("Warnings"), TEXT("Init"), TEXT("Function"),
        TEXT("HID Data"), TEXT(""), TEXT(""), TEXT(""),
        TEXT("USB Parse"), TEXT(""), TEXT(""), TEXT(""),
        TEXT(""), TEXT(""), TEXT(""), TEXT("USB Client") },
        ZONE_ERROR | ZONE_WARNING };

#endif // DEBUG


// {E5504F26-FEFA-4019-9730-79C6431B5500}
const IID IID_IBTHHIDParser = {0xe5504f26,0xfefa,0x4019,{0x97,0x30,0x79,0xc6,0x43,0x1b,0x55,0x0}};

class IBTHHIDReportHandler;
class BTHHIDPacket;

class BTHHIDParser : public IBTHHIDParser
{
public:
    BTHHIDParser(IBTHHIDReportHandler* pReportHandler);
    ~BTHHIDParser();

    // IUnknown overrides
    STDMETHOD_(ULONG, AddRef());
    STDMETHOD_(ULONG, Release());
    STDMETHOD(QueryInterface(REFIID riid, void** ppvObject));

    // IBTHHIDParser overrides
    BOOL IsInitialized();
    int SetReportDescriptor(unsigned char* pReportDescriptor, int cDescriptor);
    int ProcessInterruptReport(BYTE* pReport, int cReport);
    IBTHHIDReportHandler* GetHandler();

    // Debug functions
    void ValidateHidContextEx();
    static void ValidateClientHandleEx(PHID_CLIENT_HANDLE pHidClient);

private:
    int  ForceReportProtocol();
    int  SetIdle();

    // Internal initialisation functions
    int  Initialize(unsigned char* pReportDescriptor, int cDescriptor);
    void Deinitialize();
    BOOL InitializeTLCStructures();
    BOOL LoadHidClients();
    
    // Synchronisation helpers
    void LockHidContextEx();
    void ReleaseHidContextEx();

    // Various helpers
    static PHIDP_REPORT_IDS        GetReportDesc(PHIDP_DEVICE_DESC phidpDeviceDesc,DWORD dwReportID);
    static PHIDP_COLLECTION_DESC   GetCollectionDesc(PHIDP_DEVICE_DESC phidpDeviceDesc,DWORD dwCollectionNumber,PDWORD pdwCollectionIndex);
    static void PerformPowerEvents(PHIDP_COLLECTION_DESC phidpCollection, BYTE *pbHidPacket, DWORD cbHidPacket);

    // Registry utils
    static HKEY OpenSpecificClientRegKey(HKEY hKeyRoot, const DWORD *pdwVals, DWORD cdwVals);
    static HKEY OpenClientRegKey(
                HKEY hKeyRoot,
                const DWORD *pdwVendorVals, 
                DWORD cdwVendorVals,
        const DWORD *pdwInterfaceVals,
        DWORD cdwInterfaceVals,
                const DWORD *pdwTLCVals,
                DWORD cdwTLCVals,
                PHID_DRIVER_SETTINGS pDriverSettingsUsed);
    static HKEY FindClientRegKey(const HID_DRIVER_SETTINGS *pDriverSettings, PHID_DRIVER_SETTINGS pDriverSettingsUsed);

    // Private data
    BOOL                    m_fIsInitialized;
    IBTHHIDReportHandler*   m_pReportHandler;
    USBHID_CONTEXT          m_UsbHid;     // Holds information for one HID interface
    int                     m_cRef;       // Uses refcounting to for IUnknown (per instance) 
    static int              m_scRef;      // Uses refcounting to activate/deactivate m_hOSDevice (global)
    static HANDLE           m_hOSDevice;  // The HID class device (HID0:)
};

// Public HID functions for clients
DWORD GetReport(HID_HANDLE hDevice, HIDP_REPORT_TYPE type, PCHAR pBuffer, DWORD cbBuffer, PDWORD pcbTransferred, DWORD dwTimeout);
DWORD SetReport(HID_HANDLE hDevice, HIDP_REPORT_TYPE type, PCHAR pBuffer, DWORD cbBuffer, DWORD dwTimeout);
DWORD GetInterruptReport(HID_HANDLE hDevice, PCHAR pbBuffer, DWORD cbBuffer, PDWORD pcbTransferred, HANDLE hCancel, DWORD dwTimeout);

#define HID_CLOSE_DEVICE 1

int      BTHHIDParser::m_scRef           = 0;
HANDLE   BTHHIDParser::m_hOSDevice       = NULL;  // The HID class device (HID0:)

// List of HID functions. Passed to HID clients.
static const HID_FUNCS g_HidFuncs =
{
    sizeof(HID_FUNCS), // DWORD dwCount;

    &GetReport,
    &SetReport,
    &GetInterruptReport,
};

BTHHIDParser::BTHHIDParser(IBTHHIDReportHandler* pReportHandler) :
    m_pReportHandler(pReportHandler),
    m_fIsInitialized(FALSE),
    m_cRef(1)
{
    ZeroMemory((void*) &m_UsbHid, sizeof(m_UsbHid));
    ULONG cRef = InterlockedIncrement((LPLONG)&m_scRef);
//    if (cRef == 1)
//    {
//        m_hOSDevice = ActivateDevice(CLIENT_REGKEY_SZ, 0);
//        if (m_hOSDevice == NULL) 
//            DEBUGMSG(ZONE_ERROR, (_T("Error on ActivateDevice(%s)\r\n"), CLIENT_REGKEY_SZ));
//    }
}

BTHHIDParser::~BTHHIDParser()
{
    if (m_fIsInitialized)
        Deinitialize();

    ULONG cRef = InterlockedDecrement((LPLONG)&m_scRef);
//    if (cRef == 0)
//    {
//        BOOL fSucceeded = DeactivateDevice(m_hOSDevice);
//        if (!fSucceeded)
//            DEBUGMSG(ZONE_ERROR, (_T("Error on DeactivateDevice\r\n")));
//    }
}

ULONG BTHHIDParser::AddRef()
{
    return InterlockedIncrement((LPLONG)&m_cRef);
}

ULONG BTHHIDParser::Release()
{
    ULONG cRef = InterlockedDecrement((LPLONG)&m_cRef);
    if(cRef == 0)
        delete this;

    return cRef;
}

HRESULT BTHHIDParser::QueryInterface(REFIID riid, void** ppvObject)
{
    HRESULT hr = E_NOINTERFACE;

    if (!ppvObject)
        return E_INVALIDARG;
    
    *ppvObject = NULL;
    if ((riid == IID_IUnknown) || (riid == IID_IBTHHIDParser))
    {
        *ppvObject = this;
        ASSERT(*ppvObject);
        AddRef();
        hr = S_OK;
    }

    return hr;
}

int BTHHIDParser::SetReportDescriptor(unsigned char* pReportDescriptor, int cDescriptor)
{
    int iErr = ERROR_INVALID_PARAMETER;

    DEBUGCHK(!IsBadReadPtr(pReportDescriptor, cDescriptor));

    if (m_fIsInitialized)
        Deinitialize();

    iErr = Initialize(pReportDescriptor, cDescriptor);

    return iErr;
}

int BTHHIDParser::ProcessInterruptReport(BYTE* pReport, int cReport)
{
    PHIDP_REPORT_IDS      phidpReport;
    PHIDP_COLLECTION_DESC phidpCollection;
    PHID_CLIENT_HANDLE    pClientHandle;
    DWORD                 dwReportID;
    DWORD                 dwCollectionIndex;
    HidTLCQueue*          pQueue;

    // Must be initialized.
    DEBUGCHK(m_fIsInitialized);

    // We always get a report ID.
    dwReportID = *pReport;

    // $TODO Those reportID are causing the parser problems. Discard for now. This should be fixed SOON by the new parser
    if (dwReportID < 0 || dwReportID > 3)
        return ERROR_INVALID_PARAMETER;

    // Get the report and collection data structures
    phidpReport = GetReportDesc(m_UsbHid.phidpDeviceDesc, dwReportID);
    DEBUGCHK(phidpReport != NULL);

    phidpCollection = GetCollectionDesc(m_UsbHid.phidpDeviceDesc, 
        phidpReport->CollectionNumber, &dwCollectionIndex);
    DEBUGCHK(phidpCollection != NULL);
    DEBUGCHK(dwCollectionIndex < m_UsbHid.phidpDeviceDesc->CollectionDescLength);

    // Perform any power events listed in this report
    PerformPowerEvents(phidpCollection, pReport, cReport);

    // Send this HID packet to the proper client
    pClientHandle = &m_UsbHid.pClientHandles[dwCollectionIndex];

    // Only queue this report if we have a client that will receive it.
    if (pClientHandle->hInst != NULL) 
    {
        pQueue = pClientHandle->pQueue;
        pQueue->Lock();
        if (pQueue->IsAccepting() == TRUE) 
        {
            if (pQueue->IsFull() == FALSE) 
            {
                BOOL fRet;
                fRet = pQueue->Enqueue((PCHAR) pReport, cReport);
                DEBUGCHK(fRet);
            }
            else
                DEBUGMSG(ZONE_ERROR, (_T("Error: Queue is full. Dropping packet.\r\n")));
        }
        else
            DEBUGMSG(ZONE_HID_DATA, (_T("Queue not accepting input. Dropping packet.\r\n")));

        pQueue->Unlock();
    }

    return 0;
}

BOOL BTHHIDParser::IsInitialized()
{
    return m_fIsInitialized;
}

void BTHHIDParser::ValidateHidContextEx()
{
    LockHidContextEx();

    DEBUGCHK(m_UsbHid.Sig == USB_HID_SIG);
    DEBUGCHK(m_UsbHid.hEP0Event != NULL);
    DEBUGCHK(m_UsbHid.phidpDeviceDesc != NULL);
//    DEBUGCHK(LocalSize(m_UsbHid.phidpDeviceDesc) == sizeof(HIDP_DEVICE_DESC));  
    DEBUGCHK(m_UsbHid.pQueues != NULL);
    DEBUGCHK(m_UsbHid.pClientHandles != NULL);

    ReleaseHidContextEx();
}

void BTHHIDParser::ValidateClientHandleEx(PHID_CLIENT_HANDLE pHidClient)
{
    DEBUGCHK(pHidClient != NULL);
    DEBUGCHK(IsBadReadPtr(pHidClient, sizeof(*pHidClient)) == FALSE);
    DEBUGCHK(pHidClient->Sig == USB_HID_CLIENT_SIG);
    DEBUGCHK(pHidClient->pQueue != NULL);
    pHidClient->pQueue->Validate();
    DEBUGCHK(pHidClient->phidpPreparsedData != NULL);
    DEBUGCHK(pHidClient->pUsbHid != NULL);
    BTHHIDParser* pParser = (BTHHIDParser*) pHidClient->lpvContext;
    DEBUGCHK(pParser != NULL);
    pParser->ValidateHidContextEx();
}

int BTHHIDParser::ForceReportProtocol()
{
    return m_pReportHandler->SetProtocol(BTHID_REPORT_PROTOCOL);
}

int BTHHIDParser::SetIdle()
{
    return m_pReportHandler->SetIdle(0);
}

int BTHHIDParser::Initialize(unsigned char* pReportDescriptor, int cDescriptor)
{
    if (m_fIsInitialized)
        return ERROR_ALREADY_INITIALIZED;

    int iErr = -1;
    NTSTATUS status = 0;

    ZeroMemory((void*) &m_UsbHid, sizeof(m_UsbHid));
    InitializeCriticalSection(&m_UsbHid.csLock);

    m_UsbHid.Sig = USB_HID_SIG; // mimic a USB driver from the clients.
    m_UsbHid.Flags.Open = FALSE;
    m_UsbHid.Flags.UnloadPending = FALSE;

    // create endpoint 0 event
    m_UsbHid.hEP0Event = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (m_UsbHid.hEP0Event == NULL) {
        DEBUGMSG(ZONE_ERROR, (TEXT("CreateEvent error:%d\r\n"), GetLastError()));
        goto EXIT;
    }

    // Get the report descriptor for our interface.
    m_UsbHid.phidpDeviceDesc = (PHIDP_DEVICE_DESC) LocalAlloc(LMEM_FIXED, sizeof(HIDP_DEVICE_DESC));
    if (m_UsbHid.phidpDeviceDesc == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("LocalAlloc error:%d\r\n"), GetLastError()));
        goto EXIT;
    }

    ZeroMemory(m_UsbHid.phidpDeviceDesc, sizeof(*m_UsbHid.phidpDeviceDesc));
    status = HidP_GetCollectionDescription(
       pReportDescriptor,
       cDescriptor,
       0,
       m_UsbHid.phidpDeviceDesc
       );

    if (NT_SUCCESS(status) == FALSE) {
        DEBUGMSG(ZONE_ERROR, (_T("Problem parsing report descriptor Error: 0x%x\r\n"),status));
        goto EXIT;
    }

    // Set up our data structres for each top level collection.
    if (InitializeTLCStructures() == FALSE)
        goto EXIT;

    // Load client drivers for our top level collections

⌨️ 快捷键说明

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