![]() |
HID Komponente - Komme nicht zurecht
Hallo Leute!
Ich habe schon ein paar kleine Programme mit Delphi 7 programmiert und wollte mich mal an etwas schwereres ranmachen. wohl etwas zu schwer: Ein USB HID Gerät. Nach etwas suchen habe ich die HID Komponente von Robert Marquardt entdeckt und mit dem Read-Write Demo habe ich alle Informationen rausbekommen, die ich brauche. Ich muss die ersten 4 Bytes auslesen und 2 Bytes schreiben. Nur das bekomme ich nicht hin. Was ich schon geschafft habe (aus dem Demo rausgenommen):
Delphi-Quellcode:
Kann mir bitte jemand helfen?
procedure TForm1.JvHidDeviceController1Arrival(HidDev: TJvHidDevice);
begin if DeviceName(HidDev) = pedale Then Edit1.Text := 'Ist da'; end; procedure TForm1.JvHidDeviceController1DeviceUnplug(HidDev: TJvHidDevice); begin if DeviceName(HidDev) = pedale Then Edit1.Text := 'Ist weg'; end; Am besten wäre ein Beispiel mit einem editfeld, dass immer ausliest und ein Knopf der immer "FF" schreibt. Vielen Dank Vergessen: Ich will mein Programm so schreiben, dass es in anderen Programmen etwas auslöst. Kann ich das dann so Programmieren, das das nebenbei läuft? |
Re: HID Komponente - Komme nicht zurecht
Das handeln wir in privaten Mails ab. robert_marquardt att gmx dott de.
|
Re: HID Komponente - Komme nicht zurecht
Zitat:
|
Re: HID Komponente - Komme nicht zurecht
Machen wir.
|
Re: HID Komponente - Komme nicht zurecht
Ich hab den Robert mal die Logs, die braucht gemailt und er schaut mal was er machen kann.
Das Ergebnis kann man ja hier reinmachen und wenn er schreibt, wie er vorgegangen ist, wird das bestimmt für viele verständlicher. Seine Demos sind echt spitze, aber halt gleich zu große Schritte (mehrere gleichzeitig aufgerufene Funktionen) und dann wirds einfach zu unübersichtlich für Anfänger zu kapieren was wann wieso gemacht wird. |
Re: HID Komponente - Komme nicht zurecht
Na dann schauen wir uns mal an was die beiden Tools (Beispielprogramme der HID-Komponente) uns verraten.
Ein HID-Geraet liefert Daten in strukturierten Reports. Der Deskriptor des Geraets beschreibt die hierarchische Struktur der Reports aufs Bit genau. Leider gibt es aber viele HID-Geraete bei denen der Deskriptor schlicht falsch ist oder uninformativ. In diesem Fall haben wir ein informatives Geraet. CollectionDemo zeigt eine Uebersicht der Report-Baeume. Ein Geraet kann naemlich mehrere verschiedene Reports lesen und schreiben. Die Lese-Reports und die Schreib-Reports sind unabhaengig strukturiert. Zusaetzlich gibt es Feature-Reports, die fuer Einstellungen am Geraet gedacht sind. Diese kann man prinzipiell immer mit einer speziellen Funktion lesen und schreiben.
Code:
Die erste Zeile verraet uns das das ein "Griffin Powermate" ist. Das ist der Produktname der im Geraet abgelegt ist. VID (VendorID) und PID (ProductID) sind spezifisch fuer dieses Geraet und anhand dieser Werte kann das Betriebssystem immer einen passenden Treiber zuweisen.
HID-Devices
"Griffin PowerMate" VID=$077D PID=$0410 UsagePage=Consumer ($000C) Usage=Consumer Control ($0001) CollectionType=Application ($01) Button Input Range: UsagePage=Button ($0009) 1..1 Value Input: UsagePage=Generic Desktop ($0001) Usage=Rotational X Axis ($0033) Value Input: UsagePage=Consumer ($000C) Usage=Consumer Control ($0001) Value Output: UsagePage=Consumer ($000C) Usage=Consumer Control ($0001) Value Feature: UsagePage=Consumer ($000C) Usage=Consumer Control ($0001) Die Elemente eines Reports werden Usages genannt. Genaugenommen ist es immer ein Paar von Usage und UsagePage. Fuer viele der moeglichen Werte sind auch Bedeutungen definiert. ""Mouse", Keyboard" oder z. B. "Consumer" sind einige der UsagePage-Bedeutungen. "Consumer" ist gedacht als Auffangbecken fuer Geraete, die nicht in eine der anderen Klassen fallen. Hier hat das Geraet zwar Buttons und Achsen, aber ist kein Joystick. Die oberste Ebene des Baums sagt das es ein Geraet aus der "Consumer"-Klasse ist und das es fuer "Applications" gedacht ist (etwas anderes als "Applications" ist sehr selten). Das gibt Rahmen fuer die Bedeutung der Elemente der Reports. Der Input-Report (warum es nur einen gibt kommt spaeter) enthaelt drei Elemente: ein Button-Array mit einem Button, eine X-Drehachse und ein Element das 4 Bytes enthaelt (genaueres zeigt die UsagesDemo). Der Output-Report und der Feature-Report sind aehnlich uninformativ deklariert. Die UsagesDemo zeigt nun die Reportbeschreibungen in allen Einzelheiten. Ich werde jetzt nicht auf alles eingehen, da doch recht viele uninteressante Details dabei sind. Das hier kratzt nur an der Oberflaeche dessen was bei HID-Reports moeglich ist und ist doch schon komplex.
Code:
Erst mal kommen die drei Werte fuer die maximale Reportgroesse jedes Typs. Das ist der Wert den man z. B. beim Lesen fuer das ReadFile verwenden muss. Zusaetzlich ist vor jedem Report ein Byte mit der ReportID so das man also immer ein Byte mehr lesen muss.
Input Report Size=6
Output Report Size=1 Feature Report Size=8 Button Input ============ 0) UsagePage: Button ($0009) ReportID: 0 IsAlias: False BitField: 2 LinkCollection: 0 LinkUsage: Consumer Control ($0001) LinkUsagePage: Consumer ($000C) IsRange: True IsStringRange: False IsDesignatorRange: False IsAbsolute: True UsageMin: 1 UsageMax: 1 StringMin: 0 StringMax: 0 DesignatorMin: 0 DesignatorMax: 0 DataIndexMin: 0 DataIndexMax: 0 Value Input =========== 0) UsagePage: Generic Desktop ($0001) ReportID: 0 IsAlias: False BitField: 2 LinkCollection: 0 LinkUsage: Consumer Control ($0001) LinkUsagePage: Consumer ($000C) IsRange: False IsStringRange: False IsDesignatorRange: False IsAbsolute: True HasNull: False BitSize: 8 ReportCount: 1 UnitsExp: 0 Units: 0 LogicalMin: -127 LogicalMax: 127 PhysicalMin: 0 PhysicalMax: 0 Usage: Rotational X Axis ($0033) StringIndex: 0 DesignatorIndex: 0 DataIndex: 1 1) UsagePage: Consumer ($000C) ReportID: 0 IsAlias: False BitField: 2 LinkCollection: 0 LinkUsage: Consumer Control ($0001) LinkUsagePage: Consumer ($000C) IsRange: False IsStringRange: False IsDesignatorRange: False IsAbsolute: True HasNull: False BitSize: 8 ReportCount: 4 UnitsExp: 0 Units: 0 LogicalMin: 0 LogicalMax: 255 PhysicalMin: 0 PhysicalMax: 0 Usage: Consumer Control ($0001) StringIndex: 0 DesignatorIndex: 0 DataIndex: 2 Value Output ============ 0) UsagePage: Consumer ($000C) ReportID: 0 IsAlias: False BitField: 2 LinkCollection: 0 LinkUsage: Consumer Control ($0001) LinkUsagePage: Consumer ($000C) IsRange: False IsStringRange: False IsDesignatorRange: False IsAbsolute: True HasNull: False BitSize: 8 ReportCount: 1 UnitsExp: 0 Units: 0 LogicalMin: 0 LogicalMax: 255 PhysicalMin: 0 PhysicalMax: 0 Usage: Consumer Control ($0001) StringIndex: 0 DesignatorIndex: 0 DataIndex: 0 Value Feature ============= 0) UsagePage: Consumer ($000C) ReportID: 0 IsAlias: False BitField: 2 LinkCollection: 0 LinkUsage: Consumer Control ($0001) LinkUsagePage: Consumer ($000C) IsRange: False IsStringRange: False IsDesignatorRange: False IsAbsolute: True HasNull: False BitSize: 8 ReportCount: 8 UnitsExp: 0 Units: 0 LogicalMin: 0 LogicalMax: 255 PhysicalMin: 0 PhysicalMax: 0 Usage: Consumer Control ($0001) StringIndex: 0 DesignatorIndex: 0 DataIndex: 0 Die Namen links sind Variablennamen aus dem Record. Rechts folgen die enthaltenen Werte. Die ReportID ist immer 0 was bedeutet das es nur einen Report zum Lesen, einen zum Schreiben und einen Feature-Report gibt. Alles was Input in der Ueberschrift hat gehoert in den gelesenen Report. Das erste ist ein Button-Array das genau einen Button enthaelt. Die restlichen Angaben sind nicht sonderlich bedeutsam. Implizit ist hier das nun erst ein Bit des Reports beschrieben ist. Es gibt sicherlich nun noch ein hier unsichtbares Beschreibungselement das die restlichen 7 Bits des Bytes als unbelegt kennzeichnet. Die Drehachse folgt nun. Sie ist ein Value, was heisst das sie einen Wertebereich hat. Das Element ist unterteilt in Unterelemente mit Bitsize=8 und ReportCount=1 Stueck davon. Es ist also 8x1 Bits gross. Der gelieferte Wertebereich pro Unterelement ist -127..127, also vorzeichenbehaftet. Das letzte Element ist Bitsize=8 und ReportCount=4 also 8x4 Bits gross. Mehr laesst sich nicht herauslesen. Experimente sind angesagt. Output-Report und Feature Report erschliessen sich wohl nun von alleine. Sie sind ebenfalls uninformativ beschrieben und Experimente sind noetig. Das soll nun erst mal reichen. Ich schreibe morgen eine Demo und erklaere sie hier. |
Re: HID Komponente - Komme nicht zurecht
Ich finde es Spitze wie toll du dich um die Leute kümmerst, die sich für deine Arbeit interessieren.
Ein großes Lob an dich und ein großer Dank an mich, dass ich euch gefunden habe. ![]() |
Re: HID Komponente - Komme nicht zurecht
OK, ich gebe zu es sind keine Lenkradpedale - Man will ja nicht immer gleich die Katze aus dem Sack lassen, damit einem nicht gleich die Idee geklaut wird...
Ich erkläre vielleicht mal das Gerät, weil es an sich garnicht so schlecht ist. ![]() Es ist ein: Knopf - mehr nicht. ![]() Ebay-Preis zur Zeit 20,- Euro Man kann ihn drücken, drehen. drücken und drehen, lang drücken. Die beiliegende Software erlaubt es einem für jedes Programm einzeln bzw. Global dem PowerMate Funktionen zuzuweisen (lauter, leiser, Pfeiltasten, Tastenkombinationen) Das ist jedoch ziemlich eingeschränkt, weil viel kann man nicht machen. Ich habe schonmal eine Erweiterung programmiert, die garnicht so schlecht war: Ich habe für Photoshop im Powermate ungenutze Hotkeys hinterlegt und mittels eines Delphi-Programmes diese Hotkeys erfasst und dann ein GUI aufgerufen und das Delphi-Programm hat dann die passenden Hotkeys gesendet. So konnte man Zoomen, Pinselgrößen ändern, Brushes ändern usw. Also: Lang drücken - GUI Aufrufen Drehen im GUI - GUI Funktion auswählen Drücken im GUI - Funktion bestätigen Drehen - Zoomen, etwas durchschalten, etc. Kurz drücken - Funktion umschalten (beim Scrollen z.B. links/rechts und rauf/runter) Aber die Hotkey-Sache ist doch sehr schwammig und mehr eine Übergangslösung. Ich will also eine Treibersoftware (HID braucht ja keine Treiber in dem Sinne) schreiben, die einem für jedes Programm ein eigenes GUI ermöglicht. 3rd-Party Programme habe ich für das Powermate nicht gefunden und deshalb ist es Pionierarbeit in dieser Richtung ;) Programm-GUI-Anweisungen will ich dann per ini oder xml modular dazu machen. Und wie es sich gehört wird es Freeware... Dann hier noch die Infos die ich per Read-Write-Demo herausbekommen habe Auslesen:
Code:
Schreiben: (Per Writebefehl - 1. Doppelbyte)
Links: 00 FF 00 4F 00 0A
Rechts: 00 01 00 4F 00 0A Drücken: 01 00 00 4F 00 0A Loslassen: 00 00 00 4F 00 0A Gedrückt Links: 01 FF 00 4F 00 0A Gedrückt Rechts: 01 01 00 4F 00 0A
Code:
Also alles relativ simpel, wenn man bei der Komponente durchblickt.
LED aus 00
LED schwach 01 ... LED mittel 88 ... LED hell FF |
Re: HID Komponente - Komme nicht zurecht
Code:
Wir wissen das im 1. Byte (1. Spalte) genau ein Buttonbit deklariert ist. Gedrueckt Bit ist 1, losgelassen Bit ist 0.
Links: 00 FF 00 4F 00 0A
Rechts: 00 01 00 4F 00 0A Drücken: 01 00 00 4F 00 0A Loslassen: 00 00 00 4F 00 0A Gedrückt Links: 01 FF 00 4F 00 0A Gedrückt Rechts: 01 01 00 4F 00 0A Das zweite Byte enthaelt die Drehposition. Hier -1, 0 und 1. Das scheinen Deltas zu sein. Als Absolutposition machen diese Werte keinen Sinn. Da scheint der Report-Deskriptor doch einen Fehler zu haben, denn IsAbsolute ist True. Der 4-Byte Rest des Reports aendert sich anscheinend nicht. Moeglich ist das die aktuelle LED-Helligkeit darin steht oder Informationen die mit dem Feature-Report beeinflusst werden. Ich arbeite Code Mercenaries ![]() |
Re: HID Komponente - Komme nicht zurecht
Hab vergessen zu sagen, dass es keine "Drehwerte" und es keinen Anschlag gibt.
Wenn ich eine halbe Stunde nach links drehe kommt hunderte Male der selbe Wert. |
Re: HID Komponente - Komme nicht zurecht
Ach ja. Ideenklau is nich.
![]() Der Drehgeber gibt Deltas von sich wie eine Maus, also -1 fuer einen Bewegungsschritt linksrum und 1 fuer rechtsrum. Der Deskriptor sagt aber es sollten Absolutwerte sein, also die Drehposition. Ich schau mir mal am Dienstag die Deskriptoren von unseren SpinWarriors an ob ich da recht habe. |
Re: HID Komponente - Komme nicht zurecht
Du bist ja der Experte, aber für mich Laien sollte es doch egal sein, solange ich den richtigen Wert abfrage oder ist das eine Gefahrenquelle für Bugs?
|
Re: HID Komponente - Komme nicht zurecht
Nein, es ist kein Problem. Es versaut nur die korrekte maschinelle Interpretation des Reports. Es ist eben eine falsche Bedeutung angegeben.
|
Re: HID Komponente - Komme nicht zurecht
Hier ist das Testprogramm. Es ist noch nicht ausprobiert.
Michael94, mach mal ein Programm auf das du zwei Label und einen JvHidDeviceController legst. Danach ersetze die gane Unit1 mit dieser Source. Danach ausprobieren. Beim Einstecken sollte die LED angehen und beim Programmende sollte die LED ausgemacht werden.
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, // JvComponentBase kommt automatisch dazu wenn man die HID-Komponente // aus der JVCL benutzt. Fuer die Standalone-Verison einfach loeschen. Dialogs, JvComponentBase, JvHidControllerClass, StdCtrls; type TForm1 = class(TForm) JvHidDeviceController1: TJvHidDeviceController; Label1: TLabel; Label2: TLabel; procedure JvHidDeviceController1DeviceChange(Sender: TObject); procedure JvHidDeviceController1DeviceData(HidDev: TJvHidDevice; ReportID: Byte; const Data: Pointer; Size: Word); procedure FormDestroy(Sender: TObject); public Device: TJvHidDevice; end; var Form1: TForm1; implementation uses HID, HidUsage; {$R *.dfm} const GriffinVID = $077D; PowerMatePID = $0410; type // kein HID-Report kann groesser als 64 Byte sein THidReport = packed record ReportID: Byte; Data: array [0..62] of Byte; end; // Standard-Implementierung zur Handhabung genau eines HID-Geraets. // Es wird das erste gefundene passende Geraet genommen. procedure TForm1.JvHidDeviceController1DeviceChange(Sender: TObject); var Report: THidReport; Written: DWORD; begin // erst mal sehen ob das Geraet ausgesteckt wurde if Assigned(Device) and not Device.IsPluggedIn then begin // das Objekt wird an den Controller zurueckgegeben // Device wird dabei auf nil gesetzt JvHidDeviceController1.CheckIn(Device); // hier gehoeren Finalisierungen der Oberflaeche hin Label1.Caption := '?'; Label2.Caption := '?'; end; // schauen ob wir nach einem Geraet suchen muessen if not Assigned(Device) then // schauen ob ein Griffin PowerMate vorhanden ist if JvHidDeviceController1.CheckOutByID(Device, GriffinVID, PowerMatePID) then begin // es wurde ein Geraet gefunden // hier gehoeren Initialisierungen des Geraets und der Oberflaeche hin // wir machen die LED an FillChar(Report, SizeOf(Report), 0); // das ist ziemlich aufwaendig dafuer das wir nur eine Usage im Report setzen wollen Report.ReportID := 0; // wir wollen in einen Output-Report schreiben Device.ReportTypeParam := HidP_Output; // das benennt die spezifische Usage die gesetzt werden soll Device.UsagePageParam := HID_USAGE_PAGE_CONSUMER; Device.LinkCollectionParam := $01; // CollectionType=Application Device.UsageParam := HID_USAGE_CONSUMER_CONSUMER_CONTROL; // den Wert setzen (LED Maximum) Device.SetUsageValue($FF, Report, Device.Caps.OutputReportByteLength); // ab damit ans Geraet Device.WriteFile(Report, Device.Caps.OutputReportByteLength, Written); end; end; procedure TForm1.FormDestroy(Sender: TObject); var Report: THidReport; Written: DWORD; begin // nur wenn beim Programmende das Geraet noch eingesteckt ist if Assigned(Device) then begin // da wir in der Initialisierung das Licht eh die LED angemacht haben, // machen wir jetzt brav das Licht wieder aus. FillChar(Report, SizeOf(Report), 0); Report.ReportID := 0; Device.ReportTypeParam := HidP_Output; Device.UsagePageParam := HID_USAGE_PAGE_CONSUMER; Device.LinkCollectionParam := $01; Device.UsageParam := HID_USAGE_CONSUMER_CONSUMER_CONTROL; // Wert setzen (LED aus) Device.SetUsageValue($00, Report, Device.Caps.OutputReportByteLength); Device.WriteFile(Report, Device.Caps.OutputReportByteLength, Written); end; end; // Reports vom Geraet empfangen // Der Event gilt fuer alle ausgecheckten Geraete procedure TForm1.JvHidDeviceController1DeviceData(HidDev: TJvHidDevice; ReportID: Byte; const Data: Pointer; Size: Word); var Report: THidReport; Button: TUsage; Len: DWORD; Dial: Integer; begin // erst mal einen Designfehler der Komponente ausgleichen // wir brauchen den Report mit vorangestellter ReportID Report.ReportID := ReportID; Move(Data^, Report.Data[0], Size); // wir wollen den Buttonzustand extrahieren HidDev.ReportTypeParam := HidP_Input; HidDev.UsagePageParam := HID_USAGE_PAGE_BUTTON; HidDev.LinkCollectionParam := $01; // CollectionType=Application Len := 1; Button := $00; HidDev.GetButtons(@Button, Len, Report, Size + 1); // $01 ist die Usage des Buttons wie sie als "UsageMin: 1" von UsageDemo angegeben wurde. if Button = $01 then Label1.Caption := 'Button down' else Label1.Caption := 'Button up'; // wir wollen den Wert des Drehknopfes extrahieren // nur die veraenderten Parameter werden gesetzt HidDev.UsagePageParam := HID_USAGE_PAGE_GENERIC; HidDev.UsageParam := HID_USAGE_GENERIC_RX; HidDev.GetScaledUsageValue(Dial, Report, Size + 1); Label2.Caption := Format('%d', [Dial]); end; end. |
Re: HID Komponente - Komme nicht zurecht
Passiert garnichts. Kein Fehler, keine Reaktion.
JvComponentBase habe ich Commentgemäs aus der Uses entfernt. Da ich die auch garnicht habe. |
Re: HID Komponente - Komme nicht zurecht
Dann setz mal ein paar Breakpoints im Debugger. Einen nach CheckoutByID, damit du weisst ob das Device gefunden wird und einen an den Anfang von JvHidDeviceController1DeviceData, damit du weisst ob Daten kommen.
|
Re: HID Komponente - Komme nicht zurecht
Sorry, dass ich erst jetzt antworte:
Beide Breakpoints werden gelblich gün und haben einen Count von 0 |
Re: HID Komponente - Komme nicht zurecht
Das heisst das die Methoden vom Compiler herausoptimiert wurden. Du hast vermutlich vergessen sie der Komponente zuzuweisen.
Bei JvHidDeviceController1 auf dem Event-Tab in der IDE die Events OnDeviceChange und OnDeviceData zuweisen. Die Auswahl sollte nur je eine Methode zulassen. |
Re: HID Komponente - Komme nicht zurecht
Wir kommen der sache schon näher!
- Er ändert Label beim anstecken nicht, aber beim drehen hat Label1 immer "Button up" und Label2 immer verschiedene Zahlen. -Drücken und loslassen bewirkt nichts. - Nach ein paar mal drehen ändert sich Label2 nicht mehr. egal ob links oder rechts rum. - Mit der LED passiert garnichts. Nachtrag: Wenn die Zahlen nach ein paar mal drehen sich nicht mehr ändern, kann ich das Powermate abziehen (?, ?) und wieder anschließen, dann kann man wieder ein paar mal drehen bevor es wieder hängenbleibt. |
Re: HID Komponente - Komme nicht zurecht
Das sich die Label beim Anstecken nicht aendern ist klar. Beim Anstecken kommen keine Daten und im JvHidDeviceController1DeviceChange wird nur beim Abstecken etwas an den Labels geaendert.
Ich aender mal gleich die Source das sie den rohen Report anzeigt wie SimpleHidWrite. Schmeiss schon mal eine ListBox auf deine Form. Das die Daten haengenbleiben ist ungewoehnlich. Verhaelt sich der PowerMate genauso wenn man ihn mit SimpleHidWrite ausliest? Es sollte kein Unterschied sein. Die Aktivierung der LED ist nach deinen Angaben programmiert. Es sollte eigentlich funktionieren. Pruef mal im Debugger nach was im Report beim WriteFile steht. Wenn dort das $FF nicht im ersten Datenbyte steht, dann ist doch ein Fehler beim Setzen der Usage und es wird dann $00 also LED aus geschrieben. |
Re: HID Komponente - Komme nicht zurecht
Ich darf den Beitrag nicht mehr aendern. Neu posten geht schneller.
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, // JvComponentBase kommt automatisch dazu wenn man die HID-Komponente // aus der JVCL benutzt. Fuer die Standalone-Version einfach loeschen. Dialogs, JvComponentBase, JvHidControllerClass, StdCtrls; type TForm1 = class(TForm) JvHidDeviceController1: TJvHidDeviceController; Label1: TLabel; Label2: TLabel; ListBox1: TListBox; procedure JvHidDeviceController1DeviceChange(Sender: TObject); procedure JvHidDeviceController1DeviceData(HidDev: TJvHidDevice; ReportID: Byte; const Data: Pointer; Size: Word); procedure FormDestroy(Sender: TObject); public Device: TJvHidDevice; end; var Form1: TForm1; implementation uses HID, HidUsage; {$R *.dfm} const GriffinVID = $077D; PowerMatePID = $0410; type // kein HID-Report kann groesser als 64 Byte sein THidReport = packed record ReportID: Byte; Data: array [0..62] of Byte; end; // Standard-Implementierung zur Handhabung genau eines HID-Geraets. // Es wird das erste gefundene passende Geraet genommen. procedure TForm1.JvHidDeviceController1DeviceChange(Sender: TObject); var Report: THidReport; Written: DWORD; begin // erst mal sehen ob das Geraet ausgesteckt wurde if Assigned(Device) and not Device.IsPluggedIn then begin // das Objekt wird an den Controller zurueckgegeben // Device wird dabei auf nil gesetzt JvHidDeviceController1.CheckIn(Device); // hier gehoeren Finalisierungen der Oberflaeche hin Label1.Caption := '?'; Label2.Caption := '?'; ListBox1.Clear; end; // schauen ob wir nach einem Geraet suchen muessen if not Assigned(Device) then // schauen ob ein Griffin PowerMate vorhanden ist if JvHidDeviceController1.CheckOutByID(Device, GriffinVID, PowerMatePID) then begin // es wurde ein Geraet gefunden // hier gehoeren Initialisierungen des Geraets und der Oberflaeche hin // wir machen die LED an FillChar(Report, SizeOf(Report), 0); // das ist ziemlich aufwaendig dafuer das wir nur eine Usage im Report setzen wollen Report.ReportID := 0; // wir wollen in einen Output-Report schreiben Device.ReportTypeParam := HidP_Output; // das benennt die spezifische Usage die gesetzt werden soll Device.UsagePageParam := HID_USAGE_PAGE_CONSUMER; Device.LinkCollectionParam := $01; // CollectionType=Application Device.UsageParam := HID_USAGE_CONSUMER_CONSUMER_CONTROL; // den Wert setzen (LED Maximum) Device.SetUsageValue($FF, Report, Device.Caps.OutputReportByteLength); // ab damit ans Geraet Device.WriteFile(Report, Device.Caps.OutputReportByteLength, Written); end; end; procedure TForm1.FormDestroy(Sender: TObject); var Report: THidReport; Written: DWORD; begin // nur wenn beim Programmende das Geraet noch eingesteckt ist if Assigned(Device) then begin // da wir in der Initialisierung das Licht eh die LED angemacht haben, // machen wir jetzt brav das Licht wieder aus. FillChar(Report, SizeOf(Report), 0); Report.ReportID := 0; Device.ReportTypeParam := HidP_Output; Device.UsagePageParam := HID_USAGE_PAGE_CONSUMER; Device.LinkCollectionParam := $01; Device.UsageParam := HID_USAGE_CONSUMER_CONSUMER_CONTROL; // Wert setzen (LED aus) Device.SetUsageValue($00, Report, Device.Caps.OutputReportByteLength); Device.WriteFile(Report, Device.Caps.OutputReportByteLength, Written); end; end; // Reports vom Geraet empfangen // Der Event gilt fuer alle ausgecheckten Geraete procedure TForm1.JvHidDeviceController1DeviceData(HidDev: TJvHidDevice; ReportID: Byte; const Data: Pointer; Size: Word); var Report: THidReport; Button: TUsage; Len: DWORD; Dial: Integer; I: Integer; S: string; begin // erst mal einen Designfehler der Komponente ausgleichen // wir brauchen den Report mit vorangestellter ReportID Report.ReportID := ReportID; Move(Data^, Report.Data[0], Size); // wir wollen den Buttonzustand extrahieren HidDev.ReportTypeParam := HidP_Input; HidDev.UsagePageParam := HID_USAGE_PAGE_BUTTON; HidDev.LinkCollectionParam := $01; // CollectionType=Application Len := 1; Button := $00; HidDev.GetButtons(@Button, Len, Report, Size + 1); // $01 ist die Usage des Buttons wie sie als "UsageMin: 1" von UsageDemo angegeben wurde. if Button = $01 then Label1.Caption := 'Button down' else Label1.Caption := 'Button up'; // wir wollen den Wert des Drehknopfes extrahieren // nur die veraenderten Parameter werden gesetzt HidDev.UsagePageParam := HID_USAGE_PAGE_GENERIC; HidDev.UsageParam := HID_USAGE_GENERIC_RX; HidDev.GetScaledUsageValue(Dial, Report, Size + 1); Label2.Caption := Format('%d', [Dial]); // Rohdaten-Ausgabe S := ''; for I := 0 to Size - 1 do S := S + Format('%.2x ', [Report.Data[I]]); ListBox1.Items.Add(S); end; end. |
Re: HID Komponente - Komme nicht zurecht
Hab mir heute auch ein Powermate bestellt... werde mich dann auch zum Thema mal melden wenn es da ist, da ich auch eigenen GUI mit verschiedenen funktionen basteln will :)
Die Griffin Software reicht mir nicht :D |
Re: HID Komponente - Komme nicht zurecht
So mein powermate ist entlich da *freu*
habs dann auch gleich angeschlossen und mit readwrite getestet... Zitat:
nämlich bis 04 und bis FD kommt dann zustande, wenn ich mein PowerMate sehr schnell drehe in eine Richtung. Werd mal gucken ob ich am WE zeit finde da dann tiefer einzutauchen :) |
Re: HID Komponente - Komme nicht zurecht
$FD = -3 das sind die Deltas der Drehbewegung die man da bekommt. Genau wie bei einer Maus.
Ich habe uebrigens meinen Chef nochmal gefragt und die Usage fuer diesen Wert ist definitiv im Deskriptor falsch deklariert.
Code:
IsAbsolute muesste False sein, denn es werden ja Relativwerte geschickt. Absolutwerte wuerden bedeuten das man den Drehwinkel bekommt nicht die Winkelaenderung.
Value Input
=========== 0) UsagePage: Generic Desktop ($0001) ReportID: 0 IsAlias: False BitField: 2 LinkCollection: 0 LinkUsage: Consumer Control ($0001) LinkUsagePage: Consumer ($000C) IsRange: False IsStringRange: False IsDesignatorRange: False IsAbsolute: True HasNull: False BitSize: 8 ReportCount: 1 UnitsExp: 0 Units: 0 LogicalMin: -127 LogicalMax: 127 PhysicalMin: 0 PhysicalMax: 0 Usage: Rotational X Axis ($0033) StringIndex: 0 DesignatorIndex: 0 DataIndex: 1 Warum das jetzt nicht mit dem Auswerten des Reports per Methode geht, kann ich nicht sagen. THE MATRIX, bitte kontakte mich mal direkt und wir legen mal ein paar Debugging Sessions ein. |
Re: HID Komponente - Komme nicht zurecht
Sorry, ich war im Krankenhaus.
War ja klar, dass gleich noch jemand kommt, der einem die Idee nachmachen möchte... Ich wusste es! Danke Robert, mit deiner letzten Source kann ich was anfangen. Label1 zeigt zwar immernoch nur "Button up" an und Label2 Hängt mit den Zahlen rum, aber die Listbox geht und mit diesen Werten kann ich arbeiten. Was noch interessant wäre: LED-Werte an das Powermate senden. Vielleicht kannst du mir da bitte noch einen ganz simplen "Wert senden" Button machen. dann kann ich mir das zurechtbasteln. Vielen Dank! Euch allen ein schönes Osterfest (dir auch Matrix *grummel*) |
Re: HID Komponente - Komme nicht zurecht
So, bin schon wieder da ;)
Wie gesagt, mit der Listbox gings dann einfach. 41 Minuten bis zum zum ersten Test. @Matrix Bitte mal testen: ![]() ![]() @Robert: Hast du evtl. eine etwas elegantere Art der "Angeschlossen?" Überprüfung? Ich hab mir das anfangs aus deinem Example zusammengeschraubt.
Delphi-Quellcode:
procedure TForm1.JvHidDeviceController1DeviceUnplug(HidDev: TJvHidDevice);
begin if DeviceName(HidDev) = 'Griffin PowerMate' Then Label3.Caption := 'Powermate nicht gefunden'; end; procedure TForm1.JvHidDeviceController1Arrival(HidDev: TJvHidDevice); begin if DeviceName(HidDev) = 'Griffin PowerMate' Then Label3.Caption := 'Powermate gefunden'; end; |
Re: HID Komponente - Komme nicht zurecht
Ich bevorzuge es das ganze im OnDeviceChange konzentriert zu halten. OnArrival und OnRemoval sind nicht wirklich wichtig. Ich bedaure inzwischen sie eingefuehrt zu haben.
Lies doch mal ![]() Da geht es noch ganz anders zur Sache. Mehrere hier wollen sich jetzt so ein Ding zulegen. |
Re: HID Komponente - Komme nicht zurecht
Naja, ich habe es halt in die Tests eingebaut, um anzuzeigen, dass das Gerät gefunden wurde.
Im eigentlichen Programm wollte ich einen "Offline"-Icon in den Systray machen. Aber wenn mein HID-Guru kein Fan von dieser Funktion ist, dann lasse ich sie weg. Was ich von dir noch bräuchte wäre ein "Werte an HID senden" damit ich die LED ändern kann. Ansonsten werde ich dann alleine zurrecht kommen. |
Re: HID Komponente - Komme nicht zurecht
Du kannst die Events ruhig benutzen. Ich bedauere nur das ich sie eingebaut habe, obwohl sie nicht noetig sind. Sie schlagen fuer jedes HID-Geraet an, daher muss man abpruefen ob es das gewuenschte ist. Letzlich mache sie alles nur komplizierter ohne wirklich zur Flexibilitset beizutragen. Ich habe eh schon einen langen Weg hinter mir was Missverstaendnisse mit der Komponente betrifft. Z. B. man darf ein TJvHidDevice nicht instantiieren, deshalb ist das jetzt unmoeglich.
|
Re: HID Komponente - Komme nicht zurecht
Für den Raketenwerfer hab ich irgendwo im Netz schon eine C++ Source gesehen.
Da hat einer auch noch seine Webcam auf das Ding gesetzt und mit reingecodet. Ist halt ne Spielerei. Beim Powermate ist es ja so, dass danach Logitech auch so ein Teil gebaut hat. (natürlich besser und stylischer) Ich bleib da lieber beim Original ![]() |
Re: HID Komponente - Komme nicht zurecht
Zitat:
Delphi-Quellcode:
ersetzen durch
FillChar(Report, SizeOf(Report), 0);
// das ist ziemlich aufwaendig dafuer das wir nur eine Usage im Report setzen wollen Report.ReportID := 0; // wir wollen in einen Output-Report schreiben Device.ReportTypeParam := HidP_Output; // das benennt die spezifische Usage die gesetzt werden soll Device.UsagePageParam := HID_USAGE_PAGE_CONSUMER; Device.LinkCollectionParam := $01; // CollectionType=Application Device.UsageParam := HID_USAGE_CONSUMER_CONSUMER_CONTROL; // den Wert setzen (LED Maximum) Device.SetUsageValue($FF, Report, Device.Caps.OutputReportByteLength); // ab damit ans Geraet Device.WriteFile(Report, Device.Caps.OutputReportByteLength, Written);
Delphi-Quellcode:
Da jetzt eine Methode draus zu schnitzen sollte doch kein Problem sein.
FillChar(Report, SizeOf(Report), 0);
// wird eh vom FillChar erledigt // Report.ReportID := 0; // den Wert setzen (LED Maximum) Report.Data[0] := $FF; // ab damit ans Geraet Device.WriteFile(Report, Device.Caps.OutputReportByteLength, Written); |
Re: HID Komponente - Komme nicht zurecht
|
Re: HID Komponente - Komme nicht zurecht
Das sind Geraete fuer verschiedene Zwecke. Ich bin von Logitech-Teilen nicht so begeistert.
|
Re: HID Komponente - Komme nicht zurecht
Liste der Anhänge anzeigen (Anzahl: 1)
Wo ich jetzt noch drüber gestolpert bin ...
der ![]() auch eine klasse sache.. kommt dem iDrive noch näher ich häng mal meine delphi komponente dran... @Robert ... ist immer noch mit 255er wert :D kann ja noch jemand ändern... dafür gibts ja ne schicke community :) @Michael94 Zum testen komm ich erstmal nicht, sry - bin momentan von Windows wieder weg.... das PowerMate rennt ja auch 1a unter linux ... :) |
Re: HID Komponente - Komme nicht zurecht
Der SpaceNavigator ist für CAD Anwendungen und dementsprechend teuer.
Ich hab das Teil schon mal getestet: Nicht schlecht, aber sehr gewöhnungsbedürftig |
Re: HID Komponente - Komme nicht zurecht
Bin hier über diesen extrem interessanten Thread gestolpert und habe (auch) noch einige Fragen dazu.
Vorweg vielleicht erst einmal eine Beschreibung des 'Problems': Ich habe mir 2 schicke HPTC-Gehäuse zugelegt ( ![]() ![]() Beide Kisten haben ein VFD, diverse Bedienelemente, einen IR-Empfänger und ne FB selbst. Dieses 'Zubehör' stammt von SOUNDGRAPH und benötigt die Soft IMON / IMEDIAN. Display, Bedienelemente und Empfänger sitzt alles auf einen Board, wird via USB angeschlossen und wird als diverse HIDs eingebunden. Die Soft hat zig Einstellmöglichkeiten und ist prinzipiell nicht schlecht, aber.... A) optisch nicht mein Fall, B) läuft nicht wirklich gut mit der Empfängersoft zusammen (DVBDream) und C) ist irgendwie total überladen. Es gibt auch eine API dazu (logo in C), aber damit kann ich nur Text auf das Display geben. Ich möchte nun mehr oder weniger dieses IMON-Gerümpel 'entsorgen' und die Informationen der FB/Bedienlemente selbst auslesen und mit meinen eigenen Tools verwalten. Für das DVBDream habe ich schon einige Module/Plugins geschrieben, die auf meinem 'Normal-PC' mit einem USB-IR-Stick (IgorPlug - falls den jemand kennt...) super laufen. Auch eine Remote-Frontend für VLC ist so gut wie fertig. Wie bekomme ich das nun an den Start ? Wenn ich mir die Logs so ansehe, welche die Demo-Tools aus der HID-Komponente so alles hergeben, sehe ich eher lauter Bäume im Wald... Wenn auch mir jemand ein wenig Starthilfe geben könnte ? Was soll ich als Info noch posten ?
Delphi-Quellcode:
Die oberen 5 'Geräte' scheinen die meiner Funk-Taste/-Maus zu sein (Cherry cyMotion Pro).
HID-Devices
VID=$046A PID=$002A UsagePage=Generic Desktop ($0001) Usage=Keyboard ($0006) CollectionType=Application ($01) Button Input Range: UsagePage=Keyboard ($0007) 224..231 Button Input Range: UsagePage=Keyboard ($0007) 0..140 Button Output Range: UsagePage=LED ($0008) 1..5 VID=$046A PID=$002A UsagePage=Consumer ($000C) Usage=Consumer Control ($0001) CollectionType=Application ($01) Button Input Range: UsagePage=Consumer ($000C) 0..771 VID=$046A PID=$002A UsagePage=Generic Desktop ($0001) Usage=System Control ($0080) CollectionType=Application ($01) Button Input Range: UsagePage=Generic Desktop ($0001) 129..131 VID=$046A PID=$002A UsagePage=FF00 ($FF00) Usage=1 ($0001) CollectionType=Application ($01) Button Output: UsagePage=FF00 ($FF00) Usage=0 ($0000) VID=$046A PID=$002A UsagePage=Generic Desktop ($0001) Usage=Mouse ($0002) CollectionType=Application ($01) UsagePage=Generic Desktop ($0001) Usage=Pointing Device ($0001) CollectionType=Physical ($00) Button Input Range: UsagePage=Button ($0009) 1..7 Value Input: UsagePage=Generic Desktop ($0001) Usage=Wheel ($0038) Value Input: UsagePage=Generic Desktop ($0001) Usage=Y Axis ($0031) Value Input: UsagePage=Generic Desktop ($0001) Usage=X Axis ($0030) "USB Multimedia Keyboard" VID=$046D PID=$C312 UsagePage=Generic Desktop ($0001) Usage=Keyboard ($0006) CollectionType=Application ($01) Button Input Range: UsagePage=Keyboard ($0007) 224..231 Button Input Range: UsagePage=Keyboard ($0007) 0..255 Button Output Range: UsagePage=LED ($0008) 1..3 "USB Multimedia Keyboard" VID=$046D PID=$C312 UsagePage=Generic Desktop ($0001) Usage=System Control ($0080) CollectionType=Application ($01) Button Input: UsagePage=Generic Desktop ($0001) Usage=System Control Wake Up ($0083) Button Input: UsagePage=Generic Desktop ($0001) Usage=System Control Sleep ($0082) Button Input: UsagePage=Generic Desktop ($0001) Usage=System Control Power Down ($0081) "USB Multimedia Keyboard" VID=$046D PID=$C312 UsagePage=Consumer ($000C) Usage=Consumer Control ($0001) CollectionType=Application ($01) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Refresh ($0227) Button Input: UsagePage=Consumer ($000C) Usage=Application Launch Calculator ($0192) Button Input: UsagePage=Consumer ($000C) Usage=Application Launch Local Machine Browser ($0194) Button Input: UsagePage=Consumer ($000C) Usage=Application Launch Consumer Control Configuration ($0183) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Select All ($021E) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Paste ($021D) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Cut ($021C) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Copy ($021B) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Stop ($0226) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Forward ($0225) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Back ($0224) Button Input: UsagePage=Consumer ($000C) Usage=Eject ($00B8) Button Input: UsagePage=Consumer ($000C) Usage=Scan Previous Track ($00B6) Button Input: UsagePage=Consumer ($000C) Usage=Play/Pause ($00CD) Button Input: UsagePage=Consumer ($000C) Usage=Scan Next Track ($00B5) Button Input: UsagePage=Consumer ($000C) Usage=Stop ($00B7) Button Input: UsagePage=Consumer ($000C) Usage=Application Launch Email Reader ($018A) Button Input: UsagePage=Consumer ($000C) Usage=Help ($0095) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Bookmarks ($022A) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Home ($0223) Button Input: UsagePage=Consumer ($000C) Usage=Application Control Search ($0221) Button Input: UsagePage=Consumer ($000C) Usage=Mute ($00E2) Button Input: UsagePage=Consumer ($000C) Usage=Volume Decrement ($00EA) Button Input: UsagePage=Consumer ($000C) Usage=Volume Increment ($00E9) "USB Multimedia Keyboard" VID=$046D PID=$C312 UsagePage=FF00 ($FF00) Usage=1 ($0001) CollectionType=Application ($01) Button Input Range: UsagePage=FF00 ($FF00) 96..103 Button Input: UsagePage=FF00 ($FF00) Usage=69 ($0069) Button Input: UsagePage=FF00 ($FF00) Usage=68 ($0068) Button Input Range: UsagePage=FF00 ($FF00) 106..111 Button Input Range: UsagePage=FF00 ($FF00) 112..119 Value Feature: UsagePage=FF00 ($FF00) Usage=20 ($0020) Aber was ist das alles darunter ? Irgendwie kann ich das den vorhandenen Eingabemöglichkeiten (Gerät / FB) nicht so wirklich zuordnen.... |
Re: HID Komponente - Komme nicht zurecht
Mal so zur Frage vorweg.
Ist der IR nicht eventuell normal über lirc ansprechbar ? schon mal probiert ..... |
Re: HID Komponente - Komme nicht zurecht
Sorry für diese möglicherweise rappelblöde Gegenfrage: LIRC ? Linux ? Ich bin altehrwürdiger WinDoof'er und damit gor nüscht am Hut...
WinLIRC als solches geht nicht auf diesem Board, weil es keine COM's mehr hat. Leider... (MSI 7329 Medi Live). Die FB von Soundgraph ist eigentlich ein propper Teil, weil sie auch noch so etwas wie ein MausWheel und div. andere nützlich Tasten hat. Mit dem Ding kann ich über mein eigenes IR-Tool (m.E. wesentlich besser als WinLIRC) schon recht gut kommunizieren, aber... Ich will da nicht noch was 'anstecken' - es ist alles in den Kisten drin & dran. IR-Empfänger, VFD, Tasten wie am DVD-Player, ... Muss ich nur irgendwie mich in diese HID-Kamelle einklinken und via Events auslesen, wer wo was gearde gedrückt hat. Undlogo auch die div. LEDs an und aus machen. Irgendwie komm ich da noch nicht so ganz hinter... |
Re: HID Komponente - Komme nicht zurecht
Ich habe jetzt mal einige Stunden damit verbracht, den Sourcen auf die Spur zu kommen.
Die Demo SimpleHIDWrite wäre m.E. ja schon ganz brauchbar, da - wenn ich das richtig verstanden habe - hier eigentlich (?) ja auch eine Ausgabe der Daten des angewählten Gerätes in der HistoryListBox erfolgen soll. Es passiert aber nix.... CurrentDevice.OnData wird zwar bei der Auswahl eines Gerätes mit der procedure ShowRead belegt, aber offensichtlich nicht 'angesprungen'. Die HID-Hilfe sagt dazu: ... Der Thread wird nicht für eingecheckte Geräte gestartet, die mit Enumerate aufgezählt werden ... Und genau das ist bei mir ja der Fall. Hier wird nix ein-/ausgesteckt/gecheckt - Das SoundGraph-Panel ist immer fest mit nem internen USB-Sockel verbunden. Nun gäbe es da ja auch noch TJvHidDeviceController.OnDeviceData. Die dafür notwendige proc sähe genau so aus wie ShowRead, allerdings lässt diese sich nicht als Eventproc zuweisen. Diverse Versuche dieses irgendwie unter den Hut zu bekommen, wird nur mit Exceptions belohnt oder es tut sich weiterhin nichts. Hat jemand mal den goldenen Tipp ? |
Re: HID Komponente - Komme nicht zurecht
... und zum xten Mal wieder alle relevanten Threads durchgelesen.
Irgendwo sagte Robert, dass wenn sich ein Gerät als ??? anmeldet, werden keine Events ausgelöst, die über die HID-Kompenente empfangen werden können. Da vermute ich mal stark, dass das hier auch so ist. Bei meinem Cherry-Keyboard/Maus kommen z.B. auch nur die extra zu definierenden Zusatzkeys an. Also habe auch ich das mal mit dem kleinen Tool von Dani via RAW Input probiert. Da bekomme ich zwar alle Keyboard und Maus Events, aber von diesem SoundGraph-Teil auch nur die Keys der FB, die auf eine Applikation definiert sind und auch nur dann, wenn die läuft (auch ohne Fokus). Krise ! Es scheint bei dieser Soft so, das man bestimmte Tasten nicht 'wegdefinieren' kann. Z.B. bleibt Lautstärke immer Lautstärke und scheint direkt auf den Mixer zu wirken. Diverse andere Tasten (R-G-G-B, Player-Navigation und spez. 'Calls') kommen einfach nirgendwie/wo an/raus. Ich hege die Vermutung, die SoundGraph-progger binden dieses Front-/IR-Panel als ganz normales USB-Gerät mit speziellem Treiber ein und erst die Soft IMON macht daraus die HID-Geräte. Und dort werden dann halt erst Tasten weitergegeben, wenn sie zu einer Anwendung definiert sind. Und bestimmte Tasten bleiben dann eben intern und erreichen niemals das System. Das ist doch Käse.... Nun bliebe nur noch die Möglichkeit, irgendwie direkt auf dem USB-Bus zu lauschen ?! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz