Forum: PC-Programmierung USB


USB
von Berni (Gast)


Lesenswert?

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

von René K. (king)


Lesenswert?

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

von Berni (Gast)


Lesenswert?

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?

von René K. (king)


Lesenswert?

> 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. ;-)

von Berni (Gast)


Lesenswert?

Vielen Dank Rene
Alles super erklaert

von Berni (Gast)


Lesenswert?

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?

von René K. (king)


Lesenswert?

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.

von Berni (Gast)


Lesenswert?

GetLastError() gibt mir 0x05 zurueck.
Laut MSDN hilfe bedeutet das "Access is denied".

von René K. (king)


Lesenswert?

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

von Berni (Gast)


Lesenswert?

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.

von René K. (king)


Lesenswert?

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.

von Berni (Gast)


Lesenswert?

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.



von René K. (king)


Lesenswert?

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

von Jens (Gast)


Lesenswert?

Warum auffüllen, ist doch unnötig.

von René K. (king)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.