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

📄 gsm_unix_serial.cc

📁 对各种手机进行编程的工具包源码gsmlib 1.9版本。
💻 CC
字号:
// *************************************************************************// * GSM TA/ME library// *// * File:    gsm_unix_port.cc// *// * Purpose: UNIX serial port implementation// *// * Author:  Peter Hofmann (software@pxh.de)// *// * Created: 10.5.1999// *************************************************************************#ifdef HAVE_CONFIG_H#include <gsm_config.h>#endif#include <gsmlib/gsm_nls.h>#include <gsmlib/gsm_unix_serial.h>#include <gsmlib/gsm_util.h>#include <termios.h>#include <fcntl.h>#include <iostream>#include <strstream>#include <errno.h>#include <stdio.h>#include <unistd.h>#include <sys/ioctl.h>#include <signal.h>#include <pthread.h>using namespace std;using namespace gsmlib;static const int holdoff[] = {2000000, 1000000, 400000};static const int holdoffArraySize = sizeof(holdoff)/sizeof(int);  // alarm handling for socket read/write// the timerMtx is necessary since several threads cannot use the// timer indepently of each otherstatic pthread_mutex_t timerMtx = PTHREAD_MUTEX_INITIALIZER;// for non-GNU systems, define alarm()#ifndef HAVE_ALARMunsigned int alarm(unsigned int seconds){  struct itimerval old, newt;  newt.it_interval.tv_usec = 0;  newt.it_interval.tv_sec = 0;  newt.it_value.tv_usec = 0;  newt.it_value.tv_sec = (long int)seconds;  if (setitimer(ITIMER_REAL, &newt, &old) < 0)    return 0;  else    return old.it_value.tv_sec;}#endif// this routine is called in case of a timeoutstatic void catchAlarm(int){  // do nothing}// start timerstatic void startTimer(){  pthread_mutex_lock(&timerMtx);  struct sigaction newAction;  newAction.sa_handler = catchAlarm;  newAction.sa_flags = 0;  sigaction(SIGALRM, &newAction, NULL);  alarm(1);}// reset timerstatic void stopTimer(){  alarm(0);  sigaction(SIGALRM, NULL, NULL);  pthread_mutex_unlock(&timerMtx);}// UnixSerialPort membersvoid UnixSerialPort::throwModemException(string message) throw(GsmException){  ostrstream os;  os << message << " (errno: " << errno << "/" << strerror(errno) << ")"     << ends;  char *ss = os.str();  string s(ss);  delete[] ss;  throw GsmException(s, OSError, errno);}void UnixSerialPort::putBack(char c){  assert(_oldChar == -1);  _oldChar = c;}int UnixSerialPort::readByte() throw(GsmException){  if (_oldChar != -1)  {    int result = _oldChar;    _oldChar = -1;    return result;  }  unsigned char c;  int timeElapsed = 0;  struct timeval oneSecond;  bool readDone = false;  while (! readDone && timeElapsed < _timeoutVal)  {    if (interrupted())      throwModemException(_("interrupted when reading from TA"));    // setup fd_set data structure for select()    fd_set fdSet;    oneSecond.tv_sec = 1;    oneSecond.tv_usec = 0;    FD_ZERO(&fdSet);    FD_SET(_fd, &fdSet);    switch (select(FD_SETSIZE, &fdSet, NULL, NULL, &oneSecond))    {    case 1:    {      int res = read(_fd, &c, 1);      if (res != 1)        return -1;      else        readDone = true;      break;    }    case 0:      ++timeElapsed;      break;    default:      if (errno != EINTR)        throwModemException(_("reading from TA"));      break;    }  }  if (! readDone)    throwModemException(_("timeout when reading from TA"));#ifndef NDEBUG  if (debugLevel() >= 2)  {    // some useful debugging code    if (c == LF)      cerr << "<LF>";    else if (c == CR)      cerr << "<CR>";    else cerr << "<'" << (char) c << "'>";    cerr.flush();  }#endif  return c;}UnixSerialPort::UnixSerialPort(string device, speed_t lineSpeed,                               string initString, bool swHandshake)  throw(GsmException) :  _oldChar(-1), _timeoutVal(TIMEOUT_SECS){  struct termios t;  // open device  _fd = open(device.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);  if (_fd == -1)    throwModemException(stringPrintf(_("opening device '%s'"),                                     device.c_str()));  // switch off non-blocking mode  int fdFlags;  if ((fdFlags = fcntl(_fd, F_GETFL)) == -1)    throwModemException(_("getting file status flags failed"));  fdFlags &= ~O_NONBLOCK;  if (fcntl(_fd, F_SETFL, fdFlags) == -1)    throwModemException(_("switching of non-blocking mode failed"));  long int saveTimeoutVal = _timeoutVal;  _timeoutVal = 3;  int initTries = holdoffArraySize;  while (initTries-- > 0)  {    // flush all pending output    tcflush(_fd, TCOFLUSH);    // toggle DTR to reset modem    int mctl = TIOCM_DTR;    if (ioctl(_fd, TIOCMBIC, &mctl) < 0)      throwModemException(_("clearing DTR failed"));    // the waiting time for DTR toggling is increased with each loop    usleep(holdoff[initTries]);    if (ioctl(_fd, TIOCMBIS, &mctl) < 0)      throwModemException(_("setting DTR failed"));      // get line modes    if (tcgetattr(_fd, &t) < 0)      throwModemException(stringPrintf(_("tcgetattr device '%s'"),                                       device.c_str()));    // set line speed    cfsetispeed(&t, lineSpeed);    cfsetospeed(&t, lineSpeed);    // set the device to a sane state    t.c_iflag |= IGNPAR | (swHandshake ? IXON | IXOFF : 0);    t.c_iflag &= ~(INPCK | ISTRIP | IMAXBEL |                   (swHandshake ? 0 : IXON |  IXOFF)                   | IXANY | IGNCR | ICRNL | IMAXBEL | INLCR | IGNBRK);    t.c_oflag &= ~(OPOST);    // be careful, only touch "known" flags    t.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD |                  (swHandshake ? CRTSCTS : 0 ));    t.c_cflag |= CS8 | CREAD | HUPCL | (swHandshake ? 0 : CRTSCTS) | CLOCAL;    t.c_lflag &= ~(ECHO | ECHOE | ECHOPRT | ECHOK | ECHOKE | ECHONL |                   ECHOCTL | ISIG | IEXTEN | TOSTOP | FLUSHO | ICANON);    t.c_lflag |= NOFLSH;    t.c_cc[VMIN] = 1;    t.c_cc[VTIME] = 0;    t.c_cc[VSUSP] = 0;    // write back    if(tcsetattr (_fd, TCSANOW, &t) < 0)      throwModemException(stringPrintf(_("tcsetattr device '%s'"),                                       device.c_str()));    // the waiting time for writing to the ME/TA is increased with each loop    usleep(holdoff[initTries]);    // flush all pending input    tcflush(_fd, TCIFLUSH);    try    {      // reset modem      putLine("ATZ");      bool foundOK = false;      int readTries = 5;      while (readTries-- > 0)      {        // for the first call getLine() waits only 3 seconds        // because of _timeoutVal = 3        string s = getLine();        if (s.find("OK") != string::npos ||            s.find("CABLE: GSM") != string::npos)        {          foundOK = true;          readTries = 0;           // found OK, exit loop        }      }      // set getLine/putLine timeout back to old value      _timeoutVal = saveTimeoutVal;      if (foundOK)      {        // init modem        readTries = 5;        putLine("AT" + initString);        while (readTries-- > 0)        {          string s = getLine();          if (s.find("OK") != string::npos ||              s.find("CABLE: GSM") != string::npos)            return;                 // found OK, return        }      }    }    catch (GsmException &e)    {      _timeoutVal = saveTimeoutVal;      if (initTries == 0)        throw e;    }  }  // no response after 3 tries  throw GsmException(stringPrintf(_("reset modem failed '%s'"),                                  device.c_str()), OtherError);}string UnixSerialPort::getLine() throw(GsmException){  string result;  int c;  while ((c = readByte()) >= 0)  {    while (c == CR)    {      c = readByte();    }    if (c == LF)      break;    result += c;  }#ifndef NDEBUG  if (debugLevel() >= 1)    cerr << "<-- " << result << endl;#endif  return result;}void UnixSerialPort::putLine(string line,                             bool carriageReturn) throw(GsmException){#ifndef NDEBUG  if (debugLevel() >= 1)    cerr << "--> " << line << endl;#endif  if (carriageReturn) line += CR;  const char *l = line.c_str();    int timeElapsed = 0;  struct timeval oneSecond;  ssize_t bytesWritten = 0;  while (bytesWritten < (ssize_t)line.length() && timeElapsed < _timeoutVal)  {    if (interrupted())      throwModemException(_("interrupted when writing to TA"));    // setup fd_set data structure for select()    fd_set fdSet;    oneSecond.tv_sec = 1;    oneSecond.tv_usec = 0;    FD_ZERO(&fdSet);    FD_SET(_fd, &fdSet);    switch (select(FD_SETSIZE, NULL, &fdSet, NULL, &oneSecond))    {    case 1:    {      ssize_t bw = write(_fd, l + bytesWritten, line.length() - bytesWritten);      if (bw < 0)        throwModemException(_("writing to TA"));      bytesWritten += bw;      break;    }    case 0:      ++timeElapsed;      break;    default:      if (errno != EINTR)        throwModemException(_("writing to TA"));      break;    }  }    while (timeElapsed < _timeoutVal)  {    if (interrupted())      throwModemException(_("interrupted when writing to TA"));    startTimer();    int res = tcdrain(_fd);     // wait for output to be read by TA    stopTimer();    if (res == 0)      break;    else    {      assert(errno == EINTR);      ++timeElapsed;    }  }  if (timeElapsed >= _timeoutVal)    throwModemException(_("timeout when writing to TA"));  // echo CR LF must be removed by higher layer functions in gsm_at because  // in order to properly handle unsolicited result codes from the ME/TA}bool UnixSerialPort::wait(GsmTime timeout) throw(GsmException){  fd_set fds;  FD_ZERO(&fds);  FD_SET(_fd, &fds);  return select(FD_SETSIZE, &fds, NULL, NULL, timeout) != 0;}// set timeout for read or write in seconds.void UnixSerialPort::setTimeOut(unsigned int timeout){  _timeoutVal = timeout;}UnixSerialPort::~UnixSerialPort(){  if (_fd != -1)    close(_fd);}speed_t gsmlib::baudRateStrToSpeed(string baudrate) throw(GsmException){  if (baudrate == "300")    return B300;  else if (baudrate == "600")    return B600;  else if (baudrate == "1200")    return B1200;  else if (baudrate == "2400")    return B2400;  else if (baudrate == "4800")    return B4800;  else if (baudrate == "9600")    return B9600;  else if (baudrate == "19200")    return B19200;  else if (baudrate == "38400")    return B38400;#ifdef B57600  else if (baudrate == "57600")    return B57600;#endif#ifdef B115200  else if (baudrate == "115200")    return B115200;#endif#ifdef B230400  else if (baudrate == "230400")    return B230400;#endif#ifdef B460800  else if (baudrate == "460800")    return B460800;#endif  else    throw GsmException(stringPrintf(_("unknown baudrate '%s'"),                                    baudrate.c_str()), ParameterError);}

⌨️ 快捷键说明

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