Frage

Ich benutze CreateFile So öffnen Sie eine asynchrone Dateihandle für ein Bluetooth -HID -Gerät auf dem System. Das Gerät startet dann Streaming -Daten und ich verwende ReadFile Daten aus dem Gerät lesen. Das Problem ist, dass, wenn die Bluetooth -Verbindung fallen gelassen wird, ReadFile Gib einfach weiter ERROR_IO_PENDING Anstatt einen Fehler zu melden.

Ich kann mich nicht auf Timeouts verlassen, da das Gerät keine Daten sendet, wenn nichts zu melden ist. Ich möchte nicht, dass es sich verabschieden, wenn die Verbindung noch lebt, aber es gibt einfach keine Daten für eine Weile.

Trotzdem bemerkt der Bluetooth -Manager (sowohl der Windows One als auch der Toshiba One) sofort, dass die Verbindung verloren ging. Diese Informationen befinden sich also irgendwo im System; Es kommt einfach nicht durch ReadFile.

Ich habe verfügbar:

  • der Dateihandle (HANDLE Wert) zum Gerät,
  • Der Pfad, der verwendet wurde, um diesen Griff zu öffnen (aber ich möchte nicht versuchen, ihn ein anderes Mal zu öffnen und eine neue Verbindung herzustellen ...)
  • ein OVERLAPPED Struktur für asynchron ReadFile.

Ich bin mir nicht sicher, ob dieses Problem bluetoothspezifisch, versteckt ist oder mit Geräten im Allgemeinen auftritt. Gibt es eine Möglichkeit, wie ich entweder kann?

  • erhalten ReadFile um einen Fehler zurückzugeben, wenn die Verbindung fallen oder
  • erkennen schnell bei einer Auszeit von ReadFile ob die Verbindung noch lebt (sie muss schnell sein, weil ReadFile wird mindestens 100 Mal pro Sekunde bezeichnet) oder
  • Lösen Sie dieses Problem auf andere Weise, an die ich nicht gedacht habe?
War es hilfreich?

Lösung

Sie müssen eine Art Umfrage haben, um zu überprüfen. Wenn es keine Veranstaltung gibt, die Sie anhängen können (ich bin mit dem Treiber nicht vertraut), besteht die einfachste Möglichkeit, Ihren COM -Port durch eine Readdatei zu befragen und zu überprüfen, ob dwByTesRead> 0 Wenn Sie einen Befehl senden. Es sollte einen Statusbefehl geben, den Sie senden können, oder Sie können überprüfen, ob Sie beispielsweise an den Port schreiben und diese Bytes kopieren können. Zum Beispiel:

WriteFile(bcPort, cmd, len, &dwBytesWrite, NULL);
if (len == dwBytesWrite) {
   // Good! Return true
} else
   // Bad! Return false
}

So mache ich es in meiner Bewerbung. Unten mag wie ein Haufen Boilerplate -Code erscheinen, aber ich denke, er hilft Ihnen dabei, die Wurzel Ihres Problems zu erreichen. Ich öffne zuerst den COMM -Port zu Beginn.

Ich habe eine Reihe von COM -Ports, die ich unterhiele und überprüfe, ob sie geöffnet sind, bevor sie an einen bestimmten COM -Port schreiben. Zum Beispiel werden sie am Anfang geöffnet.

int j;
    DWORD dwBytesRead;

    if (systemDetect == SYS_DEMO)  
        return;

    if (port <= 0 || port >= MAX_PORT)
        return;

    if (hComm[port]) {
        ShowPortMessage(true, 20, port, "Serial port already open:");
        return;
    }

    wsprintf(buff, "COM%d", port);
    hComm[port] = CreateFile(buff,
                      GENERIC_READ | GENERIC_WRITE,
                      0,    //Set of bit flags that specifies how the object can be shared
                      0,    //Security Attributes
                      OPEN_EXISTING,
                      0,    //Specifies the file attributes and flags for the file
                      0);   //access to a template file

    if (hComm[port] != INVALID_HANDLE_VALUE) {
        if (GetCommState(hComm[port], &dcbCommPort)) {
            if(baudrate == 9600) {
                    dcbCommPort.BaudRate = CBR_9600;//current baud rate
            } else {
               if(baudrate == 115200) {
                   dcbCommPort.BaudRate = CBR_115200;
               }
            }
            dcbCommPort.fBinary = 1;        //binary mode, no EOF check
            dcbCommPort.fParity = 0;        //enable parity checking
            dcbCommPort.fOutxCtsFlow = 0;   //CTS output flow control
            dcbCommPort.fOutxDsrFlow = 0;   //DSR output flow control
//           dcbCommPort.fDtrControl = 1;    //DTR flow control type
            dcbCommPort.fDtrControl = 0;    //DTR flow control type
            dcbCommPort.fDsrSensitivity = 0;//DSR sensitivity
            dcbCommPort.fTXContinueOnXoff = 0; //XOFF continues Tx
            dcbCommPort.fOutX = 0;          //XON/XOFF out flow control
            dcbCommPort.fInX = 0;           //XON/XOFF in flow control
            dcbCommPort.fErrorChar = 0;     //enable error replacement
            dcbCommPort.fNull = 0;          //enable null stripping
            //dcbCommPort.fRtsControl = 1;  //RTS flow control
            dcbCommPort.fRtsControl = 0;    //RTS flow control
            dcbCommPort.fAbortOnError = 0;  //abort reads/writes on error
            dcbCommPort.fDummy2 = 0;        //reserved

            dcbCommPort.XonLim = 2048;      //transmit XON threshold
            dcbCommPort.XoffLim = 512;      //transmit XOFF threshold
            dcbCommPort.ByteSize = 8;       //number of bits/byte, 4-8
            dcbCommPort.Parity = 0;         //0-4=no,odd,even,mark,space
            dcbCommPort.StopBits = 0;       //0,1,2 = 1, 1.5, 2
            dcbCommPort.XonChar = 0x11;     //Tx and Rx XON character
            dcbCommPort.XoffChar = 0x13;    //Tx and Rx XOFF character
            dcbCommPort.ErrorChar = 0;      //error replacement character
            dcbCommPort.EofChar = 0;        //end of input character
            dcbCommPort.EvtChar = 0;        //received event character
            if (!SetCommState(hComm[port], &dcbCommPort)) {
                setBit(SystemState, SYSTEM_PORT_ERROR);
                //ShowPortMessage(true, 21, port, "Cannot set serial port state information:");
                if (!CloseHandle(hComm[port])) {
                    //ShowPortMessage(true, 22, port, "Cannot close serial port:");
                }
                hComm[port] = NULL;
                return;
            }
        } else {
            setBit(SystemState, SYSTEM_PORT_ERROR); 
            //ShowPortMessage(true, 29, port, "Cannot get serial port state information:");
            if (!CloseHandle(hComm[port])) {
                //ShowPortMessage(true, 22, port, "Cannot close serial port:");
            }
            hComm[port] = NULL;
            return;
        }

        if (!SetupComm(hComm[port], 1024*4, 1024*2)) {
            setBit(SystemState, SYSTEM_PORT_ERROR); 
            //ShowPortMessage(true, 23, port, "Cannot set serial port I/O buffer size:");
            if (!CloseHandle(hComm[port])) {
                //ShowPortMessage(true, 22, port, "Cannot close serial port:");
            }
            hComm[port] = NULL;
            return;
        }

        if (GetCommTimeouts(hComm[port], &ctmoOld)) {
            memmove(&ctmoNew, &ctmoOld, sizeof(ctmoNew));
            //default setting
            ctmoNew.ReadTotalTimeoutConstant = 100;
            ctmoNew.ReadTotalTimeoutMultiplier = 0;
            ctmoNew.WriteTotalTimeoutMultiplier = 0;
            ctmoNew.WriteTotalTimeoutConstant = 0;
            if (!SetCommTimeouts(hComm[port], &ctmoNew)) {
                setBit(SystemState, SYSTEM_PORT_ERROR); 
                //ShowPortMessage(true, 24, port, "Cannot set serial port timeout information:");
                if (!CloseHandle(hComm[port])) {
                    //ShowPortMessage(true, 22, port, "Cannot close serial port:");
                }
                hComm[port] = NULL;
                return;
            }
        } else {
            setBit(SystemState, SYSTEM_PORT_ERROR); 
            //ShowPortMessage(true, 25, port, "Cannot get serial port timeout information:");
            if (!CloseHandle(hComm[port])) {
                //ShowPortMessage(true, 22, port, "Cannot close serial port:");
            }
            hComm[port] = NULL;
            return;
        }

        for (j = 0; j < 255; j++) {
            if (!ReadFile(hComm[port], buff, sizeof(buff), &dwBytesRead, NULL)) {
                setBit(SystemState, SYSTEM_PORT_ERROR); 
                //ShowPortMessage(true, 26, port, "Cannot read serial port:");
                j = 999;    //read error
                break;
            }

            if (dwBytesRead == 0)   //No data in COM buffer
                break;

            Sleep(10);   //Have to sleep certain time to let hardware flush buffer
        }

        if (j != 999) {
            setBit(pcState[port], PORT_OPEN);
        }
    } else {
        setBit(SystemState, SYSTEM_PORT_ERROR); 
        //ShowPortMessage(true, 28, port, "Cannot open serial port:");
        hComm[port] = NULL;
    }


HANDLE TCommPorts::OpenCommPort(void) {

 // OPEN THE COMM PORT.
 if (hComm)
     return NULL;  // if already open, don't bother

 if (systemDetect == SYS_DEMO)  
    return NULL;

 hComm = CreateFile(port,
             GENERIC_READ | GENERIC_WRITE,
             0, //Set of bit flags that specifies how the object can be shared
             0, //Security Attributes
             OPEN_EXISTING,
             0, //Specifies the file attributes and flags for the file
         0);//access to a template file


// If CreateFile fails, throw an exception. CreateFile will fail if the
// port is already open, or if the com port does not exist.

// If the function fails, the return value is INVALID_HANDLE_VALUE.
// To get extended error information, call GetLastError.

 if (hComm == INVALID_HANDLE_VALUE) {
//     throw ECommError(ECommError::OPEN_ERROR);
     return INVALID_HANDLE_VALUE;
 }

 // GET THE DCB PROPERTIES OF THE PORT WE JUST OPENED
 if (GetCommState(hComm, &dcbCommPort)) {
    // set the properties of the port we want to use
    dcbCommPort.BaudRate = CBR_9600;// current baud rate
    //dcbCommPort.BaudRate = CBR_115200;
    dcbCommPort.fBinary = 1;        // binary mode, no EOF check
    dcbCommPort.fParity = 0;        // enable parity checking
    dcbCommPort.fOutxCtsFlow = 0;   // CTS output flow control
    dcbCommPort.fOutxDsrFlow = 0;   // DSR output flow control
    //dcbCommPort.fDtrControl = 1;  // DTR flow control type
    dcbCommPort.fDtrControl = 0;    // DTR flow control type
    dcbCommPort.fDsrSensitivity = 0;// DSR sensitivity
    dcbCommPort.fTXContinueOnXoff = 0; // XOFF continues Tx
    dcbCommPort.fOutX = 0;          // XON/XOFF out flow control
    dcbCommPort.fInX = 0;           // XON/XOFF in flow control
    dcbCommPort.fErrorChar = 0;     // enable error replacement
    dcbCommPort.fNull = 0;          // enable null stripping
    //dcbCommPort.fRtsControl = 1;  // RTS flow control
    dcbCommPort.fRtsControl = 0;    // RTS flow control
    dcbCommPort.fAbortOnError = 0;  // abort reads/writes on error
    dcbCommPort.fDummy2 = 0;        // reserved
    dcbCommPort.XonLim = 2048;      // transmit XON threshold
    dcbCommPort.XoffLim = 512;      // transmit XOFF threshold
    dcbCommPort.ByteSize = 8;       // number of bits/byte, 4-8
    dcbCommPort.Parity = 0;         // 0-4=no,odd,even,mark,space
    dcbCommPort.StopBits = 0;       // 0,1,2 = 1, 1.5, 2
    dcbCommPort.XonChar = 0x11;     // Tx and Rx XON character
    dcbCommPort.XoffChar = 0x13;    // Tx and Rx XOFF character
    dcbCommPort.ErrorChar = 0;      // error replacement character
    dcbCommPort.EofChar = 0;        // end of input character
    dcbCommPort.EvtChar = 0;        // received event character
 }
 else
 {
 // something is way wrong, close the port and return
    CloseHandle(hComm);
    throw ECommError(ECommError::GETCOMMSTATE);
 }


 // SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS TO OUR SETTINGS.
 // REMEMBERTHAT THE ARGUMENT FOR BuildCommDCB MUST BE A POINTER TO A STRING.
 // ALSO NOTE THAT BuildCommDCB() DEFAULTS TO NO HANDSHAKING.
 //    wsprintf(portSetting, "%s,%c,%c,%c", baud, parity, databits, stopbits);

    dcbCommPort.DCBlength = sizeof(DCB);
//    BuildCommDCB(portSetting, &dcbCommPort);

    if (!SetCommState(hComm, &dcbCommPort)) {
        // something is way wrong, close the port and return
        CloseHandle(hComm);
        throw ECommError(ECommError::SETCOMMSTATE);
    }

    // set the intial size of the transmit and receive queues.
    // I set the receive buffer to 32k, and the transmit buffer
    // to 9k (a default).
    if (!SetupComm(hComm, 1024*32, 1024*9))
    {
        // something is hay wire, close the port and return
        CloseHandle(hComm);
        throw ECommError(ECommError::SETUPCOMM);
    }
 // SET THE COMM TIMEOUTS.
    if (GetCommTimeouts(hComm,&ctmoOld)) {
        memmove(&ctmoNew, &ctmoOld, sizeof(ctmoNew));
        //default settings
        ctmoNew.ReadTotalTimeoutConstant = 100;
        ctmoNew.ReadTotalTimeoutMultiplier = 0;
        ctmoNew.WriteTotalTimeoutMultiplier = 0;
        ctmoNew.WriteTotalTimeoutConstant = 0;
        if (!SetCommTimeouts(hComm, &ctmoNew)) {
            // something is way wrong, close the port and return
            CloseHandle(hComm);
            throw ECommError(ECommError::SETCOMMTIMEOUTS);
        }
     } else {
        CloseHandle(hComm);
        throw ECommError(ECommError::GETCOMMTIMEOUTS);
     }

     return hComm;
 }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top