![]() |
EndOfFile/EndOfData bei Pipe erkennen
Wenn man mit ReadFile von einer Communications-Resource ließt und es keine/nicht genug Daten gibt, dann schläft der Thread ein, da die Funktion ja wartet, bis genug Daten gelesen wurden.
Kann man also vor dem ReadFile erkennen, ob etwas/genug zum Lesen vorhanden ist? SetFilePointer liefert hier ja immer 0 und GetFileSize arbeitet eh nicht und SetCommTimeouts hat leider keine Wirkung. Klar gäbe es noch andere Wege: - asynchrones Lesen mit Timeout - auslagern in einen Thread und die Daten via Callback rüberschicken, wenn was vorhanden ist - k.A. was sonst noch Aber ich würde gern direkt auslesen (also kein Thread) und mir wäre es lieb, wenn ich sofort erfahren würde, ob was vorhanden ist (also kein Timeout abwarten). |
AW: EndOfFile/EndOfData bei Pipe erkennen
Wenn es sich tatsächlich um eine named/unnamed Pipe handelt, empfiehlt sich die WinAPI Funktion PeekNamedPipe.
Code:
Die Funktion ist nicht blockend (d.h. kein Thread erforderlich) und liefert mit dem obigen Aufruf die Anzahl der verfügbaren Bytes.
if not PeekNamedPipe(LHandle, nil, 0, nil, @LBytesAvail, nil) then
RaiseLastOSError; Mehr unter ![]() |
AW: EndOfFile/EndOfData bei Pipe erkennen
Nee, geht leider auch nicht :cry:
Zitat:
Also derzeit scheint es halbwegs gute Ergebnisse über ReadFileEx + SleepEx als TimeOut zu geben. Ich denke mal ich werde dieses ausbauen und bei einem TimeOut einige nachfolgende Leseoperationen überspringen (einfach behaupten es gäbe keine Daten), bevor erneut gelesen wird, um den Zeitverlust durch den TimeOut zu kompensieren. Nja, als was dieses genau läuft, weiß ich auch nicht, es ist jedenfalls keine Datei. :stupid: Es handelt sich um ein Eingabegerät (HID): '\\?\hid#vid_057e&pid_0306#2&32f7afb6&0&0000#{4d1e 55b2-f16f-11cf-88cb-001111000030}' Na gut, ich versuch dann später mal mit dem ReadFileEx+SleepEx weiterzuprobieren. Leider mußte ich so auch die Ausgabe asynchron gestalten, da ich eigentlich nur ein gemeinsames FileHandle verwenden wollte ... aber mal sehn. |
AW: EndOfFile/EndOfData bei Pipe erkennen
Zitat:
|
AW: EndOfFile/EndOfData bei Pipe erkennen
Zitat:
Es ist einfach ein Gerät, welches über die Human Interface Device-Schnittstellen (HID) angesprochen wird. Also wen interessiert es hier wirklich, ob es ein Wü-kompatibles-Eingabegerät ist? :stupid: PS: Es steht alles genau drin - HID > die Schnittstelle - vid_057e > die Vendor-ID $057E - pid_0306 > die Product-ID $0306 = Wii-Controler via HID :zwinker: |
AW: EndOfFile/EndOfData bei Pipe erkennen
Also wenn es sich um folgendes Gerät handelt:
HID\VID_057e&PID_0306 HID_DEVICE_SYSTEM_GAME HID_DEVICE_UP:0001_U:0005 HID_DEVICE Les Paul Controller for Nintende Wii Model No. 95125.805 (ok, hätte vor dem antworten mal schauen sollen, was schon geschrieben wurde) könnte vielleicht das folgende Projekt interessant sein: ![]() Ist zwar C-Code, aber relativ einfach gehalten und es geht ja im wesentlichen um die API-Aufrufe. In dem Zusammenhang ist vielleicht auch noch folgender Bereich der MSDN-Library interssant: ![]() |
AW: EndOfFile/EndOfData bei Pipe erkennen
Dafür ist doch das Overlapped Flag in Readfile da. Daraufhin dann ein WaitForMultipleObjects. Da kannst du dann nach dem Event von ReadFile und ein AbbruchEvent oder Timeout prüfen und das alles im aktuellen Thread.
|
AW: EndOfFile/EndOfData bei Pipe erkennen
@Dezipaitor:
So löse ich das aktuell ja auch, aber dennoch wartet man so erstmal den TimeOut ab, bevor man sagt "nee, da gibt's nix zu holen". Ich hätte halt gern die Daten nur abgeholt, wenn überhaupt welche da sind, anstatt 'ne Weile lang zu probieren, ob ich was rausbekomm. @sparky: Ja, ich hab schon einige Codes, leider sind die Meisten für's .net oder sie arbeiten "nur" via ReadFile, welches zwar über BlueSoleil fast hervoragend arbeitet, aber unter Windows 7 direkt mit dem Windows Bluetooth-Stack eben nicht. Aber wiiuse klingt dennoch nett, drum schau ich's mir mal an. :thumb: Unter Windows sieben nutze muß statt WriteFile ![]() Statt ReadFile müßte ![]() Damit gibt's zwar noch einige Problemchen, aber ReadFile funktioniert da definitiv garnicht. Im Prinzip würde lieber komplett auf ReadFile/WriteFile verzichten, aber unter XP geht es nicht ohne BlueSoleil und somit muß ReadFile doch mit rein. HidD_GetInputReport arbeitet jedenfalls nicht blockierend und somit würde ich auch gern das ReadFile direkt mit in dieser Funktion haben, falls HidD_GetInputReport nicht arbeitet. Via Overlapped arbeitet ReadFile(Ex) zwar nicht blockierend, aber dennoch muß ich eine gewisse Zeit warten bis ich den Lesevorgang abbrech und mir sage "ok, da gibt es nichts zu holen". Sieht bestimmt sehr chaotisch aus, aber so ist es halt, wenn man vieles ausprobiert.
Delphi-Quellcode:
Function THIDDevice.Recive(Var Buffer; Len: Integer): Boolean;
Var W, W2: LongWord; O: TOverlapped; E: LongWord; Begin FLock.BeginWrite; Try If not FConnected Then DoConectionError; WriteLn('* BeginRead'); Byte(Buffer) := 0; Result := HidD_GetInputReport(FPort, @Buffer, Len); E := GetLastError; If not Result Then WriteLn('* GetInputReport - error ', E); If not Result and (E{GetLastError} in [ERROR_NOT_SUPPORTED, ERROR_CRC]) Then // Result := ReadFile(FPort, Buffer, Len, W, nil) and (W = Len); Begin ZeroMemory(@O, SizeOf(O)); O.hEvent := LongWord(Self); Result := ReadFileEx(FPort, @Buffer, Len, @O, @DummyReadCompletion) and (SleepEx(50, True) = WAIT_IO_COMPLETION) and GetOverlappedResult(FPort, O, W, False) and (W = Len); If not Result Then CancelIO(FPort); End; E := GetLastError; If not Result Then WriteLn('* ReadFile - error ', E); WriteLn('* EndRead'); WriteLn; // Begin // ZeroMemory(@O, SizeOf(O)); // O.hEvent := LongWord(Self); // If ReadFile(FPort, Buffer, Len, W, @O) Then Begin // Result := SleepEx(10, True) = WAIT_IO_COMPLETION; // If not Result Then CancelIo(FPort); // End Else Result := False; // ShowMessage(SysErrorMessage(GetLastError)); // End; Finally FLock.EndWrite; End; End; |
AW: EndOfFile/EndOfData bei Pipe erkennen
@himitsu:
Aus dem Quelltext geht leider nicht hervor wie der an Receive() übergebene Buffer initialisiert ist, vielleicht liegt da die Ursache dafür das nur Windows 7 geht (MSDN: ![]() Wenn ich Microsoft richtig verstehe, aber wer tut das schon :?, sollte es jedenfalls auch unter XP mit der Kombination HidD_GetInputReport() und ReadFile() funktionieren (MSDN: ![]() BTW welches sind denn die genauen Fehler die unter XP ausgegeben werden wenn man den unter Win7 funktionierendem Code nimmt? |
AW: EndOfFile/EndOfData bei Pipe erkennen
Da das Senden schonmal zu funktionieren scheint, geh ich mal darauf ein.
(beim Empfangen ist es ähnlich) HidD_SetOutputReport liefert unter XP+BlueSoleil ERROR_NOT_SUPPORTED zurück. Initialisiert wurde es recht "einfach". - erstmal alles mit 0 füllen und dann die nötigen Werte setzen. - danach dann die benötigten Werte setzen - und zum Schluß halt noch abseden
Delphi-Quellcode:
Ich lade gleich meine aktuellen Codes hoch.
Var Report: TWiiReport;
Report.Clear; Report.ReportID := WII_RID_LED; // setzt Byte[0] - ReportID Report.Rumble := blRumble in FOutput; // setzt Byte[1] - OutputFlags dieses Reports Report.LED1 := blLED1 in FOutput; // setzt Byte[1] ... Report.LED2 := blLED2 in FOutput; // ... Report.LED3 := blLED3 in FOutput; Report.LED4 := blLED4 in FOutput; {THIDDevice.}Send(Report, WIIMOTE_BT_REPORT_LEN); Der selbe Report wird unter XP+ ![]() und unter Win7 funktioniert nur HidD_GetInputReport. Dieses RegisterRawInputDevices klingt auch nett ... 'ne Message für die empfangenen Daten würde das Pollen (ständig nachsehn, ob was da ist) und somit dieses ReadFile-Problem obsolete machen. Aber leider weiß ich nicht, wie man das verwendet, bzw. welche Parameter man übergeben muß. Das Einzige, was ich mit der Verbindung zur Wii fand, das war ![]() mummykinoi weiß es auch nicht) |
AW: EndOfFile/EndOfData bei Pipe erkennen
Zitat:
Ich versuche gerade über die GetRawInput... Funktionen einen Barcode-Scanner mit HID Interface (Bluetooth/USB) anzubinden. Allerdings muss ich heute erst noch ein anderes Projekt zur Abgabe bereit machen. Melde mich nochmal, wenn ich weiss ob das mit der Raw Input Anbindung hinhaut. Edit: Zitat:
|
AW: EndOfFile/EndOfData bei Pipe erkennen
Er erwähnt, daß er erfahren hat, daß es dieses gibt, und fragt quasi ob/wie man dieses nutzen kann.
Zitat:
Zitat:
Zitat:
Sich dabei aber mehrkt, daß es nicht ging und dann beim nächsten Versuch direkt die andere Variante nutzt. Das werde ich wohl so ähnlich übernehmen. wiiuse nutzt dieses auch um BlueSoleil und WindowsBTStack zu unterscheiden (WriteFile=BlueSoleil, ansonsten WinBTStack). Zitat:
Der Controler wird einfach nicht verbunden, bzw. die Verbindung bricht nach wenigen Sekunden wieder zusammen/ab. Da scheint sich erst seit Win7 oder eventuell Vista etwas verbessert zu haben. Darum wird auch in fast allen Fällen, wo der WiiControler mit dem PC verbunden wird, auf BlueSoleil verwiesen. Es gibt zwar inzwischen einen Treiber, welchen jemand Anfang des Jahres veröffentlich hat, aber ausprobiert hab ich den noch nicht und wenn wir es unter Win7 über dessen eigenen BTStack hinbekommen, dann ist dieser Treiber auch eher unnötig, vorallem da er eh nur für Win7 existiert. ![]() Ach ja, was die Unterstützungen angeht, vom System her hab ich eh nur vor XP+ (notfalls auch erst ab Win7) zu unterstützen. Älteres wird explizit nicht mehr unterstützt (entweder es läuft oder nicht). Aktuell hab ich 2 APIs verwendet, welche es erst ab XP gibt. Also alle Vorschläge für diese Versionen und älteres wird eh "ignoriert" :stupid: |
AW: EndOfFile/EndOfData bei Pipe erkennen
Kurzes Update zum Thema Raw Input:
Als wahre Fundgrube hat sich ![]() Top-Level Collection (TLC) zur Geräteauswahl) inkl. Quelltext für Delphi :-D. Ausserdem ein Hinweis auf Robert Marquardt's ![]() Erfolgsmeldung kommt (hoffentlich) morgen... |
AW: EndOfFile/EndOfData bei Pipe erkennen
Schau mir grade die Programmchen an :-D
PS: Roberts HID-Zeugs ist auch in der JCL (JEDI) enthalten. |
AW: EndOfFile/EndOfData bei Pipe erkennen
Zitat:
Hatte gestern versucht dieses bei mir zu integrierren, aber egal was ich bei RegisterRawInputDevices vesuche, es kommen keine WM_INPUT bei meiner Anwendung an. Hab es mit den Werten (UsagePage=5, Usage=1) der TopLevelCollection des Devices versucht und auch mit den Werten (UsagePage=$FF00, Usage=1) von den InputButtons versucht. Nja, immerhin läuft es jetzt endlich, auch wenn es nicht optimal ist, da leider die reinkommenden Daten ein bissl viel sind, bzw. nicht über den Timer optimal genug verarbeitet werden. Hab jetzt die Anwendung auf 3 FileHandles umgestellt. - 1x GENERIC_WRITE, für die Schreibzugriffe - 1x GENERIC_READ + Overlappt, für die Lesezugriffe - 1x DesiredAccess=0, für sonstige Zugriffe Das Overlappt machte beim Schreiben leider enorme Probleme, so daß es manchmal angeblich erfollgreich war, selbst wenn das Device nicht angeschlossen war. Ohne das Assynchrone konnte man nicht Lesend zugreifen, ohne den Thread hängen zu lassen. Und da es nun eh schon 2 Handles gab, fliel das 3. Handle auch nicht weiter auf und so ist nun alles voneinander getrennt. Nun wäre es noch sehr schön, wenn das mit dem RawInput klappt, da ich den Timer nicht zu schnell laufen lassen kann/will, da ich nicht durch Pollen das System zu sehr auslasten möchte. |
AW: EndOfFile/EndOfData bei Pipe erkennen
Sorry, dass es etwas gedauert hat...
Das Projekt ist bei uns erstmal wieder auf Eis gelegt worden :( andere Sachen haben Vorrang. Ich werde aber morgen mal die Beispiel-Quellen zu dem was ich schon rausgefunden habe hier posten. Soviel schonmal vorab: WM_INPUT Messages kommen an :-D, aber dafür immer von allen Devices die den gewählten TLC-Kriterien entsprechen :? Man muss also die eingehenden Messages nach ihrem Device-Handle filtern, die Zuordnung des Device-Handle zu den HID Geräten ist möglich aber ein bischen umständlich. Das "schlechte" ist, dass man die Input-Messages nur bekommt wenn die Anwendung aktiv ist (also den Focus hat), was ich für unsere Barcode-Scanner Geschichte eigentlich vermeiden wollte. |
AW: EndOfFile/EndOfData bei Pipe erkennen
Theoretisch sollte da RIDEV_INPUTSINK helfen.
Zitat:
|
AW: EndOfFile/EndOfData bei Pipe erkennen
Liste der Anhänge anzeigen (Anzahl: 1)
Die Verwendung von RIDEV_INPUTSINK funktioniert zwar, betrifft aber wieder alle Devices die den TLC-Kriterien von RegisterRawInputDevices entsprechen. Bei einem Barcode-Scanner mit Tastatur HID also auch die normale Tastatur... und so ein Verhalten würde mit Sicherheit auf Anwenderseite für Verwirrung sorgen
Wäre aber noch zu verkraften, wenn man wenigstens die Registrierung der Devices nach der Übertragung wieder aufheben könnte (zur Info: die Barcodes werden offline gescannt und anschließend in einer separaten Programmmaske als Batch vom Benutzer übertragen) Na mal schauen ob mir da noch was einfällt :? |
AW: EndOfFile/EndOfData bei Pipe erkennen
Liste der Anhänge anzeigen (Anzahl: 1)
Cool, es geht (WinXP).
Jetzt muß ich nur noch rausfinden, warum es bei mir nicht ging. Zitat:
ansonsten: - da ich diese "alte" JEDI Windows API nicht installiert hab, hab ich mir die entsprechenden Deklarationen erstmal mit reinkopiert - den Empfang der WM_INPUT-Messages hab ich verändert - und der Aufruf von RegisterRawInputDevices wurde angepaßt, falls man da mal mehr als nur einwas registriert So, jetzt probier ich das ganze gleich nochmal unter Win7 aus. [edit] Win7 lief auch :thumb: |
AW: EndOfFile/EndOfData bei Pipe erkennen
Habe gerade festgestellt, dass bei RIDEV_INPUTSINK (ohne RIDEV_NOLEGACY) andere Anwendungen die Messages trotzdem noch erhalten - ich brauche also nur über das Device-Handle zu filtern was ich tatsächlich haben will, Super :-D
Das Flag RIDEV_REMOVE war mir bekannt, ich hatte es aber wegen der Hinweise im MSDN Artikel zur RAWINPUTDEVICE Struktur (für RegisterRawInputDevices) noch nicht verwendet: Zitat:
:oops: mir fällt beim Schreiben gerade auf, dass das System wohl keinen Grund haben wird mir weiter Messages zu schicken, wenn ich alle registrierten TLCs wieder entferne. Ich denke mal Problem gelöst. Danke für die Info, dass es auch unter Win7 funktioniert... |
AW: EndOfFile/EndOfData bei Pipe erkennen
Zitat:
|
AW: EndOfFile/EndOfData bei Pipe erkennen
Was ich grade noch Wichtiges mitbekommen hab
und weswegen ich meiner HID-Klasse demnächst ein Singlepattern verpasse. Es kann pro Anwendung immer nur ein Fenster für ein für ein Ereignis (UsagePage+Usage) gegistriert sein. Und zwar immer das Letzte bekommt die Nachrichten. Genaue Bezeichnungen haben vorrang vor ganzen Gruppen (RIDEV_PAGEONLY). Wenn man also für ein Fenster eine ganze UsagePage reserviert und für ein Anderes nur einen bestimmten Bereich (UsagePage+Usage), dann ist bei der Gruppe dieser Bereich nicht enthalten. Da ja pro Anwendung nun eh nur ein Fenster empfangen kann, ist es also nicht schlimm und auch irgendwie einleuchtend, warum man beim Deregistrieren kein Handle angeben muß/darf/braucht. |
AW: EndOfFile/EndOfData bei Pipe erkennen
Für unseren Anwendungsfall habe ich als "Singleton-Pattern" einen modalen Dialog :wink:, und wenn der (nach einem Timeout) wieder geschlossen wird gibts auch keine Raw-Input Nachrichten / Registrierung mehr. Funktioniert besser als gedacht.
Danke für die zusammenarbeit :thumb: Übrigens: Ich würde gerne den HID-Controller aus deiner WiiHID Lib zum ermitteln aller angeschlossenen HID-Geräte verwenden. Ist das Ok, da es sich um eine kommerzielle Verwendung handelt? |
AW: EndOfFile/EndOfData bei Pipe erkennen
Is OK, ich werd' da die nächsten Tage noch das RAW-Input einbauen, den nicht richtig funktionierenden Timer ausbauen und dann wird das Ganze vermutlich wieder unter 'ner passenden Multilizenz veröffentlicht, welche das erlauben müßte.
Zitat:
Muß mir jetzt nur noch überlegen, wie ich das HID und RawInput am Besten verbinde, also wie möglichst optimal die RawInputs an die entsprechenden registrierten HID-Klassen weitergeleitet/zugeordnet werden können. Und wie/ob ich ein Win7-Problem beseitige, denn mein WiiControler wird von GetRawInputDeviceList doppelt gefunden, also mit zwei verschiedenen Handles (hDevice) und es kommen alle Reports doppelt rein. (mal sehn ob ich sie dann einfach doppelt verarbeite oder ob/wie man die Doppelten ignorieren kann) |
AW: EndOfFile/EndOfData bei Pipe erkennen
Ok, wie gesagt die Anbindung der neuen Barcode-Scanner ist bei uns erstmal noch etwas zurückgestellt.
Wird die Lib auch noch Delphi Versionen ohne Unicode und References/Closures/Generics unterstützen? Falls nicht, wäre es zumindest ein Grund mehr endlich die neue Delphi Version aus der Schublade zu holen und unsere Biblithek / aktuellen Projekte anzupassen :coder: Wenn ein Device doppelt aufgelistet wird, kommen die Reports dann für jedes Handle doppelt oder pro Handle nur einmal ? Doppelt pro Handle oder nicht identifizierbar wäre ziemlich blöd für unseren Anwendung, denn die soll über die Anzahl der unterschiedlichen Eingaben zählen (d.h.: Barcode * Anzahl = Artikel * Menge). btw, wurde das Device das doppelt auftaucht zwischenzeitlich mal getrennt oder ist eine Anwendung beim Zugriff (sprich offenem Handle) abgestürzt? Dann würde ich einfachmal vermmuten das Windows beim Verwalten der Resourcen ein wenig hinterher ist :gruebel: Mal schauen ob ich das mit den Scannern unter Win7 nach stellen kann, unter XP hatte ich bisher noch keine Probleme... |
AW: EndOfFile/EndOfData bei Pipe erkennen
Das Unicode ist kein Problem, muß ich dann nur Einiges von String/Char auf WideString/WideChar umstellen und Anderes nach ANSI konvertieren.
Die Generics sind nur zur Vereinfachung drin ... mit 'ner TList und TypeCasts läßt sich das ersetzen. Also, es sollte sich schon recht leicht abwärtskompatibel machen lassen. Die kommen pro Handle nur einmal, aber als RIDI_DEVICENAME haben sie den gleichen und sonst ist auch alles gleich. Ich müßte dann also schauen, wie ich es löse, daß dann nur auf eines der beiden Handles gehört und dabei aufpassen, daß nicht was Falsches ignoriert wird. Unter XP arbeite ich mit dem BlueSoleil-Bluetooth-Stack und unter Win7 mit dem vorhandenen Bluetooth-Stack von Microsoft. Leider kann man bei dem BTS von MS nicht "wiederverbinden". (es geht nur komplett entfernen und neu verbinden :wall:, also solltes es nicht daran liegen, daß es "wiedervervunden" wurde, da sowas ja nicht geht) Beim WiiControler ist es vermutlich nicht so schlimm, wenn was doppelt ankommt, da ich selber nur auf Veränderungen reagiere. Aber dennoch müßte man so alles doppelt auswerten und vergleichen. Bei deinem Barcode-Scanner wäre es bestimmt unpraktisch, wenn dann alle Zeichen doppelt reinkommen. Nja, vielleicht ist es ja nur ein Problem mit dem Bluetooth. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz