Bonjour/Zerconf library

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ATIf.cpp Source File

ATIf.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "ATIf.h"
00025 #include "mbed.h"
00026 #include <cstdarg>
00027 
00028 #define READ_TIMEOUT 100
00029 #define TMP_BUF_SIZE 128//512
00030 
00031 #define SERIAL_BUF_LEN 512 //Huge buf needed for PPP (esp. when transferring big data chunks, using TCP)
00032 
00033 #define BAUDRATE 9600//9600//115200// 19200
00034 
00035 #include "netCfg.h"
00036 #if NET_GPRS
00037 
00038 //#define __DEBUG
00039 #include "dbg/dbg.h"
00040 
00041 ATIf::ATIf() : SerialBuf(SERIAL_BUF_LEN), m_signalsEnable(false), m_isOpen(false), m_pCurrentSignal(NULL), m_signals() 
00042 {
00043   m_readTimeout = READ_TIMEOUT; //default 1s
00044   //tmpBuf = NULL;
00045   m_tmpBuf = new char[TMP_BUF_SIZE];
00046 }
00047 
00048 ATIf::~ATIf()
00049 {
00050   if(m_tmpBuf)
00051     delete[] m_tmpBuf;
00052 }
00053 
00054 int ATIf::printf(const char* format, ... )
00055 {
00056 
00057 /*if(!m_tmpBuf)
00058     m_tmpBuf = new char[TMP_BUF_SIZE]; //is it really necessary ??*/
00059   *m_tmpBuf=0;
00060      
00061   int len = 0;
00062   
00063   //
00064 //  flushBuffer();
00065 //wait(1);
00066   //
00067     
00068   va_list argp;
00069   
00070   va_start(argp, format);
00071   len += vsprintf(m_tmpBuf, format, argp);
00072   va_end(argp);
00073   
00074   //DBG("\r\nOutBuf is : %s, mode is %d.", m_tmpBuf, m_lineMode);
00075   
00076   int err = write( m_tmpBuf, m_lineMode );
00077   if (err<0)
00078     return 0;
00079     
00080   return len;
00081   
00082 }
00083 
00084 int ATIf::scanf(const char* format, ... )
00085 {
00086 /*if(!m_tmpBuf)
00087     m_tmpBuf = new char[TMP_BUF_SIZE];*/
00088   int err = read( m_tmpBuf, TMP_BUF_SIZE - 1,  m_readTimeout, m_lineMode, 1/*Ensure at least one char is read*/ );
00089   if (err<0)
00090     return -1;//EOF
00091     
00092   DBG("Scanf'ing:\r\n%s\r\n",m_tmpBuf);
00093     
00094   int len = 0;
00095   
00096   if(strchr(format,'%')) //Ugly, determines wether format string is null or not
00097   {
00098     va_list argp;
00099     
00100     va_start(argp, format);
00101     len += vsscanf(m_tmpBuf, format, argp);
00102     va_end(argp);
00103   }
00104   else //No varargs, call strncmp
00105   {
00106  /*   if(strlen(m_tmpBuf) == 0 )
00107       return -1;*/
00108     if( !strncmp(m_tmpBuf, format, strlen(format)) )
00109     {
00110       return 0;
00111     }
00112     else
00113     {
00114       return -1;
00115     }
00116   }
00117   
00118   return len;
00119   
00120 }
00121 
00122 void ATIf::setTimeout(int timeout) //used by scanf
00123 {
00124   m_readTimeout = timeout;
00125 }
00126 
00127 void ATIf::setLineMode(bool lineMode) //Switch btw line & raw fns
00128 {
00129   m_lineMode = lineMode;
00130 }
00131 
00132 void ATIf::setSignals(bool signalsEnable)
00133 {
00134   m_signalsEnable=signalsEnable;
00135 }
00136 
00137 #ifdef __LINKING_SCRIPT_BUG_SOLVED__
00138 template<class T>
00139 void ATIf::attachSignal( const char* sigName, T* pItem, bool (T::*pMethod)(ATIf*, bool, bool*) ) //Attach Signal ("Unsollicited response code" in Telit_AT_Reference_Guide.pdf) to an handler fn
00140 {
00141   ATSigHandler sig(sigName, (ATSigHandler::CDummy*)pItem, (bool (ATSigHandler::CDummy::*)(ATIf*, bool, bool*))pMethod);
00142   m_signals.push_back(sig);
00143 }
00144 #else
00145 //defined in ATIf.h directly
00146 //(it's ugly, I know ;))
00147 #endif
00148 
00149 void ATIf::detachSignal( const char* sigName )
00150 {
00151   list<ATSigHandler>::iterator it;
00152   
00153   for ( it = m_signals.begin(); it != m_signals.end(); it++ )
00154   {
00155     if( !strcmp((*it).m_name,sigName) )
00156     {
00157       m_signals.erase(it);
00158       break;
00159     }
00160   }
00161 }
00162 
00163 ATErr ATIf::open(Serial* pSerial) //Deactivate echo, etc
00164 {
00165   DBG("\r\nOpening...");
00166   m_isOpen = true; //Must be set so that the serial port-related fns work
00167   //Setup options  
00168 //  pSerial->baud(BAUDRATE); //FIXME
00169   SerialBuf::attach(pSerial);
00170 
00171   setReadMode(false); //Discard chars
00172   setTimeout(1000);
00173   setLineMode(true); //Line Mode
00174   
00175   DBG("\r\nTrmt...");
00176  // printf("AT+IPR=%d", BAUDRATE); //FIXME
00177   wait(.100);
00178   printf("ATE"); //Deactivate echo
00179   wait(.500);
00180   flushBuffer();
00181   
00182   DBG("\r\nATE OK.");
00183   
00184   int len = writeLine("ATV1");
00185   ATErr err = AT_OK;
00186   if(len<0)
00187     err=(ATErr)len;
00188     
00189   if(!err)
00190   {
00191     err = checkOK();
00192     if (err) //No ACK from module
00193     {
00194       DBG("\r\nOpening port, error %d.", err);
00195       if(err==AT_TIMEOUT)
00196         err = AT_NOANSWER;
00197     }
00198   }
00199   
00200   if(err)
00201   {
00202     SerialBuf::detach();
00203     m_isOpen = false;
00204     return err;
00205   }
00206   
00207   DBG("\r\nNo error.");
00208   #if 0//FIXME
00209   m_signalsEnable = true;
00210   #endif
00211   //FIXME:
00212 //  m_pSerial->attach<ATIf>(this, &ATIf::onSerialInterrupt);
00213   
00214   return AT_OK;
00215 }
00216 
00217 #if NET_USB_SERIAL
00218 ATErr ATIf::open(UsbSerial* pUsbSerial) //Deactivate echo, etc
00219 {
00220   DBG("\r\nOpening...");
00221   m_isOpen = true; //Must be set so that the serial port-related fns work
00222   //Setup options  
00223   SerialBuf::attach(pUsbSerial);
00224 
00225   setReadMode(false); //Discard chars
00226   setTimeout(1000);
00227   setLineMode(true); //Line Mode
00228 
00229   printf("ATZ"); //Reinit
00230   wait(.500);  
00231   //flushBuffer();
00232 //  printf("ATE0 ^CURC=0"); //Deactivate echo & notif
00233   printf("ATE0"); //Deactivate echo & notif
00234   wait(.500);
00235   flushBuffer();
00236   
00237   DBG("\r\nATE OK.");
00238   
00239   int len = writeLine("ATQ0 V1 S0=0 &C1 &D2 +FCLASS=0");//writeLine("ATQ0 V1 S0=0 &C1 &D2 +FCLASS=0");
00240   ATErr err = AT_OK;
00241   if(len<0)
00242     err=(ATErr)len;
00243     
00244   if(!err)
00245   {
00246     err = checkOK();
00247     if (err) //No ACK from module
00248     {
00249       DBG("\r\nOpening port, error %d.", err);
00250       if(err==AT_TIMEOUT)
00251         err = AT_NOANSWER;
00252     }
00253   }
00254   
00255   if(err)
00256   {
00257     SerialBuf::detach();
00258     m_isOpen = false;
00259     return err;
00260   }
00261   
00262   DBG("\r\nNo error.");
00263   m_signalsEnable = true;
00264   //FIXME:
00265 //  m_pSerial->attach<ATIf>(this, &ATIf::onSerialInterrupt);
00266   
00267   return AT_OK;
00268 }
00269 #endif
00270 
00271 ATErr ATIf::close() //Release port
00272 {
00273   SerialBuf::detach(); //Detach serial buf
00274   m_isOpen = false;
00275   m_signalsEnable = false;
00276   return AT_OK;
00277 }
00278 
00279 ATErr ATIf::flushBuffer()
00280 {
00281   if(!m_isOpen)
00282     return AT_CLOSED;
00283   
00284   int len=0;
00285 //  char c;
00286   while(readable())
00287   {
00288    /* c = */ getc();
00289  //   DBG("\r\n[%c] discarded.", c);    
00290  //   wait(0.01);
00291     len++;
00292   }
00293   
00294   DBG("\r\n%d chars discarded.", len);
00295   
00296   return AT_OK;
00297 }
00298 
00299 ATErr ATIf::flushLine(int timeout)
00300 {
00301   if(!m_isOpen)
00302     return AT_CLOSED;
00303     
00304   Timer timer;
00305   
00306   timer.start();
00307   
00308   int len=0;
00309   char c=0;
00310   while(true)
00311   {
00312     while(!readable())
00313     {      if(timer.read_ms()>timeout)
00314       {
00315  //       DBG("Timeout!!0");
00316         return AT_TIMEOUT;
00317       }
00318     }
00319     if(c=='\x0D')
00320     {
00321       c = getc();
00322       len++;
00323       if(c=='\x0A')
00324         break;
00325     }
00326     else
00327     {
00328       c = getc();
00329       len++;
00330     }
00331   }
00332   
00333 //  DBG("\r\n%d chars discarded.", len);
00334   
00335   return AT_OK;
00336 }
00337 
00338 bool ATIf::onRead()
00339 {
00340   if(!m_signalsEnable)
00341     return false;
00342 
00343   //Save Usermode params
00344   volatile int u_readTimeout = m_readTimeout;
00345   volatile bool u_lineMode = m_lineMode;
00346 //  bool u_isOpen = m_isOpen;
00347   SerialBuf::setReadMode(true);
00348   
00349   m_readTimeout = 0; //No timeout in an interrupt fn!
00350   
00351   bool handled;
00352   if(!!flushLine(0))
00353   {
00354     SerialBuf::resetRead();
00355     //Not a complete line here, wait...
00356     handled = false;
00357   }
00358   else
00359   {
00360    SerialBuf::resetRead();
00361    handled = true; 
00362    if( handleSignal() ) //Was that a signal ?
00363     {
00364       //OK, discard data since it has been processed
00365       SerialBuf::flushRead();
00366     }
00367     else
00368     {
00369       //Keep data since it has not been processed yet
00370       //Have to be processed in usermode
00371       SerialBuf::resetRead();
00372 //      handled = false; 
00373     }
00374   }  
00375   //Restore Usermode params
00376   m_readTimeout = u_readTimeout;
00377   m_lineMode = u_lineMode;
00378   //m_isOpen = u_isOpen;
00379   return handled;
00380 }
00381 
00382 ATErr ATIf::rawOpen(Serial* pSerial, int baudrate) //Simple open function for similar non-conforming protocols
00383 {
00384   DBG("\r\nOpening...");
00385   m_isOpen = true; //Must be set so that the serial port-related fns work
00386   //Setup options  
00387   pSerial->baud(baudrate);
00388   SerialBuf::attach(pSerial);
00389 
00390   return AT_OK;
00391 }
00392 
00393 #if 0
00394 ATErr ATIf::command(const char* cmd, char* result, int resultLen, int timeout) ////WARN/FIXME: result has to be long enough!!!
00395 {  
00396   if(!m_isOpen)
00397     return AT_CLOSED;
00398   
00399   flushBuffer();
00400   
00401   int err;
00402   err = writeLine(cmd);
00403   
00404   if(err<0)
00405     { m_receiveStatus = AT_READY; return (ATErr)err; }
00406     
00407   err = readLine(result, resultLen, timeout);
00408   
00409   if(err<0)
00410     { m_receiveStatus = AT_READY; return (ATErr)err; }
00411       
00412   m_receiveStatus = AT_READY;
00413     
00414   return AT_OK;
00415   
00416 }
00417 #endif
00418 
00419 ATErr ATIf::write(const char* cmd, bool lineMode /*= false*/)
00420 {
00421   if(!m_isOpen)
00422     return AT_CLOSED;
00423 
00424   int err;  
00425   err = lineMode ? writeLine(cmd) : writeRaw(cmd);
00426 
00427   if(err<0)
00428     return (ATErr)err;
00429       
00430   return AT_OK;
00431 }
00432 
00433 
00434 ATErr ATIf::read(char* result, int resultMaxLen, int timeout, bool lineMode /*= false*/, int resultMinLen/* = 0*/)
00435 {
00436   if(!m_isOpen)
00437     return AT_CLOSED;
00438   
00439   int err;  
00440   err = lineMode ? readLine(result, resultMaxLen, timeout) :  readRaw(result, resultMaxLen, timeout, resultMinLen);
00441   
00442   if(err<0)
00443     return (ATErr)err;
00444     
00445   return AT_OK;
00446 }
00447 
00448 bool ATIf::isOpen()
00449 {
00450   return m_isOpen;
00451 }
00452 
00453 ATErr ATIf::checkOK() //Helper fn to quickly check that OK has been returned
00454 {
00455   char ret[16] = {0};
00456   int err = readLine(ret,16,m_readTimeout);
00457   
00458   if(err<0)
00459   {
00460     DBG("\r\nError in check (%s).\r\n", ret);
00461     flushBuffer(); //Discard anything in buf to avoid misparsing in the following calls
00462     return (ATErr)err;
00463   }
00464   
00465   if(!!strcmp("OK",ret))
00466   {
00467     DBG("\r\nNot an OK <%s>.\r\n", ret);
00468     flushBuffer();
00469     return AT_ERROR;
00470   }
00471   
00472   DBG("\r\nCHECK OK\r\n");
00473   
00474   return AT_OK;
00475 }
00476 
00477 #if 0
00478 void ATIf::onSerialInterrupt() //Callback from m_pSerial
00479 {
00480 return;//FIXME
00481 
00482   if(m_receiveStatus == AT_READING)
00483     return;
00484 
00485   if( m_cbObj && m_cbMeth )
00486     return (m_cbObj->*m_cbMeth)();
00487 }
00488 #endif
00489 
00490 int ATIf::readLine(char* line, int maxLen, int timeout) //Read a single line from serial port, return length or ATErr(<0)
00491 {
00492 #ifdef OLDREADLINE
00493   if(!m_isOpen)
00494     return AT_CLOSED;
00495     
00496   int len = 0;
00497   
00498   Timer timer;
00499   
00500   timer.start();
00501 #ifdef __START_CLRF_MANDAT
00502   for( int i=0; i<2; i++ )
00503   {
00504     while(!readable())
00505     {
00506       if(timer.read_ms()>timeout)
00507       {
00508 //        DBG("Timeout!!0");
00509         return AT_TIMEOUT;
00510       }
00511       wait_ms(10); //Wait 10ms
00512     }
00513     *line = getc();
00514   //  DBG("In readLine(), read : %c", *line);
00515     if( ( (i == 0) && (*line!='\x0D') )
00516      || ( (i == 1) && (*line!='\x0A') ) )
00517      return AT_PARSE;
00518   }
00519 #else
00520   
00521 #endif
00522 
00523   for( ; len < maxLen ; len++ )
00524   {
00525     timer.reset();
00526     while(!readable())
00527     {
00528       if(timer.read_ms()>timeout)
00529       {
00530 //        DBG("Timeout!!1");
00531         return AT_TIMEOUT;
00532       }
00533       wait_ms(10); //Wait 10ms
00534     }
00535     *line = getc();
00536     //DBG("In readLine(), read : %c", *line);
00537 
00538     if(*line=='\x0D')
00539     {
00540       timer.reset();
00541       while(!readable())
00542       {
00543         if(timer.read_ms()>timeout)
00544         {
00545           return AT_TIMEOUT;
00546         }
00547         wait_ms(10); //Wait 1ms
00548       }
00549       *line = getc();
00550     //  DBG("In readLine(), read : %c", *line);
00551       if(*line=='\x0A')
00552       {
00553         if(len==0)
00554         {
00555           //Start of line
00556           len--;
00557           continue;
00558         }
00559         else
00560         {
00561           *line=0; //End of line
00562           break;
00563         }
00564       }
00565       else
00566       {
00567         //Should not happen, must have lost some bytes somewhere or non AT protocol
00568         return AT_PARSE;
00569       }
00570     }
00571     line++;
00572   }
00573   
00574   if(len==maxLen)
00575     return AT_INCOMPLETE; //Buffer full, must call this method again to get end of line
00576   
00577   return len;
00578 #else
00579  if(!m_isOpen)
00580     return AT_CLOSED;
00581   
00582   Timer timer;  
00583   timer.start();
00584 
00585   int len = 0;
00586   while( len < maxLen )
00587   {
00588     timer.reset();
00589     while(!readable())
00590     {
00591       if(timer.read_ms()>timeout)
00592       {
00593         return AT_TIMEOUT;
00594       }
00595       wait_ms(10); //Wait 10ms
00596     }
00597     *line = getc();
00598 
00599     if( (*line=='\x0D') || (*line=='\x0A') )
00600     {
00601     
00602       if(len==0)
00603       {
00604         //Start of line
00605         continue;
00606       }
00607       else
00608       {
00609         *line=0; //End of line
00610         break;
00611       }
00612     }
00613     len++;  
00614     line++;
00615   }
00616   
00617   if(len==maxLen)
00618     return AT_INCOMPLETE; //Buffer full, must call this method again to get end of line
00619   
00620   return len;
00621 #endif
00622 }
00623 
00624 int ATIf::writeLine(const char* line) //Write a single line to serial port
00625 {
00626 //  char* line = (char*) _line;
00627   if(!m_isOpen)
00628     return AT_CLOSED;
00629   
00630 //  DBG("\n\rIn writeline.");
00631   
00632   int len = 0;
00633 
00634   while(*line)
00635   {
00636     putc(*line);
00637     line++;
00638     len++;
00639   }
00640   
00641  /* putc('\r');
00642   
00643     putc('\n');*/
00644   
00645   putc('\x0D');
00646 //  putc('\x0A');
00647 
00648 // DBG("\n\rWritten %d + 1", len);
00649   
00650   return len;
00651  
00652 }
00653 
00654 
00655     
00656 int ATIf::readRaw(char* str, int maxLen, int timeout /*= 0*/, int minLen /*= 0*/) //Read from serial port in buf
00657 {
00658   if(!m_isOpen)
00659     return AT_CLOSED;
00660     
00661   int len = 0;
00662   
00663   Timer timer;
00664   
00665   timer.start();
00666 
00667   for( ; len < maxLen ; len++ )
00668   {
00669     while( (len < minLen) && !readable())
00670     {
00671       if(timer.read_ms()>timeout)
00672       {
00673         return AT_TIMEOUT;
00674       }
00675       wait(.01); //Wait 10ms
00676     }
00677     
00678     if(!readable()) //Buffer read entirely
00679       break;
00680       
00681     *str = getc();
00682     str++;
00683     len++;
00684   }
00685   
00686   *str = 0; //End char
00687   
00688   return len;
00689   
00690 }
00691 
00692 int ATIf::writeRaw(const char* str) //Write directly to serial port    
00693 {
00694   if(!m_isOpen)
00695     return AT_CLOSED;
00696     
00697   int len = 0;
00698 
00699   while(*str)
00700   {
00701     putc(*str);
00702     str++;
00703     len++;
00704   }
00705   
00706   return len;
00707 }    
00708 
00709 bool ATIf::handleSignal()
00710 {
00711   bool beg = false;
00712   
00713 //  SerialBuf::setReadMode(true); //Keep chars in buf when read  
00714 //  SerialBuf::resetRead();
00715    
00716   //if( !m_pCurrentSignal ) //If no signal asked for this line
00717   if(true) //Check anyway, could have been some parsing error before
00718   {
00719     //Extract Signal Name
00720     char sigName[32]; //Should not be longer than that
00721     setLineMode(true); //Read one line  
00722 
00723     int len = scanf("%[^:]:%*[^\n]", sigName);
00724     if(len != 1)
00725       return false; //This is not a signal      
00726  //   DBG("\r\nGot signal %s\r\n", sigName);
00727   
00728     list<ATSigHandler>::iterator it;
00729 
00730     for ( it = m_signals.begin(); it != m_signals.end(); it++ )
00731     {
00732       if( !strcmp((*it).m_name, sigName) )
00733       {
00734   //      DBG("\r\nFound signal %s\r\n", sigName);
00735         m_pCurrentSignal = &(*it);
00736         beg = true;
00737         break;
00738       }
00739     }
00740     
00741     
00742   }
00743   
00744   if( !m_pCurrentSignal ) 
00745     return false; //This is not a signal or it cannot be handled
00746     
00747   bool moreData = false;
00748   //Call signal handling routine
00749   SerialBuf::resetRead(); //Rollback so that the handling fn can call scanf properly
00750   bool result = ((m_pCurrentSignal->m_cbObj)->*(m_pCurrentSignal->m_cbMeth))(this, beg, &moreData);
00751   
00752   if( !moreData ) //Processing completed
00753   {
00754     m_pCurrentSignal = NULL;
00755   }
00756   
00757   return result;
00758 }
00759 
00760 #endif