WriteFile liefert immer ERROR_INVALID_PARAMETER
-
Hallo Leute
Ich hab wieder mal ein komplexes Problem, welches ich nicht lösen kann.
Folgende Grundsituation. Ein C++ Programm mit CLR öffnet mittels CreateFile ein Handle zu einem Pic-Mikrocontroller. Die Schnittstelle ist USB.
Mit Hilfe des Handles kann ich dann entweder schreiben oder lesen, je nachdem wie ich CreateFile aufgerufen habe:WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
Ziel der ganzen Aktion soll sein, dass ich eine Schnittstellendll programmiere, die dann in unterschiedliche Programme eingebunden werden kann.
Also hab ich mir ein Design ausgedacht, wie die DLL dann von extern angesprochen werden kann. Soweit hab ich das alles fertig. Beim Testen ist mir allerdings aufgefallen, dass ich nichts Lesen und Schreiben kann. Jedoch funktioniert die ganze Sache in dem modifizierten Beispielcode den ich von Microchip genommen habe. In meiner DLL wird ein Thread gestartet der zyklisch läuft und für das Auslesen der Daten zuständig ist. Ich hab das dann aber erst mal soweit verinfacht, dass ich es in einer stinknormalen Funktion teste um potentielle Fehlerquellen auszuschließen. Funktionieren tut das ganze trotzdem nicht. Bei meinem code bekomme ich immer den Fehler ERROR_INVALID_PARAMETER wenn ich auf das Device schreibe. Bisher hab ich auch noch nicht rausgefunden, welcher Parameter dabei angemotzt wird.Hier mal die beiden Codeschnipsel
Funktionierender Codeteil aus der modifizierten Demo:
if(MatchFound == true) { DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //First call populates "StructureSize" with the correct value SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL); DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize)); //Allocate enough memory if(DetailedInterfaceDataStructure == NULL) //if null, error, couldn't allocate enough memory { //Can't really recover from this situation, just exit instead. SetupDiDestroyDeviceInfoListUM(DeviceInfoTable); //Clean up the old structure we no longer need. return; } DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods. SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); //We now have the proper device path, and we can finally open read and write handles to the device. //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate. WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = GetLastError(); ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = GetLastError(); if(ErrorStatus == ERROR_SUCCESS) {//Schreibe Testwert um zu prüfen ob das Handle stimmt DWORD BytesWritten = 0; DWORD BytesRead = 0; unsigned char InputPacketBuffer[65]; //Allocate a memory buffer equal to our endpoint size + 1 OutputPacketBuffer[0] = 0; //The first byte is the "Report ID" and does not get transmitted over the USB bus. Always set = 0. OutputPacketBuffer[1] = 0x82; //0x81 is the "Get Pushbutton State" command in the firmware WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
Hier der Code aus meiner DLL, der mir den Fehler bei WriteFile wirft!
if(DeviceIDFromRegistry->Contains(DeviceIDToFind) == true) { DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //First call populates "StructureSize" with the correct value SetupDiGetDeviceInterfaceDetail(hDevInfo, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL); DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize)); //Allocate enough memory if(DetailedInterfaceDataStructure == NULL) //if null, error, couldn't allocate enough memory { //Can't really recover from this situation, just exit instead. SetupDiDestroyDeviceInfoList(hDevInfo); //Clean up the old structure we no longer need. return false; } DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods. SetupDiGetDeviceInterfaceDetail(hDevInfo, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = GetLastError(); if(ErrorStatus == ERROR_SUCCESS) { ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = GetLastError(); } if (ErrorStatus == ERROR_SUCCESS) { DWORD BytesWritten = 0; unsigned char OutputPacketBuffer[65]; //Allocate a memory buffer equal to our endpoint size + 1 //Lese-/Schreibe Daten OutputPacketBuffer[0] = 0; OutputPacketBuffer[1] = 0x82; //Kommando um alle Eingänge zu lesen //Prüfe ob auch geschrieben wurde if (!WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0)) { ErrorStatus = GetLastError(); //Fehler beim Schreiben. Beende dich selbst. SetupDiDestroyDeviceInfoList(hDevInfo); return false; } }
Die Aufrufe aus der setupapi Bibliothek sind bei meinem Code mittels #pragma comment(lib,"setupapi.lib"); statisch gelinkt. In dem Democode wurden die Funktionen mittels DLLImport eingebunden. Aber da vermute ich nicht mein Problem, denn diese Funktionen liefern mir in beiden Bereichen die selben Werte.
Woran könnte das denn liegen, das mein Code nicht funktioniert? Hat jemand Erfahrung mit dem Schreiben und Lesen mittels CreateFile/WriteFile und ReadFile auf USB-Devices?
Ich bin für jeden noch so kleinen Tipp dankbar, denn ich bin am Ende mit meinem Latein!
Grüße
Daimonion
-
In meiner aktuellen Software habe ich ja auch ein Programm, welches die DLL lädt und die Funktionen testet. Kann es sein, dass unterschiedliche Projekteinstellungen dazu führen, dass WriteFile nicht richtig funktioniert?
Die DLL wird mit folgenden Einstellungen kompiliert:
CLR-Unterstützung: /clr
Aufrufkonvention: __stdcallBei der Testsoftware sind die Einstellungen ebenso, aber ich muß dem main ein __clrcall voranstellen.
Kann es damit zusammenhängen?
Edit:
Ich hab jetzt nochmal eine zusätzliche Funktion in die DLL programmiert:
bool test(HANDLE hndl) { DWORD BytesWritten = 0; DWORD ErrorStatus = 0; unsigned char OutputPacketBuffer[65]; //Lese-/Schreibe Daten //OutputPacketBuffer[0] = 0; //OutputPacketBuffer[1] = 0x82; //Kommando um alle Eingänge zu lesen //Prüfe ob auch geschrieben wurde if (!WriteFile(hndl, &OutputPacketBuffer, sizeof(OutputPacketBuffer), &BytesWritten, 0)) { ErrorStatus = GetLastError(); //Fehler beim Schreiben. Beende dich selbst. return false; } else return true; }
Dann hab ich die DLL in meine modifizierte Version der Microchipleute geladen, also die Version die funktioniert. Mit folgendem Ergebnis:
Rufe ich Write und Read Prozeduren in meiner modifizierten Version auf, dann werden diese korrekt ausgeführt. Rufe ich aber mit dem selben WriteHandle die Testfunktion aus meiner DLL auf, dann bekomme ich besagten Fehler.
Was kann das sein? Speicherbereiche vielleicht?
Bin über jeden Tipp dankbar!
-
An unterschiedlichen Projekt-Einstellungen liegt es ziemlich sicher nicht. Die Funktion innerhalb der Dll wird doch scheinbar korrekt aufgerufen. Und da sich alle folgenden Aktionen innerhalb dieser einen Dll abspielen, sollte das kein Problem sein.
Allerdings fällt mir folgendes auf:
daimonion schrieb:
WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = GetLastError(); if(ErrorStatus == ERROR_SUCCESS) { ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = GetLastError(); } if (ErrorStatus == ERROR_SUCCESS) { DWORD BytesWritten = 0; unsigned char OutputPacketBuffer[65]; //Allocate a memory buffer equal to our endpoint size + 1 //Lese-/Schreibe Daten OutputPacketBuffer[0] = 0; OutputPacketBuffer[1] = 0x82; //Kommando um alle Eingänge zu lesen //Prüfe ob auch geschrieben wurde if (!WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0)) { ErrorStatus = GetLastError(); //Fehler beim Schreiben. Beende dich selbst. SetupDiDestroyDeviceInfoList(hDevInfo); return false; } }
-
GetLastError liefert den Code des letzten Errors. Wenn aber kein Fehler passiert ist, ist der Wert nicht aussagekräftig. Der Wert kann auch der Fehlercode einer ganz anderen Funktion sein, die irgendwann einmal in die Hose gegangen ist.
-
Wenn WriteFile in die Hose geht, schließt Du die frisch geöffneten HANDLEs nicht.
-
Beim Aufruf von WriteFile würde ich mir das "&" beim OutputPacketBuffer sparen.
Also so:
WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = (WriteHandle == INVALID_HANDLE_VALUE) ? GetLastError() : ERROR_SUCCESS; if(ErrorStatus == ERROR_SUCCESS) { ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); ErrorStatus = (ReadHandle == INVALID_HANDLE_VALUE) ? GetLastError() : ERROR_SUCCESS; } if (ErrorStatus == ERROR_SUCCESS) { DWORD BytesWritten = 0; unsigned char OutputPacketBuffer[65]; //Allocate a memory buffer equal to our endpoint size + 1 //Lese-/Schreibe Daten OutputPacketBuffer[0] = 0; OutputPacketBuffer[1] = 0x82; //Kommando um alle Eingänge zu lesen //Prüfe ob auch geschrieben wurde if (!WriteFile(WriteHandle, OutputPacketBuffer, 65, &BytesWritten, 0)) { ErrorStatus = GetLastError(); //Fehler beim Schreiben. Beende dich selbst. CloseHandle(ReadHandle); CloseHandle(WriteHandle); SetupDiDestroyDeviceInfoList(hDevInfo); return false; } }
Das eigentliche Problem wird sich dadurch sicherlich noch nicht beheben lassen. Auch kann ich nicht erkennen, was hier schief laufen könnte. Das Problem wird wohl eher woanders liegen, nicht in dem gezeigten Code. Da müssten wir erstmal die ganze Pracht ansehen können. Vielleicht sieht man dann, was schief laufen kann.
BTW: Warum öffnest Du das Device gleich zwei mal? Warum reicht Dir nicht ein CreateFile, dafür aber mit Schreib- und Lesezugriff? Und über was für ein Gerät reden wir hier eigentlich, nach welchem Interface lässt Du das SetupApi suchen?
-
-
Hi, und Danke für die Antwort.
Der Code so wie ich ihn gepostet habe ist bei weitem nicht komplett. So viele Fehlermöglichkeiten wie da noch nicht abgefangen sind...
Nein, ich hab erst mal ein grobes Gerüst erstellt um zu schauen ob meine Idee funktioniert. Und na ja schon bei dem Gerüst bin ich gescheitert. Deswegen wende ich mich ja an euch.Ich möchte mal deine Punkte abarbeiten, um die Fragestruktur aufrecht zu erhalten.
1.) Das GetLastError einen anderen Fehler abrufen könnte ist aber durchaus nicht schön. Werde mal meinen Code so anpassen, dass das nicht mehr passieren kann.
2.) Der Code wird momentan nur gedebuggt. Später müssen die Handles natürlich wieder geschlossen werden, was sie definitiv auch tun werden.
3.) Hab ich eigentlich nur so übernommen, wie es in dem Beispiel war. In der MSDN steht es ja auch so drin. Nichtsdestotrotz hab ich das & weg gemacht. Passt mir eigentlich auch besser so.
Leider ist das Verhalten damit noch nicht behoben.
Ich werde mal ein Packet zusammenschnüren, welches ich euch dann hier posten kann.
Was ich versuche zu machen:
Ich hab einen PIC18F2550 mit dem ich via USB kommunizieren will. Auf PIC Seite ist soweit alles fertig. Auf PC Seite möchte ich nun eine DLL schreiben die ich in verschiedene Programme einbinden kann und von da aus mit wenigen Funktionen auf den PIC zugreifen kann. Als ich das PIC Programm geschrieben hab, hab ich mir eine Testsoftware für den PC geschrieben, die nach wie vor einwandfrei funktioniert! Aus dieser hab ich dann meine Codeschnipsel genommen um meine DLL aufzubauen. Selber code der einmal funktioniert und einmal nicht.
Im Endeffekt sind die Funktionen in der DLL spartansich:
init();
getInput();
getOutput();
setOutput();
usw.Die Probleme spielen sich derzeit in der init() Funktion ab die ich aus einer neuen Testapplikation aufrufe (Form mit zwei Buttons, die die jeweiligen DLL-Funktionen aufrufen)!
Noch was hab ich bemerkt. In meiner Testfunktion ( bool test() {...} ) hab ich die Variablendeklaration OutputPacketBuffer[65] aus dem Lokalen in den globalen DLL Bereich (Headerfile) verschoben und dann funktionierte WriteFile. Das könnte aber wiederrum an dem & liegen.
Edit:
So hier erst mal eine URL zu dem Testprogramm, welches ich während des programmieren des PICs geschrieben hab.
DownloadSo und hier mal die URL zu der DLL und einer kleinen Applikation, die die DLL-Funktion aufruft. Dieser Code funktioniert insoweit das Handles aufgebaut werden. WriteFile wirft aber den Fehler ERROR_INVALID_PARAMETER.
Download
-
Aha, es geht hier also um ein HID. Wie sieht denn der Report-Descriptor aus? Mich interessiert da vor allem der Output-Report.
-
BTW: Was in aller Welt soll denn die Funktion getOutput() erledigen?
-
Der Pic hat ja digitale Ein- und Ausgänge. Mit getOutput kann man sich den Zustand des Ausganges holen (0 oder 1) So braucht man in einer übergeordneten Applikation nicht alle I/Os mitführen und synchronisieren.
Report Descriptoren. Soweit wie ich das richtig verstanden hab, nutzt Microchip die gar nicht und soll auf 0 gesetzt werden. Das ist doch immer der erste Arrayindex im Buffer oder? Ich such mal die Unterlage von MC raus.
Edit:
Kommentar aus dem Beispiel von PIC:OutputPacketBuffer[0] = 0; //The first byte is the "Report ID" and does not get transmitted over the USB bus. Always set = 0.
Edit:
Okay, Report Descriptoren sind was anderesIch schau mal wo in meinem Code da was geschrieben steht. Brauchte die bisher nämlich nicht.
-
daimonion schrieb:
Der Pic hat ja digitale Ein- und Ausgänge. Mit getOutput kann man sich den Zustand des Ausganges holen (0 oder 1) So braucht man in einer übergeordneten Applikation nicht alle I/Os mitführen und synchronisieren.
Ach so, das ergibt natürlich Sinn. Ich hatte das eben auf den Report reduziert. Und da ein Output-Report grundsätzlich vom Host in den Controller gereicht wird und niemals anders herum (Einbahnstrasse), sah das auf den ersten Blick etwas putzig aus.
daimonion schrieb:
Report Descriptoren. Soweit wie ich das richtig verstanden hab, nutzt Microchip die gar nicht und soll auf 0 gesetzt werden.
Das erste Byte ist der Report-Identifier. Ob der nun benutzt wird oder nicht, ergibt sich aus dem Descriptor. Unter anderem deswegen wollte ich mir das Dingens anschauen.
Den Descriptor selber muss es aber geben. Ohne dem funktioniert das HID nämlich nicht. Wenn Du den Descriptor eben nicht finden kannst, prüfe wenigstens, ob die Größe von OutputPacketBuffer mit der benötigten Größe des Reports übereinstimmt (HIDP_CAPS.OutputReportByteLength, HidP_GetCaps).
daimonion schrieb:
Das ist doch immer der erste Arrayindex im Buffer oder? Ich such mal die Unterlage von MC raus.
Mit dem MC hat das nichts zu tun, da wirst Du im Datenblatt nichts finden. :p
-
Moin Moin schrieb:
Den Descriptor selber muss es aber geben. Ohne dem funktioniert das HID nämlich nicht. Wenn Du den Descriptor eben nicht finden kannst, prüfe wenigstens, ob die Größe von OutputPacketBuffer mit der benötigten Größe des Reports übereinstimmt (HIDP_CAPS.OutputReportByteLength, HidP_GetCaps).
Ich denke mir der Descriptor wird irgendwie durch die setupapi-Funktionen bzw. Rückwirkend durch CreateFile genutzt. Du hast ja eigentlich den kompletten Code da. Mehr hab ich da auch erst mal nicht. Ich werde mich mal informieren, welchen ReportDescriptor die MC Leute für dieses Beispiel nutzen, bzw. werd mal deine genannten Funktionen probieren, um an Infos zu kommen!
Edit: Wer stellt denn den Descriptor zur Verfügung? Das HID-Device?
EditEdit: HidP_GetCaps ist doch im WDK drin. Soweit ich das hier Überblicke, ist das in meinem VS2005 nicht drin, und runterladen geht nicht da ich bisher noch keinen Account bei MSDN hab...
-
daimonion schrieb:
Ich denke mir der Descriptor wird irgendwie durch die setupapi-Funktionen bzw. Rückwirkend durch CreateFile genutzt.
Das ist so nicht ganz richtig, denn weder CreateFile nocht die SetupAPI-Funktionen interessieren sich für die Reports. Es interessiert sich viel mehr der Treiber direkt dafür. Mit diesen Informationen ist er nämlich in der Lage, Buffer in der richtigen Größe zu allokieren. Das nächste Mal wird es interessant, wenn Du ReadFile und/oder WriteFile aufrufst. Beim Schreiben kann geschaut werden, ob es den angegebenen Report überhaupt gibt. Beim Lesen wird geschaut, welchen Report Du haben möchtest.
Außerdem gibt es noch einen ganzen Haufen Funktionen, um Reports zu parsen oder Daten aus diesen zu extrahieren oder Daten zu setzen.
daimonion schrieb:
Du hast ja eigentlich den kompletten Code da. Mehr hab ich da auch erst mal nicht.
Hier funktioniert Dein Code. Allerdings hätte ich einiges anders gemacht, aber das wollen wir besser nicht diskutieren.
daimonion schrieb:
Ich werde mich mal informieren, welchen ReportDescriptor die MC Leute für dieses Beispiel nutzen, bzw. werd mal deine genannten Funktionen probieren, um an Infos zu kommen!
Du wirst doch mehr als ein Hex-File haben, oder? Da wird doch irgendwo eine Datei zwischen sein, die "descriptors.c" oder so ähnlich heißt. Oder nicht?
daimonion schrieb:
Edit: Wer stellt denn den Descriptor zur Verfügung? Das HID-Device?
Jawoll. Das macht das Device, um den Host mitzuteilen, wie er mit dem Device umzugehen hat.
daimonion schrieb:
EditEdit: HidP_GetCaps ist doch im WDK drin. Soweit ich das hier Überblicke, ist das in meinem VS2005 nicht drin, und runterladen geht nicht da ich bisher noch keinen Account bei MSDN hab...
Ich habe das eben nicht im Blick (ich bin MSDN Kunde), aber es muss doch eine Möglichkeit geben, da einigermaßen blasenfrei heranzukommen. Ohne dem bist Du doch aufgeschmissen. Du kommst doch so nichtmal an Feature-Reports heran, Du kannst Strings nicht lesen, usw..
Aber immerhin weiß ich jetzt, warum Du Dich so mühsam durch die Registry quälst...
-
Okay, dann fangen wir mal an.
Ne bin kein MSDN Kunde. Wär vielleicht mal interessant, wenn wir hier in Zukunft öfters so was machen. Kostet das was?
Klar hab ich mehr als das Hex File. Da sieht man mal wieder, das ich noch nicht wirklich viel Ahnung von USB und HID habe. Der Report Deskriptor (bzw. ein Auszug aus dem File) folgt weiter unten.
Hier funktioniert Dein Code. Allerdings hätte ich einiges anders gemacht, aber das wollen wir besser nicht diskutieren.
Ich bin über jede Kritik erfreut. Wenn sie negativ ist, dann hab ich wenigstens was zum lernen. Ist manchmal nicht einfach aus dem nichts alles zu begreifen.
So, zurück zum Problem. Ich hab hier eine "usb_descriptor.c":
usb_descriptor.cSo wie ich das sehe, passt das da drin soweit alles so zusammen, wie auch im C++ Code. Hoffe es hilft.
Besten Dank schon mal für deine Hilfe! Hast nen Kasten Bier gut.
Grüße
Daimonion
-
daimonion schrieb:
Ne bin kein MSDN Kunde. Wär vielleicht mal interessant, wenn wir hier in Zukunft öfters so was machen. Kostet das was?
Ja, doch, man kann schon sagen, dass das was kostet:
http://download.microsoft.com/download/4/1/0/4100640B-A19F-4278-9CC3-09BD9B713111/Compare%20MSDN%20and%20Expression%20Subscriptions.pdfAber wenn ich das richtig sehe, bekommst Du das WDK auch über die Connect - Seiten. Es kann gut sein, dass es hier mit einer Anmeldung getan ist. Ich hab's jetzt aber nicht probiert.
daimonion schrieb:
So, zurück zum Problem. Ich hab hier eine "usb_descriptor.c":
Das Byte-Array ganz am Ende der Datei ist der Report-Descriptor. Auch wenn das nicht gerade ein typischer Report für Joysticks ist, sehe ich da auch keine Besonderheiten. Er passt jedenfalls zu dem, was Du da machst.
Ich sehe eben jedenfalls keinen Grund warum das nicht funktionieren soll. Und in der Tat funktioniert das bei mir auch. Ich habe lediglich VID und PID und die Größe des Reports angepasst, damit es sich mit dem von mir angeschlossenen HID verträgt. Beim Durchsteppen kann ich klar sehen, dass WriteFile mit TRUE zurückkommt (die Funktion returned, ohne das die Handles freigegeben werden und ohne den Aufruf von SetupDiDestroyDeviceInfoList
).
Probiert habe ich das mit dem Projekt "Joysticktester", zusammen mit "USB Joystick DLL".
Eben bin ich ehrlich gesagt auch einigermaßen ideenlos, sorry.
BTW: Was passiert, wenn Du die 4 Zeilen mit dem Kommentar "// Usage Minimum ..." und "// Usage Maximum..." im Report auskommentierst?
-
Herje, wenn das bei dir Funktioniert, dann weiß ich auch nicht mehr weiter...
Momentan bau ich die DLL so um, dass ich keine CLR mehr brauche. Also reines C++ mit std. Sobald ich das getan habe, werde ich nochmal ein anderes Testprogramm in Delphi schreiben und nochmal berichten!
Das Byte-Array ganz am Ende der Datei ist der Report-Descriptor. Auch wenn das nicht gerade ein typischer Report für Joysticks ist, sehe ich da auch keine Besonderheiten. Er passt jedenfalls zu dem, was Du da machst.
Der Report ist aus einer HID Generic Demo. Daher wahrscheinlich auch der recht allgemeine Report.
Danke dir auf jeden Fall für deine Hilfe!
Daimonion
-
-
Jap bin ich. Nur bin ich da nicht so aktiv.
-
So, jetzt hab ich nochmal den ganzen clr Kram aus der DLL rausgehauen und mich nur auf C++ verlassen. Weiterhin hab ich das dll Projekt nochmal neu angelegt und den Code nochmal neu eingefügt. Jetzt scheint alles zu funktioninieren!
Danke an die/den Helfer
Grüße
DaimonionEdit:
Funtkionierte doch nicht. Aber dann ist mir aufgefallen das ich meine Indexvariable für die setupapi zu zeitig inkrementiert hatte. Seitdem dieser Fehler korrigiert ist, funktionierts wirklich.