USB-Port ansprechen
-
hi aber möchte das gerne selber proggen die ansteuerung...damit ich mich dann auch gut mit usb auskenne.....
hast du schon mal mit usb und c++ was gemacht?cu
-
surf. schrieb:
hi aber möchte das gerne selber proggen die ansteuerung...damit ich mich dann auch gut mit usb auskenne.....
Na klar. Das machst Du am Besten mit dem CY7C63001. Der digitalisiert das Video-Signal mal eben so 'on the fly'. Das Komprimieren macht er dann sowieso im Schlaf, schliesslich arbeitet er intern mit satten 12MHz. Das Video-RAM bekommst Du auch prima an die 20Pins angeschlossen. Über den sage und schreibe 8 Bytes umfassenden FIFO übertragen sich die Daten ruckzuck an den PC. 25 Bilder/ Sekunde sind keine Hexerei.
So, und dann schreibst Du schnell noch den passenden Treiber und alles wird gut. Hallo?
hast du schon mal mit usb und c++ was gemacht?
Ja, habe ich. Für Video verwende ich aber handelsübliche Hardware und zum Zugriff darauf die üblichen Schnittstellen.
Kauf Dir lieber ein ordentliches Buch!
-
Hallo!
Allen noch'n gesundes neues Jahr.
Da bin ich mal wieder, mittlerweile auch ein ganzes Stück weiter.
Meinen USB/PPI-Adapter habe ich dazu bekommen, mir zu sagen was für ein Gerät er ist und dass er mit mir spricht (auf An- und Abstecken meldet er mir, dass er da ist oder nicht). Daten könnte ich auch empfangen, bloß habe ich das Problem, dass ich nicht weiß, wie ich das Datengeschäft (PC/SPS) initialisieren soll. Ich empfange zwar etwas, aber fast immer das gleiche, was nicht sein kann. Die SPS muss dazu mit dem Adapter und dem PC verbunden sein (logo ). Im Herstellerprogramm brauche ich dann nur auf beobachten klicken und das Geschäft zwischen SPS und PC wird initialisiert (ich kann die jeweiligen Veränderungen der Programmvariablen beobachten). Außerdem habe ich mitbekommen, dass das USB-Protokoll auf das PPI-Protokoll oben aufgesetzt wird, der Adapter regelt den Rest.
Wer hat eine Idee, wie ich das Geschäft zum laufen bekomme?
-
Moin!
Mit wem oder was unterhälst Du Dich denn jetzt? Ist es das HID? Wenn ja, dann ist es normal, daß Du immer die gleichen Daten bekommst.
Der Host pollt Deine Geräte in regelmäßigen Abständen. Wie oft das passiert, steht in den Descriptoren der Endpoints. Wenn ich mir jetzt an Deiner SPS einfach mal 8 digitale IOs vorstelle, wird in Deinem Input-Report auch ein Byte vorhanden sein, das den logic level repräsentiert. Und wenn sich da nichts ändert, bekommst Du immer wieder die gleichen Daten vom Gerät zurück. Das sieht man auch bei einem Joystick sehr schön: Du bekommst immer wieder die gleichen Koordinaten geliefert. Es ändert sich in den Daten erst dann etwas, wenn Du den Knüppel bewegst oder Knöpfe drückst.
Man kann natürlich auch einen SET_IDLE Request mit 0 für Duration an das Gerät senden. Dann antwortet das Gerät nur noch dann, wenn sich auch die Daten geändert haben. Dazu muß das Gerät diesen Request natürlich auch bearbeiten. Wie man diesen Request im User-Mode an das Gerät sendet, weiß ich auch nicht. Und im Kernel Mode bin nun auch nicht gerade heimisch ...
Als Abhilfe könntest Du in einem Timer mit ReadFile das Gerät befragen. Das Ergebnis vergleichst Du nun mit dem Ergebnis der vorherigen Abfrage. Hat sich etwas geändert, kannst Du entsrechend verfahren.
Ich gebe aber noch zu bedenken, daß ich SPSen allenfalls vom Hörensagen kenne. Ich hoffe trotzdem, daß Du mit den Ausführungen etwas anfangen kannst.
BTW: Klappt das nun mit dem Enumerieren, oder holst Du noch immer den Namen mit WinObj?
-
Ich unterhalte mich mit dem Adapter als HID. Da wird mir jetzt klar, warum ich immer das Gleiche empfange. Die Idee mit dem Timer hatte ich auch schon, dadurch ist mir das erst aufgefallen.
Das Enumerieren klappt wunderbar. Ich habe festgestellt, dass meine Adresse falsch gewesen ist und ich immer ein ungültiges Handle zurückbekommen habe.
Der GUID ist für HIDs immer gleich (meine Maus hat den gleichen wie der Adapter, habe ich, glaube ich jedenfalls, irgendwo in der MSDN gelesen).Die Adressierung unterscheidet sich dann nur noch von der VendorID, ProductID und dem jeweiligen Port.
Ich werde mal versuchen was aus Deinem Tip zu machen.
Danke erstmal.
-
baschti schrieb:
Der GUID ist für HIDs immer gleich (meine Maus hat den gleichen wie der Adapter, habe ich, glaube ich jedenfalls, irgendwo in der MSDN gelesen).Die Adressierung unterscheidet sich dann nur noch von der VendorID, ProductID und dem jeweiligen Port.
Ist das jetzt eine Frage oder eine Feststellung? Aber ja, der GUID ist immer gleich. Es handelt sich auch immer um die gleiche Geräteklasse.
Und ja, Mäuse sind auch HIDs, ebenso wie Joysticks und Tastaturen. Allerdings folgen diese einem speziellen Protokol (festgelegt über den Device Descriptor).
-
Morgen!
Wer immer schon mal wissen wollte, was auf seinen USB-Ports los ist, kann sich hier (www.lvr.com (-->ziemlich weit unten, unter protocol analyzers)):
den HHD USB Monitorals Demoversion von HHD Software runterladen. Das ist ein software-only tool. Dieses Tool ist ein Filtertreiber, der sich zwischen host controller und Gerätetreiber installiert. Die Software lässt dann den Datenstrom an sich vorbeilaufen und dokumentiert diesen mit. Ihr habt 30 Tage oder 100 Versuche zum testen.
Daher habe ich auch den Hex-Code, den ich eigentlich meiner SPS senden wollte, aber irgendetwas geht an meinem Prog noch nicht . Kann mir bitte jemand sagen, was daran falsch ist?
Code für eine Statusanforderung:
10 00 00 49 49 16
Das ist mein Prog in der kurzen Version (nur eine einmalige Anforderung als Consolen-Anwendung):
//Programm zur Verbindung mit dem USB_HID #include <stdio.h> #include <windows.h> int main() { HANDLE hTreiber = INVALID_HANDLE_VALUE; int string [] = {0x10, 0x00, 0x00, 0x49, 0x49, 0x16}; char getstring[] = ""; unsigned long BytesWritten, BytesRead; SetLastError(0); //USB Schnittstelle konfigurieren hTreiber = CreateFile("\\\\.\\hid#vid_0908&pid_0200#6&1d2d6ffa&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hTreiber == INVALID_HANDLE_VALUE) { printf("Verbindung zum USB-HID konnte nicht hergestellt werden!\nError %u\n", GetLastError()); CloseHandle (hTreiber); } else { //printf("Verbindung zum USB-HID konnte hergstellt werden!\n"); WriteFile(hTreiber, string, sizeof(string), &BytesWritten, NULL); ReadFile(hTreiber, getstring, sizeof(getstring), &BytesRead, NULL); printf("%x\n", getstring); CloseHandle(hTreiber); } return 0; }
Danke, für Eure Hilfe.
-
hi baschti!!
was genau willst du eigentlich realisieren?
bitte send mir mal deinen kompletten code auf: surfman19@gmx.at
möcht mir das gerne mal angucken!!! cu surf.
-
baschti schrieb:
Wer immer schon mal wissen wollte, was auf seinen USB-Ports los ist, kann sich hier (www.lvr.com (-->ziemlich weit unten, unter protocol analyzers)):
den HHD USB Monitorals Demoversion von HHD Software runterladen.
*AufDieScheisseHau* -> Sowas habe ich in Hardware.
baschti schrieb:
Code für eine Statusanforderung:
10 00 00 49 49 16
Für WriteFile benötigst Du noch ein Byte mehr (das erste Byte ist der Report-Identifier). WriteFile sollte sonst aber auch fehlschlagen. Das Gleiche gilt für den Feature-Report und den Input-Report. Hier mußt Du ebenfalls ein zusätzliches Byte übergeben.
Um sicherzugehen, solltest Du die Reoprts analysieren (HidD_GetPreparsedData/ HidP_GetCaps/ HidD_FreePreparsedData).
BTW: Du brauchst das Abfragen des Status nicht mit WriteFile anzustossen. Der Host pollt das Gerät sowieso in regelmäßigen Abständen. Den Interval legt das Gerät über den Endpoint-Descriptor fest. Du brauchst also lediglich ReadFile.
-
Hallo!
Hey, nicht gleich so grob King. scherz
Ich dachte nur, die Software wäre eine günstige Alternative. dickes Schluchzzz...Ich bin aber auch ein Dussel. Habe Euch das falsch erklärt. Der Code ist keine Statusanforderung, sondern dient dazu, sich im Token Ring als PC und Master mit der Adresse 0 anzumelden und um zu sagen, dass ich das Token haben will. Habe auch noch den Hex-Code um Variablen zu lesen und zu schreiben. Dann sollte das, abgesehen vom Report-Identifier, mit WriteFile klappen.
Jetzt verstehe ich auch, was Du mit Parsen der Reports weiter vorn gemeint hast. Gehe ich dabei vor wie beim Enumerieren und brauche ich dazu das Handle auf's Gerät? Blöde Frage vielleicht, wie mache ich das zusätzliche Byte für den Report-Identifier sichtbar aus den Reports und welches ist es? Die MSDN-Seite dazu habe ich.
Danke für Eure Antwort.@surf.
Ich versuche eine SPS über PC und USB zu steuern. Dabei geht's mir darum Variablen zu lesen und diese zu korrigieren, falls sie sich ändern.
-
baschti schrieb:
Gehe ich dabei vor wie beim Enumerieren und brauche ich dazu das Handle auf's Gerät?
Um die Report-Informationen zusammenzustellen, benötigst Du das Geräte-Handle. Schliesslich sind die Reports im Gerät gespeichert und müssen erst von dort gelesen werden. Die Funktion HidD_GetPreparsedData erledigt diesen Teil für Dich. Sind die Report-Descriptoren zusammengesammelt, kannst Du damit arbeiten. Dazu gibt es die ganzen HidP_XXX-Funktionen. Um Dir einen Überblick zu verschaffen, verwendest Du HidP_GetCaps.
In der gefüllten HID_CAPS-Struktur kannst Du nun die benötigten Buffer-Größen für die einzelnen Reports ersehen, inklusive des (ersten) zusätzlichen Bytes (<- für WriteFile einfach auf 0 setzen, IIRC).
Den Einblick vertiefen kannst Du mit HidP_GetButtonCaps und HidP_GetValueCaps.
BTW: Natürlich kannst Du die für die Reports reservierten Buffer direkt bearbeiten. Ich für meinen Teil fand aber die Möglichkeit ganz nett, das Modifizieren von den Funktionen aus hid.dll erledigen zu lassen (HidP_SetUsageValue, HidP_SetUsageValueArray, usw.).
-
Prima, danke. Werde ich gleich mal dran weiterarbeiten.
-
Hallo King!
Ich hoffe, ich nerve nicht zu sehr. Hast Du irgendeinen Fehler in meiner WriteFile/ReadFile-Anweisung weiter vorn gefunden? Denn irgendetwas klappt noch nicht.
Das Parsen der Reports hat folgendes ergeben:
(Hoffe habe alle Informationen, sind arg viele.)Usage: 1 Usage Page: 0xFFA0 Input Report Byte Length: 261 Output Report Byte Length: 261 Feature Report Byte Length: 0 Number of Link Collection Nodes: 1 Number of Input Button Caps: 0 Number of InputValue Caps: 1 Number of InputData Indices: 1 Number of Output Button Caps: 0 Number of Output Value Caps: 1 Number of Output Data Indices: 1 Number of Feature Button Caps: 0 Number of Feature Value Caps: 0 Number of Feature Data Indices: 0 --Input - GetValueCaps:-- Input - ReportID: 0xCC Input - BitField: 0xCCCC Input - BitSize: 0xCCCC Input - LinkCollection: 0xCCCC Input - LinkUsage: 0xCCCC Input - LinkUsagePage: 0xCCCC -Input - GetButtonCaps: Input - ReportID: 0xCC --Output - GetValueCaps:-- Output - ReportID: 0xCC Output - BitField: 0xCCCC Output - BitSize: 0xCCCC Output - LinkCollection: 0xCCCC Output - LinkUsage: 0xCCCC Output - LinkUsagePage: 0xCCCC -Output - GetButtonCaps: Output - ReportID: 0xCC
Der daraus resultierende Code für WriteFile sieht ja dann so aus:
CC 10 00 00 49 49 16
oder? Obwohl mich die Input/Output-ReportByteLength stutzig macht.
um den Input-Report zu parsen: (hier nur für Input, die Capabilities und Output-Anweisungen sind ja ähnlich)
HIDP_CAPS Capabilities; PHIDP_PREPARSED_DATA PreparsedData; HIDP_REPORT_TYPE HidP_Input, HidP_Output; HIDP_BUTTON_CAPS ButtonCaps; PUSHORT ButtonCapsLength; HIDP_VALUE_CAPS ValueCaps; PUSHORT ValueCapsLength; . . . printf("Input - GetValueCaps:\n\n"); HidP_GetValueCaps(HidP_Input, &ValueCaps, ValueCapsLength, PreparsedData); printf("%s0x%X\n", "Input - ReportID: ", ValueCaps.ReportID);
Doch wie sieht die ReadFile-Anweisung aus, um den Report-Identifier mit rein zu bekommen?
Danke für Deine unermüdliche Hilfe!
-
Ich habe mich unglücklich ausgedrückt. Mach Dir nicht so viele Gedanken um das erste Byte, das ist hauptsächlich zur internen Verwendung gedacht. Für Dich ist lediglich wichtig, daß das Byte vorhanden und auf 0 gesetzt ist. Bei ReadFile wird das erste Byte von der Funktion genullt; ich ziehe es jedoch vor, das schon vor dem Aufruf zu erledigen (man weiß ja nie ...).
Dein Aufruf von WriteFile kann so nicht klappen, weil zum Einen das erste Byte nicht 0 und zum Anderen zu kurz ist. Du überträgst lediglich 6 * sizeof(int) Bytes, also 24 an der Zahl (wundert mich sowieso, sollten das nicht Bytes sein?). Du mußt den Report in einem Rutsch übertragen, also alle 261 Bytes zusammen.
Readfile kann so nicht klappen, weil der Buffer mit nur einem einzigen Byte zu knapp bemessen ist. Du mußt alle 261 Bytes in einem Rutsch lesen.
Wenn WriteFile in die Hose geht, gibt es bei HIDs also zwei zusätzliche Fehlerquellen. Ist das erste Byte nicht 0, bekommst Du von GetLastError diesen Fehler:
// // MessageId: ERROR_INVALID_PARAMETER // // MessageText: // // The parameter is incorrect. // #define ERROR_INVALID_PARAMETER 87L // dderror
Ist der an WriteFile übergebene Buffer kleiner oder größer als HID_CAPS.OutputReportByteLength, gibt's diesen Fehler:
// // MessageId: ERROR_INVALID_USER_BUFFER // // MessageText: // // The supplied user buffer is not valid for the requested operation. // #define ERROR_INVALID_USER_BUFFER 1784L
Den zweitgenannten Fehler bekommst Du auch von ReadFile/ GetLastError, wenn der an ReadFile übergebene Buffer in der Größe != HID_CAPS.InputReportByteLength ist.
Deine beiden Aufrufe von HidP_GetValueCaps sind übrigens fehlgeschlagen. Gewöhn Dir ruhig an, auch mal die Rückgabewerte zu checken. Dann hättest Du das gesehen. Ich glaube aber Dir auch so schon sagen zu können, daß eh alles einer einzigen Usage zugeordnet ist. Da kannst Du Dir den folgenden Aufruf von HidP_SetUsageValueArray auch sparen, das wäre irgendwie auch nur ein unnötiges Umherkopieren der Buffer.
Warum genau nun HidP_GetValueCaps bei Dir in die Hose gegangen ist, wird vermutlich an ValueCapsLength liegen, was ja bei Dir ein Pointer ist. Und dieser Pointer zeigt nun irgendwo ins virtuelle Nirvana. Eine Initialisierung sehe ich jedenfalls nirgens. So ist's besser:
USHORT ValueCapsLength; ValueCapsLength = HID_CAPS.OutputReportByteLength; HIDP_VALUE_CAPS* pValueCaps = new HIDP_VALUE_CAPS[ValueCapsLength]; HidP_GetValueCaps(HidP_Input, pValueCaps, &ValueCapsLength, PreparsedData);
-
Es funktioniert fast. Meine Ausgabe ist nur noch nicht ganz korrekt.
Ich bekomme 0xCC oder 204 zurück.BYTE sendstring[261] = {0x00, 0x10, 0x83, 0x00, 0x49, 0xCC, 0x16}; BYTE getstring[261]; WriteFile(hTreiber, sendstring, 261, &BytesWritten, NULL); printf("WriteFile, Error: %u\n", GetLastError()); SetLastError(0); ReadFile(hTreiber, getstring, 261, &BytesRead, NULL); printf("ReadFile, Error: %u\n", GetLastError()); printf("0x%X\n", getstring[261]);
GetLastError() bringt genau das, was Du gesagt hast.
Ich hab gerade Deinen Vorschlag probiert, ist bestimmt bloß'n Schreibfehler, oder?-King- schrieb:
USHORT ValueCapsLength; ValueCapsLength = HID_CAPS.OutputReportByteLength;
Das müsste doch so heißen:
ValueCapsLength = HIDP_CAPS.OutputReportByteLength;
Da kommt bei mir aber der Fehler:
error C2275: "HIDP_CAPS" : Ungültige Verwendung dieses Typs als Ausdruck
-
baschti schrieb:
Ich bekomme 0xCC oder 204 zurück.
Von wem oder was?
baschti schrieb:
WriteFile(hTreiber, sendstring, 261, &BytesWritten, NULL); printf("WriteFile, Error: %u\n", GetLastError());
Das darfst Du so auf gar keinen Fall machen. Nach der Rückkehr von WriteFile kann GetLastError alles zurückgeben. Von Bedeutung ist das aber erst dann, wenn WriteFile auch tatsächlich fehlgeschlagen ist. Das mußt Du also prüfen, bevor Du GetLastError anwendest. Das gilt übrigens ebenso für ReadFile.
Von dieser Regel gibt's natürlich auch Ausnahmen. Als Beispiel sei hier CreateMutex genannt. Hier gibt GetLastError auch nach einem erfolgreichen Aufruf einen sinnigen Wert zurück. Das ist aber eine Ausnahme(!), und diese ist dann als solche extra dokumentiert.
Ich hab gerade Deinen Vorschlag probiert, ist bestimmt bloß'n Schreibfehler, oder?
Klar.
Da kommt bei mir aber der Fehler:
Bitte? Aber natürlich ist das ein Fehler. Ich wollte doch lediglich deutlich machen, daß der Wert aus der HIDP_CAPS-Struktur kommt. Aber eine Struktur-Instanz mußt Du noch erstellen. Also bitte:
HIDP_CAPS caps; // instanziieren HidP_GetCaps(pData, &caps); // füllen ValueCapsLength = caps.OutputReportByteLength;
Ich hoffe jedenfalls, daß Du mich damit nicht veralbern wolltest. Aber wenn Du gleich kommst und sagst, daß pData nicht bekannt ist, habe ich Gewissheit ...
-
Sorry, da hab' ich vorhin bei beiden geträumt. Langer Praktikumstag gewesen.
-King- schrieb:
baschti schrieb:
Ich bekomme 0xCC oder 204 zurück.
Von wem oder was?
Vom Adapter oder der SPS.
-
baschti schrieb:
Sorry, da hab' ich vorhin bei beiden geträumt. Langer Praktikumstag gewesen.
Ach, das ist das ganze Geheimnis. Dann bin ich beruhigt.
baschti schrieb:
Vom Adapter oder der SPS.
Aha. Wobei sich 0xCC eher nach einer nicht initialisierten Stack-Variable anhört, evetuell Aufgrund einer fehlgeschlagenen Funktion (die hätte initialisieren sollen). Ansonsten bin ich mir noch immer unklar darüber, ob die Werte nun gut oder schlecht sind. Und außerdem sind das 260 Bytes, die die SPS liefern sollte. Ein schlichtes 204 ist irgendwie ganz schön wenig ...
-
-King- schrieb:
Ein schlichtes 204 ist irgendwie ganz schön wenig ...
Habe ich mir auch so gedacht. Mal kucken, wo der Fehler liegt.
Ich danke Dir erstmal recht herzlich für Deine Hilfe.
-
Du hast mich falsch verstanden. Du übergibst doch einen Buffer mit einer Größe von 261 Byte. Davon wird jetzt ein Byte auf 0xCC gesetzt. Von welchem Byte reden wird denn nun? Und ist das jetzt gut oder schlecht? Betrifft das alle Bytes? Schlägt vielleicht ReadFile fehl (eine Prüfung hast Du ja noch nicht eingebaut)? Mit welchem Fehlercode schlägt ReadFile fehl, wenn überhaupt?