📄 hid.cpp
字号:
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 + -