SetupAPI.DLL в HID.DLL - PullRequest
       10

SetupAPI.DLL в HID.DLL

0 голосов
/ 06 апреля 2010

Используя SetupAPI, я выполняю функцию SetupDiGetClassDevs и получаю указатель или дескриптор.

Затем я запускаю цикл и запускаю:

Return = SetupDiEnumDeviceInterfaces();

с

SP_DEVICE_INTERFACE_DATA.cbSize = 0

чтобы получить размер, который должен быть SP_DEVICE_INTERFACE_DATA.

Затем я устанавливаю этот размер и снова выполняю:

SP_DEVICE_INTERFACE_DATA.cbSize = return;   // (the size)
SetupDiEnumDeviceInterfaces();

Из структур данных я получаю:

DevicePath из SP_DEVINFO_DATA и куча информации из реестра, если я хочу, я верю.

Что я действительно хочу, так это получить доступ к библиотеке HID и вызвать HidD_GetAttributes чтобы получить VendorID, ProductID и VersionNumber от этого перечисленного устройства, чтобы я мог идентифицировать устройство.

Я ожидаю, что эта конкретная информация будет поступать с самого USB-устройства. Кто-нибудь может показать мне, как это сделать?

Кстати, в моей версии Windows XP я использую путь реестра, я не могу найти HKEY_LOCAL_MACHINE\Enum\HID\...\Class.

Я даже не нахожу HKEY_LOCAL_MACHINE\Enum\. Я думаю, это потому, что я не выполнил функцию SetupDiEnumDeviceInterfaces.

Я могу найти полные данные только в Lakeview Research. Но это не распространяется на эту тему. Почему это все в сети, когда это мусор?

1 Ответ

1 голос
/ 11 мая 2010

Не уверен, что это то, что вы ищете:

BOOL CheckIfPresentAndGetUSBDevicePath(void)
{
    /* 
    Before we can "connect" our application to our USB embedded device, we must first find the device.
    A USB bus can have many devices simultaneously connected, so somehow we have to find our device only.
    This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
    a unique combination of VID and PID.  

    Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
    for each function used can be found in the MSDN library.  We will be using the following functions:

    SetupDiGetClassDevs()                   //provided by setupapi.dll, which comes with Windows
    SetupDiEnumDeviceInterfaces()           //provided by setupapi.dll, which comes with Windows
    GetLastError()                          //provided by kernel32.dll, which comes with Windows
    SetupDiDestroyDeviceInfoList()          //provided by setupapi.dll, which comes with Windows
    SetupDiGetDeviceInterfaceDetail()       //provided by setupapi.dll, which comes with Windows
    SetupDiGetDeviceRegistryProperty()      //provided by setupapi.dll, which comes with Windows
    malloc()                                //part of C runtime library, msvcrt.dll?
    CreateFile()                            //provided by kernel32.dll, which comes with Windows

    We will also be using the following unusual data types and structures.  Documentation can also be found in
    the MSDN library:

    PSP_DEVICE_INTERFACE_DATA
    PSP_DEVICE_INTERFACE_DETAIL_DATA
    SP_DEVINFO_DATA
    HDEVINFO
    HANDLE
    GUID

    The ultimate objective of the following code is to get the device path, which will be used elsewhere for getting
    read and write handles to the USB device.  Once the read/write handles are opened, only then can this
    PC application begin reading/writing to the USB device using the WriteFile() and ReadFile() functions.

    Getting the device path is a multi-step round about process, which requires calling several of the
    SetupDixxx() functions provided by setupapi.dll.
    */

    HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
    PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
    //      PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;  //Globally declared instead
    SP_DEVINFO_DATA DevInfoData;

    DWORD InterfaceIndex = 0;
    DWORD StatusLastError = 0;
    DWORD dwRegType;
    DWORD dwRegSize;
    DWORD StructureSize = 0;
    PBYTE PropertyValueBuffer;
    bool MatchFound = false;
    DWORD ErrorStatus;
    BOOL BoolStatus = FALSE;
    DWORD LoopCounter = 0;

    char * DeviceIDToFind = MY_DEVICE_ID;

    // First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
    DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    // Now look through the list we just populated.  We are trying to see if any of them match our device. 
    while(true)
    {
        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
        {
            ErrorStatus = GetLastError();
            if(ErrorStatus == ERROR_NO_MORE_ITEMS)  // Did we reach the end of the list of matching devices in the DeviceInfoTable?
            {   // Cound not find the device.  Must not have been attached.
                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);    //Clean up the old structure we no longer need.
                return FALSE;       
            }
        }
        else    // Else some other kind of unknown error ocurred...
        {
            ErrorStatus = GetLastError();
            SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);    // Clean up the old structure we no longer need.
            return FALSE;   
        }

        // Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
        // check to see if it is the correct device or not.

        // Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

        // First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

        // Allocate a buffer for the hardware ID.
        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
        if(PropertyValueBuffer == NULL) // if null, error, couldn't allocate enough memory
        {   // Can't really recover from this situation, just exit instead.
            SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);    // Clean up the old structure we no longer need.
            return FALSE;       
        }

        // Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
        // REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
        // buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
        // format "Vid_04d8&Pid_003f".
        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

        // Now check if the first string in the hardware ID matches the device ID of my USB device.
#ifdef UNICODE
        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
#else
        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
#endif

        free(PropertyValueBuffer);      // No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks

        // Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();    
        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                
        // Now check if the hardware ID we are looking at contains the correct VID/PID
        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);        
        if(MatchFound == true)
        {
            // Device must have been found.  Open WinUSB interface handle now.  In order to do this, we will need the actual device path first.
            // We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
            // time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
            // get the structure (after we have allocated enough memory for the structure.)
            DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
            // First call populates "StructureSize" with the correct value
            SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
            DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));     //Allocate enough memory
            if(DetailedInterfaceDataStructure == NULL)  //if null, error, couldn't allocate enough memory
            {   // Can't really recover from this situation, just exit instead.
                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);    //Clean up the old structure we no longer need.
                return FALSE;       
            }
            DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
            // Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
            SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

            // We now have the proper device path, and we can finally open a device handle to the device.
            // WinUSB requires the device handle to be opened with the FILE_FLAG_OVERLAPPED attribute.
            SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);    //Clean up the old structure we no longer need.
            return TRUE;
        }

        InterfaceIndex++;   
        // Keep looping until we either find a device with matching VID and PID, or until we run out of devices to check.
        // However, just in case some unexpected error occurs, keep track of the number of loops executed.
        // If the number of loops exceeds a very large number, exit anyway, to prevent inadvertent infinite looping.
        LoopCounter++;
        if(LoopCounter == 10000000) // Surely there aren't more than 10 million devices attached to any forseeable PC...
        {
            return FALSE;
        }
    }//end of while(true)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...