📄 serial.cpp
字号:
waitOutput(); setp(pbuf, pbuf + bufsize); } setg(gbuf, gbuf + bufsize, gbuf + bufsize); return 0;}int TTYStream::overflow(int c){ unsigned char ch; ssize_t rlen, req; if(bufsize < 2) { if(c == EOF) return 0; ch = (unsigned char)(c); rlen = aWrite((char *)&ch, 1); if(rlen < 1) { if(rlen < 0) clear(ios::failbit | rdstate()); return EOF; } else return c; } if(!pbase()) return EOF; req = (ssize_t)(pptr() - pbase()); if(req) { rlen = aWrite((char *)pbase(), req); if(rlen < 1) { if(rlen < 0) clear(ios::failbit | rdstate()); return EOF; } req -= rlen; } if(req)// memmove(pptr(), pptr() + rlen, req); memmove(pbuf, pbuf + rlen, req); setp(pbuf + req, pbuf + bufsize); if(c != EOF) { *pptr() = (unsigned char)c; pbump(1); } return c;}bool TTYStream::isPending(Pending pending, timeout_t timer){// if(pending == pendingInput && in_avail())// return true;// else if(pending == pendingOutput)// flush(); return Serial::isPending(pending, timer);}ttystream::ttystream() :TTYStream(){ setError(false);}ttystream::ttystream(const char *name) :TTYStream(){ setError(false); open(name);}void ttystream::close(void){#ifdef WIN32 if (INVALID_HANDLE_VALUE == dev)#else if(dev < 0)#endif return; endStream(); restore(); TTYStream::close();}void ttystream::open(const char *name){ const char *cpp; char *cp; char pathname[256]; size_t namelen; long opt; if (INVALID_HANDLE_VALUE != dev) { restore(); close(); } cpp = strrchr(name, ':'); if(cpp) namelen = cpp - name; else namelen = strlen(name); cp = pathname;#ifndef WIN32 if(*name != '/') { strcpy(pathname, "/dev/"); cp += 5; } if((cp - pathname) + namelen > 255) { error(errResourceFailure); return; }#endif setString(cp, pathname - cp + sizeof(pathname), name); cp += namelen;#ifdef WIN32 *cp++ = ':';#endif *cp = 0; Serial::open(pathname); if(INVALID_HANDLE_VALUE == dev) { error(errOpenFailed); return; } allocate(); setString(pathname, sizeof(pathname), name + namelen); cp = pathname + 1; if(*pathname == ':') cp = strtok(cp, ","); else cp = NULL; while(cp) { switch(*cp) { case 'h': case 'H': setFlowControl(flowHard); break; case 's': case 'S': setFlowControl(flowSoft); break; case 'b': case 'B': setFlowControl(flowBoth); break; case 'n': case 'N': setParity(parityNone); break; case 'O': case 'o': setParity(parityOdd); break; case 'e': case 'E': setParity(parityEven); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': opt = atol(cp); if(opt == 1 || opt == 2) { setStopBits((int)opt); break; } if(opt > 4 && opt < 9) { setCharBits((int)opt); break; } setSpeed(opt); break; default: error(errOptionInvalid); } cp = strtok(NULL, ","); } }TTYSession::TTYSession(const char *filename, int pri, int stack) :Thread(pri, stack), TTYStream(filename){ setError(false);}TTYSession::~TTYSession(){ terminate(); endSerial();}#ifndef WIN32// Not supporting this right now........//SerialPort::SerialPort(SerialService *svc, const char *name) :Serial(name),detect_pending(true),detect_output(false),detect_disconnect(true){ next = prev = NULL; service = NULL;#ifdef WIN32 if(INVALID_HANDLE_VALUE != dev)#else if(dev > -1)#endif { setError(false); service = svc; svc->attach(this); }}SerialPort::~SerialPort(){ if(service) service->detach(this); endSerial();}void SerialPort::expired(void){}void SerialPort::pending(void){}void SerialPort::disconnect(void){}void SerialPort::output(void){}void SerialPort::setTimer(timeout_t ptimer){ TimerPort::setTimer(ptimer); service->update();}void SerialPort::incTimer(timeout_t ptimer){ TimerPort::incTimer(ptimer); service->update();}void SerialPort::setDetectPending( bool val ){ if ( detect_pending != val ) { detect_pending = val;#ifdef USE_POLL if ( ufd ) { if ( val ) { ufd->events |= POLLIN; } else { ufd->events &= ~POLLIN; } }#endif service->update(); }}void SerialPort::setDetectOutput( bool val ){ if ( detect_output != val ) { detect_output = val;#ifdef USE_POLL if ( ufd ) { if ( val ) { ufd->events |= POLLOUT; } else { ufd->events &= ~POLLOUT; } }#endif service->update(); }}SerialService::SerialService(int pri, size_t stack, const char *id) :Thread(pri, stack), Mutex(id){ long opt; first = last = NULL; count = 0; FD_ZERO(&connect); ::pipe(iosync); hiwater = iosync[0] + 1; FD_SET(iosync[0], &connect); opt = fcntl(iosync[0], F_GETFL); fcntl(iosync[0], F_SETFL, opt | O_NDELAY); }SerialService::~SerialService(){ update(0); terminate(); while(first) delete first;}void SerialService::onUpdate(unsigned char flag){}void SerialService::onEvent(void){}void SerialService::onCallback(SerialPort *port){}void SerialService::attach(SerialPort *port){ enterMutex();#ifdef USE_POLL port->ufd = 0;#endif if(last) last->next = port; port->prev = last; last = port; FD_SET(port->dev, &connect); if(port->dev >= hiwater) hiwater = port->dev + 1; if(!first) { first = port; leaveMutex(); ++count; start(); } else { leaveMutex(); update(); ++count; }}void SerialService::detach(SerialPort *port){ enterMutex();#ifndef USE_POLL FD_CLR(port->dev, &connect);#endif if(port->prev) port->prev->next = port->next; else first = port->next; if(port->next) port->next->prev = port->prev; else last = port->prev; --count; leaveMutex(); update();}void SerialService::update(unsigned char flag){ ::write(iosync[1], (char *)&flag, 1);} void SerialService::run(void){ timeout_t timer, expires; SerialPort *port; unsigned char buf;#ifdef USE_POLL Poller mfd; pollfd *p_ufd; int lastcount = 0; // initialize ufd in all attached ports : // probably don't need this but it can't hurt. enterMutex(); port = first; while(port) { port->ufd = 0; port = port->next; } leaveMutex(); #else struct timeval timeout, *tvp; fd_set inp, out, err; int dev; FD_ZERO(&inp); FD_ZERO(&out); FD_ZERO(&err);#endif setCancel(cancelDeferred); for(;;) { timer = TIMEOUT_INF; while(1 == ::read(iosync[0], (char *)&buf, 1)) { if(buf) { onUpdate(buf); continue; } setCancel(cancelImmediate); sleep(TIMEOUT_INF); exit(); }#ifdef USE_POLL bool reallocate = false; enterMutex(); onEvent(); port = first; while(port) { onCallback(port); if ( ( p_ufd = port->ufd ) ) { if ( ( POLLHUP | POLLNVAL ) & p_ufd->revents ) { // Avoid infinite loop from disconnected sockets port->detect_disconnect = false; p_ufd->events &= ~POLLHUP; port->disconnect(); } if ( ( POLLIN | POLLPRI ) & p_ufd->revents ) port->pending(); if ( POLLOUT & p_ufd->revents ) port->output(); } else { reallocate = true; }retry: expires = port->getTimer(); if(expires > 0) if(expires < timer) timer = expires; if(!expires) { port->endTimer(); port->expired(); goto retry; } port = port->next; } // // reallocate things if we saw a ServerPort without // ufd set ! if ( reallocate || ( ( count + 1 ) != lastcount ) ) { lastcount = count + 1; p_ufd = mfd.getList( count + 1 ); // Set up iosync polling p_ufd->fd = iosync[0]; p_ufd->events = POLLIN | POLLHUP; p_ufd ++; port = first; while(port) { p_ufd->fd = port->dev; p_ufd->events = ( port->detect_disconnect ? POLLHUP : 0 ) | ( port->detect_output ? POLLOUT : 0 ) | ( port->detect_pending ? POLLIN : 0 ) ; port->ufd = p_ufd; p_ufd ++; port = port->next; } } leaveMutex(); poll( mfd.getList(), count + 1, timer );#else enterMutex(); onEvent(); port = first; while(port) { onCallback(port); dev = port->dev; if(FD_ISSET(dev, &err)) { port->detect_disconnect = false; port->disconnect(); } if(FD_ISSET(dev, &inp)) port->pending(); if(FD_ISSET(dev, &out)) port->output();retry: expires = port->getTimer(); if(expires > 0) if(expires < timer) timer = expires; if(!expires) { port->endTimer(); port->expired(); goto retry; } port = port->next; } FD_ZERO(&inp); FD_ZERO(&out); FD_ZERO(&err); int so; port = first; while(port) { so = port->dev; if(port->detect_pending) FD_SET(so, &inp); if(port->detect_output) FD_SET(so, &out); if(port->detect_disconnect) FD_SET(so, &err); port = port->next; } leaveMutex(); if(timer == TIMEOUT_INF) tvp = NULL; else { tvp = &timeout; timeout.tv_sec = timer / 1000; timeout.tv_usec = (timer % 1000) * 1000; } select(hiwater, &inp, &out, &err, tvp); #endif }} #endif #ifdef CCXX_NAMESPACES}#endif/** EMACS ** * Local variables: * mode: c++ * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -