Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi EndOfFile/EndOfData bei Pipe erkennen (https://www.delphipraxis.net/155143-endoffile-endofdata-bei-pipe-erkennen.html)

himitsu 10. Okt 2010 21:55


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).

sparky 11. Okt 2010 10:35

AW: EndOfFile/EndOfData bei Pipe erkennen
 
Wenn es sich tatsächlich um eine named/unnamed Pipe handelt, empfiehlt sich die WinAPI Funktion PeekNamedPipe.
Code:
if not PeekNamedPipe(LHandle, nil, 0, nil, @LBytesAvail, nil) then
  RaiseLastOSError;
Die Funktion ist nicht blockend (d.h. kein Thread erforderlich) und liefert mit dem obigen Aufruf die Anzahl der verfügbaren Bytes.

Mehr unter http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx

himitsu 11. Okt 2010 11:14

AW: EndOfFile/EndOfData bei Pipe erkennen
 
Nee, geht leider auch nicht :cry:
Zitat:

Unzulõssige Funktion
Dennoch danke und willkommen an Board. :hi:



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.

Luckie 11. Okt 2010 11:19

AW: EndOfFile/EndOfData bei Pipe erkennen
 
Zitat:

Zitat von himitsu (Beitrag 1055033)
Es handelt sich um ein Eingabegerät (HID):
'\\?\hid#vid_057e&pid_0306#2&32f7afb6&0&0000#{4d1e 55b2-f16f-11cf-88cb-001111000030}'

Ach das. ;) Diese Bezeichnungen finde ich auch immer nur geil.

himitsu 11. Okt 2010 11:35

AW: EndOfFile/EndOfData bei Pipe erkennen
 
Zitat:

Zitat von Luckie (Beitrag 1055035)
Zitat:

Zitat von himitsu (Beitrag 1055033)
Es handelt sich um ein Eingabegerät (HID):
'\\?\hid#vid_057e&pid_0306#2&32f7afb6&0&0000#{4d1e 55b2-f16f-11cf-88cb-001111000030}'

Ach das. ;) Diese Bezeichnungen finde ich auch immer nur geil.

Von der Schnittstelle her ist es ja egal um was es genau geht.
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:

sparky 11. Okt 2010 11:54

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:

sourceforge - wiiuse (edit: besonders die Funktionen in io_win.c)

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:

Using Raw Input

Dezipaitor 11. Okt 2010 12:42

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.

himitsu 11. Okt 2010 13:06

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 MSDN-Library durchsuchenHidD_SetOutputReport genommen werden, welches auch sehr gut funktioniert.
Statt ReadFile müßte MSDN-Library durchsuchenHidD_GetInputReport benutzt werden.
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;

sparky 11. Okt 2010 13:39

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: Initializing HID Reports).

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: Obtaining HID Reports by User-Mode Applications).

BTW welches sind denn die genauen Fehler die unter XP ausgegeben werden wenn man den unter Win7 funktionierendem Code nimmt?

himitsu 11. Okt 2010 15:04

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:
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);
Ich lade gleich meine aktuellen Codes hoch.

Der selbe Report wird unter XP+Bei Google suchenBlueSoleil nur via WriteFile versendet
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 http://blogs.yahoo.co.jp/mummykinoi/58265222.html , aber sehr hilfreich isses nicht unbedingt. (nicht daß ich es nicht verstehen würde, aber
mummykinoi weiß es auch nicht)


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:45 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz