|
||||
WebNoteId: 20 Title: The ScanForHidDevice() function in USBHIDIO.c returns the incorrect device. | |||||||||
Summary: This web note describes how to correct the ScanForHidDevice() function from returning the incorrect device. | |||||||||
// ------------------------------------------------------ // // ScanForHidDevice(VID,PID,TID,SID,ENUM,SHARE) - Scan thru all the HID device looking // for a match on the VID, PID and optional TID (Type ID) and SID (Serial Number). // Sets the hDevice handle varible if found and opens the device // Parameters: // VID The Vendor Indenification Number. Delcom VID = 0x0FC5; // PID The Product Indenification Number. Typically 0xB080 (see PID_ALT) // TID The Family type number. Zero=all, else only serachs for matching TID // SID The Serial number. Zero=all, else only serachs for matching SID // ENUM Eumeration. When non-zero list all matching device found. Does not leave open any device. // SHARE Share Mode. When non-zero open device in shared mode. // PID_ALT An alternate PID to search for. Tyipcally 0xA080. // // Return zero if found, else non-zero error code. // 0 = Success - A matching device has been found and openned. // 1 = No matching HID devices. // NOTES // Enum if set - prints all the devices found // 02/06/2020 - Added check for Usage ID and Page, to make should we are connecting to the Delcom Vendor Defined Device and // not one of the other HID types. Also now check of all api return failures. Added PID_ALT to serach for alt too, set to zero if not used. // ------------------------------------------------------ // unsigned int CUSBHIDIO::ScanForHIDDevice(unsigned int VID, unsigned int PID, unsigned int TID, unsigned int SID, unsigned int Enum, unsigned int ShareMode,unsigned int PID_ALT ) { //Use a series of API calls to find a HID with a matching Vendor,Product, Type and Serial ID. DelcomDeviceInfoStruct DelcomInfo; PSP_DEVICE_INTERFACE_DETAIL_DATA pDetailData; GUID HidGuid; HANDLE hDevInfo; ULONG Required; HIDD_ATTRIBUTES Attributes; SP_DEVICE_INTERFACE_DATA devInfoData; bool LastDevice = FALSE; int MemberIndex = 0; bool MyDeviceDetected = FALSE; LONG Result; ULONG Length; ULONG devcnt; DWORD SHARE_MODE; PHIDP_PREPARSED_DATA pPreparsedData; PHIDP_CAPS pCaps; // Variable init devcnt=0; Length = 0; pDetailData = NULL; hDevice=NULL; MemberIndex = 0; LastDevice = FALSE; if(ShareMode) SHARE_MODE = FILE_SHARE_READ|FILE_SHARE_WRITE; else SHARE_MODE = 0; pCaps =(PHIDP_CAPS)malloc(sizeof(HIDP_CAPS)); // API function: HidD_GetHidGuid - Get the GUID for all system HIDs. Returns: the GUID in HidGuid. 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. do { MyDeviceDetected=FALSE; //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 does not retrieve or use the structure. // If retrieving the structure, set MyDeviceInfoData.cbSize = length of MyDeviceInfoData. // and pass the structures 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. pDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length); //Set cbSize in the detailData structure. pDetailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //Call the function again, this time passing it the returned buffer size. Result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, pDetailData, Length, &Required, NULL); //Open a handle to the device. // API function: CreateFile - Returns: a handle that enables reading and writing to the device. // Requires: The DevicePath in the detailData structure returned by SetupDiGetDeviceInterfaceDetail. // NOTES: details->DevicePath - holds the name of the device - // NOTES: For file sharing set 3rd parameter to FILE_SHARE_READ|FILE_SHARE_WRITE hDevice = INVALID_HANDLE_VALUE; hDevice = CreateFile(pDetailData->DevicePath, GENERIC_READ|GENERIC_WRITE, SHARE_MODE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL); if( hDevice != INVALID_HANDLE_VALUE ) { // 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 are looking for. // To enable overlappedtransfer use: GetDeviceCapabilities() & PrepareForOverlappedTransfer() // Get the Attributes(VID,PID) Attributes.Size = sizeof(Attributes); Result = HidD_GetAttributes(hDevice, &Attributes); // Get Capabillities(USAGE ID & PAGE)pCaps->Usage = 0x0; pCaps->UsagePage = 0x0; if(HidD_GetPreparsedData(hDevice, &pPreparsedData) ) Result = HidP_GetCaps(pPreparsedData, pCaps); //Is it the desired device? if( Result && (Attributes.VendorID == VID) && ((Attributes.ProductID == PID) ||(Attributes.ProductID == PID_ALT)) && (pCaps->UsagePage==0xFF00) && (pCaps->Usage==0x00) ) { //Both the Product and Vendor IDs and Usage ID and Page match. Delcom vendor defined device found! MyDeviceDetected = TRUE; // premark it found _tcsncpy_s(DeviceName, sizeof(DeviceName), pDetailData->DevicePath, 512); // save the devicename // At this point we have found a match device. If VID, PID or ENUM are set then check for them too. if(TID || SID || Enum) { // Now check for TID SID and ENUM if non-zero Result = GetDeviceInfo(&DelcomInfo); // TRY TO READ THE DEVICE if(Result ) MyDeviceDetected = FALSE; // this function must succeed else { if(TID && (DelcomInfo.Family != TID)) MyDeviceDetected = FALSE; if(SID && (DelcomInfo.Serial != SID)) MyDeviceDetected = FALSE; if(Enum) { // if Enumerate mode enabled, just print the info and make MyDeviceDetected=FALSE so it scans all of them. //_tprintf(L"Device Found(%u): TID=%u SID=%u VER=%d Usage(%x/%x). %s ", ++devcnt, DelcomInfo.Family,DelcomInfo.Serial, DelcomInfo.Version, pCaps->UsagePage, pCaps->Usage, DeviceName); _tprintf(L"Device Found(%u): TID=%u SID=%u VER=%d. %s ", ++devcnt, DelcomInfo.Family,DelcomInfo.Serial, DelcomInfo.Version, DeviceName); MyDeviceDetected = FALSE; // Mark false, so keeps scanning } } // end of TID or SID or } } if(MyDeviceDetected == FALSE) CloseHandle(hDevice); // close the handle if device not found or enum mode } // eof if hDevice is valid //Free the memory used by the detailData structure (no longer needed). free(pDetailData); } //if (Result != 0) else { // End of List - No HID devices detected! LastDevice=TRUE; //SetupDiEnumDeviceInterfaces returned 0, so there are no more devices to check. } //If we have not found the device yet, and have not tried every available device, //try the next one. MemberIndex++; } // loop till either end of deivce list or we find our device while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE)); SetupDiDestroyDeviceInfoList(hDevInfo); //Free the memory reserved for hDevInfo by SetupDiClassDevs. free(pCaps); if (MyDeviceDetected == FALSE) { // Device not found hDevice = 0; return(1); } else { // Device Found HidD_SetNumInputBuffers(hDevice,1); //sets the maximum number of input reports that the HID class driver ring buffer can hold for a specified top-level collection. return(0); // Success } } |
home products services contact us shopping cart legal © Copyright 2024 Delcom Products Inc - R720 9/15/2024