|
qCNC 0.82-alpha
|
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