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:
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 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.
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:
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
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.
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.