[windows]Lister les peripheriques USB

Programmation d'applications complexes
cha0s
Messages : 681
Inscription : sam. 05/mars/2005 16:09

[windows]Lister les peripheriques USB

Message par cha0s »

Je suis en train de porter un code en C++ pour lister les périphériques USB cependant mes connaissances en api Windows sont plutôt limité (en tout cas c'est plus simple sous linux ^^') c'est pourquoi j'en appelle aux gourous en win32 du forum.

le code n'est pas très propres j'ai essayé de faire au plus simple.

Code : Tout sélectionner

#DIGCF_DEVICEINTERFACE = 16 ;10 en hexa


Structure SP_DEVICE_INTERFACE_DATA
  cbSize.l
  InterfaceClassGuid.GUID
  Flags.l
  Reserved.l
EndStructure


Structure SP_DEVICE_INTERFACE_DETAIL_DATA_A
  cbSize.w;
  DevicePath.s;
EndStructure

Prototype SDEDI(a,b,c,d,e)
Prototype SDGDID(DeviceInfoSet.l, DeviceInterfaceData.l, *DeviceInterfaceDetailData, DeviceInterfaceDetailDataSize.l, *RequiredSize,  *DeviceInfoData)
Prototype SDDDIL(DeviceInfoSet.l)
Prototype ProtoHidD_GHG(*GUID.GUID)






;=========================================================================================
;chargement de la lib Setupapi
;=========================================================================================
setupapi = OpenLibrary(#PB_Any,"Setupapi.dll")
SetupDiEnumDeviceInterfaces.SDEDI = GetFunction(setupapi,"SetupDiEnumDeviceInterfaces")
SetupDiGetDeviceInterfaceDetail.SDGDID = GetFunction(setupapi,"SetupDiGetDeviceInterfaceDetailW")
SetupDiDestroyDeviceInfoList.SDDDIL = GetFunction(setupapi,"SetupDiDestroyDeviceInfoList")


;=========================================================================================
;chargement de la lib Human Interface Device
;=========================================================================================
hid = OpenLibrary(#PB_Any, "hid.dll")
HidD_GetHidGuid.ProtoHidD_GHG = GetFunction(hid, "HidD_GetHidGuid")


;=========================================================================================
;-start
;=========================================================================================
*guid.GUID = AllocateMemory(SizeOf(GUID))
HidD_GetHidGuid(*guid)
hIntDevInfo = SetupDiGetClassDevs_(*guid, #Null, #Null, #DIGCF_DEVICEINTERFACE)
*didata.SP_DEVICE_INTERFACE_DATA = AllocateMemory(SizeOf(SP_DEVICE_INTERFACE_DATA))
*didata\cbSize = SizeOf(SP_DEVICE_INTERFACE_DATA)
didetail.SP_DEVICE_INTERFACE_DETAIL_DATA_A
Size.l
index = 0
While SetupDiEnumDeviceInterfaces(hIntDevInfo, #Null, *guid, index, *didata)
  Debug "found"
  Size = 0
  Debug SetupDiGetDeviceInterfaceDetail(hIntDevInfo, *didata, #Null, 0, @Size, #Null);
  Debug GetLastError_()
  
  
  index + 1
Wend

le debugeur me donne :
found
0
122
found
0
122

la fonction SetupDiGetDeviceInterfaceDetail renvoie vrai(#true) en cas de réussite donc il y a un problème comme le confirme le GetLastError qui renvoie l'erreur 122 qui correspond a ERROR_INSUFFICIENT_BUFFER.

cependant j'ai passé tout l'après midi a trouver le pourquoi du comment sans succès, si quelqu'un a une idée ......
Anonyme

Message par Anonyme »

et le code en c++ , tu peut le collé ?
cha0s
Messages : 681
Inscription : sam. 05/mars/2005 16:09

Message par cha0s »

voici la partie qui m'intéresse

Code : Tout sélectionner

	GUID guid;
	HidD_GetHidGuid(&guid);

	// get a handle to all devices that are part of the HID class
	// Brian: Fun fact:  DIGCF_PRESENT worked on my machine just fine.  I reinstalled
	//        Vista, and now it no longer finds the Wiimote with that parameter enabled...
	HDEVINFO dev_info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE);// | DIGCF_PRESENT);
	if(!dev_info) {
		WARN(_T("couldn't get device info"));
		return false;
		}

	// enumerate the devices
	SP_DEVICE_INTERFACE_DATA didata;
	didata.cbSize = sizeof(didata);
	
	unsigned index			= 0;
	unsigned wiimotes_found = 0;
	while(SetupDiEnumDeviceInterfaces(dev_info, NULL, &guid, index, &didata))
		{
		// get the buffer size for this device detail instance
		DWORD req_size = 0;
		SetupDiGetDeviceInterfaceDetail(dev_info, &didata, NULL, 0, &req_size, NULL);

		// (bizarre way of doing it) create a buffer large enough to hold the
		//  fixed-size detail struct components, and the variable string size
		SP_DEVICE_INTERFACE_DETAIL_DATA *didetail =
								(SP_DEVICE_INTERFACE_DETAIL_DATA*) new BYTE[req_size];
		_ASSERT(didetail);
		didetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

		// now actually get the detail struct
		if(!SetupDiGetDeviceInterfaceDetail(dev_info, &didata, didetail,
											req_size, &req_size, NULL)) {
			WARN(_T("couldn't get devinterface info for %u"), index);
			break;
			}

		// open a shared handle to the device to query it (this will succeed even
		//  if the wiimote is already Connect()ed)
		DEEP_TRACE(_T(".. querying device %s"), didetail->DevicePath);
		Handle = CreateFile(didetail->DevicePath, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
												  NULL, OPEN_EXISTING, 0, NULL);
		if(Handle == INVALID_HANDLE_VALUE) {
			DEEP_TRACE(_T(".... failed with err %x (probably harmless)."), 
					   GetLastError());
			goto skip;
			}
	
		// get the device attributes
		HIDD_ATTRIBUTES attrib;
		attrib.Size = sizeof(attrib);
		if(HidD_GetAttributes(Handle, &attrib))
			{
			// is this a wiimote?
			if((attrib.VendorID != VID) || (attrib.ProductID != PID))
				goto skip;

			// yes, but is it the one we're interested in?
			++wiimotes_found;
			if((wiimote_index != FIRST_AVAILABLE) &&
			   (wiimote_index != wiimotes_found))
				goto skip;

			// the wiimote is installed, but it may not be currently paired:
			if(wiimote_index == FIRST_AVAILABLE)
				TRACE(_T(".. opening Wiimote %u:"), wiimotes_found);
			else
				TRACE(_T(".. opening:"));

			// re-open the handle, but this time we don't allow write sharing
			//  (that way subsequent calls can still _discover_ wiimotes above, but
			//   will correctly fail here if they're already connected)
			CloseHandle(Handle);
			Handle = CreateFile(didetail->DevicePath, GENERIC_READ|GENERIC_WRITE,
													FILE_SHARE_READ,
													NULL, OPEN_EXISTING,
													FILE_FLAG_OVERLAPPED, NULL);
			if(Handle == INVALID_HANDLE_VALUE) {
				TRACE(_T(".... failed with err %x"), GetLastError());
				goto skip;
				}

			// clear the wiimote state & buffers
			Clear		  (false);		// preserves existing deadzones
			Internal.Clear(false);		// "
			InternalChanged = NO_CHANGE;
			memset(ReadBuff , 0, sizeof(ReadBuff));
			bConnectionLost = false;
			
			// enable async reading
			BeginAsyncRead();

			// autodetect which write method the Bluetooth stack supports,
			//  by requesting the wiimote status report:
			if(force_hidwrites && !_HidD_SetOutputReport) {
				TRACE(_T(".. can't force HID writes (not supported)"));
				force_hidwrites = false;
				}

			if(force_hidwrites)
				TRACE(_T(".. (HID writes forced)"));
			else{
				//  - try WriteFile() first as it's the most efficient (it uses
				//     harware interrupts where possible and is async-capable):
				bUseHIDwrite = false;
				RequestStatusReport();
				//  and wait for the report to arrive:
				DWORD last_time = timeGetTime();
				while(!bStatusReceived && ((timeGetTime()-last_time) < 500))
					Sleep(5);
				TRACE(_T(".. WriteFile() %s."), bStatusReceived? _T("succeeded") :
																 _T("failed"));
				}

			// try HID write method (if supported)
			if(!bStatusReceived && _HidD_SetOutputReport)
				{
				bUseHIDwrite = true;
				RequestStatusReport();
				// wait for the report to arrive:
				DWORD last_time = timeGetTime();
				while(!bStatusReceived && ((timeGetTime()-last_time) < 500))
					Sleep(5);
				// did we get it?
				TRACE(_T(".. HID write %s."), bStatusReceived? _T("succeeded") :
															   _T("failed"));
				}

			// still failed?
			if(!bStatusReceived) {
				WARN(_T("output failed - wiimote is not connected (or confused)."));
				Disconnect();
				goto skip;
				}

			// connected succesfully:
			_TotalConnected++;
			// reset it
			Reset();
			// read the wiimote calibration info
			ReadCalibration();
			// refresh the public state from the internal one (so that extension
			//  status etc. is available straight away)
			_RefreshState(false);
			// and show when we want to trigger the next periodic status request
			//  (for battery level and connection loss detection)
			NextStatusTime = timeGetTime() + REQUEST_STATUS_EVERY_MS;

			// tidy up
			delete[] (BYTE*)didetail;
			break;
			}
gnozal
Messages : 832
Inscription : mar. 07/déc./2004 17:35
Localisation : France
Contact :

Re: [windows]Lister les peripheriques USB

Message par gnozal »

cha0s a écrit :... la fonction SetupDiGetDeviceInterfaceDetail renvoie vrai(#true) en cas de réussite donc il y a un problème comme le confirme le GetLastError qui renvoie l'erreur 122 qui correspond a ERROR_INSUFFICIENT_BUFFER.
Selon MSDN, on est sensé travailler en 2 temps : [1] demander la taille du buffer nécessaire puis [2] allouer ce buffer et appeler la fonction une 2ème fois.
Using this function to get details about an interface is typically a two-step process:
Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a NULL DeviceInterfaceDetailData pointer, a DeviceInterfaceDetailDataSize of zero, and a valid RequiredSize variable. In response to such a call, this function returns the required buffer size at RequiredSize and fails with GetLastError returning ERROR_INSUFFICIENT_BUFFER.
Allocate an appropriately sized buffer and call the function again to get the interface details.
cha0s
Messages : 681
Inscription : sam. 05/mars/2005 16:09

Message par cha0s »

Mon anglais laisse a désirer donc j'ai vite lu la doc en effet sa marche mieux de cette manière :

Code : Tout sélectionner

*didetail.SP_DEVICE_INTERFACE_DETAIL_DATA_A
Size.l
index = 0
While SetupDiEnumDeviceInterfaces(hIntDevInfo, #Null, *guid, index, *didata)
  Debug "found"
  Size = 0
  SetupDiGetDeviceInterfaceDetail(hIntDevInfo, *didata, #Null, 0, @Size, #Null);
  *didetail = AllocateMemory(Size)
  *didetail\cbSize = SizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
  
  Debug SetupDiGetDeviceInterfaceDetail(hIntDevInfo, *didata, *didetail, Size, @Size, #Null)
  Debug *didetail\DevicePath
  index + 1
Wend

cependant je doit avoir fait une faute quelques part car le debugeur me sort quelques chose de difficile a lire
[quote]found
1
Ž3DΑ=DΔWDΗ\DΚyDÎ
Répondre