IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

Post Reply
exomo
Posts: 3
Joined: Thu Oct 09, 2008 2:14 pm

IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by exomo »

Hallo,
ich arbeite seit einer Weile an einem kleinen Projekt, mit dem ich meinen PC fernsteuern kann. Der Aufbau ist in etwa so wie im IOW24 Starterkit. Mein Programm ruft alle 100ms die Werte vom IR-Empfänger ab. Der Code ist größtenteils aus dem IR Beispiel.

Code: Select all

try {
        // Read the data bytes from IOWarrior
        if (IowKitReadNonBlocking(iow, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE) &&
            report.ReportID == 0x0C )
        {
            // Prevent same inserts one behind the other
            if(m_save != report.Bytes[1] || report.Bytes[0] == 16 || report.Bytes[0] == 17)
            {
                // Save the last received byte
                m_save = report.Bytes[1];

                return report.Bytes[0];
            }
        }
    }
    catch(...) {
        MessageBox(0, "Fehler beim lesen", "Error", MB_OK);
        IowKitCloseDevice(iow);
        iow = 0;
    }
Wenn jetzt das Gerät im Betrieb abgesteckt wird, stürzt das ganze Programm ab, weil IowKitReadNonBlocking nicht lesen kann. Jetzt ist meine Frage ob es irgendwie möglich ist, diesen Fehler so zu behandeln, dass nicht gleich das ganze Programm abstürzt. Ich habe ja schon ein try-catch rumgebaut, aber das bringt nichts.

Einen anderen Ansatz den ich probiert habe, ist die Idee mit dem WM_DeviceChange Messages. Das funktioniert auch ganz gut, aber eben nur unter Windows, und ich wollte das auch unter Linux verwenden. (Ich habe es noch gar nicht probiert, aber ich wollte wenn möglich systemabhängigen Code vermeiden). Aber zu der Methode habe ich trotzdem eine Frage: ist es von Windows garantiert, dass die WM_DeviceChange notification immer rechtzeitig kommt, oder kann es passieren, dass nach dem Trennen erst der Timer und dann die Notification kommt? Beim wieder anschließen ist es zum Beispiel so, dass ich die Notification bekomme, dass das Gerät verbunden ist, aber IowKitOpenDevice() schlägt trotzdem fehl.

Vielen Dank für alle hilfreichen Vorschläge.

MfG Kai
Elektron
Posts: 19
Joined: Tue Sep 30, 2008 12:57 am

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by Elektron »

In der Dokumentation der API steht:
"On error or if no data is available the function returns 0."

Also erst prüfen, was der Lesevorgang ergibt:

Code: Select all

 IOWKIT24_IO_REPORT IOReport24;
 memset(&IOReport24, 0, IOWKIT24_IO_REPORT_SIZE);	
 ReadSuccessful=0;

 ReadSuccessful=IowKitReadNonBlocking(IOWHandle, IOW_PIPE_IO_PINS, 
                (PCHAR)&IOReport24, IOWKIT24_IO_REPORT_SIZE);
Wenn dann keine Daten vorhanden sind, kannst du einen Schreibversuch unternehmen:

Code: Select all

if(!ReadSuccessful)
{
 memset(&IOReport24, 0xffff, IOWKIT24_IO_REPORT_SIZE);
 IOReport24.ReportID = 0;

 if(IowKitWrite(IOWHandle, IOW_PIPE_IO_PINS, (PCHAR)&IOReport24,
        IOWKIT24_IO_REPORT_SIZE) != IOWKIT24_IO_REPORT_SIZE)
 {
  // Schreibvorgang ist fehlgeschlagen, offensichtlich wurde der IOW abgestöpselt
 }
}
Du solltest entsprechende danach dein Programm ganz normal beenden.
User avatar
Christoph Jung
Posts: 673
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by Christoph Jung »

DeviceChange greift immer und ruft automatische alle USB-Geräte ab, die angeschlossen sind. Problematisch ist, dass nicht immer gegeben ist, dass die Reihenfolge der Auflistung der Geräte gleich ist. z.B. man hat eine USB-Festplatte, ein USB-Stick und ein IO-Warrior angeschlossen. Windows nimmt den zuerst, der zuerst "Hier" schreit. Aber mann kann in DeviceChange für diese Anwendung anpassen:

DeviceChange gefunden, Timer beenden, CloseDevice, OpenDevice, Initiatialisieren des IO-Warrior und Timer Starten.
Das sollte funktionieren. Aber es ist auch zu bedenken, dass ein DeviceChange kommt, wenn man einen USB-Stick anschließt/trennt.

Wie schon beschrieben sollte man im Timer abfangen, ob ein Lesevorgang funktioniert hat.
Software developer
Elektron
Posts: 19
Joined: Tue Sep 30, 2008 12:57 am

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by Elektron »

Als ich meinen Post verfasst habe wollte ich eigentlich schon schlafen gehen. Der Grund, warum ich dir empfohlen habe noch einen Schreibvorgang zu unternehmen, ist der folgende: Die Lesefunktion gibt den Wer "0" zurück wenn ein Fehler (d.h. der IOW abgestöpselt wurde)auftritt oder eben kein neuer Wert bereitsteht. Um letzteres auszuschließen, versucht man einen in einem Schreibvorgang auf den IOW zuzugreifen. Schlägt dieser dann auch fehl, dann kannst Du davon ausgehen, dass ersteres eingetreten ist.
exomo
Posts: 3
Joined: Thu Oct 09, 2008 2:14 pm

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by exomo »

Danke erstmal für eure Antworten.

Mein Code überprüft doch schon, ob der Rückgabewert 0 ist.

Code: Select all

if (IowKitReadNonBlocking(iow, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE) && ...
Das Problem ist ja, dass das Programm gar nicht bis zu der Überprüfung kommt, weil es vorher abstürzt.
Ein Schreibversuch gibt normal 0 zurück. Ich könnte vor jedem Leseversuch etwas schreiben, um zu sehen ob der IOW noch richtig funktioniert, aber das macht ja irgendwie auch keinen Sinn. Das würde ja die Anzahl der Zugriffe verdoppeln. Wenn es keine Andere Möglichkeit gibt, dann muss ich wohl dabei bleiben, aber es gefällt mir nicht so wirklich.

Und nochmal zu Windows und DeviceChange: Ich kann über den Namen mein Gerät eindeutig identifitieren. Ich kann damit also recht gut einen disconnect abfangen, also den Timer deaktivieren und IowKitCloseDevice() aufrufen. Allerdings möchte ich das Programm nicht beenden, sondern warten bis der IOW wieder verbunden wird. Irgendwie zeigt das Programm aber ein Verhalten, dass ich mir nicht so ganz erklären kann. Ich muss einen Verbindungsversuch machen, während der IOW nicht verbunden ist, sonst schlagen alle Versuche fehl, wenn er wieder verbunden ist. Wenn ich das CloseDevice weglasse, dann kann ich einmal wiederverbinden, bei zweiten mal (also nochmal rausziehen, reinstecken) kann ich nicht mehr verbinden. Bevor ich hier jetzt große Ratespiele veranstalte (und selber spiele) könnte mir vielleicht jemand kurz erklären wie man das korrekt machen muss mit OpenDevice() und CloseDevice(), bzw. ob ich noch eine andere Funktion brauche. In meiner Klasse sind die folgenden 2 Funktionen definiert, die bei WM_DEVICECHANGE jeweils für DEVICEREMOVECOMPLETE bzw. DEVICEARRIVAL aufgerufen werden.

Code: Select all

// open the iowarrior and enable the ir function
void IowTeil::connect() {
    iow = IowKitOpenDevice();
    if(!iow) {
        int err = GetLastError();
        throw IowException(err, "IO Warrior nicht verbunden");
    }

    /* enable IR receiver */
    IOWKIT_SPECIAL_REPORT report;

    memset(&report, 0, IOWKIT_SPECIAL_REPORT_SIZE);
    report.ReportID = 0x0C; //Setup the IOW24 with IR-function
    report.Bytes[0] = 0x01; //Enable the IR-function

    //Write to the IOWarrior
    IowKitWrite(iow, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE);

}

//close the iowarrior
void IowTeil::disconnect() {
    if(!iow) return;
    IowKitCloseDevice(iow);
    iow = 0;
}
User avatar
Christoph Jung
Posts: 673
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by Christoph Jung »

if (IowKitReadNonBlocking(iow, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE) &&
report.ReportID == 0x0C )
ist in diesem Falle evtl schuld dran, dass es zu Problemen kommt. Es wird ja abgefragt, ob ReadNonBlocking UND Report-ID korrekt sind. Wird denn vor der Abfrage auch die report-Variable auf 'null' gesetzt? ( memset() hilft da). Das ganze auch mal ohne 'try & catch' überprüft?

DeviceChange lifert ein Event, wenn man ein USB-Gerät einsteckt oder abzieht. Man muss das Programm nicht beenden.
Es dürfte kein Problem damit geben, nach wiederholten verbinden IowKitOpenDevice() aufzurufen. Voraussetzung dafür ist allerdings, dass das HANDLE (iow in dem Fall) 'null' gesetz wird, nachdem der IO-Warrior abgezogen wurde.

Die Funktion connect(), ist das die Funktion, die bei einem Device-Change aufgerufen wird? Ich würde den Schreibbefehl auch mit in die if()-Abfrage einbeziehen. Der Grund ist der, dass er durch nichts verhindert wird, wenn kein IO-Warrior da ist (sry, aber mit Exeptions kenn ich mich nicht so aus, falls das dort abgehandelt wird).
Software developer
exomo
Posts: 3
Joined: Thu Oct 09, 2008 2:14 pm

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by exomo »

Hat jetzt eine Weile gedauert bis ich mal wieder Zeit hatte, aber irgendwie komme ich einfach nicht weiter. Selbst das einfachste Testprogramm zeigt mir unerklärliches Verhalten:

Code: Select all

#include <iostream>
#include <windows.h>
#include <string>
#include "iowkit.h"

using namespace std;

int main()
{
    cout << "Start des Testprogramms" << endl;

    IOWKIT_HANDLE iow = NULL;
    iow = IowKitOpenDevice();

    if(!iow) {
        cout << "IOW kann nicht geöffnet werden" << endl;
    } else {
        cout << "IOW wurde geöffnet" << endl;
    }

    string str = "";
    getline(cin, str);

    IowKitCloseDevice(iow);
    iow =0;

    iow = IowKitOpenDevice();

    if(!iow) {
        cout << "IOW kann nicht geöffnet werden" << endl;
        return 1;
    }
    cout << "IOW wurde geöffnet" << endl;

    IowKitCloseDevice(iow);

    return 0;
}
Jetzt wirklich ganz einfach, ohne eigene Klassen, Exceptions oder sonstwas. Einfach zwei mal nacheinander IowKitOpenDevice() aufrufen, zwischen den beiden aufrufen ist eine Eingabe, damit man das USB-Kabel ein- oder ausstecken kann.

Wenn ich jetzt das Programm starte mit ausgestecktem Kabel, dann in der Pause einstecke, dann kommt ein Verbindungsfehler. Wenn ich mit eingestecktem Kabel starte und in der Pause rausziehe, kommt "IOW wurde geöffnet", was ja gar nicht sein kann.

Ich habe echt keine Ahnung warum das so ist, bzw. wie ich das richtig machen muss dass ich das Wiederverbinden kann.
friend-of-rq
Posts: 389
Joined: Sun Feb 13, 2005 1:22 pm
Location: Gerblingerode / Duderstadt
Contact:

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by friend-of-rq »

Hallo exomo,
Einen anderen Ansatz den ich probiert habe, ist die Idee mit dem WM_DeviceChange Messages. Das funktioniert auch ganz gut, aber eben nur unter Windows,
also ich habe da so meine Probleme mit wenn ich einen IOW entferne oder hinzufüge dann bekomme ich folgende Mitteilungen:
WM_DeviceChange = 537

1507924 MSG=537 WP=7 LP=0
1507924 MSG=537 WP=7 LP=0
1507924 MSG=537 WP=7 LP=0
1507924 MSG=537 WP=7 LP=0
1507924 MSG=537 WP=7 LP=0
1507924 MSG=537 WP=7 LP=0

wParam=7 kann alles bedeuten ??

Auszug aus einem Beitrag von von Rainer Reusch (Geräte kommen und gehen)

Code: Select all

"Daß bei ein paar Gerätetypen(zum Beispiel Drucker und ein USB/Parallel-Adapter) überhaupt keine DeviceChange- Botschaft generiert wird. Solche Geräte lassen sich auf diesem Weg also nicht erfassen. Weiterhin fällt auf, daß recht viele Geräte (wie USB-Geräte der HID-Klasse oder Speichermedien in einem Memory Card Reader) nur die Botschaft mit dem ominösen Parameter 0007 generieren. Da nicht zwischen Hinzufügen oder Entfernen unterschieden werden kann und auch keine genauere Eingrenzung des Gerätetyps möglich ist, hilft das nicht."
Also mir auch nicht ...
Und nochmal zu Windows und DeviceChange: Ich kann über den Namen mein Gerät eindeutig identifitieren. Ich kann damit also recht gut einen disconnect abfangen.
kannst Du mir da weiter helfen ...
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by wayoda »

Hallo,
die DeviceChange Message enthält auch Informationen ob ein Gerät eingesteckt oder entfernt wurde.

Ein Beispiel dafür findet sich in den sourcen der IowKit.dll
Datei : openclos.c
Funktion : LRESULT CALLBACK ProcessWindowMessages(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam);

Ich verwende ein ähnliches Prinzip in den C#-sourcen der CsIow-Lib
http://www.wayoda.org/csiow/index.html
in der Klasse MessageCatcher (Datei : MessageCatcher.cs)
Hier überschreibe ich die WndProc-Methode einer Instanz von
System.Windows.Forms.NativeWindow

Code: Select all

        /// Listens for WM_DEVICECHANGE messages and reports them to

        /// the listener through a delegate.

        /// </summary>

        /// <param name="m">The windows-message</param>

        protected override void WndProc(ref Message m) {

            int wparam=m.WParam.ToInt32();

            int lparam=m.LParam.ToInt32();

            if(m.Msg==HidDevice.WM_DEVICECHANGE) {

                if(wparam==HidDevice.DBT_DEVICEARRIVAL) {

                    handler(MessageCatcher.DEVICE_ADD);

                }

                else if(wparam==HidDevice.DBT_DEVICEREMOVECOMPLETE) {

                    handler(MessageCatcher.DEVICE_REMOVED);

                }

            }

            else

                base.WndProc(ref m);

        }
Prinzip ist immer das gleiche wenn der Event vom Type WM_DEVICE_CHANGE ist enthält wparam nähere Informationen was tatsächlich passiert ist. Funktioniert auch zuverlässig.
Eberhard
friend-of-rq
Posts: 389
Joined: Sun Feb 13, 2005 1:22 pm
Location: Gerblingerode / Duderstadt
Contact:

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by friend-of-rq »

Hallo wayoda,

eine Mitteilung über ein wechsel bekomme ich ja ...

1507924 MSG=537 WP=7 LP=0
nur wird im wParam nichts genaueres übermittelt.

wie könnte ich denn deine CSIOW.DLL für mich nutzen ...

ich müsste dies irgendwie mit funKtionen ähnlich wie die IOWKIT.DLL in mein Programm einbauen ...

Gruss
R.Greinert
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Re: IowKitReadNonBlocking crash abfangen, wenn nicht verbunden?

Post by wayoda »

Hallo,
die CsIow implementiert das ganze speziell für .Net aber Grundlage ist die Windows-Funktion
RegisterDeviceNotification()
http://msdn.microsoft.com/en-us/library/aa363431.aspx

Wenn ich mal annehme, dass dein Code nicht in C# geschrieben ist, würde ich einfach mal nach
" RegisterDeviceNotification() " in Verbindung mit deiner Progammiersprache googeln.
Als ich vor 2 Jahren nach C# Beispielen hierzu gesucht habe, gab es nur 3 mittelmässig hilfreiche Treffer,
heute gibt es da schon meherere hundert. Hat wohl geholfen die VisualStudioExpress-Editionen umsonst zu verteilen.

Eberhard
Post Reply