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