📄 usbhidiocdlg.cpp
字号:
HidD_GetHidGuid(&HidGuid);
/*
API function: SetupDiGetClassDevs
Returns: a handle to a device information set for all installed devices.
Requires: the GUID returned by GetHidGuid.
*/
hDevInfo=SetupDiGetClassDevs
(&HidGuid,
NULL,
NULL,
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
devInfoData.cbSize = sizeof(devInfoData);
//Step through the available devices looking for the one we want.
//Quit on detecting the desired device or checking all available devices without success.
MemberIndex = 0;
LastDevice = FALSE;
do
{
/*
API function: SetupDiEnumDeviceInterfaces
On return, MyDeviceInterfaceData contains the handle to a
SP_DEVICE_INTERFACE_DATA structure for a detected device.
Requires:
The DeviceInfoSet returned in SetupDiGetClassDevs.
The HidGuid returned in GetHidGuid.
An index to specify a device.
*/
Result=SetupDiEnumDeviceInterfaces
(hDevInfo,
0,
&HidGuid,
MemberIndex,
&devInfoData);
if (Result != 0)
{
//A device has been detected, so get more information about it.
/*
API function: SetupDiGetDeviceInterfaceDetail
Returns: an SP_DEVICE_INTERFACE_DETAIL_DATA structure
containing information about a device.
To retrieve the information, call this function twice.
The first time returns the size of the structure in Length.
The second time returns a pointer to the data in DeviceInfoSet.
Requires:
A DeviceInfoSet returned by SetupDiGetClassDevs
The SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces.
The final parameter is an optional pointer to an SP_DEV_INFO_DATA structure.
This application doesn't retrieve or use the structure.
If retrieving the structure, set
MyDeviceInfoData.cbSize = length of MyDeviceInfoData.
and pass the structure's address.
*/
//Get the Length value.
//The call will return with a "buffer too small" error which can be ignored.
Result = SetupDiGetDeviceInterfaceDetail
(hDevInfo,
&devInfoData,
NULL,
0,
&Length,
NULL);
//Allocate memory for the hDevInfo structure, using the returned Length.
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
//Set cbSize in the detailData structure.
detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
//Call the function again, this time passing it the returned buffer size.
Result = SetupDiGetDeviceInterfaceDetail
(hDevInfo,
&devInfoData,
detailData,
Length,
&Required,
NULL);
// Open a handle to the device.
// To enable retrieving information about a system mouse or keyboard,
// don't request Read or Write access for this handle.
/*
API function: CreateFile
Returns: a handle that enables reading and writing to the device.
Requires:
The DevicePath in the detailData structure
returned by SetupDiGetDeviceInterfaceDetail.
*/
DeviceHandle=CreateFile
(detailData->DevicePath,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
NULL);
DisplayLastError("CreateFile: ");
/*
API function: HidD_GetAttributes
Requests information from the device.
Requires: the handle returned by CreateFile.
Returns: a HIDD_ATTRIBUTES structure containing
the Vendor ID, Product ID, and Product Version Number.
Use this information to decide if the detected device is
the one we're looking for.
*/
//Set the Size to the number of bytes in the structure.
Attributes.Size = sizeof(Attributes);
Result = HidD_GetAttributes
(DeviceHandle,
&Attributes);
DisplayLastError("HidD_GetAttributes: ");
//Is it the desired device?
MyDeviceDetected = FALSE;
if (Attributes.VendorID == VendorID)
{
if (Attributes.ProductID == ProductID)
{
//Both the Vendor ID and Product ID match.
MyDeviceDetected = TRUE;
MyDevicePathName = detailData->DevicePath;
DisplayData("Device detected");
//Register to receive device notifications.
RegisterForDeviceNotifications();
//Get the device's capablities.
GetDeviceCapabilities();
// Find out if the device is a system mouse or keyboard.
DeviceUsage = (Capabilities.UsagePage * 256) + Capabilities.Usage;
if (DeviceUsage == 0x102)
{
UsageDescription = "mouse";
}
if (DeviceUsage == 0x106)
{
UsageDescription = "keyboard";
}
if ((DeviceUsage == 0x102) | (DeviceUsage == 0x106))
{
DisplayData("");
DisplayData("*************************");
DisplayData("The device is a system " + UsageDescription + ".");
DisplayData("Windows 2000 and Windows XP don't allow applications");
DisplayData("to directly request Input reports from or ");
DisplayData("write Output reports to these devices.");
DisplayData("*************************");
DisplayData("");
}
// Get a handle for writing Output reports.
WriteHandle=CreateFile
(detailData->DevicePath,
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
NULL);
DisplayLastError("CreateFile: ");
// Prepare to read reports using Overlapped I/O.
PrepareForOverlappedTransfer();
} //if (Attributes.ProductID == ProductID)
else
//The Product ID doesn't match.
CloseHandle(DeviceHandle);
} //if (Attributes.VendorID == VendorID)
else
//The Vendor ID doesn't match.
CloseHandle(DeviceHandle);
//Free the memory used by the detailData structure (no longer needed).
free(detailData);
} //if (Result != 0)
else
//SetupDiEnumDeviceInterfaces returned 0, so there are no more devices to check.
LastDevice=TRUE;
//If we haven't found the device yet, and haven't tried every available device,
//try the next one.
MemberIndex = MemberIndex + 1;
} //do
while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE));
if (MyDeviceDetected == FALSE)
DisplayData("Device not detected");
else
DisplayData("Device detected");
//Free the memory reserved for hDevInfo by SetupDiClassDevs.
SetupDiDestroyDeviceInfoList(hDevInfo);
DisplayLastError("SetupDiDestroyDeviceInfoList");
return MyDeviceDetected;
}
void CUsbhidiocDlg::GetDeviceCapabilities()
{
//Get the Capabilities structure for the device.
PHIDP_PREPARSED_DATA PreparsedData;
/*
API function: HidD_GetPreparsedData
Returns: a pointer to a buffer containing the information about the device's capabilities.
Requires: A handle returned by CreateFile.
There's no need to access the buffer directly,
but HidP_GetCaps and other API functions require a pointer to the buffer.
*/
HidD_GetPreparsedData
(DeviceHandle,
&PreparsedData);
DisplayLastError("HidD_GetPreparsedData: ");
/*
API function: HidP_GetCaps
Learn the device's capabilities.
For standard devices such as joysticks, you can find out the specific
capabilities of the device.
For a custom device, the software will probably know what the device is capable of,
and the call only verifies the information.
Requires: the pointer to the buffer returned by HidD_GetPreparsedData.
Returns: a Capabilities structure containing the information.
*/
HidP_GetCaps
(PreparsedData,
&Capabilities);
DisplayLastError("HidP_GetCaps: ");
//Display the capabilities
ValueToDisplay.Format("%s%X", "Usage Page: ", Capabilities.UsagePage);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Input Report Byte Length: ", Capabilities.InputReportByteLength);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Output Report Byte Length: ", Capabilities.OutputReportByteLength);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Feature Report Byte Length: ", Capabilities.FeatureReportByteLength);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of Link Collection Nodes: ", Capabilities.NumberLinkCollectionNodes);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of Input Button Caps: ", Capabilities.NumberInputButtonCaps);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of InputValue Caps: ", Capabilities.NumberInputValueCaps);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of InputData Indices: ", Capabilities.NumberInputDataIndices);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of Output Button Caps: ", Capabilities.NumberOutputButtonCaps);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of Output Value Caps: ", Capabilities.NumberOutputValueCaps);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of Output Data Indices: ", Capabilities.NumberOutputDataIndices);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of Feature Button Caps: ", Capabilities.NumberFeatureButtonCaps);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of Feature Value Caps: ", Capabilities.NumberFeatureValueCaps);
DisplayData(ValueToDisplay);
ValueToDisplay.Format("%s%d", "Number of Feature Data Indices: ", Capabilities.NumberFeatureDataIndices);
DisplayData(ValueToDisplay);
//No need for PreparsedData any more, so free the memory it's using.
HidD_FreePreparsedData(PreparsedData);
DisplayLastError("HidD_FreePreparsedData: ") ;
}
LRESULT CUsbhidiocDlg::Main_OnDeviceChange(WPARAM wParam, LPARAM lParam)
{
//DisplayData("Device change detected.");
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
switch(wParam)
{
// Find out if a device has been attached or removed.
// If yes, see if the name matches the device path name of the device we want to access.
case DBT_DEVICEARRIVAL:
DisplayData("A device has been attached.");
if (DeviceNameMatch(lParam))
{
DisplayData("My device has been attached.");
}
return TRUE;
case DBT_DEVICEREMOVECOMPLETE:
DisplayData("A device has been removed.");
if (DeviceNameMatch(lParam))
{
DisplayData("My device has been removed.");
// Look for the device on the next transfer attempt.
MyDeviceDetected = false;
}
return TRUE;
default:
return TRUE;
}
}
void CUsbhidiocDlg::OnChangeResults()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
void CUsbhidiocDlg::OnChange_txtInputReportBufferSize()
{
}
void CUsbhidiocDlg::OnChange_txtProductID()
{
CString ProductIDtext;
// Get the text in the edit box.
CEdit* m_ProductID = (CEdit*) GetDlgItem(IDC_txtProductID);
m_ProductID->GetWindowText(ProductIDtext);
// Convert the hex string in the edit box to an integer.
ProductID = strtoul("0x" + ProductIDtext, 0, 16);
MyDeviceDetected=false;
}
void CUsbhidiocDlg::OnChange_txtVendorID()
{
CString VendorIDtext;
// Get the text in the edit box.
CEdit* m_VendorID = (CEdit*) GetDlgItem(IDC_txtVendorID);
m_VendorID->GetWindowText(VendorIDtext);
// Convert the hex string in the edit box to an integer.
VendorID = strtoul("0x" + VendorIDtext, 0, 16);
MyDeviceDetected=false;
}
void CUsbhidiocDlg::On_chkUseControlTransfersOnly()
{
// TODO: Add your control notification handler code here
}
void CUsbhidiocDlg::OnClose()
{
//Anything that needs to occur on closing the application goes here.
//Free any resources used by previous API calls and still allocated.
CDialog::OnClose();
}
void CUsbhidiocDlg::On_cmdFindMyDevice()
{
CUsbhidiocDlg::FindTheHID();
}
void CUsbhidiocDlg::OnContinuous()
{
//Click the Continuous button to
//begin or stop requesting and sending periodic reports.
CString Caption;
//Find out whether Continuous is currently selected
//and take appropriate action.
m_Continuous.GetWindowText(Caption);
if (Caption == "Continuous")
{
//Enable periodic exchanges of reports.
//Change the button caption.
m_Continuous.SetWindowText("Stop Continuous");
//Start by reading and writing one pair of reports.
ReadAndWriteToDevice();
//Enable the timer to cause periodic exchange of reports.
//The second parameter is the number of milliseconds between report requests.
SetTimer(ID_CLOCK_TIMER, 5000, NULL);
}
else
{
//Stop periodic exchanges of reports.
//Change the button caption.
m_Continuous.SetWindowText("Continuous");
//Disable the timer.
KillTimer(ID_CLOCK_TIMER);
}
}
void CUsbhidiocDlg::OnOK()
{
CDialog::OnOK();
}
void CUsbhidiocDlg::OnOnce()
{
//Click the Once button to read and write one pair of reports.
ReadAndWriteToDevice();
}
void CUsbhidiocDlg::On_cmdInputReportBufferSize()
{
// Change the number of reports the HID driver's buffer can store.
// Read back and display the result.
CString InputReportBufferSizeText;
ULONG InputReportBufferSize;
boolean result;
// Look for the device if necessary.
if (MyDeviceDetected==FALSE)
{
MyDeviceDetected=FindTheHID();
}
if (MyDeviceDetected==TRUE)
{
// Get the text in the edit box.
CEdit* m_InputReportBufferSize = (CEdit*) GetDlgItem(IDC_txtInputReportBufferSize);
m_InputReportBufferSize->GetWindowText(InputReportBufferSizeText);
// Convert the string in the edit box to an integer.
InputReportBufferSize = strtoul(InputReportBufferSizeText, 0, 10);
// Set the number of Input-report buffers.
result = HidD_SetNumInputBuffers
(DeviceHandle,
InputReportBufferSize);
DisplayLastError("HidD_SetNumInputBuffers: ");
/// Retrieve the number of Input-report buffers.
result = HidD_GetNumInputBuffers
(DeviceHandle,
&InputReportBufferSize);
DisplayLastError("HidD_GetNumInputBuffers: ");
// Display the result.
if (result)
{
SetDlgItemInt (IDC_txtInputReportBufferSize, InputReportBufferSize);
}
else
{
// Windows 98 Gold doesn't support these API calls.
// The buffer size is always 2.
SetDlgItemInt (IDC_txtInputReportBufferSize, 2);
}
}
}
void CUsbhidiocDlg::On_optExchangeFeatureReports()
{
// Exchange Feature reports.
ReportType = 1;
}
void CUsbhidiocDlg::On_optExchangeInputAndOutputReports()
{
// Exchange Input and Output reports.
ReportType = 0;
}
void CUsbhidiocDlg::OnTimer(UINT nIDEvent)
{
//The timer event.
//Read and Write one pair of reports.
ReadAndWriteToDevice();
CDialog::OnTimer(nIDEvent);
}
void CUsbhidiocDlg::PrepareForOverlappedTransfer()
{
//Get a handle to the device for the overlapped ReadFiles.
ReadHandle=CreateFile
(detailData->DevicePath,
GENERIC_READ,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -