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

📄 usbhid.cpp

📁 嵌入式操作系统WINCE5.0下的USB驱动程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    udr.bmRequestType |= USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_CLASS;

    udr.bRequest = USB_REQUEST_HID_SET_REPORT;
    udr.wValue   = USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(type, bReportID);
    udr.wLength  = (USHORT) cbBuffer;

    dwErr = IssueVendorTransfer(
        pUsbHid->pUsbFuncs,
        pUsbHid->hUsbDevice,
        pfnNotify, 
        hEvent,
        USB_OUT_TRANSFER,
        &udr,
        pbBuffer,
        0,
        &dwBytesTransferred,
        dwTimeout,
        &usbErr);


    if (dwErr == ERROR_SUCCESS) {
        if (usbErr == USB_STALL_ERROR) {
            // SET_REPORT is not required according to the HID spec. If it is not 
            // present, the device may return a stall handshake.
            dwErr = ERROR_NOT_SUPPORTED;
        }
        else if (usbErr != USB_NO_ERROR) {
            dwErr = ERROR_GEN_FAILURE;
        }
    }

EXIT:
    if (hEvent != NULL) CloseHandle(hEvent);
    
    return dwErr;
}


// Retrieves the requested string descriptor and validates it.
static
DWORD
GetStringDescriptor(
    PUSBHID_CONTEXT pUsbHid,
    BYTE bIdx,
    WORD wLangId,
    PBYTE pbBuffer,
    WORD  cbBuffer,
    PDWORD pbTransferred
    )
{
    SETFNAME(_T("GetStringDescriptor"));

    PUSB_STRING_DESCRIPTOR pStringDesc = (PUSB_STRING_DESCRIPTOR) pbBuffer;
    USB_ERROR usbErr;
    USB_TRANSFER hTransfer;
    DWORD dwErr;

    PREFAST_DEBUGCHK(VALID_CONTEXT(pUsbHid));
    ValidateUsbHidContext(pUsbHid);
    
    PREFAST_DEBUGCHK(pbBuffer != NULL);
    DEBUGCHK(cbBuffer >= sizeof(USB_STRING_DESCRIPTOR));
    PREFAST_DEBUGCHK(pbTransferred != NULL);
    
    hTransfer = pUsbHid->pUsbFuncs->lpGetDescriptor(pUsbHid->hUsbDevice, NULL, NULL,
        USB_SHORT_TRANSFER_OK, USB_STRING_DESCRIPTOR_TYPE, bIdx, 
        wLangId, cbBuffer, pbBuffer);

    if (hTransfer != NULL) {
        GetTransferStatus(pUsbHid->pUsbFuncs, hTransfer, 
            pbTransferred, &usbErr);
        CloseTransferHandle(pUsbHid->pUsbFuncs, hTransfer);

        if (usbErr != USB_NO_ERROR) {
            if (usbErr == USB_STALL_ERROR) {
                dwErr = ERROR_NOT_SUPPORTED;
            }        
            else {
                dwErr = ERROR_GEN_FAILURE;
            }

            goto EXIT;
        }
    }
    else {
        dwErr = GetLastError();
        goto EXIT;
    }
    
    // We've got a descriptor. Is it valid?
    if ( (*pbTransferred < (sizeof(USB_STRING_DESCRIPTOR) - sizeof(pStringDesc->bString))) || 
         (pStringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE) ) { 
        DEBUGCHK(FALSE); // The device returned something strange.
        dwErr = ERROR_GEN_FAILURE;
        goto EXIT;
    }

    dwErr = ERROR_SUCCESS;

EXIT:
    if (dwErr != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_WARNING, (_T("%s: Error getting string descriptor %u, %u. Err=%u\r\n"),
            pszFname, bIdx, wLangId, dwErr));
    }
    
    return dwErr;    
}


// Get a device string. For predefined types see hiddi.h.
// Call with pszBuffer == NULL to get the character count required 
// (then add 1 for the NULL terminator).
DWORD
WINAPI
HidPdd_GetString(
    HID_PDD_HANDLE  hPddDevice,
    HID_STRING_TYPE stringType,
    DWORD           dwIdx,     // Only used with stringType == HID_STRING_INDEXED
    LPWSTR          pszBuffer, // Set to NULL to get character count
    DWORD           cchBuffer, // Count of chars that will fit into pszBuffer
                               // including the NULL terminator.
    PDWORD          pcchActual // Count of chars in the string NOT including
                               // the NULL terminator
    )
{
    SETFNAME(_T("HidPdd_GetString"));

    const DWORD CB_STRING_DESCRIPTOR_MAX = 0xff;

    PUSBHID_CONTEXT pUsbHid = (PUSBHID_CONTEXT) hPddDevice;

    union {
        BYTE rgbBuffer[CB_STRING_DESCRIPTOR_MAX];
        USB_STRING_DESCRIPTOR StringDesc;
    } StringDescriptor;
    
    PCUSB_DEVICE pDeviceInfo = NULL;
    DWORD dwErr;
    WORD wLangId;
//    DWORD cchToCopy;
    DWORD dwBytesTransferred;
    BYTE bIdx;

    PREFAST_DEBUGCHK(VALID_CONTEXT(pUsbHid));
    ValidateUsbHidContext(pUsbHid);

    // Mdd guarantees the following
    DEBUGCHK(stringType < HID_STRING_MAX);
    DEBUGCHK( ((stringType == HID_STRING_INDEXED) && (dwIdx != 0)) == FALSE );
    PREFAST_DEBUGCHK(pcchActual != NULL);

    if (stringType != HID_STRING_INDEXED) {
        pDeviceInfo = 
            (*pUsbHid->pUsbFuncs->lpGetDeviceInfo)(pUsbHid->hUsbDevice);
        if (pDeviceInfo == NULL) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Failure getting USB device info\r\n"), 
                pszFname));
            dwErr = ERROR_GEN_FAILURE;
            goto EXIT;
        }

        switch (stringType) {
            case HID_STRING_ID_IMANUFACTURER:
                bIdx = pDeviceInfo->Descriptor.iManufacturer;
                break;
            case HID_STRING_ID_IPRODUCT:
                bIdx = pDeviceInfo->Descriptor.iProduct;
                break;
            case HID_STRING_ID_ISERIALNUMBER:
                bIdx = pDeviceInfo->Descriptor.iSerialNumber;
                break;

            default:
                bIdx = 0;
        }

        if (bIdx == 0) {
            DEBUGMSG(ZONE_COMMENT, (_T("%s: String type %u does not exist\r\n"), 
                pszFname, stringType));
            dwErr = ERROR_NOT_FOUND;
            goto EXIT;
        }
    }
    else {
        // USB indexes strings with a byte. Make sure dwIdx can be represented
        // in a byte.
        if (dwIdx > UCHAR_MAX) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: String index 0x%x is too large\r\n"),
                pszFname, dwIdx));
            dwErr = ERROR_INVALID_PARAMETER;
            goto EXIT;
        }

        bIdx = (BYTE) dwIdx;
    }


    // Get the Zero string descriptor to determine which LANGID to use.
    // We just use the first LANGID listed.
    dwErr = GetStringDescriptor(pUsbHid, 0, 0, (PBYTE) &StringDescriptor,
        sizeof(StringDescriptor), &dwBytesTransferred);
    if (dwErr != ERROR_SUCCESS) {
        goto EXIT;
    }

    DEBUGCHK(StringDescriptor.StringDesc.bLength >= sizeof(USB_STRING_DESCRIPTOR));
    DEBUGCHK(StringDescriptor.StringDesc.bDescriptorType == USB_STRING_DESCRIPTOR_TYPE);
    wLangId = StringDescriptor.StringDesc.bString[0];

    // Get the string descriptor for the first LANGID
    dwErr = GetStringDescriptor(pUsbHid, bIdx, wLangId, (PBYTE) &StringDescriptor,
        sizeof(StringDescriptor), &dwBytesTransferred);
    if (dwErr != ERROR_SUCCESS) {
        goto EXIT;
    }

    __try {
        // Copy the character count and string into the user's buffer
        *pcchActual = (StringDescriptor.StringDesc.bLength - 2) / sizeof(WCHAR); // Does not include NULL
        if (pszBuffer != NULL) {
            StringCchCopyN(pszBuffer, cchBuffer, 
                StringDescriptor.StringDesc.bString, *pcchActual);
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Exception writing to user buffer\r\n"),
            pszFname));
        dwErr = ERROR_INVALID_PARAMETER;
    }

EXIT:
    return dwErr;    
}


// Get the idle rate for a specific report.
DWORD
WINAPI
HidPdd_GetIdle(
    HID_PDD_HANDLE hPddDevice,
    PDWORD         pdwIdle,
    DWORD          dwReportID
    )
{
    SETFNAME(_T("HidPdd_GetIdle"));

    PUSBHID_CONTEXT pUsbHid = (PUSBHID_CONTEXT) hPddDevice;
    USB_DEVICE_REQUEST udr;
    DWORD dwBytesTransferred;
    DWORD dwErr;
    BYTE bIdle;
    USB_ERROR usbErr;
    
    PREFAST_DEBUGCHK(VALID_CONTEXT(pUsbHid));
    ValidateUsbHidContext(pUsbHid);
    
    PREFAST_DEBUGCHK(pdwIdle != NULL);

    if (dwReportID > UCHAR_MAX) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Report ID of %u is too large.\r\n"),
            pszFname, dwReportID));
        dwErr = ERROR_INVALID_PARAMETER;
        goto EXIT;
    }
    
    // Do we send to the endpoint or interface?
    DetermineDestination(pUsbHid, &udr.bmRequestType, &udr.wIndex);
    udr.bmRequestType |= USB_REQUEST_DEVICE_TO_HOST | USB_REQUEST_CLASS;

    udr.bRequest = USB_REQUEST_HID_GET_IDLE;
    udr.wValue   = USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(0, dwReportID);
    udr.wLength  = 1;

    dwErr = IssueVendorTransfer(
        pUsbHid->pUsbFuncs,
        pUsbHid->hUsbDevice,
        NULL, 
        NULL,
        USB_IN_TRANSFER,
        &udr,
        &bIdle,
        0,
        &dwBytesTransferred,
        INFINITE,
        &usbErr);

    if (dwErr == ERROR_SUCCESS) {
        if (usbErr == USB_STALL_ERROR) {
            // GET_IDLE is not required according to the HID spec. If it is not 
            // present, the device may return a stall handshake.
            dwErr = ERROR_NOT_SUPPORTED;
        }
        else if (usbErr != USB_NO_ERROR) {
            dwErr = ERROR_GEN_FAILURE;
        }
    }
    else {
        // Success. Write value to user buffer.
        __try {
            *pdwIdle = (DWORD) bIdle;
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            DEBUGMSG(ZONE_ERROR, (_T("%s: Exception writing to user buffer\r\n"),
                pszFname));
            dwErr = ERROR_INVALID_PARAMETER;
        }
    }

EXIT:
    return dwErr;
}


// Set the idle rate for a specific report. The idle rate is expressed in
// 4 ms increments, so to set idle rate of 20 ms, bDuration should be 5.
// bDuration of 0 means infinite. bReportID of 0 means to apply to all
// reports.
DWORD
WINAPI
HidPdd_SetIdle(
    HID_PDD_HANDLE hPddDevice,
    DWORD          dwDuration,
    DWORD          dwReportID
    )
{
    SETFNAME(_T("HidPdd_SetIdle"));

    PUSBHID_CONTEXT pUsbHid = (PUSBHID_CONTEXT) hPddDevice;
    USB_DEVICE_REQUEST udr;
    DWORD dwBytesTransferred;
    DWORD dwErr;
    USB_ERROR usbErr;
        
    PREFAST_DEBUGCHK(VALID_CONTEXT(pUsbHid));
    ValidateUsbHidContext(pUsbHid);

    if (dwReportID > UCHAR_MAX) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Report ID of %u is too large.\r\n"),
            pszFname, dwReportID));
        dwErr = ERROR_INVALID_PARAMETER;
        goto EXIT;
    }

    if (dwDuration > UCHAR_MAX) {
        // Use the maximum possible value.
        DEBUGMSG(ZONE_WARNING, (_T("%s: Reducing duration to max BYTE value\r\n"),
            pszFname));
        dwDuration = UCHAR_MAX;
    }

    // Do we send to the endpoint or interface?
    DetermineDestination(pUsbHid, &udr.bmRequestType, &udr.wIndex);
    udr.bmRequestType |= USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_CLASS;

    udr.bRequest = USB_REQUEST_HID_SET_IDLE;
    udr.wValue   = USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(dwDuration, dwReportID);
    udr.wLength  = 0;

    dwErr = IssueVendorTransfer(
        pUsbHid->pUsbFuncs,
        pUsbHid->hUsbDevice,
        NULL, 
        NULL,
        USB_OUT_TRANSFER,
        &udr,
        NULL,
        0,
        &dwBytesTransferred,
        INFINITE,
        &usbErr);

    if (dwErr == ERROR_SUCCESS) {
        if (usbErr == USB_STALL_ERROR) {
            // SET_IDLE is not required according to the HID spec. If it is not 
            // present, the device may return a stall handshake.
            dwErr = ERROR_NOT_SUPPORTED;
        }
        else if (usbErr != USB_NO_ERROR) {
            dwErr = ERROR_GEN_FAILURE;
        }
    }

EXIT:
    return dwErr;
}


// Enable remote wakeup if possible.
static
DWORD
EnableRemoteWakeup(
    PUSBHID_CONTEXT pUsbHid,
    BOOL fEnable
    )
{
    SETFNAME(_T("EnableRemotWakeup"));
    
    DWORD dwErr;
    
    PREFAST_DEBUGCHK(pUsbHid != NULL);
    ValidateUsbHidContext(pUsbHid);
        
    dwErr = ClearOrSetFeature(
        pUsbHid->pUsbFuncs,
        pUsbHid->hUsbDevice,
        NULL,
        NULL,
        USB_SEND_TO_DEVICE,
        USB_FEATURE_REMOTE_WAKEUP,
        0,
        0,
        fEnable
        );

    if (dwErr != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (_T("%s: Set Remote Wakeup Feature failure. Error: 0x%x\r\n"), 
            pszFname, dwErr));
    }

    return dwErr;
}


// Commands the PDD to initiate some activity or configuration.
DWORD
WINAPI
HidPdd_IssueCommand(
    HID_PDD_HANDLE hPddDevice,        // PDD function parameter
    DWORD          dwMsg,             // Notification message
    WPARAM         wParam             // Message parameter
    )
{
    SETFNAME(_T("HidPdd_IssueCommand"));

    PUSBHID_CONTEXT pUsbHid = (PUSBHID_CONTEXT) hPddDevice;
    DWORD dwErr = ERROR_SUCCESS;

    ValidateUsbHidContext(pUsbHid);

    if (dwMsg == HID_PDD_REMOTE_WAKEUP) {
        dwErr = ERROR_SUCCESS;
        if (pUsbHid->Flags.RemoteWakeup == TRUE) {
            BOOL fEnable = wParam;
            dwErr = EnableRemoteWakeup(pUsbHid, fEnable);
        }
    }
    else {
        DEBUGCHK(FALSE);
        dwErr = ERROR_NOT_SUPPORTED;
    }

    return dwErr;
}


//
// ***** HID Stream Interface *****
//

// We do not expose any PDD IOCTLs, so these all pass through to the MDD.

extern "C" 
DWORD
HID_Init(
    LPCWSTR lpszDevKey
    )
{
    return HidMdd_Init(lpszDevKey);
}


extern "C" 
BOOL
HID_Deinit(
    DWORD dwContext
    )
{
    return HidMdd_Deinit(dwContext);
}


extern "C" 
DWORD
HID_Open(
    DWORD dwContext,
    DWORD dwAccMode,
    DWORD dwShrMode
    )
{
    return HidMdd_Open(dwContext, dwAccMode, dwShrMode);
}


extern "C" 
BOOL
HID_Close(
    DWORD dwContext
    )
{
    return HidMdd_Close(dwContext);
}


extern "C" 
BOOL
HID_IOControl (
    DWORD  dwContext,
    DWORD  dwCode,
    PBYTE  pInpBuf,
    DWORD  dwInpLen,
    PBYTE  pOutBuf,
    DWORD  dwOutLen,
    PDWORD pdwActualOutLen
    )
{
    // We do not have any PDD IOCTLs, so pass everything on to the MDD.
    return HidMdd_IOControl(dwContext, dwCode, pInpBuf, 
        dwInpLen, pOutBuf, dwOutLen, pdwActualOutLen);
}


⌨️ 快捷键说明

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