Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ATHandler.cpp Source File

ATHandler.cpp

00001 /*
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "ATHandler.h"
00019 #include "mbed_poll.h"
00020 #include "FileHandle.h"
00021 #include "Timer.h"
00022 #include "mbed_wait_api.h"
00023 #include "mbed_debug.h"
00024 #ifdef MBED_CONF_RTOS_PRESENT
00025 #include "rtos/Thread.h"
00026 #endif
00027 
00028 using namespace mbed;
00029 using namespace events;
00030 
00031 //#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_DEBUG
00032 #include "CellularLog.h"
00033 
00034 #if MBED_CONF_MBED_TRACE_ENABLE
00035 #define at_debug(format, ...) do { if (_debug_on) debug(format, ## __VA_ARGS__); } while (0)
00036 #else
00037 #define at_debug(...)
00038 #endif
00039 
00040 const char *mbed::OK = "OK\r\n";
00041 const uint8_t OK_LENGTH = 4;
00042 const char *mbed::CRLF = "\r\n";
00043 const uint8_t CRLF_LENGTH = 2;
00044 const char *CME_ERROR = "+CME ERROR:";
00045 const uint8_t CME_ERROR_LENGTH = 11;
00046 const char *CMS_ERROR = "+CMS ERROR:";
00047 const uint8_t CMS_ERROR_LENGTH = 11;
00048 const char *ERROR_ = "ERROR\r\n";
00049 const uint8_t ERROR_LENGTH = 7;
00050 const uint8_t MAX_RESP_LENGTH = CMS_ERROR_LENGTH;
00051 const char DEFAULT_DELIMITER = ',';
00052 
00053 static const uint8_t map_3gpp_errors[][2] =  {
00054     { 103, 3 },  { 106, 6 },  { 107, 7 },  { 108, 8 },  { 111, 11 }, { 112, 12 }, { 113, 13 }, { 114, 14 },
00055     { 115, 15 }, { 122, 22 }, { 125, 25 }, { 172, 95 }, { 173, 96 }, { 174, 97 }, { 175, 99 }, { 176, 111 },
00056     { 177, 8 },  { 126, 26 }, { 127, 27 }, { 128, 28 }, { 129, 29 }, { 130, 30 }, { 131, 31 }, { 132, 32 },
00057     { 133, 33 }, { 134, 34 }, { 140, 40 }, { 141, 41 }, { 142, 42 }, { 143, 43 }, { 144, 44 }, { 145, 45 },
00058     { 146, 46 }, { 178, 65 }, { 179, 66 }, { 180, 48 }, { 181, 83 }, { 171, 49 },
00059 };
00060 
00061 ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter) :
00062     _nextATHandler(0),
00063     _fileHandle(fh),
00064     _queue(queue),
00065     _last_err(NSAPI_ERROR_OK ),
00066     _last_3gpp_error(0),
00067     _oob_string_max_length(0),
00068     _oobs(NULL),
00069     _at_timeout(timeout),
00070     _previous_at_timeout(timeout),
00071     _fh_sigio_set(false),
00072     _processing(false),
00073     _ref_count(1),
00074     _stop_tag(NULL),
00075     _delimiter(DEFAULT_DELIMITER),
00076     _prefix_matched(false),
00077     _urc_matched(false),
00078     _error_found(false),
00079     _max_resp_length(MAX_RESP_LENGTH),
00080     _debug_on(false),
00081     _cmd_start(false)
00082 {
00083     //enable_debug(true);
00084 
00085     clear_error();
00086 
00087     if (output_delimiter) {
00088         _output_delimiter_length = strlen(output_delimiter);
00089         _output_delimiter = new char[_output_delimiter_length];
00090         for (unsigned i=0; i<_output_delimiter_length; i++) {
00091             _output_delimiter[i] = output_delimiter[i];
00092         }
00093     } else {
00094         _output_delimiter = NULL;
00095         _output_delimiter_length = 0;
00096     }
00097 
00098     reset_buffer();
00099     memset(_info_resp_prefix, 0, sizeof(_info_resp_prefix));
00100 
00101     _current_scope = NotSet;
00102     set_tag(&_resp_stop, OK);
00103     set_tag(&_info_stop, CRLF);
00104     set_tag(&_elem_stop, ")");
00105 
00106     _fileHandle->set_blocking(false);
00107 
00108     set_filehandle_sigio();
00109 }
00110 
00111 void ATHandler::enable_debug(bool enable)
00112 {
00113     _debug_on = enable;
00114 }
00115 
00116 ATHandler::~ATHandler()
00117 {
00118     while (_oobs) {
00119         struct oob_t *oob = _oobs;
00120         _oobs = oob->next;
00121         delete oob;
00122     }
00123     if (_output_delimiter) {
00124         delete [] _output_delimiter;
00125     }
00126 }
00127 
00128 void ATHandler::inc_ref_count()
00129 {
00130     _ref_count++;
00131 }
00132 
00133 void ATHandler::dec_ref_count()
00134 {
00135     _ref_count--;
00136 }
00137 
00138 int ATHandler::get_ref_count()
00139 {
00140     return _ref_count;
00141 }
00142 
00143 FileHandle *ATHandler::get_file_handle()
00144 {
00145     return _fileHandle;
00146 }
00147 
00148 void ATHandler::set_file_handle(FileHandle *fh)
00149 {
00150     _fileHandle = fh;
00151 }
00152 
00153 void ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void()> callback)
00154 {
00155     struct oob_t *oob = new struct oob_t;
00156     oob->matching_to_received = true;
00157     size_t prefix_len = strlen(prefix);
00158     if (prefix_len > _oob_string_max_length) {
00159         _oob_string_max_length = prefix_len;
00160         if (_oob_string_max_length > _max_resp_length) {
00161             _max_resp_length = _oob_string_max_length;
00162         }
00163     }
00164     oob->prefix = prefix;
00165     oob->cb = callback;
00166     oob->next = _oobs;
00167     _oobs = oob;
00168 }
00169 
00170 void ATHandler::event()
00171 {
00172     // _processing must be set before filehandle write/read to avoid repetitive sigio events
00173     if (!_processing) {
00174         _processing = true;
00175         (void) _queue.call(Callback<void(void)>(this, &ATHandler::process_oob));
00176     }
00177 }
00178 
00179 void ATHandler::lock()
00180 {
00181 #ifdef AT_HANDLER_MUTEX
00182     _fileHandleMutex.lock();
00183 #endif
00184     _processing = true;
00185     clear_error();
00186 }
00187 
00188 void ATHandler::unlock()
00189 {
00190     _processing = false;
00191 #ifdef AT_HANDLER_MUTEX
00192     _fileHandleMutex.unlock();
00193 #endif
00194     if (_fileHandle->readable() || (_recv_pos < _recv_len)) {
00195         (void) _queue.call(Callback<void(void)>(this, &ATHandler::process_oob));
00196     }
00197 }
00198 
00199 nsapi_error_t ATHandler::unlock_return_error()
00200 {
00201     nsapi_error_t err = _last_err;
00202     unlock();
00203     return err;
00204 }
00205 
00206 void ATHandler::set_at_timeout(uint32_t timeout_milliseconds, bool default_timeout)
00207 {
00208     if (default_timeout) {
00209         _previous_at_timeout = timeout_milliseconds;
00210         _at_timeout = timeout_milliseconds;
00211     } else if (timeout_milliseconds != _at_timeout) {
00212         _previous_at_timeout = _at_timeout;
00213         _at_timeout = timeout_milliseconds;
00214     }
00215 }
00216 
00217 void ATHandler::restore_at_timeout()
00218 {
00219     if (_previous_at_timeout != _at_timeout) {
00220         _at_timeout =_previous_at_timeout;
00221     }
00222 }
00223 
00224 void ATHandler::process_oob()
00225 {
00226     lock();
00227     tr_debug("process_oob %d", (_fileHandle->readable() || (_recv_pos < _recv_len)));
00228     if (_fileHandle->readable() || (_recv_pos < _recv_len)) {
00229         _current_scope = NotSet;
00230         Timer timer;
00231         timer.start();
00232         do {
00233             if (match_urc()) {
00234                 if (_fileHandle->readable() || (_recv_pos < _recv_len)) {
00235                     continue;
00236                 }
00237                 break;
00238             }
00239             // If no match found, look for CRLF and consume everything up to CRLF
00240             if (mem_str(_recv_buff, _recv_len, CRLF, CRLF_LENGTH)) {
00241                 consume_to_tag(CRLF, true);
00242             } else {
00243                 if (_fileHandle->readable()) {
00244                     fill_buffer();
00245                 } else {
00246 #ifdef MBED_CONF_RTOS_PRESENT
00247                     rtos::Thread::yield();
00248 #endif
00249                 }
00250             }
00251         } while (timer.read_ms() < 20); // URC's are very short so 20ms should be enough
00252     }
00253     tr_debug("process_oob exit");
00254 
00255     flush(); // consume anything that could not be handled
00256 
00257     unlock();
00258 }
00259 
00260 void ATHandler::set_filehandle_sigio()
00261 {
00262     if (_fh_sigio_set) {
00263         return;
00264     }
00265     _fileHandle->sigio(mbed::Callback<void()>(this, &ATHandler::event));
00266     _fh_sigio_set = true;
00267 }
00268 
00269 void ATHandler::reset_buffer()
00270 {
00271     tr_debug("%s", __func__);
00272     _recv_pos = 0; _recv_len = 0;
00273 }
00274 
00275 void ATHandler::rewind_buffer()
00276 {
00277     tr_debug("%s", __func__);
00278     if (_recv_pos > 0 && _recv_len >= _recv_pos) {
00279         _recv_len -= _recv_pos;
00280         // move what is not read to beginning of buffer
00281         memmove(_recv_buff, _recv_buff + _recv_pos, _recv_len);
00282         _recv_pos = 0;
00283     }
00284 }
00285 
00286 // we are always expecting to receive something so there is wait timeout
00287 void ATHandler::fill_buffer()
00288 {
00289     tr_debug("%s", __func__);
00290     // Reset buffer when full
00291     if (sizeof(_recv_buff) == _recv_len) {
00292         reset_buffer();
00293     }
00294 
00295     Timer timer;
00296     timer.start();
00297     do {
00298        ssize_t len = _fileHandle->read(_recv_buff + _recv_len, sizeof(_recv_buff) - _recv_len);
00299         if (len > 0) {
00300             _recv_len += len;
00301            at_debug("\n----------readable----------: %d\n", _recv_len);
00302            for (size_t i = _recv_pos; i < _recv_len; i++) {
00303                at_debug("%c", _recv_buff[i]);
00304            }
00305            at_debug("\n----------readable----------\n");
00306            return;
00307        } else if (len != -EAGAIN && len != 0) {
00308            tr_warn("%s error: %d while reading", __func__, len);
00309            break;
00310        }
00311 #ifdef MBED_CONF_RTOS_PRESENT
00312         rtos::Thread::yield();
00313 #endif
00314     } while ((uint32_t)timer.read_ms() < _at_timeout);
00315 
00316     set_error(NSAPI_ERROR_DEVICE_ERROR );
00317     tr_debug("AT TIMEOUT, scope: %d timeout: %lu", _current_scope, _at_timeout);
00318 }
00319 
00320 int ATHandler::get_char()
00321 {
00322     if (_recv_pos == _recv_len) {
00323         tr_debug("%s", __func__);
00324         reset_buffer(); // try to read as much as possible
00325         fill_buffer();
00326         if (get_last_error()) {
00327             tr_debug("%s: -1", __func__);
00328             return -1; // timeout to read
00329         }
00330     }
00331 
00332     tr_debug("%s: %c", __func__, _recv_buff[_recv_pos]);
00333 
00334     return _recv_buff[_recv_pos++];
00335 }
00336 
00337 void ATHandler::skip_param(uint32_t count)
00338 {
00339     tr_debug("%s", __func__);
00340     if (_last_err || !_stop_tag || _stop_tag->found) {
00341         return;
00342     }
00343 
00344     for (uint32_t i = 0; (i < count && !_stop_tag->found); i++) {
00345         size_t match_pos = 0;
00346         while (true) {
00347             int c = get_char();
00348             if (c == -1) {
00349                 set_error(NSAPI_ERROR_DEVICE_ERROR );
00350                 return;
00351             } else if (c == _delimiter) {
00352                 break;
00353             } else if (_stop_tag->len && c == _stop_tag->tag[match_pos]) {
00354                 match_pos++;
00355                 if (match_pos == _stop_tag->len) {
00356                     _stop_tag->found = true;
00357                     break;
00358                 }
00359             } else if (match_pos) {
00360                 match_pos = 0;
00361             }
00362         }
00363     }
00364     return;
00365 }
00366 
00367 void ATHandler::skip_param(ssize_t len, uint32_t count)
00368 {
00369     tr_debug("%s", __func__);
00370     if (_last_err || !_stop_tag || _stop_tag->found) {
00371         return;
00372     }
00373 
00374     for (uint32_t i = 0; i < count; i++) {
00375         ssize_t read_len = 0;
00376         while (read_len < len) {
00377             int c = get_char();
00378             if (c == -1) {
00379                 set_error(NSAPI_ERROR_DEVICE_ERROR );
00380                 return;
00381             }
00382             read_len++;
00383         }
00384     }
00385     return;
00386 }
00387 
00388 ssize_t ATHandler::read_bytes(uint8_t *buf, size_t len)
00389 {
00390     tr_debug("%s", __func__);
00391     if (_last_err) {
00392         return -1;
00393     }
00394 
00395     size_t read_len = 0;
00396     for (; read_len < len; read_len++) {
00397         int c = get_char();
00398         if (c == -1) {
00399             set_error(NSAPI_ERROR_DEVICE_ERROR );
00400             return -1;
00401         }
00402         buf[read_len] = c;
00403     }
00404     return read_len;
00405 }
00406 
00407 ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag)
00408 {
00409     tr_debug("%s", __func__);
00410     at_debug("\n----------read_string buff:----------\n");
00411     for (size_t i = _recv_pos; i < _recv_len; i++) {
00412         at_debug("%c", _recv_buff[i]);
00413     }
00414     at_debug("\n----------buff----------\n");
00415 
00416     if (_last_err || !_stop_tag || (_stop_tag->found && read_even_stop_tag == false)) {
00417         return -1;
00418     }
00419 
00420     uint8_t *pbuf = (uint8_t*)buf;
00421 
00422     size_t len = 0;
00423     size_t match_pos = 0;
00424 
00425     consume_char('\"');
00426 
00427     for (; len < (size + match_pos); len++) {
00428         int c = get_char();
00429         if (c == -1) {
00430             pbuf[len] = '\0';
00431             set_error(NSAPI_ERROR_DEVICE_ERROR );
00432             return -1;
00433         } else if (c == _delimiter) {
00434             pbuf[len] = '\0';
00435             break;
00436         } else if (c == '\"') {
00437             match_pos = 0;
00438             len--;
00439             continue;
00440         } else if (_stop_tag->len && c == _stop_tag->tag[match_pos]) {
00441             match_pos++;
00442             if (match_pos == _stop_tag->len) {
00443                 _stop_tag->found = true;
00444                 // remove tag from string if it was matched
00445                 len -= (_stop_tag->len - 1);
00446                 pbuf[len] = '\0';
00447                 break;
00448             }
00449         } else if (match_pos) {
00450             match_pos = 0;
00451         }
00452 
00453         pbuf[len] = c;
00454     }
00455 
00456     // Do we need _stop_found set after reading by size -> is _stop_tag_by_len needed or not?
00457     return len;
00458 }
00459 
00460 int32_t ATHandler::read_int()
00461 {
00462     tr_debug("%s", __func__);
00463 
00464      if (_last_err || !_stop_tag || _stop_tag->found) {
00465          return -1;
00466      }
00467 
00468     char buff[BUFF_SIZE];
00469     char *first_no_digit;
00470 
00471     if (read_string(buff, (size_t)sizeof(buff)) == 0) {
00472         return -1;
00473     }
00474 
00475     return std::strtol(buff, &first_no_digit, 10);
00476 }
00477 
00478 void ATHandler::set_delimiter(char delimiter)
00479 {
00480     _delimiter = delimiter;
00481 }
00482 
00483 void ATHandler::set_default_delimiter()
00484 {
00485     _delimiter = DEFAULT_DELIMITER;
00486 }
00487 
00488 void ATHandler::set_tag(tag_t* tag_dst, const char *tag_seq)
00489 {
00490     if (tag_seq) {
00491         size_t tag_len = strlen(tag_seq);
00492         set_string(tag_dst->tag, tag_seq, tag_len);
00493         tag_dst->len = tag_len;
00494         tag_dst->found = false;
00495     } else {
00496         _stop_tag = NULL;
00497     }
00498 }
00499 
00500 void ATHandler::set_stop_tag(const char *stop_tag_seq)
00501 {
00502     if (_last_err || !_stop_tag) {
00503         return;
00504     }
00505 
00506     set_tag(_stop_tag, stop_tag_seq);
00507 }
00508 
00509 void ATHandler::set_scope(ScopeType scope_type)
00510 {
00511     tr_debug("%s: %d", __func__, scope_type);
00512     if (_current_scope != scope_type) {
00513         _current_scope = scope_type;
00514         switch (_current_scope) {
00515         case RespType:
00516             _stop_tag = &_resp_stop;
00517             _stop_tag->found = false;
00518             break;
00519         case InfoType:
00520             _stop_tag = &_info_stop;
00521             _stop_tag->found = false;
00522             consume_char(' ');
00523             break;
00524         case ElemType:
00525             _stop_tag = &_elem_stop;
00526             _stop_tag->found = false;
00527             break;
00528         case NotSet:
00529             _stop_tag = NULL;
00530             return;
00531         default:
00532             break;
00533         }
00534     }
00535 }
00536 
00537 // should match from recv_pos?
00538 bool ATHandler::match(const char* str, size_t size)
00539 {
00540     tr_debug("%s: %s", __func__, str);
00541     rewind_buffer();
00542 
00543     if ((_recv_len - _recv_pos) < size) {
00544         return false;
00545     }
00546 
00547     if (str && memcmp(_recv_buff + _recv_pos, str, size) == 0) {
00548         // consume matching part
00549         _recv_pos += size;
00550         return true;
00551     }
00552     return false;
00553 }
00554 
00555 bool ATHandler::match_urc()
00556 {
00557     tr_debug("%s", __func__);
00558     rewind_buffer();
00559     size_t prefix_len = 0;
00560     for (struct oob_t *oob = _oobs; oob; oob = oob->next) {
00561         prefix_len = strlen(oob->prefix);
00562         if (_recv_len >= prefix_len) {
00563             if (match(oob->prefix, prefix_len)) {
00564                 tr_debug("URC! %s", oob->prefix);
00565                 set_scope(InfoType);
00566                 if (oob->cb) {
00567                     oob->cb();
00568                 }
00569                 information_response_stop();
00570                 return true;
00571             }
00572         }
00573     }
00574     return false;
00575 }
00576 
00577 bool ATHandler::match_error()
00578 {
00579     tr_debug("%s", __func__);
00580 
00581     if (match(CME_ERROR, CME_ERROR_LENGTH)) {
00582         at_error(true, DeviceErrorTypeErrorCME);
00583         return true;
00584     } else if (match(CMS_ERROR, CMS_ERROR_LENGTH)) {
00585         at_error(true, DeviceErrorTypeErrorCMS);
00586         return true;
00587     } else if (match(ERROR_, ERROR_LENGTH)) {
00588         at_error(false, DeviceErrorTypeNoError);
00589         return true;
00590     }
00591 
00592     return false;
00593 }
00594 
00595 void ATHandler::clear_error()
00596 {
00597     _last_err = NSAPI_ERROR_OK ;
00598     _last_at_err.errCode = 0;
00599     _last_at_err.errType = DeviceErrorTypeNoError;
00600     _last_3gpp_error = 0;
00601 }
00602 
00603 nsapi_error_t ATHandler::get_last_error() const
00604 {
00605     return _last_err;
00606 }
00607 
00608 device_err_t ATHandler::get_last_device_error() const
00609 {
00610     return _last_at_err;
00611 }
00612 
00613 void ATHandler::set_error(nsapi_error_t err)
00614 {
00615     if (_last_err == NSAPI_ERROR_OK ) {
00616         _last_err = err;
00617     }
00618 
00619     if (_last_err != err) {
00620         tr_warn("AT error code changed from %d to %d!", _last_err, err);
00621     }
00622 }
00623 
00624 int ATHandler::get_3gpp_error()
00625 {
00626     return _last_3gpp_error;
00627 }
00628 
00629 void ATHandler::set_3gpp_error(int err, DeviceErrorType error_type)
00630 {
00631     if (_last_3gpp_error) { // don't overwrite likely root cause error
00632         return;
00633     }
00634 
00635     if (error_type == DeviceErrorTypeErrorCMS && err < 128) {
00636         // CMS errors 0-127 maps straight to 3GPP errors
00637         _last_3gpp_error = err;
00638     } else {
00639         for (size_t i = 0; i<sizeof(map_3gpp_errors)/sizeof(map_3gpp_errors[0]); i++) {
00640             if (map_3gpp_errors[i][0] == err) {
00641                 _last_3gpp_error = map_3gpp_errors[i][1];
00642                 tr_debug("AT3GPP error code %d", get_3gpp_error());
00643                 break;
00644             }
00645         }
00646     }
00647 }
00648 
00649 void ATHandler::at_error(bool error_code_expected, DeviceErrorType error_type)
00650 {
00651     int32_t err = -1;
00652 
00653     if (error_code_expected && (error_type == DeviceErrorTypeErrorCMS || error_type == DeviceErrorTypeErrorCME)) {
00654         set_scope(InfoType);
00655         err = read_int();
00656 
00657         if (err != -1) {
00658             set_3gpp_error(err, error_type);
00659             _last_at_err.errCode = err;
00660             _last_at_err.errType = error_type;
00661             tr_debug("ATHandler ERROR: %d", err);
00662         } else {
00663             tr_debug("ATHandler ERROR reading failed");
00664         }
00665     }
00666 
00667     _last_err = NSAPI_ERROR_DEVICE_ERROR ;
00668 }
00669 
00670 void ATHandler::resp(const char *prefix, bool check_urc)
00671 {
00672     tr_debug("%s: %s", __func__, prefix);
00673 
00674     at_debug("\n----------resp buff:----------\n");
00675     for (size_t i = _recv_pos; i < _recv_len; i++) {
00676         at_debug("%c", _recv_buff[i]);
00677     }
00678     at_debug("\n----------buff----------\n");
00679 
00680     _prefix_matched = false;
00681     _urc_matched = false;
00682     _error_found = false;
00683 
00684     while (!get_last_error()) {
00685 
00686         match(CRLF, CRLF_LENGTH);
00687 
00688         if (match(OK, OK_LENGTH)) {
00689             set_scope(RespType);
00690             _stop_tag->found = true;
00691             return;
00692         }
00693 
00694         if (match_error()) {
00695             _error_found = true;
00696             return;
00697         }
00698 
00699         if (prefix && match(prefix, strlen(prefix))) {
00700             _prefix_matched = true;
00701             return;
00702         }
00703 
00704         if (check_urc && match_urc()) {
00705             _urc_matched = true;
00706         }
00707 
00708         // If no match found, look for CRLF and consume everything up to and including CRLF
00709         if (mem_str(_recv_buff, _recv_len, CRLF, CRLF_LENGTH)) {
00710             // If no prefix, return on CRLF - means data to read
00711             if (!prefix) {
00712                 return;
00713             }
00714             consume_to_tag(CRLF, true);
00715         } else {
00716             // If no prefix, no CRLF and no more chance to match for OK, ERROR or URC(since max resp length is already in buffer)
00717             // return so data could be read
00718             if (!prefix && ((_recv_len-_recv_pos) >= _max_resp_length)) {
00719                 return;
00720             }
00721             fill_buffer();
00722         }
00723     }
00724 
00725     return;
00726     // something went wrong so application need to recover and retry
00727 }
00728 
00729 void ATHandler::resp_start(const char *prefix, bool stop)
00730 {
00731     tr_debug("%s: %s", __func__, prefix);
00732 
00733     if (_last_err) {
00734         return;
00735     }
00736 
00737     // Try get as much data as possible
00738     rewind_buffer();
00739     fill_buffer();
00740 
00741     if (prefix) {
00742         if ((strlen(prefix) < sizeof(_info_resp_prefix))) {
00743             strcpy(_info_resp_prefix, prefix);
00744         } else {
00745             MBED_ASSERT(0);
00746         }
00747     }
00748 
00749     set_scope(RespType);
00750 
00751     resp(prefix, true);
00752 
00753     if (!stop && prefix && _prefix_matched) {
00754         set_scope(InfoType);
00755     }
00756 }
00757 
00758 // check urc because of error as urc
00759 bool ATHandler::info_resp()
00760 {
00761     tr_debug("%s", __func__);
00762     if (_last_err || _resp_stop.found) {
00763         return false;
00764     }
00765 
00766     if (_prefix_matched) {
00767         _prefix_matched = false;
00768        return true;
00769     }
00770 
00771     // If coming here after another info response was started(looping), stop the previous one.
00772     // Trying to handle stopping in this level instead of doing it in upper level.
00773     if (get_scope() == InfoType) {
00774         information_response_stop();
00775     }
00776 
00777     resp(_info_resp_prefix, false);
00778 
00779     if (_prefix_matched) {
00780        set_scope(InfoType);
00781        _prefix_matched = false;
00782        return true;
00783     }
00784 
00785     // On mismatch go to response scope
00786     set_scope(RespType);
00787     return false;
00788 }
00789 
00790 bool ATHandler::info_elem(char start_tag)
00791 {
00792     tr_debug("%s: %c", __func__, start_tag);
00793     if (_last_err) {
00794         return false;
00795     }
00796 
00797     // If coming here after another info response element was started(looping), stop the previous one.
00798     // Trying to handle stopping in this level instead of doing it in upper level.
00799     if (get_scope() == ElemType) {
00800         information_response_element_stop();
00801     }
00802 
00803     consume_char(_delimiter);
00804 
00805     if (consume_char(start_tag)) {
00806         _prefix_matched = true;
00807         set_scope(ElemType);
00808         return true;
00809     }
00810 
00811     // On mismatch go to information response scope
00812     set_scope(InfoType);
00813     return false;
00814 }
00815 
00816 bool ATHandler::consume_char(char ch)
00817 {
00818     tr_debug("%s: %c", __func__, ch);
00819     int read_char = get_char();
00820     // If we read something else than ch, recover it
00821     if (read_char != ch && read_char != -1) {
00822         _recv_pos--;
00823         return false;
00824     }
00825     return true;
00826 }
00827 
00828 bool ATHandler::consume_to_tag(const char *tag, bool consume_tag)
00829 {
00830     tr_debug("%s: %s", __func__, tag);
00831     size_t match_pos = 0;
00832 
00833     while (true) {
00834         int c = get_char();
00835         if (c == -1) {
00836             break;
00837         } else if (c == tag[match_pos]) {
00838             match_pos++;
00839             if (match_pos == strlen(tag)) {
00840                 if (!consume_tag) {
00841                     _recv_pos -= strlen(tag);
00842                 }
00843                 return true;
00844             }
00845         } else if (match_pos) {
00846             match_pos = 0;
00847         }
00848     }
00849     tr_debug("consume_to_tag not found");
00850     return false;
00851 }
00852 
00853 bool ATHandler::consume_to_stop_tag()
00854 {
00855     tr_debug("%s", __func__);
00856 
00857     if (!_stop_tag || (_stop_tag && _stop_tag->found) || _error_found) {
00858         return true;
00859     }
00860 
00861     if (consume_to_tag((const char*)_stop_tag->tag, true)) {
00862         return true;
00863     }
00864 
00865     tr_debug("consume_to_stop_tag not found");
00866     set_error(NSAPI_ERROR_DEVICE_ERROR );
00867     return false;
00868 }
00869 
00870 // consume by size needed?
00871 
00872 void ATHandler::resp_stop()
00873 {
00874     // Do not return on error so that we can consume whatever there is in the buffer
00875 
00876     tr_debug("%s", __func__);
00877 
00878     if (_current_scope == ElemType) {
00879         information_response_element_stop();
00880         set_scope(InfoType);
00881     }
00882 
00883     if (_current_scope == InfoType) {
00884         information_response_stop();
00885     }
00886 
00887     // Go for response stop_tag
00888     if (consume_to_stop_tag()) {
00889         set_scope(NotSet);
00890     }
00891 
00892     // Restore stop tag to OK
00893     set_tag(&_resp_stop, OK);
00894     // Reset info resp prefix
00895     memset(_info_resp_prefix, 0, sizeof(_info_resp_prefix));
00896 }
00897 
00898 void ATHandler::information_response_stop()
00899 {
00900     tr_debug("%s", __func__);
00901     if (consume_to_stop_tag()) {
00902         set_scope(RespType);
00903     }
00904 }
00905 
00906 void ATHandler::information_response_element_stop()
00907 {
00908     tr_debug("%s", __func__);
00909     if (consume_to_stop_tag()) {
00910         set_scope(InfoType);
00911     }
00912 }
00913 
00914 ATHandler::ScopeType ATHandler::get_scope()
00915 {
00916     return _current_scope;
00917 }
00918 
00919 void ATHandler::set_string(char *dest, const char *src, size_t src_len)
00920 {
00921     memcpy(dest, src, src_len);
00922     dest[src_len] = '\0';
00923 }
00924 
00925 const char* ATHandler::mem_str(const char* dest, size_t dest_len, const char* src, size_t src_len)
00926 {
00927     if (dest_len > src_len) {
00928         for(size_t i = 0; i < dest_len-src_len+1; ++i) {
00929             if(memcmp(dest+i, src, src_len) == 0) {
00930                 return dest+i;
00931             }
00932         }
00933     }
00934     return NULL;
00935 }
00936 
00937 void ATHandler::cmd_start(const char* cmd)
00938 {
00939     tr_debug("AT> %s", cmd);
00940 
00941     if (_last_err != NSAPI_ERROR_OK ) {
00942         return;
00943     }
00944 
00945     (void)write(cmd, strlen(cmd));
00946 
00947     _cmd_start = true;
00948 }
00949 
00950 void ATHandler::write_int(int32_t param)
00951 {
00952     tr_debug("write_int: %d", param);
00953     // do common checks before sending subparameter
00954     if (check_cmd_send() == false) {
00955         return;
00956     }
00957 
00958     // write the integer subparameter
00959     const int32_t str_len = 12;
00960     char number_string[str_len];
00961     int32_t result = sprintf(number_string, "%ld", param);
00962     if (result > 0 && result < str_len) {
00963         (void)write(number_string, strlen(number_string));
00964     }
00965 }
00966 
00967 void ATHandler::write_string(const char* param, bool useQuotations)
00968 {
00969     tr_debug("write_string: %s, %d", param, useQuotations);
00970     // do common checks before sending subparameter
00971     if (check_cmd_send() == false) {
00972         return;
00973     }
00974 
00975     // we are writing string, surround it with quotes
00976     if (useQuotations && write("\"", 1) != 1) {
00977         return;
00978     }
00979 
00980     (void)write(param, strlen(param));
00981 
00982     if (useQuotations) {
00983         // we are writing string, surround it with quotes
00984         (void)write("\"", 1);
00985     }
00986 }
00987 
00988 void ATHandler::cmd_stop()
00989 {
00990     if (_last_err != NSAPI_ERROR_OK ) {
00991         return;
00992     }
00993      // Finish with CR
00994     (void)write(_output_delimiter, _output_delimiter_length);
00995 }
00996 
00997 size_t ATHandler::write_bytes(const uint8_t *data, size_t len)
00998 {
00999     if (_last_err != NSAPI_ERROR_OK ) {
01000         return 0;
01001     }
01002 
01003     ssize_t write_len = write(data, len);
01004     return write_len < 0 ? 0 : (size_t)write_len;
01005 }
01006 
01007 ssize_t ATHandler::write(const void *data, size_t len)
01008 {
01009     pollfh fhs;
01010     fhs.fh = _fileHandle;
01011     fhs.events = POLLOUT;
01012     ssize_t write_len = -1;
01013 
01014     int count = poll(&fhs, 1, _at_timeout);
01015     if (count > 0 && (fhs.revents & POLLOUT)) {
01016         write_len = _fileHandle->write(data, len);
01017     }
01018 
01019     if (write_len < 0 || (size_t)write_len != len) {
01020         set_error(NSAPI_ERROR_DEVICE_ERROR );
01021     }
01022 
01023     return write_len;
01024 }
01025 
01026 // do common checks before sending subparameters
01027 bool ATHandler::check_cmd_send()
01028 {
01029     if (_last_err != NSAPI_ERROR_OK ) {
01030         return false;
01031     }
01032 
01033     // Don't write delimiter if this is the first subparameter
01034     if (_cmd_start) {
01035         _cmd_start = false;
01036     } else {
01037         if (write(&_delimiter, 1) != 1) {
01038             // writing of delimiter failed, return. write() already have set the _last_err
01039             return false;
01040         }
01041     }
01042 
01043     return true;
01044 }
01045 
01046 void ATHandler::flush()
01047 {
01048     while (_fileHandle->readable()) {
01049         reset_buffer();
01050         fill_buffer();
01051     }
01052     reset_buffer();
01053 }