I am using the Microsoft HID SDK to communicate with a Freescale JM60 processor. I found this problem in the sample driver, that uses the HID library. The issue occurs when there are multiple HID devices connected to the machine. The problem is that createfile will always fail, causing HIDopen to report that your HID device was not found.
My solution, admittedly a hack, was to searth through the available HID devices backwards, with the logic that the device I am trying to connect to was the last device attached. It works for me, it may not work for everybody.
I attached portions of the original code below. Notice the note after creatfile. What happens is that after A HID device is opened, that does NOT match the VID/PID of the device you are looking for, the createfile ALWAYS fails. As a reult, the device you are looking for is never found.
As I said, the solution i used was to walk the index backwards. As long as the device you are looking for was the last HID device to be plugged in, the code will find that first, createfile will work, and you will successfully open your connection to your HID device.
If anyone need the complete code with the fix I described above, please email me at: eric.gregori@emgrobotics.com
do {
BOOLEAN Result;
/* Get information about the HID device with the 'Index' array entry */
Result = SetupDiEnumDeviceInterfaces( HidDevInfo, 0, &HidGuid, Index, &devInfoData);
/* If we run into this condition, then there are no more entries to examine, we might as well return FALSE at point */
if(Result == FALSE)
{
r=1;
msg="Device not found.";
break;
}
if(GotRequiredSize == FALSE)
{
/* 3) Get the size of the DEVICE_INTERFACE_DETAIL_DATA structure. The first call will return an error condition, but we'll get the
size of the strucure */
Result = SetupDiGetDeviceInterfaceDetail( HidDevInfo, &devInfoData, NULL, 0, &DataSize, NULL);
GotRequiredSize = TRUE;
/* allocate memory for the HidDevInfo structure */
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) _alloca(DataSize);
/* set the size parameter of the structure */
detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
}
/* 4) Now call the function with the correct size parameter. This function will return data from one of the array members that
Step #2 pointed to. This way we can start to identify the attributes of particular HID devices. */
Result = SetupDiGetDeviceInterfaceDetail( HidDevInfo, &devInfoData, detailData, DataSize, &RequiredSize, NULL);
/* 5) Open a file handle to the device. Make sure the attibutes specify overlapped transactions or the IN transaction may block the input thread. */
hid_dev = CreateFile( detailData->DevicePath, GENERIC_READ GENERIC_WRITE, /* read / write access*/
FILE_SHARE_READ FILE_SHARE_WRITE, // EMG Fix for my HP Dual Core
NULL, /* No security */
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, /* overlapped I/O */
NULL); /* no template */
/* 6) Get the Device VID & PID to see if it's the device we want */
if(hid_dev != INVALID_HANDLE_VALUE) <-------------------- Failure is seen here
{
HIDD_ATTRIBUTES HIDAttrib;
HIDAttrib.Size = sizeof(HIDAttrib);
HidD_GetAttributes( hid_dev, &HIDAttrib);
if((HIDAttrib.VendorID == vid) && (HIDAttrib.ProductID == pid))
{ /* Found HID device. */
/* get a handle to a buffer that describes the device's capabilities. This
line plus the following two lines of code extract the report length the
device is claiming to support */
PHIDP_PREPARSED_DATA hpd;
HidD_GetPreparsedData(hid_dev, &hpd);
/* extract the capabilities info */
HIDP_CAPS hid_cap;
HidP_GetCaps(hpd , &hid_cap);
/* Free the memory allocated when getting the preparsed data */
HidD_FreePreparsedData(hpd);
/* This will be needed by writes. */
OutputReportByteLength = hid_cap.OutputReportByteLength;
obuf=(char *)malloc(OutputReportByteLength);
/* and this by reads */
InputReportByteLength=hid_cap.InputReportByteLength;
ibuf=(char *) malloc(InputReportByteLength);
/* create a new event for overlapped read. */
read_done=CreateEvent(0, false, true, NULL);
r=0;
break;
}
/* 7) Close the Device Handle because we didn't find the device with the correct VID and PID */
CloseHandle(hid_dev);
}
else
{
code left out
}
code left out
Index--; /* increment the array index to search the next entry */
} while(1);
My solution, admittedly a hack, was to searth through the available HID devices backwards, with the logic that the device I am trying to connect to was the last device attached. It works for me, it may not work for everybody.
I attached portions of the original code below. Notice the note after creatfile. What happens is that after A HID device is opened, that does NOT match the VID/PID of the device you are looking for, the createfile ALWAYS fails. As a reult, the device you are looking for is never found.
As I said, the solution i used was to walk the index backwards. As long as the device you are looking for was the last HID device to be plugged in, the code will find that first, createfile will work, and you will successfully open your connection to your HID device.
If anyone need the complete code with the fix I described above, please email me at: eric.gregori@emgrobotics.com
do {
BOOLEAN Result;
/* Get information about the HID device with the 'Index' array entry */
Result = SetupDiEnumDeviceInterfaces( HidDevInfo, 0, &HidGuid, Index, &devInfoData);
/* If we run into this condition, then there are no more entries to examine, we might as well return FALSE at point */
if(Result == FALSE)
{
r=1;
msg="Device not found.";
break;
}
if(GotRequiredSize == FALSE)
{
/* 3) Get the size of the DEVICE_INTERFACE_DETAIL_DATA structure. The first call will return an error condition, but we'll get the
size of the strucure */
Result = SetupDiGetDeviceInterfaceDetail( HidDevInfo, &devInfoData, NULL, 0, &DataSize, NULL);
GotRequiredSize = TRUE;
/* allocate memory for the HidDevInfo structure */
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) _alloca(DataSize);
/* set the size parameter of the structure */
detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
}
/* 4) Now call the function with the correct size parameter. This function will return data from one of the array members that
Step #2 pointed to. This way we can start to identify the attributes of particular HID devices. */
Result = SetupDiGetDeviceInterfaceDetail( HidDevInfo, &devInfoData, detailData, DataSize, &RequiredSize, NULL);
/* 5) Open a file handle to the device. Make sure the attibutes specify overlapped transactions or the IN transaction may block the input thread. */
hid_dev = CreateFile( detailData->DevicePath, GENERIC_READ GENERIC_WRITE, /* read / write access*/
FILE_SHARE_READ FILE_SHARE_WRITE, // EMG Fix for my HP Dual Core
NULL, /* No security */
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, /* overlapped I/O */
NULL); /* no template */
/* 6) Get the Device VID & PID to see if it's the device we want */
if(hid_dev != INVALID_HANDLE_VALUE) <-------------------- Failure is seen here
{
HIDD_ATTRIBUTES HIDAttrib;
HIDAttrib.Size = sizeof(HIDAttrib);
HidD_GetAttributes( hid_dev, &HIDAttrib);
if((HIDAttrib.VendorID == vid) && (HIDAttrib.ProductID == pid))
{ /* Found HID device. */
/* get a handle to a buffer that describes the device's capabilities. This
line plus the following two lines of code extract the report length the
device is claiming to support */
PHIDP_PREPARSED_DATA hpd;
HidD_GetPreparsedData(hid_dev, &hpd);
/* extract the capabilities info */
HIDP_CAPS hid_cap;
HidP_GetCaps(hpd , &hid_cap);
/* Free the memory allocated when getting the preparsed data */
HidD_FreePreparsedData(hpd);
/* This will be needed by writes. */
OutputReportByteLength = hid_cap.OutputReportByteLength;
obuf=(char *)malloc(OutputReportByteLength);
/* and this by reads */
InputReportByteLength=hid_cap.InputReportByteLength;
ibuf=(char *) malloc(InputReportByteLength);
/* create a new event for overlapped read. */
read_done=CreateEvent(0, false, true, NULL);
r=0;
break;
}
/* 7) Close the Device Handle because we didn't find the device with the correct VID and PID */
CloseHandle(hid_dev);
}
else
{
code left out
}
code left out
Index--; /* increment the array index to search the next entry */
} while(1);
Welcome
I decided to create this blog after doing my second .NET project for school, I am going back to school to get my MSCS.The purpose of this blog is for me to share software tidbit and information that I have found and or discovered, for the benefit of myself and other ( I have a terrible memory ).
I am also heavily involved in Robotics and embedded software engineering ( I work for Freescale Semiconductor ). I plan on posting information and links about robotics here also.
For work I develop embedded Linux, WinCE, and bare metal applications for everything from ARM11 processors done to 8bit processors.
I have never done a blog before, so bear with me. I am also a terrible speller, so my apologies in advance.
Eric Gregori - seeprogrammer - www.EMGRobotics.com - www.EMGWare.com -www.RobotSee.com
Comments
0 comments to "HID SDK bug"
Post a Comment