2012-05-14 41 views
5

Puede alguien ver si estoy haciendo bien por favor:Mis SetupDiEnumDeviceInterfaces no está funcionando

//DeviceManager.h 
#include <windows.h> 
//#include <hidsdi.h> 
#include <setupapi.h> 
#include <iostream> 
#include <cfgmgr32.h> 
#include <tchar.h> 
#include <devpkey.h> 

extern "C"{ 
    #include <hidsdi.h> 
} 

//#pragma comment (lib, "setupapi.lib") 

class DeviceManager 
{ 
public: 
    DeviceManager(); 
    ~DeviceManager(); 

    void ListAllDevices(); 
    void GetDevice(std::string vid, std::string pid); 

    HANDLE PSMove; 
    byte reportBuffer; 
private: 
    HDEVINFO deviceInfoSet;    //A list of all the devices 
    SP_DEVINFO_DATA deviceInfoData;  //A device from deviceInfoSet 

    SP_DEVICE_INTERFACE_DATA deviceInterfaceData; 
    SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailedData; 

}; 

//DeviceManager.cpp 
#include"DeviceManager.h" 

DeviceManager::DeviceManager() 
{ 
    deviceInfoSet = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); //Gets all Devices 
} 

DeviceManager::~DeviceManager() 
{ 
} 

void DeviceManager::ListAllDevices() 
{ 
    DWORD deviceIndex = 0; 

    deviceInfoData.cbSize = sizeof(deviceInfoData); 

    while(SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, &deviceInfoData)) 
    { 
     deviceInfoData.cbSize = sizeof(deviceInfoData); 

     ULONG tcharSize; 
     CM_Get_Device_ID_Size(&tcharSize, deviceInfoData.DevInst, 0); 
     TCHAR* deviceIDBuffer = new TCHAR[tcharSize]; //the device ID will be stored in this array, so the tcharSize needs to be big enough to hold all the info. 
                 //Or we can use MAX_DEVICE_ID_LEN, which is 200 

     CM_Get_Device_ID(deviceInfoData.DevInst, deviceIDBuffer, MAX_PATH, 0); //gets the devices ID - a long string that looks like a file path. 

     /* 
     //SetupDiGetDevicePropertyKeys(deviceInfoSet, &deviceInfoData, &devicePropertyKey, NULL, 0, 0); 
     if(deviceIDBuffer[8]=='8' && deviceIDBuffer[9]=='8' && deviceIDBuffer[10]=='8' && deviceIDBuffer[11]=='8' && //VID 
      deviceIDBuffer[17]=='0' && deviceIDBuffer[18]=='3' && deviceIDBuffer[19]=='0' && deviceIDBuffer[20]=='8') //PID 
     { 
      std::cout << deviceIDBuffer << "\t<-- Playstation Move" << std::endl; 
     } 
     else 
     { 
      std::cout << deviceIDBuffer << std::endl; 
     }*/ 

     std::cout << deviceIDBuffer << std::endl; 

     deviceIndex++; 
    } 
} 

void DeviceManager::GetDevice(std::string vid, std::string pid) 
{ 

    DWORD deviceIndex = 0; 
    deviceInfoData.cbSize = sizeof(deviceInfoData); 

    while(SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, &deviceInfoData)) 
    { 
     deviceInfoData.cbSize = sizeof(deviceInfoData); 

     ULONG IDSize; 
     CM_Get_Device_ID_Size(&IDSize, deviceInfoData.DevInst, 0); 

     TCHAR* deviceID = new TCHAR[IDSize]; 

     CM_Get_Device_ID(deviceInfoData.DevInst, deviceID, MAX_PATH, 0); 

     if(deviceID[8]==vid.at(0) && deviceID[9]==vid.at(1) && deviceID[10]==vid.at(2) && deviceID[11]==vid.at(3) && //VID 
      deviceID[17]==pid.at(0) && deviceID[18]==pid.at(1) && deviceID[19]==pid.at(2) && deviceID[20]==pid.at(3)) //PID 
     { 
      //DWORD requiredBufferSize; 
      //SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &requiredBufferSize, 


      HDEVINFO deviceInterfaceSet = SetupDiGetClassDevs(&deviceInfoData.ClassGuid, NULL, NULL, DIGCF_ALLCLASSES); 

      DWORD deviceInterfaceIndex = 0; 
      deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); 
      while(SetupDiEnumDeviceInterfaces(deviceInterfaceSet, NULL, &deviceInterfaceData.InterfaceClassGuid, deviceInterfaceIndex, &deviceInterfaceData)) 
      { 
       deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); 
       std::cout << deviceInterfaceIndex << std::endl; 

       deviceInterfaceIndex++; 
      } 

      //std::cout << deviceInterfaceData.cbSize << std::endl; 

      break; 
     } 

     deviceIndex++; 
    } 
} 

Mis SetupDiEnumDeviceInterfaces (en la función GetDevice()) no está haciendo nada. Ni siquiera está entrando en el ciclo while ... ¿Puede alguien tratar de señalar qué es lo que estoy haciendo mal, por favor?

Gracias

Editar/MÁS INFORMACIÓN: Acabo de llamar a la función GetLastError() y se ha vuelto un 259 - ERROR_NO_MORE_ITEMS. ¿Es posible que un dispositivo no contenga interfaces?

+2

'SetupDiEnumDeviceInfo' vuelve falsa entonces. Mire la documentación para determinar por qué esto podría ser y luego use su depurador. Si todavía no puede resolverlo, haga una pregunta más específica sobre dónde se quedó atascado. – AJG85

+0

Entonces, ¿puedo preguntar si el deviceInfoData.ClassGuid se ha pasado correctamente? Quiero decir, se supone que estoy pasando ese guid para obtener el deviceInterfaceSet? ¿O no puedo pasarle un GUID diferente? – Danny

+1

Si nunca ingresa el bucle while, nunca llega a esa línea de código, lo que significa que está utilizando 'deviceInfoSet' asignado en el constructor. Sugerencia: utilice 'FormatMessage' con' GetLastError' para determinar específicamente qué salió mal después de la llamada a 'SetupDiEnumDeviceInfo'. Simplemente podría ser que no hay ningún dispositivo USB activo presente en el sistema. – AJG85

Respuesta

7

Vaya con esto.


He intentado hackear tu código original lo menos posible; los siguientes códigos (para mí al menos) llegar hasta el interior while(SetupDiEnumDeviceInterfaces..):

void DeviceManager::GetDeviceUSB(std::string vid, std::string pid) 
{ 
    DWORD deviceIndex = 0; 
    deviceInfoData.cbSize = sizeof(deviceInfoData); 

    //buried somewhere deep in the ddk 
    static GUID GUID_DEVINTERFACE_USB_HUB={ 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} }; 
    static GUID GUID_DEVINTERFACE_USB_DEVICE ={ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; 
    static GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER={ 0x3abf6f2d, 0x71c4, 0x462a, {0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27}}; 

    //get usb device interfaces 
    HDEVINFO deviceInterfaceSet=SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_DEVICEINTERFACE); 


    while(SetupDiEnumDeviceInfo(deviceInterfaceSet, deviceIndex, &deviceInfoData)) 
    { 
     deviceInfoData.cbSize = sizeof(deviceInfoData); 

     ULONG IDSize; 
     CM_Get_Device_ID_Size(&IDSize, deviceInfoData.DevInst, 0); 

     TCHAR* deviceID = new TCHAR[IDSize]; 

     CM_Get_Device_ID(deviceInfoData.DevInst, deviceID, MAX_PATH, 0); 

     if(deviceID[8]==vid.at(0) && deviceID[9]==vid.at(1) && deviceID[10]==vid.at(2) && deviceID[11]==vid.at(3) && //VID 
      deviceID[17]==pid.at(0) && deviceID[18]==pid.at(1) && deviceID[19]==pid.at(2) && deviceID[20]==pid.at(3)) //PID 
     { 
      DWORD deviceInterfaceIndex = 0; 
      deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); 

      while(SetupDiEnumDeviceInterfaces(deviceInterfaceSet, &deviceInfoData, &GUID_DEVINTERFACE_USB_DEVICE, deviceInterfaceIndex, &deviceInterfaceData)) 
      { 
       deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); 
       std::cout << deviceInterfaceIndex << std::endl; 

       //get some more details etc 
       //DWORD requiredBufferSize; 
       //SetupDiGetDeviceInterfaceDetail(deviceInterfaceSet, &deviceInterfaceData, NULL, 0, &requiredBufferSize, 

       deviceInterfaceIndex++; 
      } 
     } 

     deviceIndex++; 
    } 
} 



que yo sepa, este método recoge los mismos dispositivos que con su OP constructor de llamada:
(NB: i incluido algunos otros guids interfaz útil)

deviceInfoSet = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); //Gets all Devices 


pero yo estoy haciendo esto para obtener el dispositivo interfaces de:

// /coughs/ you might want to put back the DIGCF_PRESENT flag i removed for testing 
HDEVINFO deviceInterfaceSet=SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_DEVICEINTERFACE); 


también paso el deviceInfoData a SetupDiEnumDeviceInterfaces ya que de acuerdo a la documentación:

Un puntero a un SP_DEVINFO_DATA estructura que especifica un elemento de información de dispositivo en DeviceInfoSet. Este parámetro es opcional y puede ser NULO. Si se especifica este parámetro, SetupDiEnumDeviceInterfaces restringe la enumeración a las interfaces que son compatibles con el dispositivo especificado. Si este parámetro es NULL, las llamadas repetidas a SetupDiEnumDeviceInterfaces devuelven información acerca de las interfaces que están asociadas con todos los elementos de información del dispositivo en DeviceInfoSet. Este puntero es típicamente devuelto por SetupDiEnumDeviceInfo.



    [Editar: Notas adicionales (; conforme a lo solicitado;)]


El dispositivo USB tiene un asociado configuración clase y interfaz clase (s):

Desde device setup classes documentation:

La clase de configuración del dispositivo define los instalador de clase y de clase co-instaladores que están involucrados en la instalación del dispositivo de

Desde el device interface classes documentation: clase de interfaz

Un dispositivo es una forma de exportar el dispositivo y la funcionalidad del controlador a otros componentes del sistema, incluidos otros controladores, como , así como las aplicaciones en modo de usuario


Also, see this handy comparison
Also, this related doc is useful


Así:

deviceInfoSet = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL,DIGCF_PRESENT|DIGCF_ALLCLASSES); 

esta es la recuperación de todos los configuración conjuntos de información de clase y el filtrado sobre "USB"


Usted podía hacer esto:

deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES|DIGCF_DEVICEINTERFACE);` 

Esto recupera la información de clase establece para los dispositivos que soportan una interfaz de dispositivo de cualquier clase . (La aplicación de un ID emumerator s/a "USB" parece tener ningún efecto) Fundamentalmente, sin embargo: The function adds to the device information set a device information element that represents such a device and then adds to the device information element a device interface list that contains all the device interfaces that the device supports.


(Y nota:SP_DEVINFO_DATA.ClassGuid es siempre el GUID de configuración del dispositivo clase)


que yo sepa:
pero entonces todavía tiene que proporcionar una WH InterfaceClassGuid invocando SetupDiEnumDeviceInterfaces() ~ tbh, realmente no entiendo por qué esto sería necesario si la persona que llama proporciona el DeviceInfoData opcional pero como es todo de fuente cerrada, ¿cómo lo sabría?:)


& Aquí es info regarding GUID_DEVINTERFACE_USB_DEVICE


(; exención de responsabilidad: yo no trabajo para M $; no tratar las informaciones anteriores con recelo :) & & de dyoRs curso;)



Espero que esto ayude, la mejor de las suertes!

+0

que funciona y es exactamente lo que necesito! Muchas gracias: D. Si no te importa, ¿también puedo pedirte que me expliques un poco más sobre el GUID que has declarado en la parte superior? ¿Por qué los necesitamos cuando uso TEXT ("USB")? ¿Cuál es la diferencia? ¿O puede al menos proporcionarme un enlace donde pueda buscar más información sobre los GUID que ha declarado? Gracias: D – Danny

+0

noP, ver la respuesta revisada ,, btw lol, soy * no un [alot] (http://hyperboleandahalf.blogspot.co.uk/2010/04/alot-is-better-than-you-at -todo.html) XD – violet313

+1

Ojalá pudiera votar esto más de una vez. Debe haber puesto mucho esfuerzo en esta respuesta. Tengo una información más para agregar, después de haber estado agitado por más de un día buscándolo: si su dispositivo es un dispositivo WinUSB, entonces el GUID que pase a 'SetupDiEnumDeviceInterfaces()' será el valor "DeviceInterfaceGUIDs" del registro/inf archivo. Dudo mucho que esto esté documentado en cualquier lugar. –

3

El problema comienza con la forma en que se llama a SetupDiGetClassDevs.

Si usted está buscando para obtener una ruta de dispositivo, utilice SetupDiGetClassDevs (& GUID_DEVINTERFACE_USB_DEVICE ,,,)

SetupDiEnumDeviceInterfaces falla con el error 259 si se le da la SetupDiGetClassDevs mal GUID en ClassGuid que dice MS Ayuda es Un puntero al GUID para una clase de configuración de dispositivo o una clase de interfaz de dispositivo.

Incluir archivo devguid.h contiene un conjunto de valores GUID_DEVCLASS. Estos son NOT lo mismo que los valores GUID_DEVINTERFACE_ * que es el que necesita.

Use #include <uuids.h> que incluye ksuuids.h donde encontrará GUID_DEVINTERFACE_ * valores.

Hay una explicación más detallada en mi sitio web, con algún código fuente que debería ayudar a enumerar correctamente los dispositivos USB.

Ver http://pixcl.com/SetupDiEnumInterfaces_Fail.htm

Cuestiones relacionadas