Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 14:23:23 by
