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

📄 setup.cpp

📁 hidclass source code for windows ce use
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    DUMP_USB_DEVICE_DESCRIPTOR(pDeviceInfo->Descriptor);
    DUMP_USB_CONFIGURATION_DESCRIPTOR(pDeviceInfo->lpActiveConfig->Descriptor);

    pUsbHid = (PUSBHID_CONTEXT)HidAlloc(sizeof(USBHID_CONTEXT));
    if (pUsbHid == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname,
            GetLastError()));
        goto EXIT;
    }
    ZeroMemory(pUsbHid, sizeof(USBHID_CONTEXT));

    pUsbHid->Sig = USB_HID_SIG;
    InitializeCriticalSection(&pUsbHid->csLock);
    pUsbHid->hUsbDevice = hUsbDevice;
    pUsbHid->pUsbInterface = pUsbInterface;

    DUMP_USB_INTERFACE_DESCRIPTOR(pUsbHid->pUsbInterface->Descriptor, 
        pUsbHid->pUsbInterface->Descriptor.bInterfaceNumber);

    pUsbHid->hHidDriver = ActivateDeviceEx(HID_REGKEY_SZ, NULL, 0, CLIENT_REGKEY_SZ);
    if (pUsbHid->hHidDriver == NULL) {
        DEBUGMSG(ZONE_ERROR,(_T("%s: Unable to activate HID stream driver\r\n"), 
            pszFname));
        goto EXIT;
    }

    if (pUsbInterface->lpEndpoints == NULL) {
        DEBUGMSG(ZONE_ERROR,(_T("%s: Missing endpoint descriptors\r\n"), 
            pszFname));
        goto EXIT;
    }
    pEndpoint = &pUsbInterface->lpEndpoints[0];
    DEBUGCHK(pEndpoint != NULL);
    
    // Regarding bSendToInterface.  The original HID spec said that the Hid
    // descriptor would come after the interface and endpoint descriptors.
    // It also said that class specific commands should be sent to the endpoint.
    // The next spec said that the HID descriptor would come after the interface
    // descriptor (not at the end) and that commands should be sent to the
    // interface, not to the endpoint.  So, I'm assuming that if I find the
    // Hid descriptor after the interface, the device is following the new spec
    // and I should send commands to the interface.  Otherwise, I'll send them
    // to the endpoint, as stated in the old spec.
    pHidDescriptor = (PHID_DESCRIPTOR) pUsbInterface->lpvExtended;
    
    if (pHidDescriptor == NULL) {
        pHidDescriptor = (PHID_DESCRIPTOR) pUsbInterface->lpEndpoints->lpvExtended;
        if (pHidDescriptor == NULL) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Missing HID descriptor\r\n"), pszFname));
            goto EXIT;
        }
        else {
            pUsbHid->fSendToInterface = FALSE;
        }
    }
    else {
        pUsbHid->fSendToInterface = TRUE;
    }

    DUMP_USB_HID_DESCRIPTOR((*pHidDescriptor));

    pUsbHid->pUsbFuncs = pUsbFuncs;

    pUsbHid->Flags.Open = FALSE;
    pUsbHid->Flags.UnloadPending = FALSE;

    // create endpoint 0 event
    pUsbHid->hEP0Event = CreateEvent(NULL, MANUAL_RESET_EVENT, FALSE, NULL);
    if (pUsbHid->hEP0Event == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: CreateEvent error:%d\r\n"), pszFname, 
            GetLastError()));
        goto EXIT;
    }

    // set the USB interface/pipes
    if (SetUsbInterface(pUsbHid) == FALSE) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: SetUsbInterface failed!\r\n"), pszFname));
        goto EXIT;
    }
    
    // Mouse and keyboard HID devices might have a boot protocol that can be 
    // used at boot time. We never use the boot protocol and the devices
    // should default to the standard report format, but they are not 
    // guaranteed to. Therefore, we will manually set the report protocol here.
    if (pUsbInterface->Descriptor.bInterfaceSubClass == HID_INTERFACE_BOOT_SUBCLASS) {
        SetReportProtocol(pUsbHid);
    }

    // Allocate space temporarily for the report descriptor for our interface.
    cbReportDescriptor = pHidDescriptor->wDescriptorLength;
    pbReportDescriptor = (PBYTE) HidAlloc(cbReportDescriptor);
    if (pbReportDescriptor == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname,
            GetLastError()));
        goto EXIT;
    }

    // Get the report descriptor for our interface.
    if (GetReportDescriptor(pUsbHid, pbReportDescriptor, 
            cbReportDescriptor) == FALSE) {
        goto EXIT;
    }

    // Remember if this device can wake the system.
    if (pDeviceInfo->lpActiveConfig->Descriptor.bmAttributes & USB_CONFIG_REMOTE_WAKEUP) {
        pUsbHid->Flags.RemoteWakeup = TRUE;
    }

    // Determine how many interrupt transfers to issue at once
    SetQueuedTransfers(CLIENT_REGKEY_SZ);

    // Pass the report descriptor off to the MDD.
    if (HidMdd_Attach(
            (HID_PDD_HANDLE) pUsbHid,
            pbReportDescriptor,
            cbReportDescriptor,
            pDeviceInfo->Descriptor.idVendor,
            pDeviceInfo->Descriptor.idProduct,
            pDeviceInfo->Descriptor.bcdDevice,
            pUsbHid->pUsbInterface->Descriptor.bInterfaceNumber,
            &pUsbHid->pvNotifyParameter,
            &pUsbHid->cbMaxReport) == FALSE) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Failed initializing HID Mdd\r\n"), 
            pszFname));
        goto EXIT;
    }
    pUsbHid->Flags.MddInitialized = TRUE;

    // Create the thread that receives the data from the device.
    // Only do this, though, if there are input reports.
    if (pUsbHid->cbMaxReport && CreateInterruptThread(pUsbHid) == FALSE) {
        goto EXIT;
    }

    ValidateUsbHidContext(pUsbHid);

    fErr = FALSE;

EXIT:
    if (pbReportDescriptor != NULL) HidFree(pbReportDescriptor);
    
    if ((fErr == TRUE) && (pUsbHid != NULL)) {
        RemoveDeviceContext(pUsbHid);
		pUsbHid = NULL;
    }

    DEBUGMSG(ZONE_INIT, (_T("-%s\r\n"), pszFname));
    return pUsbHid;
}


// Helper routine to start an Interrupt Transfer.
static
USB_TRANSFER
StartInterruptTransfer(
    PUSBHID_CONTEXT pUsbHid,
    PBYTE pbBuffer,
    DWORD cbBuffer,
    HANDLE hev
    )
{
    SETFNAME(_T("StartInterruptTransfer"));

    PREFAST_DEBUGCHK(pUsbHid);
    DEBUGCHK(pbBuffer);
    DEBUGCHK(hev);

#ifdef DEBUG
    FillMemory(pbBuffer, cbBuffer, GARBAGE_BYTE);
#endif

    USB_TRANSFER hTransfer = pUsbHid->pUsbFuncs->lpIssueInterruptTransfer(
        pUsbHid->InterruptIn.hPipe,
        DefaultTransferComplete,
        hev,
        USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK,
        cbBuffer,
        pbBuffer,
        NULL
        );

    if (hTransfer == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: IssueInterruptTransfer failed\r\n"), 
            pszFname));
    }

    return hTransfer;
}


#ifdef DEBUG
// Validates a PUSB_HID_TRANSFER
static
void
ValidateTransfer(
    const USB_HID_TRANSFER *pTransfer
    )
{
    PREFAST_DEBUGCHK(pTransfer);
    DEBUGCHK(pTransfer->hev);
    DEBUGCHK(pTransfer->hev != GARBAGE_PVOID);
    DEBUGCHK(pTransfer->hTransfer);
    DEBUGCHK(pTransfer->hTransfer != GARBAGE_PVOID);
    DEBUGCHK(pTransfer->rgbBuffer);
    DEBUGCHK(pTransfer->rgbBuffer != GARBAGE_PVOID);
}
#else
#define ValidateTransfer(ptr)
#endif // DEBUG


// Receives the interrupt reports from the device
static
DWORD
WINAPI
InterruptThreadProc(
    LPVOID lpParameter
    )
{
    SETFNAME(_T("InterruptThreadProc"));

    PUSBHID_CONTEXT pUsbHid = (PUSBHID_CONTEXT) lpParameter;
    BYTE  cTransfers; // Count of valid transfers
    BYTE  bTransfer;
    DWORD cbBuffer;
    BOOL  fUnloadPending = FALSE;
    USB_HID_TRANSFER *pTransfers = NULL;

    PREFAST_DEBUGCHK(pUsbHid != NULL);
    ValidateUsbHidContext(pUsbHid);

	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

    cbBuffer = pUsbHid->cbMaxReport;

    cTransfers = g_bQueuedTransfers;
    DEBUGCHK(cTransfers >= MIN_QUEUED_TRANSFERS);
    DEBUGCHK(cTransfers <= MAX_QUEUED_TRANSFERS);
    DEBUGMSG(ZONE_COMMENT, (_T("%s: Thread started for %u queued transfers\r\n"),
        pszFname, cTransfers));

    DWORD cbTransfer = sizeof(USB_HID_TRANSFER) + cbBuffer;
    DWORD cbTransfers = cbTransfer * cTransfers;

    pTransfers = (PUSB_HID_TRANSFER) HidAlloc(cbTransfers);
    if (pTransfers == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: LocalAlloc error:%d\r\n"), pszFname, 
            GetLastError()));
        goto EXIT;
    }
#ifdef DEBUG
    FillMemory(pTransfers, cbTransfers, GARBAGE_BYTE);
#endif

    for (bTransfer = 0; bTransfer < cTransfers; ++bTransfer) {
        PUSB_HID_TRANSFER pTransfer = &pTransfers[bTransfer];
        pTransfer->rgbBuffer = ((PBYTE) &pTransfers[cTransfers]) + (cbBuffer * bTransfer);
        pTransfer->hev = CreateEvent(NULL, AUTO_RESET_EVENT, FALSE, NULL);
        if (pTransfer->hev == NULL) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: CreateEvent error:%d\r\n"), 
                pszFname, GetLastError()));
            cTransfers = bTransfer; // Invalidate this transfer
            break;
        }
           
        pTransfer->hTransfer = StartInterruptTransfer(pUsbHid,
            pTransfer->rgbBuffer, cbBuffer, pTransfer->hev);
        
        if (pTransfer->hTransfer == NULL) {
            CloseHandle(pTransfer->hev);
#ifdef DEBUG
            FillMemory(pTransfer, cbTransfer, GARBAGE_BYTE);
#endif
            cTransfers = bTransfer; // Invalidate this transfer
            break;
        }
    }

    if (cTransfers == 0) {
        ERRORMSG(1, (_T("USB HID: Unable to issue interrupt transfers\r\n")));
        goto EXIT;
    }

#ifdef DEBUG
    // At this point, indices 0 through cTransfers-1 are valid
    {
        for (BYTE bDebugIdx = 0; bDebugIdx < cTransfers; ++bDebugIdx) {
            ValidateTransfer(&pTransfers[bDebugIdx]);
        }
    }
#endif

    bTransfer = 0;
    while (fUnloadPending == FALSE) {
        DEBUGCHK(bTransfer < cTransfers);
        PUSB_HID_TRANSFER pTransfer = &pTransfers[bTransfer];
        ValidateTransfer(pTransfer);
        DWORD dwWait = WaitForSingleObject(pTransfer->hev, INFINITE);

        if (dwWait == WAIT_OBJECT_0) {
            DWORD dwBytesTransferred;
            USB_ERROR usbError;
            
            ValidateTransfer(pTransfer);
            
            GetTransferStatus(pUsbHid->pUsbFuncs, pTransfer->hTransfer, 
                &dwBytesTransferred, &usbError);
            CloseTransferHandle(pUsbHid->pUsbFuncs, pTransfer->hTransfer);

            if (usbError != USB_NO_ERROR) {
                // Device has probably been unplugged. Allow time for 
                // USBDeviceNotifications to get the news.

                // Since this could be a real error, we'll clean up the
                // hardware, just in case.
                ResetPipe(pUsbHid->pUsbFuncs, pUsbHid->InterruptIn.hPipe, 0);

                if (usbError == USB_STALL_ERROR) {
                    ClearOrSetFeature( 
                        pUsbHid->pUsbFuncs,
                        pUsbHid->hUsbDevice,
                        NULL,
                        NULL,
                        USB_SEND_TO_ENDPOINT,
                        USB_FEATURE_ENDPOINT_STALL,
                        pUsbHid->InterruptIn.bIndex,
                        0,
                        FALSE);
                }
                
                const DWORD dwSleepTime = 25;
                Sleep(dwSleepTime);
            }
            else {
                DWORD dwErr = HidMdd_ProcessInterruptReport(pTransfer->rgbBuffer, 
                    dwBytesTransferred, pUsbHid->pvNotifyParameter);
                DEBUGCHK(dwErr == ERROR_SUCCESS);
            }

            // Restart this transfer. If it fails, the device has been unplugged.
            pTransfer->hTransfer = StartInterruptTransfer(pUsbHid,
                pTransfer->rgbBuffer, cbBuffer, pTransfer->hev);
            if (pTransfer->hTransfer == NULL) {
                DEBUGMSG(ZONE_COMMENT, (_T("%s: Failed starting interrupt transfer. ")
                    _T("Assuming device removed\r\n"), pszFname));
                break;
            }

            // Wait on the next transfer
            if (++bTransfer == cTransfers) {
                bTransfer = 0;
            }
        }
        else {
            ERRORMSG(1, (_T("USB HID: Failure in WaitForSingleObject--returned %u\r\n"),
                dwWait));
            break;
        }            

        fUnloadPending = pUsbHid->Flags.UnloadPending;
    }

    // Clean up the valid transfers
    for (bTransfer = 0; bTransfer < cTransfers; ++bTransfer) {
        PUSB_HID_TRANSFER pTransfer = &pTransfers[bTransfer];
        DEBUGCHK(pTransfer->hev && (pTransfer->hev != GARBAGE_PVOID));
        
        // The final time through the interrupt loop might get a NULL transfer.
        if (pTransfer->hTransfer) {
            CloseTransferHandle(pUsbHid->pUsbFuncs, pTransfer->hTransfer);
            WaitForSingleObject(pTransfer->hev, INFINITE);
        }

        CloseHandle(pTransfer->hev);
    }

EXIT:
    if (pTransfers) HidFree(pTransfers);

    return 0;
}


// Create the thread that will receive the device's interrupt data
BOOL
CreateInterruptThread(
    PUSBHID_CONTEXT pUsbHid
    )
{
    SETFNAME(_T("CreateInterruptThread"));

    BOOL fRet = FALSE;
    
    PREFAST_DEBUGCHK(pUsbHid != NULL);
	DEBUGCHK(VALID_CONTEXT(pUsbHid));

    pUsbHid->hThread = CreateThread(NULL, 0, InterruptThreadProc, pUsbHid, 
        0, NULL);
    if (pUsbHid->hThread == NULL) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: CreateThread error:%d\r\n"), 
            pszFname, GetLastError()));
        goto EXIT;
    }
#ifdef DEBUG
	pUsbHid->fhThreadInited = TRUE;
#endif

    fRet = TRUE;

EXIT:
    return fRet;
}


⌨️ 快捷键说明

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