?? setup.cpp
字號:
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 + -