![]() |
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:40 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