qCNC 0.82-alpha
/home/trilog/Desktop/project/gui/Final/src/lib/qextserialport/win_qextserialport.cpp
Go to the documentation of this file.
00001 
00002 
00003 #include <QMutexLocker>
00004 #include <QDebug>
00005 #include <QRegExp>
00006 #include "qextserialport.h"
00007 
00008 void QextSerialPort::platformSpecificInit()
00009 {
00010     Win_Handle=INVALID_HANDLE_VALUE;
00011     ZeroMemory(&overlap, sizeof(OVERLAPPED));
00012     overlap.hEvent = CreateEvent(NULL, true, false, NULL);
00013     winEventNotifier = 0;
00014     bytesToWriteLock = new QReadWriteLock;
00015     _bytesToWrite = 0;
00016 }
00017 
00021 void QextSerialPort::platformSpecificDestruct() {
00022     CloseHandle(overlap.hEvent);
00023     delete bytesToWriteLock;
00024 }
00025 
00026 QString QextSerialPort::fullPortNameWin(const QString & name)
00027 {
00028     QRegExp rx("^COM(\\d+)");
00029     QString fullName(name);
00030     if(fullName.contains(rx)) {
00031         int portnum = rx.cap(1).toInt();
00032         if(portnum > 9) // COM ports greater than 9 need \\.\ prepended
00033             fullName.prepend("\\\\.\\");
00034     }
00035     return fullName;
00036 }
00037 
00044 bool QextSerialPort::open(OpenMode mode) {
00045     unsigned long confSize = sizeof(COMMCONFIG);
00046     Win_CommConfig.dwSize = confSize;
00047     DWORD dwFlagsAndAttributes = 0;
00048     if (queryMode() == QextSerialPort::EventDriven)
00049         dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;
00050 
00051     QMutexLocker lock(mutex);
00052     if (mode == QIODevice::NotOpen)
00053         return isOpen();
00054     if (!isOpen()) {
00055         /*open the port*/
00056         Win_Handle=CreateFileA(port.toAscii(), GENERIC_READ|GENERIC_WRITE,
00057                               0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
00058         if (Win_Handle!=INVALID_HANDLE_VALUE) {
00059             QIODevice::open(mode);
00060             /*configure port settings*/
00061             GetCommConfig(Win_Handle, &Win_CommConfig, &confSize);
00062             GetCommState(Win_Handle, &(Win_CommConfig.dcb));
00063 
00064             /*set up parameters*/
00065             Win_CommConfig.dcb.fBinary=TRUE;
00066             Win_CommConfig.dcb.fInX=FALSE;
00067             Win_CommConfig.dcb.fOutX=FALSE;
00068             Win_CommConfig.dcb.fAbortOnError=FALSE;
00069             Win_CommConfig.dcb.fNull=FALSE;
00070             setBaudRate(Settings.BaudRate);
00071             setDataBits(Settings.DataBits);
00072             setStopBits(Settings.StopBits);
00073             setParity(Settings.Parity);
00074             setFlowControl(Settings.FlowControl);
00075             setTimeout(Settings.Timeout_Millisec);
00076             SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00077 
00078             //init event driven approach
00079             if (queryMode() == QextSerialPort::EventDriven) {
00080                 Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD;
00081                 Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
00082                 Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
00083                 Win_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
00084                 Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
00085                 SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
00086                 if (!SetCommMask( Win_Handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) {
00087                     qWarning() << "failed to set Comm Mask. Error code:", GetLastError();
00088                     return false;
00089                 }
00090                 winEventNotifier = new QWinEventNotifier(overlap.hEvent, this);
00091                 connect(winEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(onWinEvent(HANDLE)));
00092                 WaitCommEvent(Win_Handle, &eventMask, &overlap);
00093             }
00094         }
00095     } else {
00096         return false;
00097     }
00098     return isOpen();
00099 }
00100 
00105 void QextSerialPort::close()
00106 {
00107     QMutexLocker lock(mutex);
00108     if (isOpen()) {
00109         flush();
00110         QIODevice::close(); // mark ourselves as closed
00111         CancelIo(Win_Handle);
00112         if (CloseHandle(Win_Handle))
00113             Win_Handle = INVALID_HANDLE_VALUE;
00114         if (winEventNotifier)
00115             winEventNotifier->deleteLater();
00116 
00117         _bytesToWrite = 0;
00118 
00119         foreach(OVERLAPPED* o, pendingWrites) {
00120             CloseHandle(o->hEvent);
00121             delete o;
00122         }
00123         pendingWrites.clear();
00124     }
00125 }
00126 
00131 void QextSerialPort::flush() {
00132     QMutexLocker lock(mutex);
00133     if (isOpen()) {
00134         FlushFileBuffers(Win_Handle);
00135     }
00136 }
00137 
00144 qint64 QextSerialPort::size() const {
00145     int availBytes;
00146     COMSTAT Win_ComStat;
00147     DWORD Win_ErrorMask=0;
00148     ClearCommError(Win_Handle, &Win_ErrorMask, &Win_ComStat);
00149     availBytes = Win_ComStat.cbInQue;
00150     return (qint64)availBytes;
00151 }
00152 
00157 qint64 QextSerialPort::bytesAvailable() const {
00158     QMutexLocker lock(mutex);
00159     if (isOpen()) {
00160         DWORD Errors;
00161         COMSTAT Status;
00162         if (ClearCommError(Win_Handle, &Errors, &Status)) {
00163             return Status.cbInQue + QIODevice::bytesAvailable();
00164         }
00165         return (qint64)-1;
00166     }
00167     return 0;
00168 }
00169 
00173 void QextSerialPort::translateError(ulong error) {
00174     if (error&CE_BREAK) {
00175         lastErr=E_BREAK_CONDITION;
00176     }
00177     else if (error&CE_FRAME) {
00178         lastErr=E_FRAMING_ERROR;
00179     }
00180     else if (error&CE_IOE) {
00181         lastErr=E_IO_ERROR;
00182     }
00183     else if (error&CE_MODE) {
00184         lastErr=E_INVALID_FD;
00185     }
00186     else if (error&CE_OVERRUN) {
00187         lastErr=E_BUFFER_OVERRUN;
00188     }
00189     else if (error&CE_RXPARITY) {
00190         lastErr=E_RECEIVE_PARITY_ERROR;
00191     }
00192     else if (error&CE_RXOVER) {
00193         lastErr=E_RECEIVE_OVERFLOW;
00194     }
00195     else if (error&CE_TXFULL) {
00196         lastErr=E_TRANSMIT_OVERFLOW;
00197     }
00198 }
00199 
00208 qint64 QextSerialPort::readData(char *data, qint64 maxSize)
00209 {
00210     DWORD retVal;
00211     QMutexLocker lock(mutex);
00212     retVal = 0;
00213     if (queryMode() == QextSerialPort::EventDriven) {
00214         OVERLAPPED overlapRead;
00215         ZeroMemory(&overlapRead, sizeof(OVERLAPPED));
00216         if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, & overlapRead)) {
00217             if (GetLastError() == ERROR_IO_PENDING)
00218                 GetOverlappedResult(Win_Handle, & overlapRead, & retVal, true);
00219             else {
00220                 lastErr = E_READ_FAILED;
00221                 retVal = (DWORD)-1;
00222             }
00223         }
00224     } else if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, NULL)) {
00225         lastErr = E_READ_FAILED;
00226         retVal = (DWORD)-1;
00227     }
00228     return (qint64)retVal;
00229 }
00230 
00239 qint64 QextSerialPort::writeData(const char *data, qint64 maxSize)
00240 {
00241     QMutexLocker lock( mutex );
00242     DWORD retVal = 0;
00243     if (queryMode() == QextSerialPort::EventDriven) {
00244         OVERLAPPED* newOverlapWrite = new OVERLAPPED;
00245         ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED));
00246         newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL);
00247         if (WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, newOverlapWrite)) {
00248             CloseHandle(newOverlapWrite->hEvent);
00249             delete newOverlapWrite;
00250         }
00251         else if (GetLastError() == ERROR_IO_PENDING) {
00252             // writing asynchronously...not an error
00253             QWriteLocker writelocker(bytesToWriteLock);
00254             _bytesToWrite += maxSize;
00255             pendingWrites.append(newOverlapWrite);
00256         }
00257         else {
00258             qDebug() << "serialport write error:" << GetLastError();
00259             lastErr = E_WRITE_FAILED;
00260             retVal = (DWORD)-1;
00261             if(!CancelIo(newOverlapWrite->hEvent))
00262                 qDebug() << "serialport: couldn't cancel IO";
00263             if(!CloseHandle(newOverlapWrite->hEvent))
00264                 qDebug() << "serialport: couldn't close OVERLAPPED handle";
00265             delete newOverlapWrite;
00266         }
00267     } else if (!WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, NULL)) {
00268         lastErr = E_WRITE_FAILED;
00269         retVal = (DWORD)-1;
00270     }
00271     return (qint64)retVal;
00272 }
00273 
00279 void QextSerialPort::ungetChar(char c) {
00280 
00281     /*meaningless on unbuffered sequential device - return error and print a warning*/
00282     TTY_WARNING("QextSerialPort: ungetChar() called on an unbuffered sequential device - operation is meaningless");
00283 }
00284 
00293 void QextSerialPort::setFlowControl(FlowType flow) {
00294     QMutexLocker lock(mutex);
00295     if (Settings.FlowControl!=flow) {
00296         Settings.FlowControl=flow;
00297     }
00298     if (isOpen()) {
00299         switch(flow) {
00300 
00301             /*no flow control*/
00302             case FLOW_OFF:
00303                 Win_CommConfig.dcb.fOutxCtsFlow=FALSE;
00304                 Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE;
00305                 Win_CommConfig.dcb.fInX=FALSE;
00306                 Win_CommConfig.dcb.fOutX=FALSE;
00307                 SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00308                 break;
00309 
00310             /*software (XON/XOFF) flow control*/
00311             case FLOW_XONXOFF:
00312                 Win_CommConfig.dcb.fOutxCtsFlow=FALSE;
00313                 Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE;
00314                 Win_CommConfig.dcb.fInX=TRUE;
00315                 Win_CommConfig.dcb.fOutX=TRUE;
00316                 SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00317                 break;
00318 
00319             case FLOW_HARDWARE:
00320                 Win_CommConfig.dcb.fOutxCtsFlow=TRUE;
00321                 Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_HANDSHAKE;
00322                 Win_CommConfig.dcb.fInX=FALSE;
00323                 Win_CommConfig.dcb.fOutX=FALSE;
00324                 SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00325                 break;
00326         }
00327     }
00328 }
00329 
00340 void QextSerialPort::setParity(ParityType parity) {
00341     QMutexLocker lock(mutex);
00342     if (Settings.Parity!=parity) {
00343         Settings.Parity=parity;
00344     }
00345     if (isOpen()) {
00346         Win_CommConfig.dcb.Parity=(unsigned char)parity;
00347         switch (parity) {
00348 
00349             /*space parity*/
00350             case PAR_SPACE:
00351                 if (Settings.DataBits==DATA_8) {
00352                     TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Space parity with 8 data bits is not supported by POSIX systems.");
00353                 }
00354                 Win_CommConfig.dcb.fParity=TRUE;
00355                 break;
00356 
00357             /*mark parity - WINDOWS ONLY*/
00358             case PAR_MARK:
00359                 TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning:  Mark parity is not supported by POSIX systems");
00360                 Win_CommConfig.dcb.fParity=TRUE;
00361                 break;
00362 
00363             /*no parity*/
00364             case PAR_NONE:
00365                 Win_CommConfig.dcb.fParity=FALSE;
00366                 break;
00367 
00368             /*even parity*/
00369             case PAR_EVEN:
00370                 Win_CommConfig.dcb.fParity=TRUE;
00371                 break;
00372 
00373             /*odd parity*/
00374             case PAR_ODD:
00375                 Win_CommConfig.dcb.fParity=TRUE;
00376                 break;
00377         }
00378         SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00379     }
00380 }
00381 
00400 void QextSerialPort::setDataBits(DataBitsType dataBits) {
00401     QMutexLocker lock(mutex);
00402     if (Settings.DataBits!=dataBits) {
00403         if ((Settings.StopBits==STOP_2 && dataBits==DATA_5) ||
00404             (Settings.StopBits==STOP_1_5 && dataBits!=DATA_5)) {
00405         }
00406         else {
00407             Settings.DataBits=dataBits;
00408         }
00409     }
00410     if (isOpen()) {
00411         switch(dataBits) {
00412 
00413             /*5 data bits*/
00414             case DATA_5:
00415                 if (Settings.StopBits==STOP_2) {
00416                     TTY_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits.");
00417                 }
00418                 else {
00419                     Win_CommConfig.dcb.ByteSize=5;
00420                     SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00421                 }
00422                 break;
00423 
00424             /*6 data bits*/
00425             case DATA_6:
00426                 if (Settings.StopBits==STOP_1_5) {
00427                     TTY_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits.");
00428                 }
00429                 else {
00430                     Win_CommConfig.dcb.ByteSize=6;
00431                     SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00432                 }
00433                 break;
00434 
00435             /*7 data bits*/
00436             case DATA_7:
00437                 if (Settings.StopBits==STOP_1_5) {
00438                     TTY_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits.");
00439                 }
00440                 else {
00441                     Win_CommConfig.dcb.ByteSize=7;
00442                     SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00443                 }
00444                 break;
00445 
00446             /*8 data bits*/
00447             case DATA_8:
00448                 if (Settings.StopBits==STOP_1_5) {
00449                     TTY_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits.");
00450                 }
00451                 else {
00452                     Win_CommConfig.dcb.ByteSize=8;
00453                     SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00454                 }
00455                 break;
00456         }
00457     }
00458 }
00459 
00477 void QextSerialPort::setStopBits(StopBitsType stopBits) {
00478     QMutexLocker lock(mutex);
00479     if (Settings.StopBits!=stopBits) {
00480         if ((Settings.DataBits==DATA_5 && stopBits==STOP_2) ||
00481             (stopBits==STOP_1_5 && Settings.DataBits!=DATA_5)) {
00482         }
00483         else {
00484             Settings.StopBits=stopBits;
00485         }
00486     }
00487     if (isOpen()) {
00488         switch (stopBits) {
00489 
00490             /*one stop bit*/
00491             case STOP_1:
00492                 Win_CommConfig.dcb.StopBits=ONESTOPBIT;
00493                 SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00494                 break;
00495 
00496             /*1.5 stop bits*/
00497             case STOP_1_5:
00498                 TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX.");
00499                 if (Settings.DataBits!=DATA_5) {
00500                     TTY_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits");
00501                 }
00502                 else {
00503                     Win_CommConfig.dcb.StopBits=ONE5STOPBITS;
00504                     SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00505                 }
00506                 break;
00507 
00508             /*two stop bits*/
00509             case STOP_2:
00510                 if (Settings.DataBits==DATA_5) {
00511                     TTY_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits");
00512                 }
00513                 else {
00514                     Win_CommConfig.dcb.StopBits=TWOSTOPBITS;
00515                     SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00516                 }
00517                 break;
00518         }
00519     }
00520 }
00521 
00555 void QextSerialPort::setBaudRate(BaudRateType baudRate) {
00556     QMutexLocker lock(mutex);
00557     if (Settings.BaudRate!=baudRate) {
00558         switch (baudRate) {
00559             case BAUD50:
00560             case BAUD75:
00561             case BAUD134:
00562             case BAUD150:
00563             case BAUD200:
00564                 Settings.BaudRate=BAUD110;
00565                 break;
00566 
00567             case BAUD1800:
00568                 Settings.BaudRate=BAUD1200;
00569                 break;
00570 
00571             case BAUD76800:
00572                 Settings.BaudRate=BAUD57600;
00573                 break;
00574 
00575             default:
00576                 Settings.BaudRate=baudRate;
00577                 break;
00578         }
00579     }
00580     if (isOpen()) {
00581         switch (baudRate) {
00582 
00583             /*50 baud*/
00584             case BAUD50:
00585                 TTY_WARNING("QextSerialPort: Windows does not support 50 baud operation.  Switching to 110 baud.");
00586                 Win_CommConfig.dcb.BaudRate=CBR_110;
00587                 break;
00588 
00589             /*75 baud*/
00590             case BAUD75:
00591                 TTY_WARNING("QextSerialPort: Windows does not support 75 baud operation.  Switching to 110 baud.");
00592                 Win_CommConfig.dcb.BaudRate=CBR_110;
00593                 break;
00594 
00595             /*110 baud*/
00596             case BAUD110:
00597                 Win_CommConfig.dcb.BaudRate=CBR_110;
00598                 break;
00599 
00600             /*134.5 baud*/
00601             case BAUD134:
00602                 TTY_WARNING("QextSerialPort: Windows does not support 134.5 baud operation.  Switching to 110 baud.");
00603                 Win_CommConfig.dcb.BaudRate=CBR_110;
00604                 break;
00605 
00606             /*150 baud*/
00607             case BAUD150:
00608                 TTY_WARNING("QextSerialPort: Windows does not support 150 baud operation.  Switching to 110 baud.");
00609                 Win_CommConfig.dcb.BaudRate=CBR_110;
00610                 break;
00611 
00612             /*200 baud*/
00613             case BAUD200:
00614                 TTY_WARNING("QextSerialPort: Windows does not support 200 baud operation.  Switching to 110 baud.");
00615                 Win_CommConfig.dcb.BaudRate=CBR_110;
00616                 break;
00617 
00618             /*300 baud*/
00619             case BAUD300:
00620                 Win_CommConfig.dcb.BaudRate=CBR_300;
00621                 break;
00622 
00623             /*600 baud*/
00624             case BAUD600:
00625                 Win_CommConfig.dcb.BaudRate=CBR_600;
00626                 break;
00627 
00628             /*1200 baud*/
00629             case BAUD1200:
00630                 Win_CommConfig.dcb.BaudRate=CBR_1200;
00631                 break;
00632 
00633             /*1800 baud*/
00634             case BAUD1800:
00635                 TTY_WARNING("QextSerialPort: Windows does not support 1800 baud operation.  Switching to 1200 baud.");
00636                 Win_CommConfig.dcb.BaudRate=CBR_1200;
00637                 break;
00638 
00639             /*2400 baud*/
00640             case BAUD2400:
00641                 Win_CommConfig.dcb.BaudRate=CBR_2400;
00642                 break;
00643 
00644             /*4800 baud*/
00645             case BAUD4800:
00646                 Win_CommConfig.dcb.BaudRate=CBR_4800;
00647                 break;
00648 
00649             /*9600 baud*/
00650             case BAUD9600:
00651                 Win_CommConfig.dcb.BaudRate=CBR_9600;
00652                 break;
00653 
00654             /*14400 baud*/
00655             case BAUD14400:
00656                 TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 14400 baud operation.");
00657                 Win_CommConfig.dcb.BaudRate=CBR_14400;
00658                 break;
00659 
00660             /*19200 baud*/
00661             case BAUD19200:
00662                 Win_CommConfig.dcb.BaudRate=CBR_19200;
00663                 break;
00664 
00665             /*38400 baud*/
00666             case BAUD38400:
00667                 Win_CommConfig.dcb.BaudRate=CBR_38400;
00668                 break;
00669 
00670             /*56000 baud*/
00671             case BAUD56000:
00672                 TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 56000 baud operation.");
00673                 Win_CommConfig.dcb.BaudRate=CBR_56000;
00674                 break;
00675 
00676             /*57600 baud*/
00677             case BAUD57600:
00678                 Win_CommConfig.dcb.BaudRate=CBR_57600;
00679                 break;
00680 
00681             /*76800 baud*/
00682             case BAUD76800:
00683                 TTY_WARNING("QextSerialPort: Windows does not support 76800 baud operation.  Switching to 57600 baud.");
00684                 Win_CommConfig.dcb.BaudRate=CBR_57600;
00685                 break;
00686 
00687             /*115200 baud*/
00688             case BAUD115200:
00689                 Win_CommConfig.dcb.BaudRate=CBR_115200;
00690                 break;
00691 
00692             /*128000 baud*/
00693             case BAUD128000:
00694                 TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 128000 baud operation.");
00695                 Win_CommConfig.dcb.BaudRate=CBR_128000;
00696                 break;
00697 
00698             /*256000 baud*/
00699             case BAUD256000:
00700                 TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 256000 baud operation.");
00701                 Win_CommConfig.dcb.BaudRate=CBR_256000;
00702                 break;
00703         }
00704         SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
00705     }
00706 }
00707 
00712 void QextSerialPort::setDtr(bool set) {
00713     QMutexLocker lock(mutex);
00714     if (isOpen()) {
00715         if (set) {
00716             EscapeCommFunction(Win_Handle, SETDTR);
00717         }
00718         else {
00719             EscapeCommFunction(Win_Handle, CLRDTR);
00720         }
00721     }
00722 }
00723 
00728 void QextSerialPort::setRts(bool set) {
00729     QMutexLocker lock(mutex);
00730     if (isOpen()) {
00731         if (set) {
00732             EscapeCommFunction(Win_Handle, SETRTS);
00733         }
00734         else {
00735             EscapeCommFunction(Win_Handle, CLRRTS);
00736         }
00737     }
00738 }
00739 
00758 ulong QextSerialPort::lineStatus(void) {
00759     unsigned long Status=0, Temp=0;
00760     QMutexLocker lock(mutex);
00761     if (isOpen()) {
00762         GetCommModemStatus(Win_Handle, &Temp);
00763         if (Temp&MS_CTS_ON) {
00764             Status|=LS_CTS;
00765         }
00766         if (Temp&MS_DSR_ON) {
00767             Status|=LS_DSR;
00768         }
00769         if (Temp&MS_RING_ON) {
00770             Status|=LS_RI;
00771         }
00772         if (Temp&MS_RLSD_ON) {
00773             Status|=LS_DCD;
00774         }
00775     }
00776     return Status;
00777 }
00778 
00779 bool QextSerialPort::waitForReadyRead(int msecs)
00780 {
00781     //@todo implement
00782     return false;
00783 }
00784 
00785 qint64 QextSerialPort::bytesToWrite() const
00786 {
00787     QReadLocker rl(bytesToWriteLock);
00788     return _bytesToWrite;
00789 }
00790 
00791 /*
00792   Triggered when there's activity on our HANDLE.
00793 */
00794 void QextSerialPort::onWinEvent(HANDLE h)
00795 {
00796     QMutexLocker lock(mutex);
00797     if(h == overlap.hEvent) {
00798         if (eventMask & EV_RXCHAR) {
00799             if (sender() != this && bytesAvailable() > 0)
00800                 emit readyRead();
00801         }
00802         if (eventMask & EV_TXEMPTY) {
00803             /*
00804               A write completed.  Run through the list of OVERLAPPED writes, and if
00805               they completed successfully, take them off the list and delete them.
00806               Otherwise, leave them on there so they can finish.
00807             */
00808             qint64 totalBytesWritten = 0;
00809             QList<OVERLAPPED*> overlapsToDelete;
00810             foreach(OVERLAPPED* o, pendingWrites) {
00811                 DWORD numBytes = 0;
00812                 if (GetOverlappedResult(Win_Handle, o, & numBytes, false)) {
00813                     overlapsToDelete.append(o);
00814                     totalBytesWritten += numBytes;
00815                 } else if( GetLastError() != ERROR_IO_INCOMPLETE ) {
00816                     overlapsToDelete.append(o);
00817                     qWarning() << "CommEvent overlapped write error:" << GetLastError();
00818                 }
00819             }
00820 
00821             if (sender() != this && totalBytesWritten > 0) {
00822                 QWriteLocker writelocker(bytesToWriteLock);
00823                 emit bytesWritten(totalBytesWritten);
00824                 _bytesToWrite = 0;
00825             }
00826 
00827             foreach(OVERLAPPED* o, overlapsToDelete) {
00828                 OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o));
00829                 CloseHandle(toDelete->hEvent);
00830                 delete toDelete;
00831             }
00832         }
00833         if (eventMask & EV_DSR) {
00834             if (lineStatus() & LS_DSR)
00835                 emit dsrChanged(true);
00836             else
00837                 emit dsrChanged(false);
00838         }
00839     }
00840     WaitCommEvent(Win_Handle, &eventMask, &overlap);
00841 }
00842 
00851 void QextSerialPort::setTimeout(long millisec) {
00852     QMutexLocker lock(mutex);
00853     Settings.Timeout_Millisec = millisec;
00854 
00855     if (millisec == -1) {
00856         Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD;
00857         Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
00858     } else {
00859         Win_CommTimeouts.ReadIntervalTimeout = millisec;
00860         Win_CommTimeouts.ReadTotalTimeoutConstant = millisec;
00861     }
00862     Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
00863     Win_CommTimeouts.WriteTotalTimeoutMultiplier = millisec;
00864     Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
00865     if (queryMode() != QextSerialPort::EventDriven)
00866         SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
00867 }
00868 
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines