WriteFile auf HID Gerät
-
Hi,
ich öffne ein Handle auf ein an den PC (Win XP) angestecktes HID Gerät.
hUSBDevice = CreateFile((LPCTSTR) pDeviceListEntry->pDevicePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); pOpenDevicesListEntry->hDevice = hUSBDevice;Jetzt möchte ich mit WriteFileEx Daten an das Device schicken.
memset(&ov,0,sizeof(ov)); ov.hEvent = CreateEvent(NULL, true, false, NULL); HidD_GetAttributes(pOpenDevicesListEntry->hDevice, &HIDAttributes); if (WriteFileEx(pOpenDevicesListEntry->hDevice, pubData, udwLen, &ov, WriteFileIOCompletionRoutine)) WaitForSingleObjectEx(ov.hEvent,INFINITE,true); else dwError = GetLastError();Jetztbringt WriteFile aber immer false zurück und GetLastError() gibt Error nummer 87 (Parameter Error) zurück. Ich wüßte aber jetzt nicht welcher Parameter Falsch sein könnte. Wenn ich das Handle auf das Device mit HIDD_GetAttributes verwende geht das. Die anderen Parameter benutze ich sonst bei WriteFile auch immer so.
Wäre über einen Tip dankbar.
MfG
-
Normalerweise kann man auf Geräte nur mittels Gerätetreiber reden...
Ich hab zumindest noch nie ein funktionierende UM Lösung gesehen...
-
Jochen Kalmbach schrieb:
Normalerweise kann man auf Geräte nur mittels Gerätetreiber reden...
WriteFile spricht doch nicht mit dem virtuellen Nirvana, sondern mit dem Treiber. Für HIDs braucht man zudem noch nichtmal einen Treiber zu installieren, da Windiws diesen bereits mitbringt.
@maikhaenig
Wenn ich mal davon ausgehe, dass pOpenDevicesListEntry->hDevice gültig ist, wird das Problem in pubData und udwLen zu finden sein. Du weißt schon dass Du ein Byte mehr an den Treiber schicken mußt als der Report groß ist? Und Du hast dieses extra Byte für den Report-Identifier auch entsprechend initialisiert?Übrigens: Was ist der Sinn von WriteFileEx? Du wartest doch gleich im nächsten Schritt INFINITE auf die Beendigung. Da kannst Du doch gleich WriteFile nehmen. Ach ja, noch etwas: Das event, das Du über die OVERLAPPED-Struktur übergibst, wird zumindest von WriteFileEx ignoriert. Wenn Du also bei der Ex-Version bleiben willst, kannst Dui Dir das Erzeugen des Events sparen.
-
Also mein Report Descriptor sieht so aus.
{ HID_GLOBAL_USAGE_PAGE+2, 0xFF, 0xFF, HID_LOCAL_USAGE+1, 0xFF, HID_MAIN_COLLECTION+1,HID_COLLECTION_APPLICATION, HID_LOCAL_USAGE+1, 0xFF, HID_GLOBAL_LOGICAL_MINIMUM+1, 0x80, HID_GLOBAL_LOGICAL_MAXIMUM+1, 0x7F, HID_GLOBAL_REPORT_COUNT+1, 1, HID_GLOBAL_REPORT_SIZE+1, 8, HID_MAIN_INPUT+1,0, HID_LOCAL_USAGE+1, 0xFF, HID_GLOBAL_LOGICAL_MINIMUM+1, 0x80, HID_GLOBAL_LOGICAL_MAXIMUM+1, 0x7F, HID_GLOBAL_REPORT_COUNT+1, 1, HID_GLOBAL_REPORT_SIZE+1, 8, HID_MAIN_INPUT+1,0, HID_MAIN_ENDCOLLECTION }Das heißt ich kann ein Byte senden. Also muß ich in WriteFileEx zwei Byte übergen das erste o das Zweite meine Daten.
WriteFileEx(pOpenDevicesListEntry->hDevice, Test, 2, &ov, WriteFileIOCompletionRoutine)aber da kommt immer noch der Fehler 87.
MfG
-
maikhaenig schrieb:
Das heißt ich kann ein Byte senden.
Bitte was? Wie kannst Du das anhand des Input-Reports sehen? Viel interessanter ist doch wohl der Output-Report.
Aber wie dem auch sein, der gezeigte Report besteht aus zweimal ein Byte. Wenn das der Output-Report gewesen wäre, hättest Du auf alle Fälle drei Bytes senden müssen (länge des Reports + 1), denn Reports müssen immer am Stück versendet werden, siehe auch HIDP_CAPS.OutputReportByteLength.
-
Also ist was an meinem Report Desrciptor nicht richtig.
wenn ich den dann so mache müte es doch ein Byte in jede Richtung sein:
{ HID_GLOBAL_USAGE_PAGE+2, 0xFF, 0xFF, HID_LOCAL_USAGE+1, 0xFF, HID_MAIN_COLLECTION+1,HID_COLLECTION_APPLICATION, HID_LOCAL_USAGE+1, 0xFF, HID_GLOBAL_LOGICAL_MINIMUM+1, 0x80, HID_GLOBAL_LOGICAL_MAXIMUM+1, 0x7F, HID_GLOBAL_REPORT_COUNT+1, 1, HID_GLOBAL_REPORT_SIZE+1, 8, HID_MAIN_INPUT+1,0, HID_LOCAL_USAGE+1, 0xFF, HID_GLOBAL_LOGICAL_MINIMUM+1, 0x80, HID_GLOBAL_LOGICAL_MAXIMUM+1, 0x7F, HID_GLOBAL_REPORT_COUNT+1, 1, HID_GLOBAL_REPORT_SIZE+1, 8, ---> HID_MAIN_OUTPUT+1,0, HID_MAIN_ENDCOLLECTION }Wenn ich jetzt 3 bytes zum PC Schicken will muß ich 3 mal ein Byte als Input hier angeben oder? Und bei 2 Bytes zum Gerät 2 Bytes als Output?
MfG
-
Ja, so kann das gehen. Jetzt hast Du ein Byte zum PC und ein Byte vom PC. So, wie es jetzt ist, mußt Du tatsächlich nur zwei Bytes an WriteFile übergeben (again: siehe HIDP_CAPS.OutputReportByteLength). Das zusätzliche Byte muß aber vor dem Aufruf initialisert sein (in Deinem Fall mit 0, da Du nicht mit IDs arbeitest).
Allerdings glaube ich nicht, dass das so einfach ist. Du kannst doch nicht einfach den Descriptor ändern, ohne die Firmware im Gerät anzupassen?!
Wenn ich jetzt 3 bytes zum PC Schicken will muß ich 3 mal ein Byte als Input hier angeben oder?
Das ist richtig. Da Du nicht mit IDs arbeitest, braucht die Firmware das zusätzliche Byte nicht mitzuschicken. Allerdings muß der Buffer, den Du an ReadFile übergibst 4 Bytes groß sein (HIDP_CAPS.InputReportByteLength), da der Treiber auf das zusätzliche Byte besteht. Und wieder muß das zusätzliche Byte vor dem Aufruf von ReadFile initialisiert sein (in Deinem Fall mit 0, da Du nicht mit IDs arbeitest).
-
also so hat das schon mal in Richtung Gerät funktioniert zumindest kam ein Byte an auch wenn es noch nicht das richtige ist.
Achso ich kann die Firmware Ändern, da das ein Development Kit (AT91SAM9260-EK) ist und bis jetzt nur die USB Schnittstelle existiert.
Ich will dem jetzt beibringen 63 Bytes zu empfangen. Gibt es da eine einfachere möglichkeit beim Report Descriptor außer das eine Byte 63 mal hintereinander zu schreiben?
MfG
-
ich konnte jetzt auch ein Byte vom Gerät an den PC senden.
Achso die Bytes kann man durch erhöhen des ReportCounts auf die gewünschte Byteanzahl erhöhen.
MfG
-
maikhaenig schrieb:
Achso die Bytes kann man durch erhöhen des ReportCounts auf die gewünschte Byteanzahl erhöhen.
Dann haben aber alle 63 Bytes die selbe USAGE. Überlege mal, ob Du das nicht feiner unterteilen kannst. Auf Seiten des Hosts könnte das weitaus übersichtlicher werden.
-
Wie meinst du das mit Feiner unterteilen?
Ich will nur Daten hin und her schicken und die Bandbreite von 63 kByte/s ausnutzen?
MfG
-
maikhaenig schrieb:
Wie meinst du das mit Feiner unterteilen?
Naja, eben nicht einfach nur den Report-Count hochsetzen, sondern mehrere Male ReportSize- und Count angeben mit unterschiedlichen USAGEs. Damit kannst Du dann mit HidP_GetUsageValue/HidP_GetUsageValueArray gezielt auf die Daten zugreifen, die Dich interessieren.
maikhaenig schrieb:
Ich will nur Daten hin und her schicken und die Bandbreite von 63 kByte/s ausnutzen?
Wenn Du einen Daten-Strom hast, funktioniert das Vorgeschlagene natürlich nicht vernünftig. Damit habe ich allerdings nicht gerechnet, da Du von 64 möglichen Bytes pro Transfer nur 63 überträgst. Ansonsten solltest Du überlegen, gerade weil Geschwindigkeit wichtig ist, auf Bulk-Transfers zu wechseln. Zwar hast Du dann die Rate nicht garantiert, aber das sollte wohl kein Problem sein. An heutigen High-Speed HUBs mit Tranaction Translator (der Host hat ja nun auch einen HUB) für Dein FS-Device wird das immer klappen. Aber Du mußt Dich dafür selber um einen Treiber bemühen.
-
Hi,
das mit dem Report Count hochsetzen funkrioniert Prima da kann ich mir dann immer genau die 64 Bytes abholen (sind 64 Bytes hab zuerst gedacht 1 Byte die Report ID 0 aber es geht auch ohne ID). Die Daten sind immer Teile einer Nachicht hängt halt immer davon ab wie groß diese ist.
Ich hatte zuerst ein Programm mit Bulk Transfers ich habe den BULK USB Treiber aus dem DDK benutzt unter WinXP, den kann ich zwar noch für Windows Vista übersetzen aber für 2000 geht das nicht da USB da eine andere Architektur hat.
Da wollte ich mal das HID ausprobieren, da das unabhängig ist und 64 kByte/s für die Anwendung ausreichen.
Ich wolte ja auch erst die Communication Device Class benutzen nur da ist immer so ne Virtuelle COM Schnittstelle rumgeschwirt die dann auch andere Programme nutzen können.
Bin für andere Vorschläge immer offen.
MfG