Ermittlung der Gerätepfadnamen von USB HIDs klappt nicht.

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Holger
Beiträge: 53
Registriert: 25.02.2005 21:17

Ermittlung der Gerätepfadnamen von USB HIDs klappt nicht.

Beitrag von Holger »

Beim zweiten Aufruf der Funktion "SetupDiGetDeviceInterfaceDetailA_()" sollte der String des Gerätepfadnamens vom HIDs im DetailDataBuffer+4
stehen. Der folgende Code funktioniert bis dahin, nur es wird kein Pfadname zurückgegeben.
Der Code soll alle angeschlossenen HIDs scannen ( funktioniert z.B. mit einem USB Joystick und allen anderen HIDs ). Der MemberIndex steht momentan noch auf 0, da ich nur ein HID angeschlossen habe.
Was mache ich falsch ???
Der orginale und funktionierende VB Code:

http://www.lvr.com/files/usbhidio2.zip

Die MSDN: http://www.msdn.microsoft.com/library/

Code: Alles auswählen

OpenLibrary(0,"hid.dll")
OpenLibrary(1,"setupapi.dll")
Debug "HidD_GetHidGuid Zeiger: "+Str(IsFunction(0,"HidD_GetHidGuid"))
Debug "SetupDiGetClassDevsA Zeiger: "+Str(IsFunction(1,"SetupDiGetClassDevsA"))
Debug "SetupDiEnumDeviceInterfaces Zeiger: "+Str(IsFunction(1,"SetupDiEnumDeviceInterfaces"))
Debug "SetupDiGetDeviceInterfaceDetailA Zeiger: "+Str(IsFunction(1,"SetupDiGetDeviceInterfaceDetailA"))

*HidGuid=AllocateMemory(16)   ;128bit HID Guid
CallFunction(0,"HidD_GetHidGuid",*HidGuid)
*DeviceInfoSet=CallFunction(1,"SetupDiGetClassDevsA",*HidGuid,0,0,$2|$10)
Debug "DeviceInfoSet Zeiger: "+Str(*DeviceInfoSet)

Structure SP_DEVICE_INTERFACE_DATA
cbSize.l
InterfaceClassGuid1.l[1]
InterfaceClassGuid2.w[2]
InterfaceClassGuid3.b[8]
Flags.l
Reserved.l
EndStructure

Structure SP_DEVICE_INTERFACE_DETAIL_DATA
cbSize.l
DevicePath.s
EndStructure

DeviceInterfaceData.SP_DEVICE_INTERFACE_DATA
DeviceInterfaceDetailData.SP_DEVICE_INTERFACE_DETAIL_DATA

DeviceInterfaceData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DATA)

MemberIndex.l=0

Result.l=CallFunction(1,"SetupDiEnumDeviceInterfaces",*DeviceInfoSet,0,*HidGuid,MemberIndex,DeviceInterfaceData)
Debug "InterfaceClassGuid Data1= "+Hex(DeviceInterfaceData\InterfaceClassGuid1)
Debug "InterfaceClassGuid Data2= "+Hex(DeviceInterfaceData\InterfaceClassGuid2[0])
Debug "InterfaceClassGuid Data3= "+Hex(DeviceInterfaceData\InterfaceClassGuid2[1])
Debug "Flags= "+Str(DeviceInterfaceData\Flags)

RequiredSize.l

Result.l=CallFunction(1,"SetupDiGetDeviceInterfaceDetailA",*DeviceInfoSet,DeviceInterfaceData,0,0,@RequiredSize,0)
Debug "Erster SetupDiGetDeviceInterfaceDetailA() Aufruf: RequiredSize= "+Str(RequiredSize)

DetailData.l=RequiredSize

DeviceInterfaceDetailData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA)

Dim DetailDataBuffer.b(RequiredSize)

RtlMoveMemory_(@DetailDataBuffer(0),@DeviceInterfaceDetailData\cbSize,4)
Debug DetailDataBuffer(0)
Debug DeviceInterfaceDetailData\cbsize

Debug Result.l=CallFunction(1,"SetupDiGetDeviceInterfaceDetailA",*DeviceInfoSet,DeviceInterfaceData,@DetailDataBuffer,DetailData,@RequiredSize,0)
Debug PeekS(@DetailDataBuffer+4)

End
Eventuell liegt es an der Struktur DeviceInterfaceData, in der eine 16Byte InterfaceClassGuid geschrieben wird ?
Kann man in einer Struktur eine Variable deklarieren, die länger als Long ist ( eben die 16Byte der Guid), ohne auf Arrays zurückgreifen zu müssen ?

Vielen Dank für die Antwort(en)
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Ermittlung der Gerätepfadnamen von USB HIDs klappt nicht

Beitrag von ts-soft »

Holger hat geschrieben: Kann man in einer Struktur eine Variable deklarieren, die länger als Long ist ( eben die 16Byte der Guid), ohne auf Arrays zurückgreifen zu müssen ?

Vielen Dank für die Antwort(en)
Die GUID-Struktur ist in PB schon deklariert und hat auch 16 Byte.

Code: Alles auswählen

Structure Test
  test.GUID
EndStructure
Mußte in etwa so einbauen, ich hoffe das hilft
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Habs jetzt mal umgestellt, obs was nützt weiß ich nicht :wink:

Code: Alles auswählen

OpenLibrary(0,"hid.dll")
OpenLibrary(1,"setupapi.dll")
Debug "HidD_GetHidGuid Zeiger: "+Str(IsFunction(0,"HidD_GetHidGuid"))
Debug "SetupDiGetClassDevsA Zeiger: "+Str(IsFunction(1,"SetupDiGetClassDevsA"))
Debug "SetupDiEnumDeviceInterfaces Zeiger: "+Str(IsFunction(1,"SetupDiEnumDeviceInterfaces"))
Debug "SetupDiGetDeviceInterfaceDetailA Zeiger: "+Str(IsFunction(1,"SetupDiGetDeviceInterfaceDetailA"))

;*HidGuid=AllocateMemory(16)   ;128bit HID Guid
HidGuid.GUID
CallFunction(0,"HidD_GetHidGuid",HidGuid)
*DeviceInfoSet=CallFunction(1,"SetupDiGetClassDevsA",HidGuid,0,0,$2|$10)
Debug "DeviceInfoSet Zeiger: "+Str(*DeviceInfoSet)

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

Structure SP_DEVICE_INTERFACE_DETAIL_DATA
cbSize.l
DevicePath.s
EndStructure

DeviceInterfaceData.SP_DEVICE_INTERFACE_DATA
DeviceInterfaceDetailData.SP_DEVICE_INTERFACE_DETAIL_DATA

DeviceInterfaceData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DATA)

MemberIndex.l=0

Result.l=CallFunction(1,"SetupDiEnumDeviceInterfaces",*DeviceInfoSet,0,HidGuid,MemberIndex,DeviceInterfaceData)
Debug "InterfaceClassGuid Data1= " + Hex(DeviceInterfaceData\InterfaceClassGuid\Data1)
;Debug "InterfaceClassGuid Data1= "+Hex(DeviceInterfaceData\InterfaceClassGuid1)
Debug "InterfaceClassGuid Data2= " + Hex(DeviceInterfaceData\InterfaceClassGuid\Data2)
;Debug "InterfaceClassGuid Data2= "+Hex(DeviceInterfaceData\InterfaceClassGuid2[0])
Debug "InterfaceClassGuid Data3= " + Hex(DeviceInterfaceData\InterfaceClassGuid\Data3)
;Debug "InterfaceClassGuid Data3= "+Hex(DeviceInterfaceData\InterfaceClassGuid2[1])
Debug "InterfaceClassGuid Data4= " + Hex(DeviceInterfaceData\InterfaceClassGuid\Data4)
Debug "Flags= "+Str(DeviceInterfaceData\Flags)

RequiredSize.l

Result.l=CallFunction(1,"SetupDiGetDeviceInterfaceDetailA",*DeviceInfoSet,DeviceInterfaceData,0,0,@RequiredSize,0)
Debug "Erster SetupDiGetDeviceInterfaceDetailA() Aufruf: RequiredSize= "+Str(RequiredSize)

DetailData.l=RequiredSize

DeviceInterfaceDetailData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA)

Dim DetailDataBuffer.b(RequiredSize)

RtlMoveMemory_(@DetailDataBuffer(0),@DeviceInterfaceDetailData\cbSize,4)
Debug DetailDataBuffer(0)
Debug DeviceInterfaceDetailData\cbsize

Debug Result.l=CallFunction(1,"SetupDiGetDeviceInterfaceDetailA",*DeviceInfoSet,DeviceInterfaceData,@DetailDataBuffer,DetailData,@RequiredSize,0)
Debug PeekS(@DetailDataBuffer+4)

End
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Holger
Beiträge: 53
Registriert: 25.02.2005 21:17

Beitrag von Holger »

Leider klappts immer noch nicht, aber ich kann keinen Fehler feststellen.
Mit der VB Syntax kenne ich mich aber (fast) nicht aus - wahrscheinlich liegts an dem DetailDataBuffer Array, der ja die Struktur DeviceInterface DetailData enthalten soll.

Vielen Dank für den .GUID Tipp :D

Übrigens funktioniert es auch nicht, wenn man das Array durch einen AllocateMemory() ersetzt, wie z.B. :

Code: Alles auswählen

;Dim DetailDataBuffer.b(RequiredSize)

;RtlMoveMemory_(@DetailDataBuffer(0),@DeviceInterfaceDetailData\cbSize,4)
;Debug DetailDataBuffer(0)
;Debug DeviceInterfaceDetailData\cbsize

*DetailDataBuffer.l=AllocateMemory(RequiredSize)
RtlMoveMemory_(*DetailDataBuffer,@DeviceInterfaceDetailData\cbSize,4)
Debug PeekB(*DetailDataBuffer)


Debug Result.l=CallFunction(1,"SetupDiGetDeviceInterfaceDetailA",*DeviceInfoSet,DeviceInterfaceData,*DetailDataBuffer,DetailData,@RequiredSize,0)
Debug PeekS(*DetailDataBuffer+4)

End
Zuletzt geändert von Holger am 01.10.2005 02:11, insgesamt 1-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Da ich auf VB auch keinen grossen Bock habe, hab ich mir die Sources nicht geladen, werde es aber mal nachholen, vielleicht finde ich ja noch was
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Holger
Beiträge: 53
Registriert: 25.02.2005 21:17

Beitrag von Holger »

Ich habe einen Fehler gefunden.

Code: Alles auswählen

Structure SP_DEVICE_INTERFACE_DETAIL_DATA 
cbSize.l 
DevicePath.s 
EndStructure

DeviceInterfaceDetailData.SP_DEVICE_INTERFACE_DETAIL_DATA
DeviceInterfaceDetailData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA)
Die Länge der Struktur ist laut SizeOf 8 Bytes lang. Aber warum, wenn 4 Bytes für cbSize und 1 Byte für ein String benötigt wird ? Der Speicherverbrauch wird ja im Handbuch mit Stringlänge+1 angegeben und da noch kein String in DevicePath.s eingetragen ist, müßte die Länge der Struktur 5 Bytes lang sein, oder ?

Übrigens funktioniert der zweite SetupDiGetDeviceInterfaceDetailA_() Aufruf nur, wenn in cbSize 5 eingetragen wird, was ja auch das VB Programm usbhidio.exe ( o.g. Link ) anzeigt.
Bei DevicePath.b wird die Funktion zwar erfolgreich aufgerufen, trotzdem finde ich im Array keinen String.
Unterscheidet sich der Speicherverbrauch der Strings in VB und PB ?

Die MSDN Seite zur SP_DEVICE_INTERFACE_DETAIL_DATA Struktur:
http://msdn.microsoft.com/library/defau ... ca.xml.asp
Holger
Beiträge: 53
Registriert: 25.02.2005 21:17

Beitrag von Holger »

Eben grad hab ich im Handbuch entdeckt, das der Datentyp "TChar", der in der MSDN Strukturbeschreibung bei DevicePath angegeben wird, in PureBasic als Byte oder Word definiert werden muss.
Also stimmt schon mal DevicePath.b und damit auch die Strukturlänge.
Im Array sind auch Daten, die aber erst in einen String ( und dann eventuell in Unicode ??? ) gewandelt werden müssen.
Wie wandele ich einen String in Unicode ?
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

>> Wie wandele ich einen String in Unicode ?
Mit String2Unicode.pb
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Holger
Beiträge: 53
Registriert: 25.02.2005 21:17

Beitrag von Holger »

Die Unicode Wandlung scheint nur in VB nötig zu sein, denn die Übergabe des Gerätepfadnamens an CreateFileA_() (ANSI Version) wird von der MSDN so beschrieben:
"To specify such a UNC path, use the "\\?\UNC\" prefix".

Bei der ANSI Version ist die Länge auf MAX_PATH (260 Zeichen) begrenzt.
Der von SetupDiGetDeviceInterfaceDetailA_() zurückgegebene DevicePathName hat aber nur 82 Zeichen.
Eine Kopie meiner Debugger Ausgabe:

HidD_GetHidGuid Zeiger: 1871515981
SetupDiGetClassDevsA Zeiger: 2016591180
SetupDiEnumDeviceInterfaces Zeiger: 2016514876
SetupDiGetDeviceInterfaceDetailA Zeiger: 2016594488
CreateFileA Zeiger: 2011742635
DeviceInfoSet Zeiger: 1526544
InterfaceClassGuid Data1= 4D1E55B2
InterfaceClassGuid Data2= FFFFF16F
InterfaceClassGuid Data3= 11CF
Flags= 1
Erster SetupDiGetDeviceInterfaceDetailA() Aufruf: RequiredSize= 86
Gerätpfadname: \\?\hid#vid_046d&pid_c20c#6&9a4567e&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
HidDevice Handle: 2940

Folgender Code funktioniert:

Code: Alles auswählen

OpenLibrary(0,"hid.dll") 
OpenLibrary(1,"setupapi.dll")
OpenLibrary(2,"kernel32.dll")
 
Debug "HidD_GetHidGuid Zeiger: "+Str(IsFunction(0,"HidD_GetHidGuid")) 
Debug "SetupDiGetClassDevsA Zeiger: "+Str(IsFunction(1,"SetupDiGetClassDevsA")) 
Debug "SetupDiEnumDeviceInterfaces Zeiger: "+Str(IsFunction(1,"SetupDiEnumDeviceInterfaces")) 
Debug "SetupDiGetDeviceInterfaceDetailA Zeiger: "+Str(IsFunction(1,"SetupDiGetDeviceInterfaceDetailA")) 
Debug "CreateFileA Zeiger: "+Str(IsFunction(2,"CreateFileA"))

HidGuid.GUID 
CallFunction(0,"HidD_GetHidGuid",HidGuid) 
*DeviceInfoSet=CallFunction(1,"SetupDiGetClassDevsA",HidGuid,0,0,$2|$10) 
Debug "DeviceInfoSet Zeiger: "+Str(*DeviceInfoSet) 

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

Structure SP_DEVICE_INTERFACE_DETAIL_DATA 
cbSize.l 
DevicePath.b
EndStructure 

DeviceInterfaceData.SP_DEVICE_INTERFACE_DATA 
DeviceInterfaceDetailData.SP_DEVICE_INTERFACE_DETAIL_DATA 

DeviceInterfaceData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DATA)

MemberIndex.l=0 

Result.l=CallFunction(1,"SetupDiEnumDeviceInterfaces",*DeviceInfoSet,0,HidGuid,MemberIndex,DeviceInterfaceData) 
Debug "InterfaceClassGuid Data1= " + Hex(DeviceInterfaceData\InterfaceClassGuid\Data1) 
Debug "InterfaceClassGuid Data2= " + Hex(DeviceInterfaceData\InterfaceClassGuid\Data2) 
Debug "InterfaceClassGuid Data3= " + Hex(DeviceInterfaceData\InterfaceClassGuid\Data3)
Debug "Flags= "+Str(DeviceInterfaceData\Flags) 

RequiredSize.l 

Result.l=CallFunction(1,"SetupDiGetDeviceInterfaceDetailA",*DeviceInfoSet,DeviceInterfaceData,0,0,@RequiredSize,0) 
Debug "Erster SetupDiGetDeviceInterfaceDetailA() Aufruf: RequiredSize= "+Str(RequiredSize) 

DetailData=RequiredSize 
DeviceInterfaceDetailData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA) 

Dim DetailDataBuffer.b(RequiredSize) 

RtlMoveMemory_(@DetailDataBuffer(0),@DeviceInterfaceDetailData\cbSize,4) 
 
CallFunction(1,"SetupDiGetDeviceInterfaceDetailA",*DeviceInfoSet,DeviceInterfaceData,@DetailDataBuffer(0),DetailData,@RequiredSize,0)

DevicePathName.s=PeekS(@DetailDataBuffer(4))
Debug "Gerätpfadname: "+DevicePathName

HidDevice.l=CallFunction(2,"CreateFileA",@DevicePathName,$80000000|$40000000,$1|$2,0,3,0,0)
;oder
;HidDevice.l=CreateFile_(@DevicePathName,$80000000|$40000000,$1|$2,0,3,0,0)

Debug "HidDevice Handle: "+Str(HidDevice)

End
Allerdings weiß ich nicht, ob das Handle stimmt, da usbhidio.exe als Handle 90h ausgibt. Bestehen Unterschiede zwischen der in PureBasic unterstützen Funktion "CreateFile_()" und dem Aufruf per CallFunction(), bei dem die Funktion "CreateFileA" benutzt wird?
Beides gibt mir dasselbe Handle zurück.

Wie ist der Funktionsname bei UniCode Funktionen ( bei ANSI ist die Endung ja "A" ) und warum gibt mir usbhidio.exe ein Handle mit 90h zurück ?
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Es besteht zur Zeit kein Unterschied zwischen "CreateFile_()" und "CreateFileA", da PB bis einschließlich 3.94 immer die ANSI-Version benutzt!

Dieselbe Funktion als Unicode endet mit W statt A
Den Rest kann ich Dir nicht beantworten
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten