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 #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 }
Generated on Tue Jul 12 2022 15:17:16 by
1.7.2