Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 15:37:03 by 1.7.2