⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nativeserial_linux.cpp

📁 tinyos2.0版本驱动
💻 CPP
字号:
//$Id: NativeSerial_linux.cpp,v 1.5 2007/06/05 21:08:55 idgay Exp $/* "Copyright (c) 2000-2003 The Regents of the University of California.   * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement * is hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. *  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." *///@author Cory Sharp <cssharp@eecs.berkeley.edu>#include <stdexcept>#include <sstream>#include <iostream>#include <fstream>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <termio.h>#include <termios.h>#include <signal.h>#include <errno.h>#include "NativeSerialEnums.h"using namespace NativeSerialEnums;class comm_port_error : public std::runtime_error{  public:    comm_port_error( const char* msg ): std::runtime_error(msg) { }};class NativeSerial{public:  typedef std::string String;private:  std::string m_portname;  int m_fd;  int m_events_in;  int m_events_out;  bool m_wait_for_events;protected:  void note( std::string s )  {    //std::cout << "NativeSerial_linux " << m_portname << ": " << s << std::endl;  }  String cat( const char* prefix, const String& err )  {    return (prefix == NULL ? "" : String(prefix)+": ") + err;  }  void errno_wrap( bool error, const char* extra_err = NULL )  {    if( error && (errno != 0) )      throw comm_port_error( cat(extra_err, strerror(errno)).c_str() );  }  void block_on_read( bool block )  {note( "block_on_read begin" );    fcntl( m_fd, F_SETFL, (block ? 0 : FNDELAY) );note( "block_on_read end" );  }  struct termios get_comm_state()  {note( "get_comm_state begin" );    struct termios options;    errno_wrap( tcgetattr( m_fd, &options ) == -1, "get_comm_state" );note( "get_comm_state end" );    return options;  }  int get_modem_status()  {note( "get_modem_status begin" );    int status = 0;    errno_wrap( ioctl( m_fd, TIOCMGET, &status ) == -1, "get_modem_status" );note( "get_modem_status end" );    return status;  }  void set_modem_status( int status )  {note( "set_modem_status begin" );    errno_wrap( ioctl( m_fd, TIOCMSET, &status ) == -1, "set_modem_status" );note( "set_modem_status end" );  }  int baud_to_enum( int baud )  {    switch( baud )    {      case 0: return B0;      case 50: return B50;      case 75: return B75;      case 110: return B110;      case 134: return B134;      case 150: return B150;      case 200: return B200;      case 300: return B300;      case 600: return B600;      case 1200: return B1200;      case 1800: return B1800;      case 2400: return B2400;      case 4800: return B4800;      case 9600: return B9600;      case 19200: return B19200;      case 38400: return B38400;      case 57600: return B57600;      case 115200: return B115200;      case 230400: return B230400;    }    throw comm_port_error("baud_to_enum, bad baud rate");  }  int enum_to_baud( int baudenum )  {    switch( baudenum )    {      case B0: return 0;      case B50: return 50;      case B75: return 75;      case B110: return 110;      case B134: return 134;      case B150: return 150;      case B200: return 200;      case B300: return 300;      case B600: return 600;      case B1200: return 1200;      case B1800: return 1800;      case B2400: return 2400;      case B4800: return 4800;      case B9600: return 9600;      case B19200: return 19200;      case B38400: return 38400;      case B57600: return 57600;      case B115200: return 115200;      case B230400: return 230400;    }    throw comm_port_error("enum_to_baud, bad baud rate");  }/*  static DWORD map_events_to_win32( int event )  {    DWORD ev = 0;    if( event & DATA_AVAILABLE ) ev |= EV_RXCHAR;    if( event & OUTPUT_EMPTY ) ev |= EV_TXEMPTY;    if( event & CTS ) ev |= EV_CTS;    if( event & DSR ) ev |= EV_DSR;    if( event & RING_INDICATOR ) ev |= EV_RING;    if( event & CARRIER_DETECT ) ev |= EV_RLSD;    if( event & OVERRUN_ERROR ) ev |= EV_ERR;    if( event & PARITY_ERROR ) ev |= EV_ERR;    if( event & FRAMING_ERROR ) ev |= EV_ERR;    if( event & BREAK_INTERRUPT ) ev |= EV_BREAK;    return ev;  }  static int map_events_from_win32( DWORD ev, DWORD errors )  {    int event = 0;    if( ev & EV_RXCHAR ) event |= DATA_AVAILABLE;    if( ev & EV_TXEMPTY ) event |= OUTPUT_EMPTY;    if( ev & EV_CTS ) event |= CTS;    if( ev & EV_DSR ) event |= DSR;    if( ev & EV_RING ) event |= RING_INDICATOR;    if( ev & EV_RLSD ) event |= CARRIER_DETECT;    if( ev & EV_ERR )    {      if( errors & CE_BREAK ) event |= BREAK_INTERRUPT;      if( errors & CE_FRAME ) event |= FRAMING_ERROR;      if( errors & CE_IOE ) throw comm_port_error("Win32 Comm IO Error");      if( errors & CE_MODE ) throw comm_port_error("Win32 Comm Invalid Mode");      if( errors & CE_OVERRUN ) event |= OVERRUN_ERROR;      if( errors & CE_RXOVER ) event |= OVERRUN_ERROR; //?? okay      if( errors & CE_RXPARITY ) event |= PARITY_ERROR;      if( errors & CE_TXFULL ) event |= OVERRUN_ERROR; //?? okay    }    if( ev & EV_BREAK ) event |= BREAK_INTERRUPT;    return event;  }*/public:  void setSerialPortParams( int baudrate, int databits, int stopbits, int parity )  {note( "setSerialPortParams begin" );    struct termios state = get_comm_state();    int baudenum = baud_to_enum(baudrate);    errno_wrap( cfsetispeed( &state, baudenum ) == -1, "baudrate" );    errno_wrap( cfsetospeed( &state, baudenum ) == -1, "baudrate" );    //throw comm_port_error("nuthin");    state.c_cflag &= ~CSIZE;    switch( databits )    {      case 5: state.c_cflag |= CS5; break;      case 6: state.c_cflag |= CS6; break;      case 7: state.c_cflag |= CS7; break;      case 8: default: state.c_cflag |= CS8;    }    if( stopbits == STOPBITS_2 )      state.c_cflag |= CSTOPB;    else      state.c_cflag &= ~CSTOPB;    state.c_cflag |= PARENB;    switch( parity )    {      case NPARITY_EVEN: state.c_cflag &= ~PARODD; break;      case NPARITY_ODD: state.c_cflag |= PARODD; break;      case NPARITY_NONE: default: state.c_cflag &= ~PARENB;    }    errno_wrap( tcsetattr( m_fd, TCSANOW, &state ) == -1, "set_comm_state" );note( "setSerialPortParams end" );  }  int getBaudRate()  {    struct termios state = get_comm_state();    return enum_to_baud( cfgetospeed( &state ) );  }  int getDataBits()  {    switch( get_comm_state().c_cflag & CSIZE )    {      case CS5: return 5;      case CS6: return 6;      case CS7: return 7;      case CS8: default: return 8;    }  }  int getStopBits()  {    int stop = get_comm_state().c_cflag;    return (stop & CSTOPB) ? STOPBITS_2 : STOPBITS_1;  }  int getParity()  {    int parity = get_comm_state().c_cflag;    if( parity & PARENB )      return (parity & PARODD) ? NPARITY_ODD : NPARITY_EVEN;    return NPARITY_NONE;  }  int read( signed char* buffer, int off, int len )  {note( "read begin" );    int nread = ::read( m_fd, buffer+off, len );    errno_wrap( nread == -1, "read" );#if 0printf("   ...  read:");for( int i=0; i<nread; i++ )  printf(" %02x",buffer[off+i]&255);printf("\n");#endifnote( "read end" );    return nread;  }  int write( const signed char* buffer, int off, int len )  {note( "write begin" );    int nwritten = ::write( m_fd, buffer+off, len );    errno_wrap( nwritten == -1, "write" );#if 0printf("   ... wrote:");for( int i=0; i<nwritten; i++ )  printf(" %02x",buffer[off+i]&255);printf("\n");#endifnote( "write end" );    return nwritten;  }  int read()  {    signed char byte;    return (read(&byte,0,1) > 0) ? ((unsigned char)byte) : -1;  }  int write( int b )  {    signed char byte = b;    return write( &byte, 0, 1 );  }  int available()  {note( "available begin" );    int navail = 0;    int rv = 0;    errno_wrap( rv=ioctl( m_fd, FIONREAD, &navail ) == -1, "available" );//printf("... fionread=%d, rv=%d\n",navail,rv);note( "available end" );    return navail;  }  void notifyOn( int event, bool enable )  {    if( enable )      m_events_in |= event;    else      m_events_in &= ~event;  }  bool isNotifyOn( int event )  {    return (m_events_in & event) != 0;  }  bool waitForEvent()  {note( "waitForEvent begin" );    fd_set input;    struct timeval tv;    m_events_out = 0;    int fd = m_fd;    while( m_wait_for_events && (m_fd != -1) && (m_events_out == 0) )    {      FD_ZERO( &input );      FD_SET( fd, &input );      tv.tv_sec = 0;      tv.tv_usec = 100*1000; // 1ms is the minimum resolution, at best      if( select( fd+1, &input, NULL, NULL, &tv ) == -1 )      {	if( errno == EINTR )	  break;	errno_wrap( true, "waitForEvent.select" );      }      if( FD_ISSET( fd, &input ) )	m_events_out |= DATA_AVAILABLE;    }    m_wait_for_events = true;note( "waitForEvent end" );    return (m_events_out != 0);  }  bool cancelWait()  {note( "cancelWait begin" );    m_wait_for_events = false;note( "cancelWait end" );  }  bool didEventOccur( int event )  {    return (m_events_out & event) != 0;  }  void setDTR( bool high )  {    if( high )      set_modem_status( get_modem_status() | TIOCM_DTR );    else      set_modem_status( get_modem_status() & ~TIOCM_DTR );  }  void setRTS( bool high )  {    if( high )      set_modem_status( get_modem_status() | TIOCM_RTS );    else      set_modem_status( get_modem_status() & ~TIOCM_RTS );  }  bool isDTR()  {    return (get_modem_status() & TIOCM_DTR) != 0;  }  bool isRTS()  {    return (get_modem_status() & TIOCM_RTS) != 0;  }  bool isCTS()  {    return (get_modem_status() & TIOCM_CTS) != 0;  }  bool isDSR()  {    return (get_modem_status() & TIOCM_DSR) != 0;  }  bool isRI()  {    return (get_modem_status() & TIOCM_RI) != 0;  }  bool isCD()  {    return (get_modem_status() & TIOCM_CD) != 0;  }  void sendBreak( int millis )  {  }  NativeSerial( const char* portname ):    m_fd(-1),    m_events_in(0),     m_events_out(0),    m_wait_for_events(true)  {    m_portname = portname;note( "constructor begin" );    m_fd = open( portname, O_RDWR | O_NOCTTY | O_NONBLOCK );    errno_wrap( m_fd == -1, "open" );//std::cout << "NativeSerial constructor [1] " << portname << std::endl;    block_on_read(false);    // set default port parmeters    //struct termios options = get_comm_state();    struct termios options;    memset( &options, 0, sizeof(options) );    // disable rts/cts, no parity bits, one stop bit, clear databits mask    //local mode, enable receiver, 8 databits    options.c_cflag = CLOCAL | CREAD | CS8;    //raw mode    options.c_lflag = 0;    //disable software flow control, etc    options.c_iflag = IGNPAR | IGNBRK;    //raw output mode    options.c_oflag = 0;    //set thresholds    options.c_cc[VMIN] = 0;    options.c_cc[VTIME] = 0;    errno_wrap( tcflush( m_fd, TCIOFLUSH ) == -1, "flush" );    errno_wrap( tcsetattr( m_fd, TCSANOW, &options ) == -1, "setattr" );    setDTR(false);    setRTS(false);note( "constructor end" );  }  ~NativeSerial()  {note( "destructor begin" );    close();note( "destructor end" );  }  void close()  {note( "close begin" );//std::cout << "NativeSerial_linux close fd=" << m_fd << std::endl;    if( m_fd != -1 )    {      cancelWait();      struct timeval tv = { tv_sec:0, tv_usec:1100 };      select( 0, NULL, NULL, NULL, &tv );      ::close( m_fd );      m_fd = -1;    }note( "close end" );  }  static std::string getTOSCommMap()  {    const char* env = getenv( "TOSCOMMMAP" );    return (env == NULL) ? "com1=/dev/ttyS0:usb1=/dev/ttyUSB0" : env;  }};#include "TOSComm_wrap.cxx"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -