Hallo,
es geht mal wieder um USB aus VB oder VC++. Hab ein paar Fragen, die
ich trotz Suche im Forum leider beantworten konnte. Oder ich bin zu
blöd zum Suchen.
1. Gibt es eine universelle DLL bzw. ein universelles Objekt, ähnlich
dem COM-Port-Objekt aus VB, mit dem man auf USB zugreifen kann? Frei
verfügbar natürlich, denn dass es das in "teuer" gibt, weiss ich
latürnich!!!
2. Falls 1. verneint werden muss, gibt es die Möglichkeit, über die
WinAPI auf USB zuzugreifen? Wenn ja, wie? Links erwünscht!
Danke!
Ralf
1. Nein, gibt es nicht. Allerdings gibt es Bausteine von SiLabs,
Profilic oder FTDI, die Dir die normale serielle Schnittstelle
nachbilden. Auch gibt es für diese Chips eigene APIs zur Kommunikation
vom Hertsller.
2. Über API geht das natürlich. Das geht sogar ganz genau so, wie das
mit der normalen Seriellen auch geht: CreateFile, ReadFile, WriteFile,
DeviceIoControl und CloseHandle. Wie Du die drei mittigen Funktionen
anwendest, ist abhängig vom verwendeten Gerät.
Sofern Du noch etwas mehr mit dem USB vorhast, kann ich nur dringend
raten, ein Buch zu lesen. Jan Axelson hat in seinem 'Handbuch für
Entwickler' übrigens auch einige Beispiele für VB und VC.
zu 1: KERNEL32.DLL :-)
zu 2: Das USB Gerät verwenden wie eine Datei:
=> CreateFile(),ReadFile(),WriteFile(),CloseHandle()
Das Größte Problem dabei ist den entsprechenden
"Dateinamen"=Symbolic-Link zu finden.
=> SetupDi* Funktionen aus der setupapi.dll/lib
Je nach Endpunkt (Lesen/Schreiben) im USB-Gerät gibt es dann
verschiedene "PIPE"s ("PIPE00"/"PIPE01").
Gruss
> Je nach Endpunkt (Lesen/Schreiben) im USB-Gerät gibt es dann> verschiedene "PIPE"s ("PIPE00"/"PIPE01").
Aus der Sicht des Anwenders stimmt das so nicht. Die Quelle oder das
Ziel der Daten bestimmt einzig und allein der Treiber.
@King Stimmt, also darauf achten welches PIPE<xx> für lesen und
schreiben verwendet werden muß.
Fällt mir gerade ein - ohne PIPE kann der Endpunkt 0 = Controlkanal
angesprochen werden.
Gruss
Man muß darauf achten, welchen Treiber man verwendet. Ich habe hier zum
Beispiel einen Treiber, der ganz ohne Angabe einer Pipe EP3 zum
Schreiben/ Lesen verwendet (das weiß ich deswegen so genau, weil
Treiber und Gerät von mir sind).
Erstmal danke für die Beiträge. Hätte nicht gedacht, dass in so kurzer
Zeit so viele zusammenkommen grins
Okay, also über API. Muss ich mir erstmal beibringen. Ist das arg
schwer?!?
@René:
Kannst du deinen Code hier posten?
Ralf
Hi!
Windows macht USB nur kompliziert und es existiert doch eine einfache
Möglichkeit, USB-Geräte zu verwalten:
Die Bibliothek heißt LIBUSB und ist für mehrere Betriebssysteme
erhältlich (auch WIN32). Mit nem beiliegenden Tool generiert man
einfach nen eigenen Treiber (.ini) für das entsprechende Gerät und
lässt das Gerät mit den neuen Treiber laufen. Mit der C-Bibliothek oder
ner DLL stehen alle USB-Funktionen zur Verfügung (Lesen schreiben auf
Endpoints, Descriptoren, ...).
Hab auch vor kurzen so ein Projekt durchgeführt welches unter
www.ime.jku.at/tusb publiziert ist (Vermerk auf die Doku bzw.
Präsentation).
Hoffe, ich konnte etwas helfen
mfg Weichinger Klaus
www.weinga-unity.at.tt
Es hätte ja alles so einfach sein können.
Ich habe auch versucht ein HID Device anzusprechen, mit den oben
genannten Funktionen. Allerdings habe ich da ein paar Probleme.
1. Mein Device wird ordnungsgemäß gefunden. Es wird auch ein gültiger
Handle mit CreateFile erzeugt.
2. WriteFile() und ReadFile schlägt fehl. Fehler 1784: Der angegebene
Benutzerpuffer ist für den Vorgang ungültig???
unsigned char buffer[]={0,'e','s','t','T','e','s','t'};;
unsigned long num;
WriteFile(handle,buffer,8,&num,NULL));
Was kann das sein?
> Es hätte ja alles so einfach sein können.
Es ist so einfach.
> Was kann das sein?
Der Länge des Puffers, den Du zu schreiben versuchst, stimmt nicht mit
der tatsächlichen Länge überein. Die Längen müssen exakt stimmen. Bei
Reports, die einen Identifier benötigen, ist das Länge + 1.
Wie sieht denn der überhaupt InputReport-Descriptor aus?
also das mit dem WriteFile habe ich inzwischen hinbekommen. Es lag
wirklich an der Puffergröße, aber bei Readfile haberts noch.
Hier ist also der Report Descriptor. Den habe ich mir aus verschiedenen
App-Notes, vor allem aber aus der Projektarbeit von Klaus Weichinger
(sehr Aufschlussreich, siehe oben) zusammengestellt:
usb_configuration =
{
{ 9, CONFIGURATION, CONF_LENGTH, NB_INTERFACE, CONF_NB,
CONF_INDEX, CONF_ATTRIBUTES, MAX_POWER},
{ 9, INTERFACE, INTERFACE_NB, ALTERNATE, NB_ENDPOINT,
INTERFACE_CLASS,
INTERFACE_SUB_CLASS, INTERFACE_PROTOCOL, INTERFACE_INDEX },
{ 9, HID, 0x1101, 0, 1, REPORT, 0x2e00 },
{ 7, ENDPOINT, ENDPOINT_NB_1, EP_ATTRIBUTES_1, EP_SIZE_1,
EP_INTERVAL_1 },
{ 0x06,0xA0, 0xFF, /* Usage Page (User Defined) */
0x09,0xA5, /* Usage (Vendor defined) */
0xA1,0x01, /* Collection (Application) */
0x09,0xa6,
// Input Report
0x09,0xA7,
0x15,0x80, /* Logical Minimum (-128) */
0x25,0x7F, /* Logical Maximum (127) */
0x75,0x08, /* Report Size (8 bit) */
0x95,0x08, /* Report Count (8 byte) */
0x81,0x02, /* Input (Data, Variable, Absolute) */
// output report
0x09, 0xA9,
0x15,0x80, /* Logical Minimum (-128) */
0x25,0x7F, /* Logical Maximum (127) */
0x75,0x08, /* Report Size (8 bit) */
0x95,0x08, /* Report Count (8 byte) */
0x91,0x08, /* Output (Data, Variable, */
// Feature report
0x09, 0xAA,
0x15,0x80, /* Logical Minimum (-128) */
0x25,0x7F, /* Logical Maximum (127) */
0x75,0x08, /* Report Size (8 bit) */
0x95,0x08, /* Report Count (8 byte) */
0xB1,0x02, /* Output (Data, Variable, */
0xC0 /* End Collection */
}
Ich habe einen Interrupt In Endpoint 1, der alle 10ms abgefragt werden
sollte (was aber anscheinend auch nicht gemacht wird).
Ein Aufruf wie folgt:
unsigned char buffer[10]={0,'e','s','t'};;
unsigned long num;
ReadFile(m_HIDComm.HidHandle,buffer,10,&num,NULL);
verschwindet im Nirvana, es werden keine Daten gelesen. Es wird aber
auch keine Anforderung an den MC gesendet.
Ist das korrekt so?
Wenn ich also ein Readfile Request, bekomme ich keinen Fehler.
Allerding habe ich den Puffer auf 10 (8+ 2 Bytes) gesetzt, sonst kam
der bekannte Fehler 1784.
Was ist da komisch?
Beste Grüße Joerg
So, wie ich das sehe, benötigst Du einen Buffer der Größe 8+1 Byte. Das
erste Byte muß dabei vor dem Lesen genullt werden.
Wie groß der Buffer tatsächlich zu sein hat, erfährst Du übrigens von
HidP_GetCaps.
BTW: Das Abfragen alle 10 ms funktioniert auch ohne das eine Anwendung
läuft, die das Gerät bedient; das geht ganz und gar ohne Dein Zutun.
Für mich hört sich das im Momement an, als hättest Du noch einen dicken
Bock in Deiner Firmware. Um sicherzugehen, solltest Du auf alle Fälle
einen Protokoll-Analyzer zu Hilfe nehmen. Dann siehst Du sofort, was da
passiert. Da Du über die Enumeration bereits hinaus bist, sollten auch
die reinen Software-Lösungen taugen. Allerdings kann ich da nichts
empfehlen, da ich die selber nicht verwende (mir steht ein in Hardware
gegossener Analyzer zur Verfügung).
@ King
Das glaube ich auch, das mit dem Bock meine ich. Aber es ist mir sehr
mystisch, was der Treiber macht. Irgendwie scheint der die empfangenen
Daten zu Filtern und für ihn uninteressante Dinge wegzuwerfen.
Übrigens funktioniert Readfile zwar nicht, aber Hid_GetFeature
funtkioniert. Dabei wird ein Get_Report Control Request ausgeführt.
Aber wieso geht das nicht mit ReadFile???
Vielen Dank für deine Antworten.
Beste Grüße
Joerg
Da wird definitiv nichts gefiltert. Der Host fragt Deinen Controller im
angegebenen Intervall ab und speichert den kompletten Report in einem
Ringbuffer. Wieviele Reports in diesem Buffer gespeichert werden, kannst
Du mit HidD_SetNumInputBuffers einstellen. ReadFile holt sich dann die
Daten aus diesem Buffer, sofern vorhanden.
Wenn das bei Dir nicht funktionieren will, kann es z.B. daran liegen,
daß Du die Requests lediglich NACKst. Oder vielleicht sendest Du Daten
in einer Länge, die sich nicht mit dem Descriptor deckt. Auch wenn ich
mich wiederhole, aber schau Dir das mit einem Protokoll Analyzer an,
z.B.:
http://sourceforge.net/projects/usbsnoop/
Ob der gut oder schlecht ist, kann ich, wie gesagt, nicht beurteilen.
Ich verwende ihn selber nicht. Aber ganz sicher ist das besser als gar
nichts.
bei mir ist es genau umgekehrt:
ReadFile klappt super, das was ich mit den µC an einen Endpunkt (bei
mir EP1) lade, wird vom PC angefordert und visualisiert.
aber WriteFile klappt nicht. meine host-anwendung fängt dann an
"abzuschmieren". dann klappt nicht mal readFile mehr.
und obwohl ich GetLastError() aufrufe, wird kein fehler angezeigt.
die host-anwendung ist mit vb geschrieben. bei ReadFile hab ich den
overlapped-modus aktiviert wegen dem multithreading. bei WriteFile
nicht, könnte es daran liegen?
übrigens benutze ich als µC einen PSoC. ist super leicht handzuhaben.
und vorallem kann man in kurzer zeit eine usb-gerät/application
programmieren. ich bin begeistert
> die host-anwendung ist mit vb geschrieben. bei ReadFile hab ich den> overlapped-modus aktiviert wegen dem multithreading. bei WriteFile> nicht, könnte es daran liegen?
Das verstehe ich nicht. Overlapped wird bei CreateFile mit dem Flag
FILE_FLAG_OVERLAPPED aktiviert und nirgendwo anders. Einmal aktiviert
gilt das für WriteFile ebenso wie für ReadFile. Mir ist es ein
absolutes Rätsel, wie Du bei diesen Funktionen etwas aktivieren/
deaktivieren willst.
Beachten mußt Du aber, daß wenn Du mit FILE_FLAG_OVERLAPPED arbeitest,
der letzte Parameter nicht genullt werden darf:
"If hFile was opened with FILE_FLAG_OVERLAPPED, the lpOverlapped
parameter must not be NULL."
Quelle (Beschreibung des letzten Parameters):
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/writefile.asp?frame=true
Außerdem verstehe ich nicht, wie und wo Du GetLastError aufrufst, wenn
doch während des WriteFile-Aufrufes die Anwendung abschmiert.
> übrigens benutze ich als µC einen PSoC. ist super leicht> handzuhaben. und vorallem kann man in kurzer zeit eine usb-> gerät/application programmieren. ich bin begeistert
Ich verwende nicht den PSoC. Ich habe einen Controller, für den es vom
Hersteller bereits eine fix und fertige HID Firmware gibt. Da mußt Du
gar nichts mehr programmieren. Ich bin begeistert.
sorry, dass ich mich unverständlich ausgedrückt habe. das wenn ich mit
FILE_FLAG_OVERLAPPED arbeite den letzte Parameter nicht nullen darf,
weiß ich auch.
Das sind einer meiner aufrufe der api, vielleicht versteht man besser
was ich meine:
Public Function OpenForRead(FileName As String) As Long
OpenForRead = CreateFile(FileName, GENERIC_READ,
FILE_SHARE_READWRITE, SA, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0)
End Function
Public Function OpenForWrite(FileName As String) As Long
OpenForWrite = CreateFile(FileName, GENERIC_WRITE,
FILE_SHARE_READWRITE, SA, OPEN_EXISTING, 0, 0)
End Function
...... GetLastError rufe ich wie folgt auf:
Success = WriteFile(WriteHandle, Sample_Rate(0), 2, BytesWritten, 0)
If (Success = 0) Then
Message.Text = "Error " & GetLastError() & " sending command
to device"
Call CloseProcessMonitoringDevice
Exit Sub
Else
'anweisungen....
End if
ich denke es liegt an meiner firmware, werde mir noch mal den hid
report descriptor anschauen.
>Ich verwende nicht den PSoC. Ich habe einen Controller, für den es>vom>Hersteller bereits eine fix und fertige HID Firmware gibt. Da mußt>Du>gar nichts mehr programmieren. Ich bin begeistert.
dann verrate uns doch welchen controller du benutzt :)
Wer oder was ist Sample_Rate(0) und was steht da drin? Bist Du sicher,
daß das Gerät nur ein einziges Byte an Nutzdaten erwartet (das geht,
ist dann aber doch ziemlich ungewöhnlich)?
> dann verrate uns doch welchen controller du benutzt :)
SiLabs C8051F320, im Moment schaue ich mir auch den F345 an.
Ausführliche Samples gibt es aber inzwischen von so ziemlich jedem
Hersteller.