AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi wie Hardware (HID) erkennen und via Programm verbinden/trennen?
Thema durchsuchen
Ansicht
Themen-Optionen

wie Hardware (HID) erkennen und via Programm verbinden/trennen?

Ein Thema von himitsu · begonnen am 12. Okt 2010 · letzter Beitrag vom 23. Nov 2010
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#1

wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 12. Okt 2010, 07:22
Moin,

via SetupDiEnumDeviceInterfaces kann man ja die "angeschlossenen" HID-Geräte erkennen/auflisten.
"Leider" werden auch alle Geräte erkannt, welche einmal/aktuell in der HID-Verwaltung drinstehn.
Also alle Geräte, welche über "Gerät verbinden" gesucht und verbunden wurden.
Nach einem Neustart von Windows oder wenn die Verbindung zum Gerät andersweitig getrennt wurde, stehen die "verbundenen" Geräte aber nur noch im Leerlauf drin und sind physisch nicht mehr verbunden (stehen aber nich in der Liste der ).

Heißt, man kann sie zwar über SetupDiEnumDeviceInterfaces finden, man kann via CreateFile drauf zugreifen und z.B. über HidD_GetAttributes etwas auslesen,
aber kummunizieren (ReadFile, WriteFile und Co.) kann man mit dem Gerät nicht.




Gibt es da eine Möglichkeit, ohne probehalber über ReadFile/WriteFile drauf zuzugreifen, rauszufinden, ob das Gerät im Leerlauf oder verbunden ist?

Warum nicht über ReadFile und Co. ist recht einfach geklärt.
Ich würde diese Funktionalität gern direkt in meine HID-Verwaltungs-/Basisklassen inegrieren und diese weiß nicht wieviel Byte für eine Übertragung darüber verwendet werden müssen und sie kennt auch das "Protokoll" nicht, um einen "harmlosen" Befehl zum Testen nehmen zu können.




Und kann man das ganze auch irgendwie programmseitig verbinden/trennen?
Also via eigenem Delphi-Programm ein Gerät verbinden, trennen, entfernen oder suchen?

Also wenn ich z.B. bei einem nicht verbundenen WiiControler den SyncModus starte (Button 1+2 oder Sync drücken), dann soll das Programm dieses erfahren und das Gerät automatisch verbinden,
ohne daß man selber in die Bluetooth-Umgebung geht und dieses manuell verbindet.
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Union
Union

Registriert seit: 18. Mär 2004
Ort: Luxembourg
3.492 Beiträge
 
Delphi 7 Enterprise
 
#2

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 12. Okt 2010, 16:19
Arbeitest Du nicht mit SP_DEVICE_INTERFACE_DATA? Dort gibt es einen Member Flags der genau das beinhaltet: SPINT_ACTIVE oder SPINT_REMOVED.
Ibi fas ubi proxima merces
sudo /Developer/Library/uninstall-devtools --mode=all
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 13. Okt 2010, 09:00
Ohh, das gibt es ja wirklich dort.
Ja, ich arbeite damit, aber den Code dafür hatte ich auch nur übernommen und so dieses nicht erkannt/gefunden.

Werd' es heute Abend mal ausprobieren.


Fehlt jetzt nur noch eine Möglichkeit die BT-Geräte über das eigene Programm verbinden und entfernen zu können.
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 13. Okt 2010, 18:25
Nee, funktioniert leider garnicht.
Es wird SPINT_ACTIVE angegeben, aber das Device ist definitiv noch im "Leerlauf", also nicht verbunden.
Und wenn ich es dann verbinde, dann ändert sich an diesen Flags auch nichts.

PC hochgefahren > Device im "Leerlauf" und Status=SPINT_ACTIVE
Gerät verbunden > unverändert Status=SPINT_ACTIVE
Gerät getrennt (nicht entfernt) > Device wird von SetupDiEnumDeviceInterfaces nicht mehr gefunden, obwohl es doch der selbe Status sein sollte, wie zu Anfang
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 23. Okt 2010, 09:24
Ich dreh langsam noch durch.

Aktuell hab ich meinen Code so, über diesen wollte ich auch mit testen, ob das Device verbunden ist.
Delphi-Quellcode:
Case FPortAccess of
  paWriteFile: Begin
    ...
  End;
  paSetOutputReport:
    ...
  Else Begin
    Result := HidD_SetOutputReport(FPort, Report, Len);
    If not Result Then Begin
      ResetEvent(FOverlappt.hEvent);
      If not WriteFile(FPort, Report, FOutputReportSize, W, @FOverlappt) Then Begin
        E := GetLastError;
        If (E = ERROR_HANDLE_EOF) or (E = $048F{ERROR_DEVICE_NOT_CONNECTED}) Then Begin
          DoDisconnect;
          Result := False;
          Exit;
        End;
        W := WaitForSingleObject(FOverlappt.hEvent, FTimeout);
        If (W = WAIT_TIMEOUT) or (W = WAIT_FAILED)
            or not GetOverlappedResult(FPort, FOverlappt, W, False) Then Begin
          CancelIo(FOverlappt.hEvent);
          Result := False;
          Exit;
        End Else FPortAccess := paWriteFile;
      End;
      Result := True;
    End Else FPortAccess := paSetOutputReport;
  End;
End;
Nur liefert WriteFile oftmals direkt True (natürlich ohne einen Fehlercode zu setzen), selbst wenn das Device nicht verbunden ist, sich also nur im Leerlauf befindet.

Vorher hatte ich den Code so,
aber hier lieferte WriteFile auch manchmal direkt True und somit False als Result, auch wenn das Device erfolgreich angesteuert wurde.
Delphi-Quellcode:
Case FPortAccess of
  paWriteFile: Begin
    ...
  End;
  paSetOutputReport:
    ...
  Else Begin
    Result := HidD_SetOutputReport(FPort, Report, Len);
    If not Result Then Begin
      ResetEvent(FOverlappt.hEvent);
      If not WriteFile(FPort, Report, FOutputReportSize, W, @FOverlappt) Then Begin
        E := GetLastError;
        If (E = ERROR_HANDLE_EOF) or (E = $048F{ERROR_DEVICE_NOT_CONNECTED}) Then Begin
          DoDisconnect;
          Result := False;
          Exit;
        End;
        W := WaitForSingleObject(FOverlappt.hEvent, FTimeout);
* If (W = WAIT_TIMEOUT) or (W = WAIT_FAILED)
* or not GetOverlappedResult(FPort, FOverlappt, W, False) Then Begin
* CancelIo(FOverlappt.hEvent);
* Result := False;
* End Else Begin
* FPortAccess := paWriteFile;
* Result := True;
* End;
* End Else Result := False;
    End Else FPortAccess := paSetOutputReport;
  End;
End;

Also WriteFile liefert manchmal True, wenn das Device erfolgreich angesteuert wurde und leider auch dann, wenn es nicht angeschlossen ist und somit garnicht angesteuert wurde.

Somit laß ich jetzt erstmal die obere Variante, aber leider kann ich es so nicht nutzen, um zu erkennen, ob das Device überhaupt verbunden ist.
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 12. Nov 2010, 17:14


Weiß denn wirklich keiner, wie man "getrennte" HID- oder genauer Bluetooth-Geräte, welche sich im Standby befinden wiederverbinden kann?

Bzw. die man Bluetooth-Geräte via Programm suchen/verbinden/wiederverwinden/trennen/auswerfen kann?
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Assarbad
Assarbad

Registriert seit: 8. Okt 2010
Ort: Frankfurt am Main
1.234 Beiträge
 
#7

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 13. Nov 2010, 04:43
Bei Speichergeräten müßte MSDN-Library durchsuchenIOCTL_STORAGE_LOAD_MEDIA gehen, aber hier weiß ich es nicht sicher, jedoch sieht mir MSDN-Library durchsuchenIOCTL_HID_ACTIVATE_DEVICE danach aus als könne es dafür gut sein. Probier das mal mit MSDN-Library durchsuchenDeviceIoControl.
Oliver
"... aber vertrauen Sie uns, die Physik stimmt." (Prof. Harald Lesch)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#8

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 13. Nov 2010, 09:32
Das IOCTL_STORAGE_LOAD_MEDIA, IOCTL_HID_ACTIVATE_DEVICE und IOCTL_HID_DEACTIVATE_DEVICE klingt schonmal gut.
Werd' ich dann mal ausprobieren.
Nja, wenn ich Pech hab, dann sind die für eine Nutzung in 'nem HID Minidriver, welchen ich nicht hab/nutze.

Das dort entdeckte IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER klingt och nett.

OK, danke erstmal und bis nach den Tests.






Zum Suchen hatte ich mir gestern auch dieses hier zusammengebastelt.
Delphi-Quellcode:
Uses JwaBluetoothAPIs;

Var
  RH: HBLUETOOTH_RADIO_FIND;
  RP: BLUETOOTH_FIND_RADIO_PARAMS;
  R: THandle;
  RI: BLUETOOTH_RADIO_INFO;
  DH: HBLUETOOTH_DEVICE_FIND;
  DP: BLUETOOTH_DEVICE_SEARCH_PARAMS;
  DI: BLUETOOTH_DEVICE_INFO;

RP.dwSize := SizeOf(RP);
RH := BluetoothFindFirstRadio(@RP, R);
If RH <> 0 Then Begin
  Repeat
    RI.dwSize := SizeOf(RI);
    If BluetoothGetRadioInfo(R, RI) = ERROR_SUCCESS Then Begin
      ShowMessage(Format('address (%02x:%02x:%02x:%02x:%02x:%02x)'#10 +
        'name "%s"'#10'class %d'#10'subversion %d'#10'manufacturer %d', [
        RI.address.rgBytes[0], RI.address.rgBytes[1], RI.address.rgBytes[2],
        RI.address.rgBytes[3], RI.address.rgBytes[4], RI.address.rgBytes[5],
        RI.szName, RI.ulClassofDevice, RI.lmpSubversion, RI.manufacturer]));
    End Else ShowMessage(SysErrorMessage(GetLastError));

    ZeroMemory(@DP, SizeOf(DP));
    DP.dwSize := SizeOf(DP);
    {DP.fReturnAuthenticated := True;{}
    {DP.fReturnRemembered := True;{}
    {DP.fReturnUnknown := True;{}
    {}DP.fReturnConnected := True;{}
    {DP.fIssueInquiry := True;{}
    DP.hRadio := R;
    DI.dwSize := SizeOf(DI);
    DH := BluetoothFindFirstDevice(DP, DI);
    If DH <> 0 Then Begin
      Repeat
        ShowMessage(Format('address (%02x:%02x:%02x:%02x:%02x:%02x)'#10'class %d'#10 +
          'connected %d'#10'remembered %d'#10'authenticated %d'#10'name "%s"', [
          DI.Address.rgBytes[0], DI.Address.rgBytes[1], DI.Address.rgBytes[2],
          DI.Address.rgBytes[3], DI.Address.rgBytes[4], DI.Address.rgBytes[5],
          DI.ulClassofDevice, Ord(DI.fConnected), Ord(DI.fRemembered),
          Ord(DI.fAuthenticated), DI.szName]));
      Until not BluetoothFindNextDevice(DH, DI);
      BluetoothFindDeviceClose(DH);
    End Else If GetLastError <> ERROR_NO_MORE_ITEMS Then ShowMessage(SysErrorMessage(GetLastError));

    CloseHandle(R);
  Until not BluetoothFindNextRadio(RH, R);
  BluetoothFindRadioClose(RH);
End Else If GetLastError <> ERROR_NO_MORE_ITEMS Then ShowMessage(SysErrorMessage(GetLastError));

ZeroMemory(@DP, SizeOf(DP));
DP.dwSize := SizeOf(DP);
{DP.fReturnAuthenticated := True;{}
{DP.fReturnRemembered := True;{}
{DP.fReturnUnknown := True;{}
{}DP.fReturnConnected := True;{}
{DP.fIssueInquiry := True;{}
//DP.hRadio := 0;
DI.dwSize := SizeOf(DI);
DH := BluetoothFindFirstDevice(DP, DI);
If DH <> 0 Then Begin
  Repeat
    ShowMessage(Format('address (%02x:%02x:%02x:%02x:%02x:%02x)'#10'class %d'#10 +
      'connected %d'#10'remembered %d'#10'authenticated %d'#10'name "%s"', [
      DI.Address.rgBytes[0], DI.Address.rgBytes[1], DI.Address.rgBytes[2],
      DI.Address.rgBytes[3], DI.Address.rgBytes[4], DI.Address.rgBytes[5],
      DI.ulClassofDevice, Ord(DI.fConnected), Ord(DI.fRemembered),
      Ord(DI.fAuthenticated), DI.szName]));
    //if BluetoothRemoveDevice(DI.Address) <> ERROR_SUCCESS then
    // ShowMessage(SysErrorMessage(GetLastError));
  Until Not BluetoothFindNextDevice(DH, DI);
  BluetoothFindDeviceClose(DH);
End Else If GetLastError <> ERROR_NO_MORE_ITEMS Then ShowMessage(SysErrorMessage(GetLastError));
Leider findet das garnichs oder nicht alles.
Jedenfalls schein ich es nicht hinzibekommen das BLUETOOTH_DEVICE_SEARCH_PARAMS (DP) so zu setzen, daß alles gefunden wird.

Weiteres, wie Nachfolgendes, hab ich noch nicht ausprobieren (können).
BluetoothRemoveDevice
BluetoothAuthenticateDevice
BluetoothSetServiceState
BluetoothEnumerateInstalledServices
BluetoothIsConnectable
BluetoothEnableIncomingConnections
BluetoothRegisterForAuthentication
BluetoothUnregisterAuthentication
BluetoothSendAuthenticationResponse


Mein Problem ist auch noch, daß ich es einmal hinbekommen hatte, mein Device zwar aufzulisten, aber eine "Verbindung" zum zugehörigen HID-Control war nicht möglich.
Im Prinzip könnte ich in meiner HID-Komponente noch sowas wie das "address (%02x:%02x:%02x:%02x:%02x:%02x)" benötigen,
denn wenn ich z.B. zwei gleiche Controls angeschlossen hab, dann weiß ich nicht direkt, welches meiner HID-Objekte welchem Control in der Bluetooth-Verwaltung entspricht.



[add]
Wenn ich BluetoothGetRadioInfo direkt auf ein FileHandle zu einem HID-Device loslaß, dann meint es zwar "alles OK" (ERROR_SUCCESS), aber der ganze Record ist nur mit Nullen gefüllt.
Und BluetoothGetDeviceInfo meint dann nur ERROR_NOT_FOUND.
(wär ja auch zu einfach gewesen)



[add]
Hab es nun ganz einfach erstmal mit dem Auswerfen versucht.
Bei IOCTL_HID_DEACTIVATE_DEVICE auf das DeviceHandle "\\?\hid#vid_057e&pid...0030}" angewendet sagt mir DeviceIoControl was von OK/True, aber nichts passiert.
Ich weiß allerdings nicht wie ich was genau als In-Parameter an DeviceIoControl übergeben soll, aber egal was, es bleibt beim True und es hat dennoch keinerlei Auswirkungen (Control bleibt angemeldet und nutzbar).

Wenn das Trennen/Deaktivieren eines verbundenen Gerätes schon nicht funktioniert, dann erspar ich mir die Versuche mit IOCTL_HID_ACTIVATE_DEVICE erstmal.

Auch bei IOCTL_STORAGE_LOAD_MEDIA wird True geliefert und ebenfalls nichts passiert.
(hier natürlich andersrum, also das Gerät befindet sich, laut der Bluetooth-Steuerung, im "Leerlauf" und war/ist noch nicht verbunden)
Wobei ich bei IOCTL_STORAGE_LOAD_MEDIA nicht viel falsch machen kann, da alle Parameter eh nil sind.
$2B or not $2B

Geändert von himitsu (13. Nov 2010 um 11:10 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Assarbad
Assarbad

Registriert seit: 8. Okt 2010
Ort: Frankfurt am Main
1.234 Beiträge
 
#9

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 13. Nov 2010, 15:27
Hab es nun ganz einfach erstmal mit dem Auswerfen versucht.
Bei IOCTL_HID_DEACTIVATE_DEVICE auf das DeviceHandle "\\?\hid#vid_057e&pid...0030}" angewendet sagt mir DeviceIoControl was von OK/True, aber nichts passiert.
Ich weiß allerdings nicht wie ich was genau als In-Parameter an DeviceIoControl übergeben soll, aber egal was, es bleibt beim True und es hat dennoch keinerlei Auswirkungen (Control bleibt angemeldet und nutzbar).
Du öffnest aber das Gerät schon mit CreateFile?! ...

Du bist aber auch sicher, daß du bspw. erfolgreich ein Handle bekommst? Wenn ja, dann versuch mal bitte MSDN-Library durchsuchenZwDeviceIoControlFile (ntdll.dll, die Zw* und Nt* ist vom Usermode aus identisch) um den IOCTL zu senden. Da interessiert uns dann was der Treiber in IoStatusBlock einträgt. Speziell der Statuscode da drin wird uns interessieren. Die Win32-Funktion MSDN-Library durchsuchenDeviceIoControl ist etwas ... nunja ... da genau diese Fehlerinfo verlorengeht. Meines Wissens nach ist der Rückgabewert von ZwDeviceIoControlFile normalerweise identisch mit dem in IoStatusBlock, aber es mag auch Unterschiede geben. Einerlei, DeviceIoControl verschluckt alle diese Informationen.
Oliver
"... aber vertrauen Sie uns, die Physik stimmt." (Prof. Harald Lesch)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: wie Hardware (HID) erkennen und via Programm verbinden/trennen?

  Alt 13. Nov 2010, 15:58
Delphi-Quellcode:
H := CreateFile(PChar(DeviceInfos.DeviceInterface.DevicePath),
  GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE,
  nil, OPEN_EXISTING, 0, 0);
Und ja, das Handle ist gültig, jedenfalls kann ich es für die anderen HID-Funktionen problemlos nutzen.

Ansonsten gibt es im Netz leider nicht all zuviele Informationen zu IOCTL_HID_DEACTIVATE_DEVICE
und wenn doch, dann wird da fast immer über eine HID minidriver implementation geschrieben.
Tja, einen solchen Mini-Treiber habe ich nicht, bzw. ich wollte sowas nicht unbedingt selber schreiben.




BluetoothGetRadioInfo liefert mir nun wenigstens schonmal den BT-Master/Sender
und über BluetoothFindFirstDevice bekomm ich endlich mein BT-Gerät aufgelistet.

Nur gibt es da sowenige Informationen über dieses Gerät, daß ich keine Verbindung zu einem meiner HID-Geräte herstellen kann, geschweige denn diese zu Steuern (/verbinden/trennen/entfernen).




http://www.delphipraxis.net/155160-w...ml#post1061174
Da unten drann hab ich mal eine Version angehängt, welche aktuell funktionierende Aufrufe enthält.

Im #Log werden z.B. die erkannten BT-Geräte und die wenigen schon bekannten Daten aufgelistet.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz