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

📄 gsm_win32_serial.cc

📁 对各种手机进行编程的工具包源码gsmlib 1.9版本。
💻 CC
字号:
// *************************************************************************// * GSM TA/ME library// *// * File:    gsm_win32_port.cc// *// * Purpose: WIN32 serial port implementation// *// * Author:  Frediano Ziglio (freddy77@angelfire.com)// *// * Created: 25.10.2000// *************************************************************************#ifdef HAVE_CONFIG_H#include <gsm_config.h>#endif#include <winsock.h>#include <gsmlib/gsm_nls.h>#include <gsmlib/gsm_win32_serial.h>#include <gsmlib/gsm_util.h>#include <fcntl.h>#include <iostream>#include <strstream>#include <errno.h>#include <stdio.h>#include <assert.h>#include <signal.h>using namespace std;using namespace gsmlib;static long int timeoutVal = TIMEOUT_SECS;struct ExceptionSafeOverlapped: public OVERLAPPED{  ExceptionSafeOverlapped()  {    memset((OVERLAPPED*)this,0,sizeof(OVERLAPPED));    hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );     if (hEvent == INVALID_HANDLE_VALUE)       throw GsmException(_("error creating event"),OSError,GetLastError());  }  ~ExceptionSafeOverlapped()  { CloseHandle(hEvent); }};typedef BOOL (WINAPI *TCancelIoProc)(HANDLE file);TCancelIoProc CancelIoProc = NULL;BOOL CancelIoHook(HANDLE file){  if (CancelIoProc)    return CancelIoProc(file);  HMODULE hmodule = GetModuleHandle("KERNEL32");  if (hmodule)  {    CancelIoProc = (TCancelIoProc)GetProcAddress(hmodule,"CancelIo");    if (CancelIoProc)      return CancelIoProc(file);  }                           return TRUE;}#define CancelIo CancelIoHook// Win32SerialPort membersvoid Win32SerialPort::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 Win32SerialPort::putBack(char c){  assert(_oldChar == -1);  _oldChar = c;}int Win32SerialPort::readByte() throw(GsmException){  if (_oldChar != -1)  {    int result = _oldChar;    _oldChar = -1;    return result;  }  char c;  int timeElapsed = 0;  bool readDone = true;  ExceptionSafeOverlapped  over;  DWORD initTime = GetTickCount();  DWORD dwReaded;  if (!ReadFile(_file,&c,1,&dwReaded,&over))  {    readDone = false;    if (GetLastError() != ERROR_IO_PENDING)    {      throwModemException(_("reading from TA"));    }    while(!readDone)    {      if (interrupted())        throwModemException(_("interrupted when reading from TA"));      // wait another second      switch(WaitForSingleObject(over.hEvent,1000))      {      case WAIT_TIMEOUT:        break;      case WAIT_OBJECT_0:      case WAIT_ABANDONED:	      // !!! do a infinite loop if (bytesWritten < lenght) ?        GetOverlappedResult(_file,&over,&dwReaded,TRUE);        readDone = true;        break;      case WAIT_FAILED:        throwModemException(_("reading from TA"));      }      timeElapsed = (GetTickCount() - initTime)/1000U;      // timeout elapsed ?      if (timeElapsed >= timeoutVal)      {        CancelIo(_file);        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;}Win32SerialPort::Win32SerialPort(string device, int lineSpeed,                               string initString, bool swHandshake)  throw(GsmException) :  _oldChar(-1){ try {  int holdoff[] = {2000, 1000, 400};  // open device  _file = CreateFile(device.c_str(),GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );  if (_file == INVALID_HANDLE_VALUE)    throwModemException(stringPrintf(_("opening device '%s'"),                                     device.c_str()));  int initTries = 3;  while (initTries-- > 0)  {    // flush all pending output    FlushFileBuffers(_file);    // toggle DTR to reset modem    if (!EscapeCommFunction(_file,CLRDTR))      throwModemException(_("clearing DTR failed"));    Sleep(holdoff[initTries]);    if (!EscapeCommFunction(_file,SETDTR))      throwModemException(_("setting DTR failed"));    DCB dcb;    // get line modes    if (!GetCommState(_file,&dcb))      throwModemException(stringPrintf(_("GetCommState device '%s'"),                                       device.c_str()));//    if (tcgetattr(_fd, &t) < 0)//      throwModemException(stringPrintf(_("tcgetattr device '%s'"),//                                       device.c_str()));    // set the device to a sane state    dcb.fBinary = TRUE;    dcb.BaudRate = lineSpeed;    // n,8,1    dcb.fParity = FALSE;    dcb.Parity = 0;    dcb.ByteSize = 8;    dcb.StopBits = 0;    if (!swHandshake)    {      dcb.fInX = FALSE;      dcb.fOutX = FALSE;      dcb.fOutxDsrFlow = FALSE;      dcb.fOutxCtsFlow = FALSE;    }    else    {      dcb.fInX  = TRUE;      dcb.fOutX = TRUE;      dcb.fOutxDsrFlow = FALSE;      dcb.fOutxCtsFlow = FALSE;    }    dcb.fDtrControl = DTR_CONTROL_ENABLE;    dcb.fRtsControl = RTS_CONTROL_ENABLE;    //    t.c_iflag |= IGNPAR;//    t.c_iflag &= ~(INPCK | ISTRIP | IMAXBEL |//                   (swHandshake ? CRTSCTS : 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);//    t.c_cflag|= CS8 | CREAD | HUPCL |//      (swHandshake ? IXON |  IXOFF : 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 (!SetCommState(_file,&dcb))      throwModemException(stringPrintf(_("SetCommState device '%s'"),                                       device.c_str()));    Sleep(holdoff[initTries]);    if (!SetupComm(_file,1024,1024))      throwModemException(stringPrintf(_("SetupComm device '%s'"),                                       device.c_str()));     // flush all pending input    PurgeComm(_file,PURGE_RXABORT|PURGE_RXCLEAR);    try    {      // reset modem      putLine("ATZ");      bool foundOK = false;      int readTries = 5;      while (readTries-- > 0)      {        string s = getLine();        if (s.find("OK") != string::npos ||            s.find("CABLE: GSM") != string::npos)        {          foundOK = true;          readTries = 0;           // found OK, exit loop        }      }      if (foundOK)      {        // init modem        readTries = 5;        // !!! no not declare this in loop, compiler error on Visual C++        // (without SP and with SP4)        string s;         putLine("AT" + initString);        do        {          s = getLine();          if (s.find("OK") != string::npos ||              s.find("CABLE: GSM") != string::npos)            return;                 // found OK, return        } while(--readTries);      }    }    catch (GsmException &e)    {      if (initTries == 0)        throw e;    }  }  // no response after 3 tries  throw GsmException(stringPrintf(_("reset modem failed '%s'"),                                  device.c_str()), OtherError); } catch (GsmException &e) {  if ( _file != INVALID_HANDLE_VALUE)   CloseHandle(_file);    throw e; }}string Win32SerialPort::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 Win32SerialPort::putLine(string line,                             bool carriageReturn) throw(GsmException){#ifndef NDEBUG  if (debugLevel() >= 1)    cerr << "--> " << line << endl;#endif  if (carriageReturn) line += CR;  // !!! BUG, mantain this pointer isn't corrent, use iterator !!!  const char *l = line.c_str();    FlushFileBuffers(_file);      // flush all pending input and output  int timeElapsed = 0;  DWORD bytesWritten = 0;  ExceptionSafeOverlapped over;  DWORD initTime = GetTickCount();  if (!WriteFile(_file,l,line.length(),&bytesWritten,&over))  {    if (GetLastError() != ERROR_IO_PENDING)    {      throwModemException(_("writing to TA"));    }    while(bytesWritten < (DWORD)line.length())    {      if (interrupted())        throwModemException(_("interrupted when writing to TA"));      // wait another second      switch(WaitForSingleObject(over.hEvent,1000))      {      case WAIT_TIMEOUT:        break;      case WAIT_OBJECT_0:      case WAIT_ABANDONED:	// !!! do a infinite loop if (bytesWritten < lenght) ?        GetOverlappedResult(_file,&over,&bytesWritten,TRUE);        break;      case WAIT_FAILED:        throwModemException(_("writing to TA"));      }      timeElapsed = (GetTickCount() - initTime)/1000U;      // timeout elapsed ?      if (timeElapsed >= timeoutVal)      {        CancelIo(_file);        throwModemException(_("timeout when writing to TA"));      }    }  }  return;/*  // empty buffer  SetCommMask(_file,EV_TXEMPTY);  DWORD dwEvent;  ResetEvent(over.hEvent);  if( WaitCommEvent(_file,&dwEvent,&over) )    return; // already empty  // check true errors  if (GetLastError() != ERROR_IO_PENDING)    throwModemException(_("error comm waiting"));  while(timeElapsed < timeoutVal)  {    if (interrupted())      throwModemException(_("interrupted when flushing to TA"));    switch( WaitForSingleObject( over.hEvent, 1000 ) )     {    case WAIT_TIMEOUT:      break;    // successfully flushed    case WAIT_ABANDONED:    case WAIT_OBJECT_0:      return;    default:      throwModemException(_("error waiting"));    }    timeElapsed = (GetTickCount() - initTime)/1000U;  }  CancelIo(_file);  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 Win32SerialPort::wait(GsmTime timeout) throw(GsmException){  // See differences from UNIX  // Why do I use Windows ?  DWORD dwEvent;  SetCommMask(_file,EV_RXCHAR);  if (!timeout)  {    if( !WaitCommEvent(_file,&dwEvent,NULL) )      throwModemException(_("error comm waiting"));    return true;  }    ExceptionSafeOverlapped over;  if( !WaitCommEvent(_file,&dwEvent,&over) )  {    // check true errors    if (GetLastError() != ERROR_IO_PENDING)      throwModemException(_("error comm waiting"));    switch( WaitForSingleObject( over.hEvent, timeout->tv_sec*1000U+(timeout->tv_usec/1000U) ) )     {    case WAIT_TIMEOUT:      CancelIo(_file);      return false;    case WAIT_ABANDONED:    case WAIT_OBJECT_0:      return true;    default:      throwModemException(_("error waiting"));    }  }  return true;}void Win32SerialPort::setTimeOut(unsigned int timeout){  timeoutVal = timeout;}Win32SerialPort::~Win32SerialPort(){  if ( _file != INVALID_HANDLE_VALUE)    CloseHandle(_file);}int gsmlib::baudRateStrToSpeed(string baudrate) throw(GsmException){  if (baudrate == "300")    return 300;  else if (baudrate == "600")    return 600;  else if (baudrate == "1200")    return 1200;  else if (baudrate == "2400")    return 2400;  else if (baudrate == "4800")    return 4800;  else if (baudrate == "9600")    return 9600;  else if (baudrate == "19200")    return 19200;  else if (baudrate == "38400")    return 38400;  else if (baudrate == "57600")    return 57600;  else if (baudrate == "115200")    return 115200;  else    throw GsmException(stringPrintf(_("unknown baudrate '%s'"),                                    baudrate.c_str()), ParameterError);}

⌨️ 快捷键说明

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