LONG CSerial::WaitEvent (DWORD dwTimeout, LPOVERLAPPED lpOverlapped) { // Check if time-outs are supported CheckRequirements(lpOverlapped,dwTimeout); // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit qDebug() << ("CSerial::WaitEvent - Device is not opened\n"); return m_lLastError; } #ifndef SERIAL_NO_OVERLAPPED // Check if an overlapped structure has been specified if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) { // Set the internal error code m_lLastError = ERROR_INVALID_FUNCTION; // Issue an error and quit qDebug() << ("CSerial::WaitEvent - Overlapped I/O is disabled, specified parameters are illegal.\n"); return m_lLastError; } // Wait for the event to happen OVERLAPPED ovInternal; if (!lpOverlapped && m_hevtOverlapped) { // Setup our own overlapped structure memset(&ovInternal,0,sizeof(ovInternal)); ovInternal.hEvent = m_hevtOverlapped; // Use our internal overlapped structure lpOverlapped = &ovInternal; } // Make sure the overlapped structure isn't busy //_ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); // Wait for the COM event if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),lpOverlapped)) { // Set the internal error code long lLastError = ::GetLastError(); // Overlapped operation in progress is not an actual error if (lLastError != ERROR_IO_PENDING) { // Save the error m_lLastError = lLastError; // Issue an error and quit //qDebug() << ("CSerial::WaitEvent - Unable to wait for COM event\n"); return m_lLastError; } // We need to block if the client didn't specify an overlapped structure if (lpOverlapped == &ovInternal) { // Wait for the overlapped operation to complete switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) { case WAIT_OBJECT_0: // The overlapped operation has completed break; case WAIT_TIMEOUT: // Cancel the I/O operation CancelCommIo(); // The operation timed out. Set the internal error code and quit m_lLastError = ERROR_TIMEOUT; return m_lLastError; default: // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit qDebug() << ("CSerial::WaitEvent - Unable to wait until COM event has arrived\n"); return m_lLastError; } } } else { // The operation completed immediatly. Just to be sure // we'll set the overlapped structure's event handle. if (lpOverlapped) ::SetEvent(lpOverlapped->hEvent); } #else // Wait for the COM event if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),0)) { // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit qDebug() << ("CSerial::WaitEvent - Unable to wait for COM event\n"); return m_lLastError; } #endif // Return successfully return m_lLastError; }
LONG CSerial::Write (const void* pData, size_t iLen, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) { // Check if time-outs are supported CheckRequirements(lpOverlapped,dwTimeout); // Overlapped operation should specify the pdwWritten variable _ASSERTE(!lpOverlapped || pdwWritten); // Reset error state m_lLastError = ERROR_SUCCESS; // Use our own variable for read count DWORD dwWritten; if (pdwWritten == 0) { pdwWritten = &dwWritten; } // Reset the number of bytes written *pdwWritten = 0; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Device is not opened\n"); return m_lLastError; } #ifndef SERIAL_NO_OVERLAPPED // Check if an overlapped structure has been specified if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) { // Set the internal error code m_lLastError = ERROR_INVALID_FUNCTION; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped I/O is disabled, specified parameters are illegal.\n"); return m_lLastError; } // Wait for the event to happen OVERLAPPED ovInternal; if (!lpOverlapped && m_hevtOverlapped) { // Setup our own overlapped structure memset(&ovInternal,0,sizeof(ovInternal)); ovInternal.hEvent = m_hevtOverlapped; // Use our internal overlapped structure lpOverlapped = &ovInternal; } // Make sure the overlapped structure isn't busy _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); // Write the data if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,lpOverlapped)) { // Set the internal error code long lLastError = ::GetLastError(); // Overlapped operation in progress is not an actual error if (lLastError != ERROR_IO_PENDING) { // Save the error m_lLastError = lLastError; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n"); return m_lLastError; } // We need to block if the client didn't specify an overlapped structure if (lpOverlapped == &ovInternal) { // Wait for the overlapped operation to complete switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) { case WAIT_OBJECT_0: // The overlapped operation has completed if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwWritten,FALSE)) { // Set the internal error code m_lLastError = ::GetLastError(); _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped completed without result\n"); return m_lLastError; } break; case WAIT_TIMEOUT: // Cancel the I/O operation CancelCommIo(); // The operation timed out. Set the internal error code and quit m_lLastError = ERROR_TIMEOUT; return m_lLastError; default: // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Unable to wait until data has been sent\n"); return m_lLastError; } } } else { // The operation completed immediatly. Just to be sure // we'll set the overlapped structure's event handle. if (lpOverlapped) ::SetEvent(lpOverlapped->hEvent); } #else // Write the data if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,0)) { // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n"); return m_lLastError; } #endif // Return successfully return m_lLastError; }
int CSerial::read(void* pData, size_t iLen, DWORD* pdwRead, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) { // Check if time-outs are supported CheckRequirements(lpOverlapped,dwTimeout); // Overlapped operation should specify the pdwRead variable //_ASSERTE(!lpOverlapped || pdwRead); // Reset error state m_lLastError = ERROR_SUCCESS; // Use our own variable for read count DWORD dwRead; if (pdwRead == 0) { pdwRead = &dwRead; } // Reset the number of bytes read *pdwRead = 0; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit qDebug() << ("CSerial::Read - Device is not opened\n"); //return m_lLastError; return -1; } #ifdef _DEBUG // The debug version fills the entire data structure with // 0xDC bytes, to catch buffer errors as soon as possible. memset(pData,0xDC,iLen); #endif #ifndef SERIAL_NO_OVERLAPPED // Check if an overlapped structure has been specified if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) { // Set the internal error code m_lLastError = ERROR_INVALID_FUNCTION; // Issue an error and quit qDebug() << ("CSerial::Read - Overlapped I/O is disabled, specified parameters are illegal.\n"); //return m_lLastError; return -1; } // Wait for the event to happen OVERLAPPED ovInternal; if (lpOverlapped == 0) { // Setup our own overlapped structure memset(&ovInternal,0,sizeof(ovInternal)); ovInternal.hEvent = m_hevtOverlapped; // Use our internal overlapped structure lpOverlapped = &ovInternal; } // Make sure the overlapped structure isn't busy //_ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); // Read the data if (!::ReadFile(m_hFile,pData,iLen,pdwRead,lpOverlapped)) { // Set the internal error code long lLastError = ::GetLastError(); int bytesRead = *pdwRead; // Overlapped operation in progress is not an actual error if (lLastError != ERROR_IO_PENDING) { // Save the error m_lLastError = lLastError; // Issue an error and quit qDebug() << ("CSerial::Read - Unable to read the data\n"); //return m_lLastError; return -1; } // We need to block if the client didn't specify an overlapped structure if (lpOverlapped == &ovInternal) { // Wait for the overlapped operation to complete switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) { case WAIT_OBJECT_0: // The overlapped operation has completed if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwRead,FALSE)) { // Set the internal error code m_lLastError = ::GetLastError(); qDebug() << ("CSerial::Read - Overlapped completed without result\n"); //return m_lLastError; } return bytesRead; case WAIT_TIMEOUT: // Cancel the I/O operation CancelCommIo(); // The operation timed out. Set the internal error code and quit m_lLastError = ERROR_TIMEOUT; //return m_lLastError; return bytesRead; default: // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit qDebug() << ("CSerial::Read - Unable to wait until data has been read\n"); //return m_lLastError; return -1; } } } else { // The operation completed immediately. Just to be sure // we'll set the overlapped structure's event handle. if (lpOverlapped) ::SetEvent(lpOverlapped->hEvent); return *pdwRead; } #else // Read the data if (!::ReadFile(m_hFile,pData,iLen,pdwRead,0)) { // Set the internal error code m_lLastError ::GetLastError())); // Issue an error and quit qDebug() << ("CSerial::Read - Unable to read the data\n"); return m_lLastError; }