Ermittlung der Gerätepfadnamen von USB HIDs klappt nicht.

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
bingo
Beiträge: 118
Registriert: 16.09.2004 18:33
Wohnort: thüringen
Kontaktdaten:

Beitrag von bingo »

habe mal diesen thread als anregung benutzt ... :wink:

Code: Alles auswählen

;auflisten aller HDDs per DiskClassGuid

DiskClassGuid.GUID

DiskClassGuid\Data1 = $53f56307
DiskClassGuid\Data2 = $b6bf
DiskClassGuid\Data3 = $11d0
DiskClassGuid\Data4[0] = $94
DiskClassGuid\Data4[1] = $f2
DiskClassGuid\Data4[2] = $00
DiskClassGuid\Data4[3] = $a0
DiskClassGuid\Data4[4] = $c9
DiskClassGuid\Data4[5] = $1e
DiskClassGuid\Data4[6] = $fb
DiskClassGuid\Data4[7] = $8b

#DIGCF_PRESENT = 2
#DIGCF_INTERFACEDEVICE = $10

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

DeviceInterfaceInfoData.SP_DEVICE_INTERFACE_DATA
DeviceInterfaceInfoData\cbSize=SizeOf(DeviceInterfaceInfoData) 

Structure SP_DEVINFO_DATA 
  cbSize.l 
  ClassGuid.GUID 
  DevInst.l 
  Reserved.l 
EndStructure 

DeviceInfoData.SP_DEVINFO_DATA
DeviceInfoData\cbSize=SizeOf(DeviceInfoData) 

Structure SP_DEVICE_INTERFACE_DETAIL_DATA
cbSize.l
DevicePath.b[#ANYSIZE_ARRAY]
EndStructure

DEVICE_INTERFACE_DETAIL_DATA.SP_DEVICE_INTERFACE_DETAIL_DATA
DEVICE_INTERFACE_DETAIL_DATA\cbSize=SizeOf(DEVICE_INTERFACE_DETAIL_DATA) 

hDeviceInfoSet = SetupDiGetClassDevs_(@DiskClassGuid,0,0,#DIGCF_PRESENT|#DIGCF_INTERFACEDEVICE)

#SPDRP_HARDWAREID = 1

buffer = 500
*MemoryID = AllocateMemory(buffer)

i=0 
OpenLibrary(1,"setupapi.dll")
*F1 = IsFunction(1, "SetupDiEnumDeviceInterfaces") 
*F2 = IsFunction(1, "SetupDiGetDeviceInterfaceDetailA")
*F3 = IsFunction(1, "SetupDiGetDeviceRegistryPropertyA") 

While CallFunctionFast(*F1,hDeviceInfoSet,0,@DiskClassGuid,i,@DeviceInterfaceInfoData)
i+1 

CallFunctionFast(*F2,hDeviceInfoSet,@DeviceInterfaceInfoData,0,0,@laenge,@DeviceInfoData)

Dim DetailDataBuffer.b(laenge) 

RtlMoveMemory_(@DetailDataBuffer(0),@DEVICE_INTERFACE_DETAIL_DATA\cbSize,4) 

CallFunctionFast(*F2,hDeviceInfoSet,@DeviceInterfaceInfoData,@DetailDataBuffer(0),laenge,@tmp,0)

Debug PeekS(@DetailDataBuffer(4))

CallFunctionFast(*F3,hDeviceInfoSet,@DeviceInfoData,#SPDRP_HARDWAREID,0,*MemoryID,buffer,@laengehid) 

Debug PeekS(*MemoryID)
zeromemory_(*MemoryID,buffer)

hdevice = CreateFile_(PeekS(@DetailDataBuffer(4)),#GENERIC_READ|#GENERIC_WRITE,#FILE_SHARE_READ|#FILE_SHARE_WRITE,0,#OPEN_EXISTING,0,0)

;weitere operationen nun möglich mit DeviceIoControl...
Debug hdevice

Wend

SetupDiDestroyDeviceInfoList_(hDeviceInfoSet) 

CloseLibrary(1) 

FreeMemory(*MemoryID)
...um geräte anhand von klassen zu finden .
1:0>1
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 »

@bingo
:allright: funzt
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 »

So, funktioniert:

Code: Alles auswählen

OpenLibrary(0,"hid.dll") 
OpenLibrary(1,"setupapi.dll")
 
HidGuid.GUID 
CallFunction(0,"HidD_GetHidGuid",HidGuid) 
*DeviceInfoSet=CallFunction(1,"SetupDiGetClassDevsA",HidGuid,0,0,$2|$10)

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

Structure HIDD_ATTRIBUTES
size.l
VendorID.w
ProductID.w
VersionNumber.w
EndStructure

Structure HIDP_CAPS
Usage.w
UsagePage.w
InputReportByteLength.w
OutputReportByteLength.w
FeatureReportByteLength.w
Reserved.w[17]
NumberLinkCollectionNodes.w
NumberInputButtonCaps.w
NumberInputValueCaps.w
NumberInputDataIndices.w
NumberOutputButtonCaps.w
NumberOutputValueCaps.w
NumberOutputDataIndices.w
NumberFeatureButtonCaps.w
NumberFeatureValueCaps.w
NumberFeatureDataIndices.w
EndStructure
 

DeviceInterfaceData.SP_DEVICE_INTERFACE_DATA 
DeviceInterfaceDetailData.SP_DEVICE_INTERFACE_DETAIL_DATA 
DeviceAttributes.HIDD_ATTRIBUTES
DeviceCaps.HIDP_CAPS

MemberIndex.l=0

;Beginn der HID Erkennung

Repeat

DeviceInterfaceData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DATA)

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=CreateFile_(@DevicePathName,$80000000|$40000000,$1|$2,0,3,0,0)

Debug "HidDevice Handle: "+Str(HidDevice)

DeviceAttributes\Size=SizeOf(HIDD_ATTRIBUTES)

CallFunction(0,"HidD_GetAttributes",HidDevice,DeviceAttributes)
Debug "VendorID: "+Hex(DeviceAttributes\VendorID)
Debug "ProductID: "+Hex(DeviceAttributes\ProductID)
Debug "Versionsnummer: "+Hex(DeviceAttributes\VersionNumber)

MemberIndex=MemberIndex+1

Until Result=0

;Ende der HID Erkennung

;Die Repeat/Until Schleife kann man mit bekannten Vendor-/ProductIDs vergleichen
;um sie bei Erreichen des gesuchten HIDs zu verlassen.
;Das Handle (HidDevice.l) des HIDs wird für andere HidD_xxx Funktionen benötigt.
;Falls die "SetupDiGetDeviceInterfaceDetailA" Funktion Result=0 ausgibt, ist
;kein weiteres HID verfügbar.
;Jetzt ist per WriteFile_() / Read_File_() ein Datentransfer möglich, falls
;man alle Eigenschaften des HID kennt
;falls nicht, weiter ...

;---------------------------------------------------------------------------
;um an weitere Infos des aktuellen HIDs zu kommen ( wie z.B. Hersteller- /
;Produktstring:  

;WideChar Konvertierung
;eine andere Lösung fiel mir für den Test nicht ein, vielleicht gibt es
;dafür eine API Funktion ?

Dim StringWide.b(100) ; 100Bytes müßten ausreichen

CallFunction(0,"HidD_GetManufacturerString",HidDevice,@StringWide(0),100)
String.s=""
For a=0 To 50
String.s=String+PeekS(@StringWide(0+(a*2)))
Next
Debug "Manufacturer: "+String

CallFunction(0,"HidD_GetProductString",HidDevice,@StringWide(0),100)
String.s=""
For a=0 To 50
String.s=String+PeekS(@StringWide(0+(a*2)))
Next
Debug "Product: "+String

;weitere nützliche HidD_xxx Funktionen im DDK oder auf der MSDN

;---------------------------------------------------------------------------
;noch mehr HID Infos ( z.B. Länge der Input / Output Reports )
;per HidP_xxx Funktionen: 
;"HidD_GetPreparsedData" muss einmalig vor einer oder mehreren
;HidP_xxx Funktion(en) aufgerufen werden

*PreparsedData.l
CallFunction(0,"HidD_GetPreparsedData",HidDevice,@*PreparsedData.l)

CallFunction(0,"HidP_GetCaps",*PreparsedData,DeviceCaps)
Debug "Input Report Länge: "+Str(DeviceCaps\InputReportByteLength)
Debug "Output Report Länge: "+Str(DeviceCaps\OutputReportByteLength)

;weitere nützliche HidP_xxx Funktionen im DDK oder auf der MSDN
;z.B. für Mengen an Infos: HidP_GetValueCaps_()

;---------------------------------------------------------------------------
;Beim Beenden des HID Kommunikation müssen die Ressourcen freigegen werden:

CallFunction(0,"HidD_FreePreparsedData",*PreparsedData)
CallFunction(1,"SetupDiDestroyDeviceInfoList",*DeviceInfoSet)
CloseHandle_(HidDevice)

End
Ich hoffe, daß kein Fehler drinsteckt, weil ich nur einen USB Joystick dranhabe, aber die Schleife müßte funktionieren
( ein Device muss aber eingestöpselt sein, da die Schleife ohne If/EndIf mindestens einmal durchläuft ).

Ist in erster Linie für diejenigen interessant, die ein eigenes HID bauen ( HIDs, wie z.B. Mäuse oder Joysticks werden ja von PB unterstützt ).
An den Datentransfer mit WriteFile_() / ReadFile_() werde ich mich dransetzen, wenn ich es geschafft habe, daß mein USB Interface von Windows als HID erkannt wird.

Vielleicht gibt es hier noch andere USB Bastler? Ich benutze den NationalSemiconductor USBN9603...

Nochmals vielen Dank für die Antworten

PS: Habe vergessen, die beiden Libs zu schließ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

Beitrag von ts-soft »

@Holger
Zeile 145 gibts nen Speicherzugriffsfehler. Bis auf die ersten Werte, ist alles leer. Hab allerdings nur ne Maus und nen ausgeschalteten Drucker über USB angeschlossen.
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 »

Eventuell liegts an dem Reserved Array in der HIDP_CAPS Struktur. Das Array wird in der MSDN mit 17 Words angegeben.
Vielleicht das Array in der Struktur mit 16 Words angeben, denn 0-16 sind ja 17 Words ?
Kannst Du mal bitte den "Result.l" debuggen und den MemberIndex auf 0 und 1 setzen ?
Wenn Result 0 ergibt, wird die Maus nicht als HID erkannt.
Bitte auch noch Deine Debuggerwerte.

Übrigens mit v3.94 geschrieben.

Mein Debugger:

MemberIndex: 0
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: 892
VendorID: 46D
ProductID: FFFFC20C
Versionsnummer: 103
Manufacturer: Logitech
Product: WingMan Precision USB
Input Report Länge: 4
Output Report Länge: 0

Wenn ich am Anfang den MemberIndex auf 1 setze, bekomme ich:

MemberIndex: 1
InterfaceClassGuid Data1= 0
InterfaceClassGuid Data2= 0
InterfaceClassGuid Data3= 0
Flags= 0
Erster SetupDiGetDeviceInterfaceDetailA() Aufruf: RequiredSize= 0

Dann brichts ab und ich bekomme den Error "Array index out of bounds"
bei Zeile 80 DevicePathName.s=PeekS(@DetailDataBuffer(4)).
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 »

Bei MemberIndex 0:
InterfaceClassGuid Data1= 4D1E55B2
InterfaceClassGuid Data2= FFFFF16F
InterfaceClassGuid Data3= 11CF
Flags= 1
Erster SetupDiGetDeviceInterfaceDetailA() Aufruf: RequiredSize= 86
Gerätpfadname: \\?\hid#vid_05fe&pid_0011#6&e7bdac4&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
HidDevice Handle: -1
VendorID: 0
ProductID: 0
Versionsnummer: 0
Manufacturer:
Product:
und Fehler in Zeile 144

Bei MemberIndex1 ist der Fehler bereits in Zeile 80 und alle Debuggerausgaben sind 0
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 »

Der Gerätepfad wird ermittelt, allerdings schlägt in Zeile 83 die Ermittlung des Handles fehl (HidDevice=-1):

Code: Alles auswählen

HidDevice.l=CreateFile_(@DevicePathName,$80000000|$40000000,$1|$2,0,3,0,0)
Wenn ich diese Zeile ersetze durch

Code: Alles auswählen

HidDevice.l=CreateFile_(@DevicePathName,0,0,0,3,0,0)
bekomme ich dieselben DebuggerWerte - funktioniert bei mir also.
Aber mit den Konstanten blicke ich sowieso noch nicht durch.
Wie bekomme ich die Werte der Konstanten, die in der MSDN mit z.B. GENERIC_READ oder FILE_SHARE_WRITE beschrieben werden ?

MSDN: http://msdn.microsoft.com/library/defau ... tefile.asp

Eventuell liegts daran, daß die Maus im System schon aktiviert wurde, eine Art Schutzfunktion von Windows, die den Zugriff verweigert ?
Holger
Beiträge: 53
Registriert: 25.02.2005 21:17

Beitrag von Holger »

Auweia, schlimmer Fehler ;)
Die Konstanten hat ja PB schon drin ...

Code: Alles auswählen

HidDevice.l=CreateFile_(@DevicePathName,#GENERIC_READ|#GENERIC_WRITE,#FILE_SHARE_READ|#FILE_SHARE_WRITE,0,#OPEN_EXISTING,0,0)
Danke an bingo :D

Heute werde ich mich durch die Konstanten in CreateFile_() durchgraben, aber jetzt erstmal ab ins Bett ...
Holger
Beiträge: 53
Registriert: 25.02.2005 21:17

Beitrag von Holger »

Jetzt funktioniert es bei allen HIDs ( ich habe eine Maus und einen Joystick dran).

Code: Alles auswählen

OpenLibrary(0,"hid.dll") 
OpenLibrary(1,"setupapi.dll")
 
HidGuid.GUID 
CallFunction(0,"HidD_GetHidGuid",HidGuid) 
*DeviceInfoSet=CallFunction(1,"SetupDiGetClassDevsA",HidGuid,0,0,$2|$10)

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

Structure HIDD_ATTRIBUTES
size.l
VendorID.w
ProductID.w
VersionNumber.w
EndStructure

DeviceInterfaceData.SP_DEVICE_INTERFACE_DATA 
DeviceInterfaceDetailData.SP_DEVICE_INTERFACE_DETAIL_DATA 
DeviceAttributes.HIDD_ATTRIBUTES

MemberIndex.l=0

Repeat

DeviceInterfaceData\cbSize=SizeOf(SP_DEVICE_INTERFACE_DATA)

If CallFunction(1,"SetupDiEnumDeviceInterfaces",*DeviceInfoSet,0,HidGuid,MemberIndex,DeviceInterfaceData)=0
Break
EndIf

Debug "HID Nummer: "+Str(MemberIndex)
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 

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=CreateFile_(@DevicePathName,0,#FILE_SHARE_READ|#FILE_SHARE_WRITE,0,#OPEN_EXISTING,0,0)
Debug "HidDevice Handle: "+Str(HidDevice)

DeviceAttributes\Size=SizeOf(HIDD_ATTRIBUTES)

CallFunction(0,"HidD_GetAttributes",HidDevice,DeviceAttributes)
Debug "VendorID: "+Hex(DeviceAttributes\VendorID)
Debug "ProductID: "+Hex(DeviceAttributes\ProductID)
Debug "Versionsnummer: "+Hex(DeviceAttributes\VersionNumber)

Dim StringWideChar.b(100)

CallFunction(0,"HidD_GetManufacturerString",HidDevice,@StringWideChar(0),100)
String.s=""
For a=0 To 50
String.s=String+PeekS(@StringWideChar(0+(a*2)))
Next
Debug "Manufacturer: "+String

CallFunction(0,"HidD_GetProductString",HidDevice,@StringWideChar(0),100)
String.s=""
For a=0 To 50
String.s=String+PeekS(@StringWideChar(0+(a*2)))
Next
Debug "Product: "+String

Debug "--------------------------------------------------"

MemberIndex=MemberIndex+1
ForEver

CallFunction(1,"SetupDiDestroyDeviceInfoList",*DeviceInfoSet)
CloseHandle_(HidDevice)
CloseLibrary(0)
CloseLibrary(1)

End
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 »

HID Nummer: 0
InterfaceClassGuid Data1= 4D1E55B2
InterfaceClassGuid Data2= FFFFF16F
InterfaceClassGuid Data3= 11CF
Flags= 1
Erster SetupDiGetDeviceInterfaceDetailA() Aufruf: RequiredSize= 86
Gerätpfadname: \\?\hid#vid_05fe&pid_0011#6&e7bdac4&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
HidDevice Handle: 1960
VendorID: 5FE
ProductID: 11
Versionsnummer: 1
Manufacturer: Cypress Semi.
Product: Cypress Ultra Mouse
--------------------------------------------------
Aber meine Drucker kriege ich nicht zu fassen. Aber schön, das Du doch noch zum Erfolg gekommen bist
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