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

📄 hidmdd.cpp

📁 嵌入式操作系统WINCE5.0下的USB驱动程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        // Set idle rate
        DEBUGCHK(pHidContext->hidpDeviceDesc.ReportIDs != NULL);
        
        for (dwIdx = 0; dwIdx < pHidContext->hidpDeviceDesc.ReportIDsLength; ++dwIdx) {
            PHIDP_REPORT_IDS phidpReport = &pHidContext->hidpDeviceDesc.ReportIDs[dwIdx];
            
            if (phidpReport->CollectionNumber == dwCollection) {
                // This report falls under this collection.
                DEBUGMSG(ZONE_COMMENT, (_T("%s: Setting report %u to idle rate of %u\r\n"),
                    pszFname, phidpReport->ReportID, dwDuration));
                dwErr = HidPdd_SetIdle(pHidContext->hPddDevice,
                    dwDuration, phidpReport->ReportID);
            
                if (dwErr != ERROR_SUCCESS) {
                    DEBUGMSG(ZONE_WARNING, 
                        (_T("%s: Unable to set idle rate for device\r\n"),
                        pszFname));
                }
            }
        }
    }
}


// Load a HID client for each top level collection, if possible.
// Returns FALSE if there was a major error. Returns TRUE even
// if certain TLC's do not have clients. This is not an error
// because internal processing will still be performed on unhandled
// reports (like power events).
static
BOOL
LoadHidClients(
    PHID_CONTEXT pHidContext,
    DWORD dwVendorId,
    DWORD dwProductId,
    DWORD dwReleaseNumber,
    DWORD dwInterface
    )
{
    SETFNAME(_T("LoadHidClients"));

    BOOL fRet = FALSE;
    DWORD cCollections;
    DWORD dwIdx;
    DWORD dwType;
    LONG iErr;
    HID_DRIVER_SETTINGS driverSettings;
    
    PREFAST_DEBUGCHK(pHidContext != NULL);
    ValidateHidContext(pHidContext);

    // Initially set all reports on the interface to infinite idle
    DEBUGMSG(ZONE_COMMENT, (_T("%s: Setting all reports to infinite idle\r\n"),
        pszFname));
    HidPdd_SetIdle(pHidContext->hPddDevice, 0, 0);

    cCollections = pHidContext->hidpDeviceDesc.CollectionDescLength;
    
    driverSettings.dwVendorId = dwVendorId;
    driverSettings.dwProductId = dwProductId;
    driverSettings.dwReleaseNumber = dwReleaseNumber;
    driverSettings.dwInterfaceNumber = dwInterface;

    for (dwIdx = 0; dwIdx < cCollections; ++dwIdx)
    {
        PHIDP_COLLECTION_DESC pCollection = &pHidContext->hidpDeviceDesc.CollectionDesc[dwIdx];
        PHID_CLIENT_HANDLE pClientHandle = &pHidContext->pClientHandles[dwIdx];
        TCHAR szBuf[MAX_PATH];
        DWORD cchBuf = dim(szBuf);
        HKEY hKey;
        HKEY hSubKey = NULL;
        HINSTANCE hInst = NULL;
        LPHID_CLIENT_ATTACH pfnAttach;
        BOOL fSuccess = FALSE;

        DEBUGCHK(pClientHandle->hInst == NULL);
        DEBUGCHK(pClientHandle->pQueue != NULL);

        driverSettings.dwCollection = pCollection->CollectionNumber;
        driverSettings.dwUsagePage = pCollection->UsagePage;
        driverSettings.dwUsage = pCollection->Usage;

        hKey = FindClientRegKey(&driverSettings, &pClientHandle->driverSettings);

        if (hKey == NULL) {
            // No match for top level collection. Just continue.
            goto CONTINUE;
        }
        
        iErr = RegEnumKeyEx(hKey, 0, szBuf, &cchBuf, NULL, NULL, NULL, NULL);
        if (iErr != ERROR_SUCCESS) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Could not enumerate subkey of LoadClient key. Error %i\r\n"),
                pszFname, iErr));
            goto CONTINUE;
        }

        iErr = RegOpenKey(hKey, szBuf, &hSubKey);
        if (iErr != ERROR_SUCCESS) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Could not open subkey \"%s\"of LoadClient key. Error %i\r\n"),
                pszFname, szBuf, iErr));
            goto CONTINUE;
        }

        // ** At this point we have our client key **

        // Set various device features.
        SetRemoteWakeup(pHidContext, hSubKey);
        SetIdleRate(pHidContext, hSubKey, pCollection->CollectionNumber);

        cchBuf = dim(szBuf);
        iErr = RegQueryValueEx(hSubKey, DLL_VALUE_SZ, NULL, &dwType, 
            (PBYTE) szBuf, &cchBuf);
        if (iErr != ERROR_SUCCESS || dwType != REG_SZ) {
            DEBUGMSG(ZONE_ERROR, (_T("s: Could not get %s value in LoadClient key.\r\n"),
                pszFname, DLL_VALUE_SZ));
            goto CONTINUE;
        }
        szBuf[dim(szBuf) - 1] = 0; // Force NULL-termination.

        hInst = LoadDriver(szBuf);
        if (hInst == NULL) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Could not load client DLL %s\r\n"), 
                pszFname, szBuf));
            goto CONTINUE;
        }
        
        pfnAttach = (LPHID_CLIENT_ATTACH) GetProcAddress(hInst, SZ_HID_CLIENT_ATTACH);
        if (pfnAttach == NULL) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Could not get the address of %s from %s\r\n"),
                pszFname, SZ_HID_CLIENT_ATTACH, szBuf));
            goto CONTINUE;
        }

        __try {
            fSuccess = (*pfnAttach)(
                (HID_HANDLE) pClientHandle,
                &g_HidFuncs, 
                &pClientHandle->driverSettings,
                pCollection->PreparsedData,
                &pClientHandle->lpvNotifyParameter,
                0);
        }
        __except(EXCEPTION_EXECUTE_HANDLER) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Exception in attach procedure %s in %s\r\n"),
                pszFname, SZ_HID_CLIENT_ATTACH, szBuf));
        }

        if (fSuccess != TRUE) {
            DEBUGMSG(ZONE_INIT, (_T("%s: Failure in attach procedure %s in %s\r\n"),
                pszFname, SZ_HID_CLIENT_ATTACH, szBuf));
            goto CONTINUE;
        }

        // Turn on this client's queue.
        pClientHandle->pQueue->AcceptNewReports(TRUE);

        // Finally this client has been initialized. Save our hInst.
        pClientHandle->hInst = hInst;
        
CONTINUE:
        if (hKey != NULL) RegCloseKey(hKey);
        if (hSubKey != NULL) RegCloseKey(hSubKey);
        if (pClientHandle->hInst == NULL) {
            // We did not successfully initialize the client.
            if (hInst != NULL) FreeLibrary(hInst);
            
            DEBUGMSG(ZONE_COMMENT, (_T("%s: No client found for HID top level collection 0x%X-0x%X on interface 0x%X\r\n"),
                pszFname, pCollection->UsagePage, pCollection->Usage, 
                dwInterface));
        }
    }

    fRet = TRUE;

    return fRet;
}


// We have data structures for each top level collection. This initializes them.
static
BOOL
InitializeTLCStructures(
    PHID_CONTEXT pHidContext
    )
{
    SETFNAME(_T("InitializeTLCStructures"));

    BOOL fRet = FALSE;
    DWORD cCollections;
    DWORD dwIdx;
    
    PREFAST_DEBUGCHK(pHidContext != NULL);
    
    // Allocate our HID queues. One for each top level collection.
    cCollections = pHidContext->hidpDeviceDesc.CollectionDescLength;
    pHidContext->pQueues = new HidTLCQueue[cCollections];
    
    if (pHidContext->pQueues == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Memory allocation error\r\n"), pszFname));
        goto EXIT;
    }

    // Allocate our HID client handles. One for each TLC.
    pHidContext->pClientHandles = (PHID_CLIENT_HANDLE) 
        HidAlloc(sizeof(HID_CLIENT_HANDLE) * cCollections);
    if (pHidContext->pClientHandles == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
        goto EXIT;
    }

    // Initialize our HID queues and client handles.
    for (dwIdx = 0; dwIdx < cCollections; ++dwIdx) 
    {        
        BOOL fSucceeded;
        PHIDP_COLLECTION_DESC phidpCollection = 
            &pHidContext->hidpDeviceDesc.CollectionDesc[dwIdx];
        PHID_CLIENT_HANDLE pClientHandle = &pHidContext->pClientHandles[dwIdx];
        
        fSucceeded = pHidContext->pQueues[dwIdx].Initialize(
            HID_TLC_QUEUE_DEFAULT_CAPACITY, 
            phidpCollection->InputLength);

        if (fSucceeded == FALSE) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Failed initializing queue\r\n"), pszFname));
            goto EXIT;
        }

        pClientHandle->Sig = HID_CLIENT_SIG;
        pClientHandle->hInst = NULL;
        pClientHandle->lpvNotifyParameter = NULL;
        pClientHandle->pHidContext = pHidContext;
        pClientHandle->pQueue = &pHidContext->pQueues[dwIdx];
        pClientHandle->phidpPreparsedData = phidpCollection->PreparsedData;
    }

    fRet = TRUE;

EXIT:
    return fRet;
}


// Frees the Hid context for a specific PDD-defined device. Calls any
// client's notification routine and releases the library.
//
// Note that synchronization is unnecessary because the only threads
// that will call into the MDD at this point are the client's. We do
// not free the data structures until the client is completely closed.
// If HID_IOControl ever does anything specific to a Hid context, then
// synchronization will need to be added.
static
void
FreeHidContext(
    PHID_CONTEXT pHidContext
    )
{
    SETFNAME(_T("FreeHidContext"));
    
    DWORD cCollections = 0;
    DWORD dwIdx;
    
    DEBUGCHK(pHidContext != NULL);

    if (VALID_HID_CONTEXT(pHidContext)) {
        cCollections = pHidContext->hidpDeviceDesc.CollectionDescLength;

        if (pHidContext->pQueues != NULL)
        {
            // Tell each queue that it is closing.
            for (dwIdx = 0; dwIdx < cCollections; ++dwIdx) 
            {
                HidTLCQueue *pQueue = &pHidContext->pQueues[dwIdx];
                if (pQueue->IsInitialized() == TRUE) {
                    pQueue->Close();
                }
            }
        }

        if (pHidContext->pClientHandles != NULL) {
            // Notify each client that its device has been removed.
            for (dwIdx = 0; dwIdx < cCollections; ++dwIdx) {
                PHID_CLIENT_HANDLE pHidClient = &pHidContext->pClientHandles[dwIdx];
                if (pHidClient->hInst != NULL) {
                    LPHID_CLIENT_NOTIFICATIONS lpNotifications;

                    lpNotifications = (LPHID_CLIENT_NOTIFICATIONS) 
                        GetProcAddress(pHidClient->hInst, SZ_HID_CLIENT_NOTIFICATIONS);

                    if (lpNotifications == NULL) {
                        DEBUGMSG(ZONE_ERROR, (_T("%s: Could not get client address of %s\r\n"),
                            pszFname, SZ_HID_CLIENT_NOTIFICATIONS));
                    }
                    else 
                    {
                        __try {
                            (*lpNotifications)(HID_CLOSE_DEVICE, 0, 
                                pHidClient->lpvNotifyParameter);
                        } 
                        __except(EXCEPTION_EXECUTE_HANDLER) {
                              DEBUGMSG(ZONE_ERROR,(_T("%s: Exception in notification proc\r\n"), 
                                pszFname));
                        }
                    }

    				FreeLibrary(pHidClient->hInst);
                }
            }

            HidFree(pHidContext->pClientHandles);
        }

        if (pHidContext->pQueues != NULL) delete [] pHidContext->pQueues;
        
        HidP_FreeCollectionDescription(&pHidContext->hidpDeviceDesc);

        HidFree(pHidContext);
    }    
    else {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Invalid Parameter\r\n"), pszFname));
        DEBUGCHK(FALSE);
    }
}


// Determine the length of the longest input report.
static
BOOL
DetermineMaxInputReportLength(
    PHIDP_DEVICE_DESC phidpDeviceDesc,
    PDWORD pcbMaxReport
    )
{
    PREFAST_DEBUGCHK(phidpDeviceDesc);
    PREFAST_DEBUGCHK(pcbMaxReport);

    *pcbMaxReport = 0;
    
    for (DWORD dwReport = 0; dwReport < phidpDeviceDesc->ReportIDsLength; ++dwReport) {
        PHIDP_REPORT_IDS phidpReportIds = &phidpDeviceDesc->ReportIDs[dwReport];
        *pcbMaxReport = max(*pcbMaxReport, phidpReportIds->InputLength);
    }

    return TRUE;
}


// Called with that report descriptor and ID structure of a newly-connected
// device.
BOOL
WINAPI
HidMdd_Attach(
    HID_PDD_HANDLE           hPddDevice,
    PHIDP_REPORT_DESCRIPTOR  pbReportDescriptor,
    DWORD                    cbReportDescriptor,
    DWORD                    dwVendorId,
    DWORD                    dwProductId,
    DWORD                    dwReleaseNumber,
    DWORD                    dwInterface,
    PVOID                   *ppvNotifyParameter,
    PDWORD                   pcbMaxInputReport
    )
{
    SETFNAME(_T("HidMdd_Attach"));

    BOOL fRet = FALSE;
    PHID_CONTEXT pHidContext = NULL;
    NTSTATUS status;
    
    DEBUGMSG(ZONE_INIT, (_T("+%s"), pszFname));
    
    DEBUGCHK(pbReportDescriptor != NULL);
    PREFAST_DEBUGCHK(ppvNotifyParameter != NULL);
    PREFAST_DEBUGCHK(pcbMaxInputReport);

    DumpHIDReportDescriptor(pbReportDescriptor, cbReportDescriptor);
    
    pHidContext = (PHID_CONTEXT) HidAlloc(sizeof(HID_CONTEXT));
    if (pHidContext == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname, 
            GetLastError()));
        goto EXIT;
    }
    ZeroMemory(pHidContext, sizeof(HID_CONTEXT));
    
    pHidContext->Sig = HID_SIG;
    pHidContext->hPddDevice = hPddDevice;

    // Now that we've allocated space for it, let's parse the report descriptor.
    status = HidP_GetCollectionDescription(
       pbReportDescriptor,
       cbReportDescriptor,
       0,
       &pHidContext->hidpDeviceDesc
       );

    if (NT_SUCCESS(status) == FALSE) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Problem parsing report descriptor Error: 0x%x\r\n"),
            pszFname, status));
        goto EXIT;
    }
    
    DumpHIDDeviceDescription(&pHidContext->hidpDeviceDesc);

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

    // Determine how long the longest input report may be.
    if ( DetermineMaxInputReportLength(&pHidContext->hidpDeviceDesc,
            pcbMaxInputReport) == FALSE ) {
        goto EXIT;
    }

    if (LoadHidClients(pHidContext, dwVendorId, dwProductId, 
            dwReleaseNumber, dwInterface) == FALSE) {
        goto EXIT;
    }

    *ppvNotifyParameter = (PVOID) pHidContext;

    DumpDeviceStrings(pHidContext);
    
    fRet = TRUE;
    
EXIT:
    if (fRet == FALSE) {
        if (pHidContext != NULL) {
            FreeHidContext(pHidContext);
        }
        
        *ppvNotifyParameter = NULL;
    }

    DEBUGMSG(ZONE_INIT, (_T("-%s"), pszFname));

    return fRet;

⌨️ 快捷键说明

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