BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
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 12:21:42 by
