📄 serial.cpp
字号:
Serial::Error Serial::setSpeed(unsigned long speed){ unsigned long rate; switch(speed) {#ifdef B115200 case 115200: rate = B115200; break; #endif#ifdef B57600 case 57600: rate = B57600; break; #endif#ifdef B38400 case 38400: rate = B38400; break; #endif case 19200: rate = B19200; break; case 9600: rate = B9600; break; case 4800: rate = B4800; break; case 2400: rate = B2400; break; case 1200: rate = B1200; break; case 600: rate = B600; break; case 300: rate = B300; break; case 110: rate = B110; break;#ifdef B0 case 0: rate = B0; break;#endif default: return error(errSpeedInvalid); }#ifdef WIN32 DCB * dcb = (DCB *)current; dcb->DCBlength = sizeof(DCB); GetCommState(dev, dcb); dcb->BaudRate = rate; SetCommState(dev, dcb) ;#else struct termios *attr = (struct termios *)current; cfsetispeed(attr, rate); cfsetospeed(attr, rate); tcsetattr(dev, TCSANOW, attr);#endif return errSuccess;}Serial::Error Serial::setFlowControl(Flow flow){#ifdef WIN32 DCB * attr = (DCB *)current; attr->XonChar = ASCII_XON; attr->XoffChar = ASCII_XOFF; attr->XonLim = 100; attr->XoffLim = 100; switch(flow) { case flowSoft: attr->fInX = attr->fOutX = 1; break; case flowBoth: attr->fInX = attr->fOutX = 1; case flowHard: attr->fOutxCtsFlow = 1; attr->fRtsControl = RTS_CONTROL_HANDSHAKE; break; case flowNone: break; default: return error(errFlowInvalid); } SetCommState(dev, attr);#else struct termios *attr = (struct termios *)current; attr->c_cflag &= ~CRTSCTS; attr->c_iflag &= ~(IXON | IXANY | IXOFF); switch(flow) { case flowSoft: attr->c_iflag |= (IXON | IXANY | IXOFF); break; case flowBoth: attr->c_iflag |= (IXON | IXANY | IXOFF); case flowHard: attr->c_cflag |= CRTSCTS; break; case flowNone: break; default: return error(errFlowInvalid); } tcsetattr(dev, TCSANOW, attr);#endif return errSuccess;}Serial::Error Serial::setStopBits(int bits){#ifdef WIN32 DCB * attr = (DCB *)current; switch(bits) { case 1: attr->StopBits = ONESTOPBIT; break; case 2: attr->StopBits = TWOSTOPBITS; break; default: return error(errStopbitsInvalid); } SetCommState(dev, attr);#else struct termios *attr = (struct termios *)current; attr->c_cflag &= ~CSTOPB; switch(bits) { case 1: break; case 2: attr->c_cflag |= CSTOPB; break; default: return error(errStopbitsInvalid); } tcsetattr(dev, TCSANOW, attr);#endif return errSuccess;}Serial::Error Serial::setCharBits(int bits){#ifdef WIN32 DCB * attr = (DCB *)current; switch(bits) { case 5: case 6: case 7: case 8: attr->ByteSize = bits; break; default: return error(errCharsizeInvalid); } SetCommState(dev, attr);#else struct termios *attr = (struct termios *)current; attr->c_cflag &= ~CSIZE; switch(bits) { case 5: attr->c_cflag |= CS5; break; case 6: attr->c_cflag |= CS6; break; case 7: attr->c_cflag |= CS7; break; case 8: attr->c_cflag |= CS8; break; default: return error(errCharsizeInvalid); } tcsetattr(dev, TCSANOW, attr);#endif return errSuccess;}Serial::Error Serial::setParity(Parity parity){#ifdef WIN32 DCB * attr = (DCB *)current; switch(parity) { case parityEven: attr->Parity = EVENPARITY; break; case parityOdd: attr->Parity = ODDPARITY; break; case parityNone: attr->Parity = NOPARITY; break; default: return error(errParityInvalid); } SetCommState(dev, attr);#else struct termios *attr = (struct termios *)current; attr->c_cflag &= ~(PARENB | PARODD); switch(parity) { case parityEven: attr->c_cflag |= PARENB; break; case parityOdd: attr->c_cflag |= (PARENB | PARODD); break; case parityNone: break; default: return error(errParityInvalid); } tcsetattr(dev, TCSANOW, attr);#endif return errSuccess;}void Serial::sendBreak(void){#ifdef WIN32 SetCommBreak(dev); Thread::sleep(100L); ClearCommBreak(dev);#else tcsendbreak(dev, 0);#endif}void Serial::toggleDTR(timeout_t millisec){#ifdef WIN32 EscapeCommFunction(dev, CLRDTR); if(millisec) { Thread::sleep(millisec); EscapeCommFunction(dev, SETDTR); }#else struct termios tty, old; tcgetattr(dev, &tty); tcgetattr(dev, &old); cfsetospeed(&tty, B0); cfsetispeed(&tty, B0); tcsetattr(dev, TCSANOW, &tty); if(millisec) { Thread::sleep(millisec); tcsetattr(dev, TCSANOW, &old); }#endif}bool Serial::isPending(Pending pending, timeout_t timeout){#ifdef WIN32 unsigned long dwError; COMSTAT cs; ClearCommError(dev, &dwError, &cs); if(timeout == 0 || ((pending == pendingInput) && (0 != cs.cbInQue)) || ((pending == pendingOutput) && (0 != cs.cbOutQue)) || (pending == pendingError)) { switch(pending) { case pendingInput: return (0 != cs.cbInQue); case pendingOutput: return (0 != cs.cbOutQue); case pendingError: return false; } } else { Thread::Cancel save = Thread::enterCancel(); OVERLAPPED ol; DWORD dwMask; BOOL suc; memset(&ol, 0, sizeof(OVERLAPPED)); ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if(pending == pendingInput) dwMask = EV_RXCHAR; else if(pending == pendingOutput) dwMask = EV_TXEMPTY; else // on error dwMask = EV_ERR; SetCommMask(dev, dwMask); // let's wait for event or timeout if((suc = WaitCommEvent(dev, &dwMask, &ol)) == FALSE) { if(GetLastError() == ERROR_IO_PENDING) { dwError = WaitForSingleObject(ol.hEvent, timeout); suc = (dwError == WAIT_OBJECT_0); SetCommMask(dev, 0); } else ClearCommError(dev, &dwError, &cs); } if(ol.hEvent != INVALID_HANDLE_VALUE) CloseHandle(ol.hEvent); Thread::exitCancel(save); if(suc == FALSE) return false; return true; }#else int status;#ifdef HAVE_POLL struct pollfd pfd; pfd.fd = dev; pfd.revents = 0; switch(pending) { case pendingInput: pfd.events = POLLIN; break; case pendingOutput: pfd.events = POLLOUT; break; case pendingError: pfd.events = POLLERR | POLLHUP; break; } status = 0; while(status < 1) { if(timeout == TIMEOUT_INF) status = poll(&pfd, 1, -1); else status = poll(&pfd, 1, timeout); if(status < 1) { if(status == -1 && errno == EINTR) continue; return false; } } if(pfd.revents & pfd.events) return true;#else struct timeval tv; fd_set grp; struct timeval *tvp = &tv; if(timeout == TIMEOUT_INF) tvp = NULL; else { tv.tv_usec = (timeout % 1000) * 1000; tv.tv_sec = timeout / 1000; } FD_ZERO(&grp); FD_SET(dev, &grp); switch(pending) { case pendingInput: status = select(dev + 1, &grp, NULL, NULL, tvp); break; case pendingOutput: status = select(dev + 1, NULL, &grp, NULL, tvp); break; case pendingError: status = select(dev + 1, NULL, NULL, &grp, tvp); break; } if(status < 1) return false; if(FD_ISSET(dev, &grp)) return true;#endif#endif // WIN32 return false;}TTYStream::TTYStream(const char *filename, timeout_t to) : streambuf(), Serial(filename),#ifdef HAVE_OLD_IOSTREAM iostream()#else iostream((streambuf *)this) #endif{#ifdef HAVE_OLD_IOSTREAM init((streambuf *)this);#endif gbuf = pbuf = NULL; timeout = to; if(INVALID_HANDLE_VALUE != dev) allocate();}TTYStream::TTYStream() : streambuf(), Serial(),#ifdef HAVE_OLD_IOSTREAM iostream()#else iostream((streambuf *)this)#endif{#ifdef HAVE_OLD_IOSTREAM init((streambuf *)this);#endif timeout = 0; gbuf = pbuf = NULL;}TTYStream::~TTYStream(){ endStream(); endSerial();}void TTYStream::endStream(void){ if(bufsize) sync(); if(gbuf) { delete[] gbuf; gbuf = NULL; } if(pbuf) { delete[] pbuf; pbuf = NULL; } bufsize = 0; clear();}void TTYStream::allocate(void){ if(INVALID_HANDLE_VALUE == dev) return;#ifdef _PC_MAX_INPUT bufsize = fpathconf(dev, _PC_MAX_INPUT);#else bufsize = MAX_INPUT;#endif gbuf = new char[bufsize]; pbuf = new char[bufsize]; if(!pbuf || !gbuf) { error(errResourceFailure); return; } clear();#if !(defined(STLPORT) || defined(__KCC)) setg(gbuf, gbuf + bufsize, 0);#endif setg(gbuf, gbuf + bufsize, gbuf + bufsize); setp(pbuf, pbuf + bufsize);}int TTYStream::doallocate(){ if(bufsize) return 0; allocate(); return 1;}void TTYStream::interactive(bool iflag){#ifdef WIN32 if(dev == INVALID_HANDLE_VALUE)#else if(dev < 0)#endif return; if(bufsize >= 1) endStream(); if(iflag) { // setting to unbuffered mode bufsize = 1; gbuf = new char[bufsize];#if !(defined(STLPORT) || defined(__KCC))#if defined(__GNUC__) && (__GNUC__ < 3) setb(0,0);#endif #endif setg(gbuf, gbuf+bufsize, gbuf+bufsize); setp(pbuf, pbuf); return; } if(bufsize < 2) allocate();}int TTYStream::uflow(void){ int rlen; unsigned char ch; if(bufsize < 2) { if(timeout) { if(Serial::isPending(pendingInput, timeout)) rlen = aRead((char *)&ch, 1); else rlen = -1; } else rlen = aRead((char *)&ch, 1); if(rlen < 1) { if(rlen < 0) clear(ios::failbit | rdstate()); return EOF; } return ch; } else { ch = underflow(); gbump(1); return ch; }}int TTYStream::underflow(void){ ssize_t rlen = 1; if(!gptr()) return EOF; if(gptr() < egptr()) return (unsigned char)*gptr(); rlen = (ssize_t)((gbuf + bufsize) - eback()); if(timeout && !Serial::isPending(pendingInput, timeout)) rlen = -1; else rlen = aRead((char *)eback(), rlen); if(rlen < 1) { if(rlen < 0) { clear(ios::failbit | rdstate()); error(errInput); } return EOF; } setg(eback(), eback(), eback() + rlen); return (unsigned char) *gptr();}int TTYStream::sync(void){ if(bufsize > 1 && pbase() && ((pptr() - pbase()) > 0)) { overflow(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -