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

📄 hid.cpp

📁 Intel PXA270 Wince5.0 BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                                pstData->mouse.pAxes[index]->max,
                                pstData->mouse.pAxes[index]->wUsagePage,
                                pstData->mouse.pAxes[index]->wUsage));
                }
            }
            break;
    }
#else //RETAIL
    UnusedParameter(pstData);
#endif //DEBUG

}   


SDataDescription*
CHid::AllocateDescriptionStruct(
                               SDataDescription **ppstDataDescriptionHead)
{
    SDataDescription *pstData = *ppstDataDescriptionHead;

    if (*ppstDataDescriptionHead == NULL) {
        *ppstDataDescriptionHead = new SDataDescription;
        pstData = *ppstDataDescriptionHead;
    }
    else {
        pstData = (*ppstDataDescriptionHead)->pNext;
        while (pstData != NULL) {
            pstData = pstData->pNext;
        }
        pstData = new SDataDescription;
    }

    if (pstData != NULL) {
        memset(pstData, 0x00, sizeof(SDataDescription));
    }

    return (pstData);    
}


SDataDescription*
CHid::DeallocateDescriptionStruct(
                                 SDataDescription *pstDataDescription)
{
    UINT axis;
    SDataDescription *pstNext = pstDataDescription->pNext;

    switch (pstDataDescription->deviceType) {
        case gcDeviceTypeKeyboard:
            if (pstDataDescription->keybd.pressedKeys != NULL) {
                delete[] pstDataDescription->keybd.pressedKeys;
            }
            break;

        case gcDeviceTypeJoystick:
            for (axis = 0; axis < gcMaxJoyAxes; axis++) {
                if (pstDataDescription->joy.pAxes[axis] != NULL) {
                    delete[] pstDataDescription->joy.pAxes[axis];               
                }
            }
            if (pstDataDescription->joy.pButtonOffsets != NULL) {
                delete[] pstDataDescription->joy.pButtonOffsets;
            }
            break;

        case gcDeviceTypeMouse:
            for (axis = 0; axis < gcMaxMouseAxes; axis++) {
                if (pstDataDescription->mouse.pAxes[axis] != NULL) {
                    delete[] pstDataDescription->mouse.pAxes[axis];             
                }
            }
            if (pstDataDescription->mouse.pButtonOffsets != NULL) {
                delete[] pstDataDescription->mouse.pButtonOffsets;
            }
            break;
    }   

    delete pstDataDescription;
    return (pstNext);
}   



// This should be handled in HIDNewDevice
#ifdef OHCI_DESC_BUG_WORKAROUND

BOOL
CHid::GetConfigDesc(
                   SHidDevice *pstHidDevice,
                   UINT size)
{
    DEBUGCHK((pstHidDevice->signalStatus & gcSignalStatusCtrl) == 0);

    pstHidDevice->configStatus = gcConfigStatusGettingConfigDesc;

    if (pstHidDevice->dataBufferSize < size) {
        if (pstHidDevice->pDataBuffer != NULL) {
            delete[] pstHidDevice->pDataBuffer;
        }

        pstHidDevice->pDataBuffer = new BYTE[size];
        pstHidDevice->dataBufferSize = size;
    }

    pstHidDevice->signalStatus |= gcSignalStatusCtrlPending;

    pstHidDevice->hCtrlTransfer = 
    m_lpUsbFuncs->lpGetDescriptor(pstHidDevice->hDevice,
                                  ControlCompletionStub,
                                  pstHidDevice,
                                  USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK,
                                  USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                  0,0,
                                  pstHidDevice->dataBufferSize,
                                  pstHidDevice->pDataBuffer);
    if (pstHidDevice->hCtrlTransfer == NULL) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::GetDeviceDesc, Error %u in IssueVendorTransfer\r\n"),GetLastError()));
        pstHidDevice->signalStatus &= ~gcSignalStatusCtrlPending;
        return FALSE;
    }

    return TRUE;
}


BOOL
CHid::ParseConfigDesc(
                     SHidDevice *pstHidDevice)
{
    DEBUGMSG(ZONE_FUNCTION,(TEXT("+CHid::ParseConfigDesc\r\n")));

    PUSB_CONFIGURATION_DESCRIPTOR pCd;
    PUSB_INTERFACE_DESCRIPTOR pId;
    PUSB_ENDPOINT_DESCRIPTOR pEd;
    PHID_DESCRIPTOR pHd;

    UINT actualLength;
    UINT interfaceNumber = 0;
    UINT endpointNumber = 0;

    pCd = (PUSB_CONFIGURATION_DESCRIPTOR)pstHidDevice->pDataBuffer;

    ASSERT(pCd != NULL);

    actualLength = pCd->wTotalLength;
    if (actualLength > pstHidDevice->dataBufferSize) {
        // We didn't get enough.  Get the descriptor again, this time
        // with the right length.
        GetConfigDesc(pstHidDevice, actualLength);
        return (FALSE);
    }

    pstHidDevice->bConfigurationValue = pCd->bConfigurationValue;

    // 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.

    pId = (PUSB_INTERFACE_DESCRIPTOR)(pstHidDevice->pDataBuffer +
                                      sizeof(USB_CONFIGURATION_DESCRIPTOR));

    if (pId->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE) {
        DEBUGMSG(ZONE_ERROR,
                 (TEXT("!CHid::ParseConfigDesc: Invalid configuation descriptor.\r\n")
                  TEXT("0x%02X is not USB_INTERFACE_DESCRIPTOR_TYPE.\r\n"),
                  pId->bDescriptorType));
        //BUGBUG how should we deal with this?
        return (FALSE);
    }

    pHd = (PHID_DESCRIPTOR)((PBYTE)pId + sizeof(USB_INTERFACE_DESCRIPTOR));
    if (pHd->bDescriptorType == HID_DESCRIPTOR_TYPE) {
        pstHidDevice->bSendToInterface = TRUE;
        pstHidDevice->endptOrIntrNum = pId->bInterfaceNumber;
        pEd = (PUSB_ENDPOINT_DESCRIPTOR)((PBYTE)pHd + pHd->bLength);
    }
    else {
        pEd = (PUSB_ENDPOINT_DESCRIPTOR)pHd;
        pHd = (PHID_DESCRIPTOR)((PBYTE)pEd + pEd->bLength);
        if (pEd->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE ||
            pHd->bDescriptorType != HID_DESCRIPTOR_TYPE) {
            DEBUGMSG(ZONE_ERROR,
                     (TEXT("!CHid::ParseConfigDesc Error, invalid configuation descriptor.\r\n")
                      TEXT("0x%02X not Endpoint and 0x%02X not Hid\r\n"),
                      pEd->bDescriptorType, pHd->bDescriptorType));
            //BUGBUG how should we deal with this?
            return (FALSE);
        }

        pstHidDevice->endptOrIntrNum = pEd->bEndpointAddress;
    }

    pstHidDevice->wReportDescriptorLength = pHd->wDescriptorLength;

    // Open interrupt pipe
    pstHidDevice->hIntrPipe = m_lpUsbFuncs->lpOpenPipe(pstHidDevice->hDevice,pEd);
    if (pstHidDevice->hIntrPipe == NULL) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::HidNewDevice - Error %u opening interrupt pipe for device\r\n"),GetLastError()));
        return (FALSE);
    }

    GetReport(pstHidDevice);
    
    DEBUGMSG(ZONE_FUNCTION,(TEXT("-CHid::ParseConfigDesc\r\n")));
    return (TRUE);   
}

#endif // OHCI_DESC_BUG_WORKAROUND

BOOL
CHid::SetIdle(
               SHidDevice *pstHidDevice,
               DWORD reportId, /* or 0 for "all reports" */
               DWORD idleRate  /* in ms, or INFINITE */)
{
    USB_DEVICE_REQUEST Dr;
    USB_TRANSFER h;

    DEBUGCHK((reportId & 0xFF) == reportId); // reportId is really a byte-size datum
    if (idleRate == INFINITE)
        idleRate = 0;  // the HID request takes 0 to mean INFINITE
    else if (idleRate == 0)
        idleRate = 1;  // since 0 means INFINITE, to poll at the default freq., use 1.
    else
        idleRate = (idleRate + 3) / 4; // round to 4ms interval w/out accidentally getting 0.
    if (idleRate > 255)
        idleRate = 255;  // must be a byte-size datum
    
    Dr.bmRequestType =
        USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_CLASS |
        (pstHidDevice->bSendToInterface ? USB_REQUEST_FOR_INTERFACE : USB_REQUEST_FOR_ENDPOINT);
    Dr.bRequest = USB_REQUEST_HID_SET_IDLE;
    Dr.wValue   = (WORD) (idleRate << 8 | reportId);
    Dr.wIndex   = pstHidDevice->endptOrIntrNum; // ASSERT it's an ifc number
    Dr.wLength  = 0;

    h = m_lpUsbFuncs->lpIssueVendorTransfer(pstHidDevice->hDevice, 
                                            NULL,
                                            0,
                                            0,
                                            &Dr,
                                            NULL, 0);
    if (h == NULL) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::SetIdle - Error %u in IssueVendorTransfer\r\n"),
                             GetLastError()));
        return FALSE;
    }

    m_lpUsbFuncs->lpCloseTransfer(h);  // don't care about the status
    
    return TRUE;
}

BOOL
CHid::SetReport(
               SHidDevice *pstHidDevice,
               DWORD reportId, /* or 0 for "all reports" */
               PVOID pData,
               WORD lenData)
{
    USB_DEVICE_REQUEST Dr;
    USB_TRANSFER h;

    DEBUGCHK((reportId & 0xFF) == reportId); // reportId is really a byte-size datum
    
    Dr.bmRequestType =
        USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_CLASS |
        (pstHidDevice->bSendToInterface ? USB_REQUEST_FOR_INTERFACE : USB_REQUEST_FOR_ENDPOINT);
    Dr.bRequest = USB_REQUEST_HID_SET_REPORT;
    // The 0x02 in the high byte sets the report type to 'Output'.
    Dr.wValue   = 0x0200 | (BYTE) reportId;
    Dr.wIndex   = pstHidDevice->endptOrIntrNum; // ASSERT it's an ifc number
    Dr.wLength  = lenData;

    h = m_lpUsbFuncs->lpIssueVendorTransfer(pstHidDevice->hDevice, 
                                            NULL,
                                            0,
                                            0,
                                            &Dr,
                                            pData, 0);
    if (h == NULL) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::SetReport - Error %u in IssueVendorTransfer\r\n"),
                             GetLastError()));
        return FALSE;
    }

    m_lpUsbFuncs->lpCloseTransfer(h);  // don't care about the status
    
    return TRUE;
}

// This should really be called GetReportDescriptor. Sigh.
BOOL
CHid::GetReport(
               SHidDevice *pstHidDevice)
{
    DEBUGCHK((pstHidDevice->signalStatus & gcSignalStatusCtrl) == 0);
    
    // Go through these contortions so that we can tack a properly aligned
    // setup buffer onto the end of the data buffer and free them both later
    // with a single invocation of the delete operator.
    struct tmp { char a; USB_DEVICE_REQUEST b; };
    UINT algn = (UINT) &((struct tmp *)0)->b;
    UINT size = pstHidDevice->wReportDescriptorLength;
    UINT off  = (size + algn - 1) & ~(algn - 1);
    UINT tot  = off + sizeof(USB_DEVICE_REQUEST);
    DEBUGCHK( (algn & (algn - 1)) == 0 ); // algn will always be a power of two
    
    pstHidDevice->configStatus = gcConfigStatusGettingReport;

    if (pstHidDevice->dataBufferSize < tot) {
        if (pstHidDevice->pDataBuffer != NULL) {
            delete[] pstHidDevice->pDataBuffer;
        }

        pstHidDevice->pDataBuffer = new BYTE[tot];
        pstHidDevice->dataBufferSize = tot;
    }

    // Can't use GetDescriptor for this request, because that assumes request is for device
    PUSB_DEVICE_REQUEST pDr = (PUSB_DEVICE_REQUEST) &pstHidDevice->pDataBuffer[off];

    if (pstHidDevice->bSendToInterface) {
        pDr->bmRequestType = USB_REQUEST_DEVICE_TO_HOST |
                             USB_REQUEST_FOR_INTERFACE;
    }
    else {
        pDr->bmRequestType = USB_REQUEST_DEVICE_TO_HOST |
                             USB_REQUEST_FOR_ENDPOINT;
    }
    pDr->bRequest = USB_REQUEST_GET_DESCRIPTOR;
    pDr->wValue   = USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(HID_REPORT_DESCRIPTOR_TYPE, 0);
    pDr->wIndex   = pstHidDevice->endptOrIntrNum;
    pDr->wLength  = size;

    pstHidDevice->signalStatus |= gcSignalStatusCtrlPending;

    pstHidDevice->hCtrlTransfer = 
    m_lpUsbFuncs->lpIssueVendorTransfer(pstHidDevice->hDevice, 
                                        ControlCompletionStub,
                                        pstHidDevice,
                                        USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK,
                                        pDr,
                                        pstHidDevice->pDataBuffer,0);
    if (pstHidDevice->hCtrlTransfer == NULL) {
        DEBUGMSG(ZONE_ERROR,(TEXT("!CHid::GetReport - Error %u in IssueVendorTransfer\r\n"),GetLastError()));
        pstHidDevice->signalStatus &= ~gcSignalStatusCtrlPending;
        delete[] pstHidDevice->pDataBuffer;
        pstHidDevice->pDataBuffer = NULL;
        pstHidDevice->dataBufferSize = 0;
        return FALSE;
    }
    return TRUE;
}


BOOL
CHid::SubmitInterrupt(
                     SHidDevice *pstHidDevice)
{
    DEBUGCHK((pstHidDevice->signalStatus & gcSignalStatusIntr) == 0);
    
    UINT size = pstHidDevice->intrBufferSize;

    if (size == 0) {
        DEBUGMSG(ZONE_ERROR, 

⌨️ 快捷键说明

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