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