Hallo, ich hab bei den Descriptoren etwas nicht verstanden, und zwar; Woher wissen die Endpoints zu welchen Interfaces sie gehoeren. Konkret: Ich hab schreib eine Firmware fuer einen uC mit 2 Interaces. Jedes Interface bekommt 2+1 Endpoints(In und Out, und Endpoint0). Wie kann ich bei den Endpoint descriptoren angeben, dass sie zum jenen Interface gehoeren? Wenn ich das Device als HID anmelde und mehrere Interfaces besitzt, wird jedes Interface als eigenes Device im Geraetemanager angezeigt? Gruss Bernhard
> Woher wissen die Endpoints zu welchen Interfaces sie gehoeren. Deskriptoren sind abhängig von der Lage. Endpoint-Descriptoren folgen immer einem Interface-Descriptor, stehen diesem niemals voran. Ein Endpunkt gehört immer zum direkt vorangegangenen Interface-Descriptor. Beispiel: Interface1-HID-Endpoint1-Endpoint2-Interface2-Endpoint3-Endpoint4 Endpoint1 und Endpoint2 ist Interface1 vorangegangen, dazu gehören sie dann auch. Von EP3 und EP4 nach links gesehen ist Interface2 der nächste erreichbare Deskriptor, diesem Interface gehören sie dann an. EP0 gehört immer dem Gerät und lässt sich nicht zuordnen. Alle Interfaces teilen sich diesen Endpunkt. > Wenn ich das Device als HID anmelde und mehrere Interfaces besitzt, wird > jedes Interface als eigenes Device im Geraetemanager angezeigt? Jawoll.
Vielen Dank Rene, fuer die praeziese Antwort. Wie kann ich auf die verschiedenen Endpoints ueber HID zugreifen? Ich hab bis jetzt immer nur Reports und Features gefunden. Mir scheint als laufen die alle ueber den Control Endpoint. Ich benutze die hid.lib und setupapi.lib von MS DDK. Gruss Bernhard P.S. Kennt jemand ein ausfuehrliches Buch ueber USB-HID?
> Wie kann ich auf die verschiedenen Endpoints ueber HID zugreifen? Du kannst das gar nicht, der Treiber entscheidet über das Was und Wohin, siehe unten. > Ich hab bis jetzt immer nur Reports und Features gefunden. Genau so ist es, die Kommunikation mit einem HID läuft einzig und allein über Reports (Features sind auch in Reports verpackt). Auch werden immer ganze Reports verschickt. Es ist nicht möglich, nur einen Teil der in einem Report-Deskriptor beschrieben Daten zu versenden. > Mir scheint als laufen die alle ueber den Control Endpoint. Das kann sein, muß aber nicht sein. Wenn ein HID keinen Endpoint besitzt, muß EP0 genommen werden (Set_Report, Get_Report). Wenn das HID einen zusätzlichen Interrupt-IN-EP besitzt, wird natürlich dieser für Input-Reports verwendet. So ist es auch für die andere Richtung. Besitzt das HID einen Interrupt-OUT-EP, wird auch dieser OUT-EP verwendet (es sei denn, Du arbeitest mit Win98, erste Version). Der Treiber weiß anhand der Deskriptoren wohin die Reports gehen / woher sie kommen und erledigt den Transfer für Dich. Du mußt, wie gesagt, nur einen gültigen Report zusammenstellen. > Ich benutze die hid.lib und setupapi.lib von MS DDK. Wenn Du per SetupDiGetDeviceInterfaceDetail den Pfad zum Gerät ermittelt und es damit geöffnet hast, sendest Du deine Output-Reports mit WriteFile und empfängst Input-Reports mit ReadFile. Obacht: Wenn Du Dir die Capabilities Deines Geräts genauer anschaust (HidP_GetCaps, HIDP_CAPS), wirst Du feststellen, daß HID_CAPS.XxxReportByteLength jeweils ein Byte größer ist als der zugehörige tatsächliche Report. Das wird gemacht, um mit Report-IDs arbeiten zu können. Das erste Byte, noch vor dem eigentlichen Report, ist dann eben auch dieser Report-Identifier. Da ich Dir unterstelle, nicht mit IDs zu arbeiten, mußt Du dieses Byte nullen. Initialisierst Du dieses Byte nicht oder nicht richtig, werden die Funktionen ReadFile, WriteFile, HidD_XetFeature fehlschlagen! > P.S. Kennt jemand ein ausfuehrliches Buch ueber USB-HID? Jan Axelsons Werke sind zwar Bücher über den USB an sich, sind aber absolut HID zentriert. Ein reines HID Buch gibt es meines Wissens nicht. Aber für die Feinheiten gibt es immer noch die offizielle Spezifikation und, wenn das nicht hilft, dieses Forum hier. ;-)
Hallo, hab ich nun folgendes Problem: Ich frage mit SetupDiGetDeviceInterfaceDetail den Pfad meines USB-HID Geraetes ab, und speichere den Pfad in der Variable "devicePath". In der Pfadangabe kann ich den VID und PID sehen, und ist soweit richtig. Wenn ich nun ein CreateFile ausfuehren moechte, bekomme ich ein INVALID_HANDLE zurueck. Mein Aufruf sieht so aus: HANDLE hHidDeviceHandle = CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); Geraet wird ordnungsgemaess angemeldet. Ich kann die Descriptoren mit HClient aus dem DDK von MS abfragen und ueberpruefen. Laut HClient stimmt alles. Mach ich hier was falsch?
Wenn CreateFile fehlschlägt, erfährst Du den Grund hierfür von GetLastError. Diesen Fehlercode hätte ich schon gern gewusst, bevor ich mir weiter Gedanken mache.
Richtig, das ist ERROR_ACCESS_DENIED (winerror.h). Das kann passieren, wenn das Gerät bereits belegt ist, da Du das Gerät exclusive öffnen willst. So wirst Du beispielsweise Schwierigkeiten bekommen, eine Maus exclusive zu öffnen, solange das System die Maus verwendet. Du hast jetzt zwei Möglichkeiten zur Abhilfe: 1) Du beendest das Programm, das das HID bereits verwendet. 2) Du teilst Dir das Gerät mit dem anderen Programm (Parameter 3 von CreateFile). Das Teilen funktioniert natürlich nur, wenn das andere Programm dies zulässt und das Gerät nicht seinerseits exclusive geöffnet hat (also mit Parameter 3 von CreateFile = 0).
Ok, Loesung 1 hat geholfen. Thx Ich benutz den TIUSB 3410 mit Application Loader. Der Loader hatte die ganze Zeit das Device blockiert. Bekomm jetzt erfolgreich, ueber EP0 und desweiteren EP1 im Interrupt Modus, Uebertragungen zustande. Komisch ist, wenn ich BULK Transfer im Descriptor waehle, dass die Pakete jetzt ueber EP0 geschickt werden und nicht mehr ueber EP1. Da EP0 nur einen 8 Byte Puffer hat werden groessere Pakete aufgeteilt, und meine Datenrate geht in den Keller.
Ein HID kommuniziert ausschließlich über Interrupt Transfers. Neben dem EP0 hast Du maximal einen Interrupt-IN EP und maximal einen Interrupt-OUT EP. Wenn einer dieser beides EPs fehlt, wird selbstverständlich auf EP0 zurückgefallen, Dein Bulk-EP ignoriert. Das Verhalten, das Du siehst, ist also völlig in Ordnung. Du kannst sogar froh sein, daß Dir der Treiber das fehlerhafte Gerät nicht gleich deaktiviert und versucht, aus der verkorksten Situation noch das Beste zu machen.
Ist es eigentlich möglich, verschieden große Datenpakete zu verschicken mit nur einem Report? Ich möchte nicht für jede Paketgröße einen eigenen Report mit entsprechender Länge anlegen.
> Ist es eigentlich möglich, verschieden große Datenpakete zu verschicken > mit nur einem Report? Wie ich bereits im zweiten Beitrag schrieb: Nein, das ist nicht möglich. Ein Report ist ein Report und so wird er auch verschickt. Mach den Report groß genug, stelle den Nutzdaten die tatsächliche Länge voran und fülle den unbenutzten Rest mit nullen auf.
> Warum auffüllen, ist doch unnötig.
Die Länge eines Reports, den Du sendest, muß exakt mit der im Deskriptor
ausgiesenen Länge überein stimmen. Du darfst nicht weniger Bytes
übertragen als ausgewiesen. Zumindest unter meinem Windows bekomme ich
Reports nicht gelesen, wenn ich, wie von Dir vorgeschlagen, irgendetwas
in einer nicht bekannten Länge sende. Das füllen des FIFOs ist daher
nicht unnötig, IMO.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.