Kev Mann / mbed-dev-OS5_10_4
Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /*
kevman 0:38ceb79fef03 2 * Copyright (c) 2017, Arm Limited and affiliates.
kevman 0:38ceb79fef03 3 * SPDX-License-Identifier: Apache-2.0
kevman 0:38ceb79fef03 4 *
kevman 0:38ceb79fef03 5 * Licensed under the Apache License, Version 2.0 (the "License");
kevman 0:38ceb79fef03 6 * you may not use this file except in compliance with the License.
kevman 0:38ceb79fef03 7 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 8 *
kevman 0:38ceb79fef03 9 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 10 *
kevman 0:38ceb79fef03 11 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 12 * distributed under the License is distributed on an "AS IS" BASIS,
kevman 0:38ceb79fef03 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 14 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 15 * limitations under the License.
kevman 0:38ceb79fef03 16 */
kevman 0:38ceb79fef03 17
kevman 0:38ceb79fef03 18 #include <ctype.h>
kevman 0:38ceb79fef03 19 #include <stdio.h>
kevman 0:38ceb79fef03 20 #include <limits.h>
kevman 0:38ceb79fef03 21 #include "ATHandler.h"
kevman 0:38ceb79fef03 22 #include "mbed_poll.h"
kevman 0:38ceb79fef03 23 #include "FileHandle.h"
kevman 0:38ceb79fef03 24 #include "mbed_wait_api.h"
kevman 0:38ceb79fef03 25 #include "mbed_debug.h"
kevman 0:38ceb79fef03 26 #include "rtos/Thread.h"
kevman 0:38ceb79fef03 27 #include "Kernel.h"
kevman 0:38ceb79fef03 28 #include "CellularUtil.h"
kevman 0:38ceb79fef03 29
kevman 0:38ceb79fef03 30 using namespace mbed;
kevman 0:38ceb79fef03 31 using namespace events;
kevman 0:38ceb79fef03 32 using namespace mbed_cellular_util;
kevman 0:38ceb79fef03 33
kevman 0:38ceb79fef03 34 #include "CellularLog.h"
kevman 0:38ceb79fef03 35
kevman 0:38ceb79fef03 36 // URCs should be handled fast, if you add debug traces within URC processing then you also need to increase this time
kevman 0:38ceb79fef03 37 #define PROCESS_URC_TIME 20
kevman 0:38ceb79fef03 38
kevman 0:38ceb79fef03 39 const char *mbed::OK = "OK\r\n";
kevman 0:38ceb79fef03 40 const uint8_t OK_LENGTH = 4;
kevman 0:38ceb79fef03 41 const char *mbed::CRLF = "\r\n";
kevman 0:38ceb79fef03 42 const uint8_t CRLF_LENGTH = 2;
kevman 0:38ceb79fef03 43 const char *CME_ERROR = "+CME ERROR:";
kevman 0:38ceb79fef03 44 const uint8_t CME_ERROR_LENGTH = 11;
kevman 0:38ceb79fef03 45 const char *CMS_ERROR = "+CMS ERROR:";
kevman 0:38ceb79fef03 46 const uint8_t CMS_ERROR_LENGTH = 11;
kevman 0:38ceb79fef03 47 const char *ERROR_ = "ERROR\r\n";
kevman 0:38ceb79fef03 48 const uint8_t ERROR_LENGTH = 7;
kevman 0:38ceb79fef03 49 const uint8_t MAX_RESP_LENGTH = CMS_ERROR_LENGTH;
kevman 0:38ceb79fef03 50 const char DEFAULT_DELIMITER = ',';
kevman 0:38ceb79fef03 51
kevman 0:38ceb79fef03 52 static const uint8_t map_3gpp_errors[][2] = {
kevman 0:38ceb79fef03 53 { 103, 3 }, { 106, 6 }, { 107, 7 }, { 108, 8 }, { 111, 11 }, { 112, 12 }, { 113, 13 }, { 114, 14 },
kevman 0:38ceb79fef03 54 { 115, 15 }, { 122, 22 }, { 125, 25 }, { 172, 95 }, { 173, 96 }, { 174, 97 }, { 175, 99 }, { 176, 111 },
kevman 0:38ceb79fef03 55 { 177, 8 }, { 126, 26 }, { 127, 27 }, { 128, 28 }, { 129, 29 }, { 130, 30 }, { 131, 31 }, { 132, 32 },
kevman 0:38ceb79fef03 56 { 133, 33 }, { 134, 34 }, { 140, 40 }, { 141, 41 }, { 142, 42 }, { 143, 43 }, { 144, 44 }, { 145, 45 },
kevman 0:38ceb79fef03 57 { 146, 46 }, { 178, 65 }, { 179, 66 }, { 180, 48 }, { 181, 83 }, { 171, 49 },
kevman 0:38ceb79fef03 58 };
kevman 0:38ceb79fef03 59
kevman 0:38ceb79fef03 60 ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) :
kevman 0:38ceb79fef03 61 _nextATHandler(0),
kevman 0:38ceb79fef03 62 _fileHandle(fh),
kevman 0:38ceb79fef03 63 _queue(queue),
kevman 0:38ceb79fef03 64 _last_err(NSAPI_ERROR_OK),
kevman 0:38ceb79fef03 65 _last_3gpp_error(0),
kevman 0:38ceb79fef03 66 _oob_string_max_length(0),
kevman 0:38ceb79fef03 67 _oobs(NULL),
kevman 0:38ceb79fef03 68 _at_timeout(timeout),
kevman 0:38ceb79fef03 69 _previous_at_timeout(timeout),
kevman 0:38ceb79fef03 70 _at_send_delay(send_delay),
kevman 0:38ceb79fef03 71 _last_response_stop(0),
kevman 0:38ceb79fef03 72 _fh_sigio_set(false),
kevman 0:38ceb79fef03 73 _processing(false),
kevman 0:38ceb79fef03 74 _ref_count(1),
kevman 0:38ceb79fef03 75 _is_fh_usable(true),
kevman 0:38ceb79fef03 76 _stop_tag(NULL),
kevman 0:38ceb79fef03 77 _delimiter(DEFAULT_DELIMITER),
kevman 0:38ceb79fef03 78 _prefix_matched(false),
kevman 0:38ceb79fef03 79 _urc_matched(false),
kevman 0:38ceb79fef03 80 _error_found(false),
kevman 0:38ceb79fef03 81 _max_resp_length(MAX_RESP_LENGTH),
kevman 0:38ceb79fef03 82 _debug_on(MBED_CONF_CELLULAR_DEBUG_AT),
kevman 0:38ceb79fef03 83 _cmd_start(false),
kevman 0:38ceb79fef03 84 _start_time(0)
kevman 0:38ceb79fef03 85 {
kevman 0:38ceb79fef03 86 clear_error();
kevman 0:38ceb79fef03 87
kevman 0:38ceb79fef03 88 if (output_delimiter) {
kevman 0:38ceb79fef03 89 _output_delimiter = new char[strlen(output_delimiter) + 1];
kevman 0:38ceb79fef03 90 if (!_output_delimiter) {
kevman 0:38ceb79fef03 91 MBED_ASSERT(0);
kevman 0:38ceb79fef03 92 } else {
kevman 0:38ceb79fef03 93 memcpy(_output_delimiter, output_delimiter, strlen(output_delimiter) + 1);
kevman 0:38ceb79fef03 94 }
kevman 0:38ceb79fef03 95 } else {
kevman 0:38ceb79fef03 96 _output_delimiter = NULL;
kevman 0:38ceb79fef03 97 }
kevman 0:38ceb79fef03 98
kevman 0:38ceb79fef03 99 reset_buffer();
kevman 0:38ceb79fef03 100 memset(_recv_buff, 0, sizeof(_recv_buff));
kevman 0:38ceb79fef03 101 memset(_info_resp_prefix, 0, sizeof(_info_resp_prefix));
kevman 0:38ceb79fef03 102
kevman 0:38ceb79fef03 103 _current_scope = NotSet;
kevman 0:38ceb79fef03 104 set_tag(&_resp_stop, OK);
kevman 0:38ceb79fef03 105 set_tag(&_info_stop, CRLF);
kevman 0:38ceb79fef03 106 set_tag(&_elem_stop, ")");
kevman 0:38ceb79fef03 107
kevman 0:38ceb79fef03 108 _fileHandle->set_blocking(false);
kevman 0:38ceb79fef03 109
kevman 0:38ceb79fef03 110 set_filehandle_sigio();
kevman 0:38ceb79fef03 111 }
kevman 0:38ceb79fef03 112
kevman 0:38ceb79fef03 113 void ATHandler::set_debug(bool debug_on)
kevman 0:38ceb79fef03 114 {
kevman 0:38ceb79fef03 115 _debug_on = debug_on;
kevman 0:38ceb79fef03 116 }
kevman 0:38ceb79fef03 117
kevman 0:38ceb79fef03 118 ATHandler::~ATHandler()
kevman 0:38ceb79fef03 119 {
kevman 0:38ceb79fef03 120 while (_oobs) {
kevman 0:38ceb79fef03 121 struct oob_t *oob = _oobs;
kevman 0:38ceb79fef03 122 _oobs = oob->next;
kevman 0:38ceb79fef03 123 delete oob;
kevman 0:38ceb79fef03 124 }
kevman 0:38ceb79fef03 125 if (_output_delimiter) {
kevman 0:38ceb79fef03 126 delete [] _output_delimiter;
kevman 0:38ceb79fef03 127 }
kevman 0:38ceb79fef03 128 }
kevman 0:38ceb79fef03 129
kevman 0:38ceb79fef03 130 void ATHandler::inc_ref_count()
kevman 0:38ceb79fef03 131 {
kevman 0:38ceb79fef03 132 _ref_count++;
kevman 0:38ceb79fef03 133 }
kevman 0:38ceb79fef03 134
kevman 0:38ceb79fef03 135 void ATHandler::dec_ref_count()
kevman 0:38ceb79fef03 136 {
kevman 0:38ceb79fef03 137 _ref_count--;
kevman 0:38ceb79fef03 138 }
kevman 0:38ceb79fef03 139
kevman 0:38ceb79fef03 140 int ATHandler::get_ref_count()
kevman 0:38ceb79fef03 141 {
kevman 0:38ceb79fef03 142 return _ref_count;
kevman 0:38ceb79fef03 143 }
kevman 0:38ceb79fef03 144
kevman 0:38ceb79fef03 145 FileHandle *ATHandler::get_file_handle()
kevman 0:38ceb79fef03 146 {
kevman 0:38ceb79fef03 147 return _fileHandle;
kevman 0:38ceb79fef03 148 }
kevman 0:38ceb79fef03 149
kevman 0:38ceb79fef03 150 void ATHandler::set_file_handle(FileHandle *fh)
kevman 0:38ceb79fef03 151 {
kevman 0:38ceb79fef03 152 _fileHandle = fh;
kevman 0:38ceb79fef03 153 }
kevman 0:38ceb79fef03 154
kevman 0:38ceb79fef03 155 void ATHandler::set_is_filehandle_usable(bool usable)
kevman 0:38ceb79fef03 156 {
kevman 0:38ceb79fef03 157 _is_fh_usable = usable;
kevman 0:38ceb79fef03 158 }
kevman 0:38ceb79fef03 159
kevman 0:38ceb79fef03 160 nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void()> callback)
kevman 0:38ceb79fef03 161 {
kevman 0:38ceb79fef03 162 if (find_urc_handler(prefix, &callback)) {
kevman 0:38ceb79fef03 163 tr_warn("URC already added with prefix: %s", prefix);
kevman 0:38ceb79fef03 164 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 165 }
kevman 0:38ceb79fef03 166
kevman 0:38ceb79fef03 167 struct oob_t *oob = new struct oob_t;
kevman 0:38ceb79fef03 168 if (!oob) {
kevman 0:38ceb79fef03 169 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 170 } else {
kevman 0:38ceb79fef03 171 size_t prefix_len = strlen(prefix);
kevman 0:38ceb79fef03 172 if (prefix_len > _oob_string_max_length) {
kevman 0:38ceb79fef03 173 _oob_string_max_length = prefix_len;
kevman 0:38ceb79fef03 174 if (_oob_string_max_length > _max_resp_length) {
kevman 0:38ceb79fef03 175 _max_resp_length = _oob_string_max_length;
kevman 0:38ceb79fef03 176 }
kevman 0:38ceb79fef03 177 }
kevman 0:38ceb79fef03 178
kevman 0:38ceb79fef03 179 oob->prefix = prefix;
kevman 0:38ceb79fef03 180 oob->prefix_len = prefix_len;
kevman 0:38ceb79fef03 181 oob->cb = callback;
kevman 0:38ceb79fef03 182 oob->next = _oobs;
kevman 0:38ceb79fef03 183 _oobs = oob;
kevman 0:38ceb79fef03 184 }
kevman 0:38ceb79fef03 185
kevman 0:38ceb79fef03 186 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 187 }
kevman 0:38ceb79fef03 188
kevman 0:38ceb79fef03 189 void ATHandler::remove_urc_handler(const char *prefix, mbed::Callback<void()> callback)
kevman 0:38ceb79fef03 190 {
kevman 0:38ceb79fef03 191 struct oob_t *current = _oobs;
kevman 0:38ceb79fef03 192 struct oob_t *prev = NULL;
kevman 0:38ceb79fef03 193 while (current) {
kevman 0:38ceb79fef03 194 if (strcmp(prefix, current->prefix) == 0 && current->cb == callback) {
kevman 0:38ceb79fef03 195 if (prev) {
kevman 0:38ceb79fef03 196 prev->next = current->next;
kevman 0:38ceb79fef03 197 } else {
kevman 0:38ceb79fef03 198 _oobs = current->next;
kevman 0:38ceb79fef03 199 }
kevman 0:38ceb79fef03 200 delete current;
kevman 0:38ceb79fef03 201 break;
kevman 0:38ceb79fef03 202 }
kevman 0:38ceb79fef03 203 prev = current;
kevman 0:38ceb79fef03 204 current = prev->next;
kevman 0:38ceb79fef03 205 }
kevman 0:38ceb79fef03 206 }
kevman 0:38ceb79fef03 207
kevman 0:38ceb79fef03 208 bool ATHandler::find_urc_handler(const char *prefix, mbed::Callback<void()> *callback)
kevman 0:38ceb79fef03 209 {
kevman 0:38ceb79fef03 210 struct oob_t *oob = _oobs;
kevman 0:38ceb79fef03 211 while (oob) {
kevman 0:38ceb79fef03 212 if (strcmp(prefix, oob->prefix) == 0 && oob->cb == *callback) {
kevman 0:38ceb79fef03 213 return true;
kevman 0:38ceb79fef03 214 }
kevman 0:38ceb79fef03 215 oob = oob->next;
kevman 0:38ceb79fef03 216 }
kevman 0:38ceb79fef03 217
kevman 0:38ceb79fef03 218 return false;
kevman 0:38ceb79fef03 219 }
kevman 0:38ceb79fef03 220
kevman 0:38ceb79fef03 221 void ATHandler::event()
kevman 0:38ceb79fef03 222 {
kevman 0:38ceb79fef03 223 // _processing must be set before filehandle write/read to avoid repetitive sigio events
kevman 0:38ceb79fef03 224 if (!_processing) {
kevman 0:38ceb79fef03 225 _processing = true;
kevman 0:38ceb79fef03 226 (void) _queue.call(Callback<void(void)>(this, &ATHandler::process_oob));
kevman 0:38ceb79fef03 227 }
kevman 0:38ceb79fef03 228 }
kevman 0:38ceb79fef03 229
kevman 0:38ceb79fef03 230 void ATHandler::lock()
kevman 0:38ceb79fef03 231 {
kevman 0:38ceb79fef03 232 #ifdef AT_HANDLER_MUTEX
kevman 0:38ceb79fef03 233 _fileHandleMutex.lock();
kevman 0:38ceb79fef03 234 #endif
kevman 0:38ceb79fef03 235 _processing = true;
kevman 0:38ceb79fef03 236 clear_error();
kevman 0:38ceb79fef03 237 _start_time = rtos::Kernel::get_ms_count();
kevman 0:38ceb79fef03 238 }
kevman 0:38ceb79fef03 239
kevman 0:38ceb79fef03 240 void ATHandler::unlock()
kevman 0:38ceb79fef03 241 {
kevman 0:38ceb79fef03 242 _processing = false;
kevman 0:38ceb79fef03 243 #ifdef AT_HANDLER_MUTEX
kevman 0:38ceb79fef03 244 _fileHandleMutex.unlock();
kevman 0:38ceb79fef03 245 #endif
kevman 0:38ceb79fef03 246 if (_fileHandle->readable() || (_recv_pos < _recv_len)) {
kevman 0:38ceb79fef03 247 (void) _queue.call(Callback<void(void)>(this, &ATHandler::process_oob));
kevman 0:38ceb79fef03 248 }
kevman 0:38ceb79fef03 249 }
kevman 0:38ceb79fef03 250
kevman 0:38ceb79fef03 251 nsapi_error_t ATHandler::unlock_return_error()
kevman 0:38ceb79fef03 252 {
kevman 0:38ceb79fef03 253 nsapi_error_t err = _last_err;
kevman 0:38ceb79fef03 254 unlock();
kevman 0:38ceb79fef03 255 return err;
kevman 0:38ceb79fef03 256 }
kevman 0:38ceb79fef03 257
kevman 0:38ceb79fef03 258 void ATHandler::set_at_timeout(uint32_t timeout_milliseconds, bool default_timeout)
kevman 0:38ceb79fef03 259 {
kevman 0:38ceb79fef03 260 if (default_timeout) {
kevman 0:38ceb79fef03 261 _previous_at_timeout = timeout_milliseconds;
kevman 0:38ceb79fef03 262 _at_timeout = timeout_milliseconds;
kevman 0:38ceb79fef03 263 } else if (timeout_milliseconds != _at_timeout) {
kevman 0:38ceb79fef03 264 _previous_at_timeout = _at_timeout;
kevman 0:38ceb79fef03 265 _at_timeout = timeout_milliseconds;
kevman 0:38ceb79fef03 266 }
kevman 0:38ceb79fef03 267 }
kevman 0:38ceb79fef03 268
kevman 0:38ceb79fef03 269 void ATHandler::restore_at_timeout()
kevman 0:38ceb79fef03 270 {
kevman 0:38ceb79fef03 271 if (_previous_at_timeout != _at_timeout) {
kevman 0:38ceb79fef03 272 _at_timeout = _previous_at_timeout;
kevman 0:38ceb79fef03 273 }
kevman 0:38ceb79fef03 274 }
kevman 0:38ceb79fef03 275
kevman 0:38ceb79fef03 276 void ATHandler::process_oob()
kevman 0:38ceb79fef03 277 {
kevman 0:38ceb79fef03 278 if (!_is_fh_usable) {
kevman 0:38ceb79fef03 279 tr_debug("process_oob, filehandle is not usable, return...");
kevman 0:38ceb79fef03 280 return;
kevman 0:38ceb79fef03 281 }
kevman 0:38ceb79fef03 282 lock();
kevman 0:38ceb79fef03 283 tr_debug("process_oob readable=%d, pos=%u, len=%u", _fileHandle->readable(), _recv_pos, _recv_len);
kevman 0:38ceb79fef03 284 if (_fileHandle->readable() || (_recv_pos < _recv_len)) {
kevman 0:38ceb79fef03 285 _current_scope = NotSet;
kevman 0:38ceb79fef03 286 uint32_t timeout = _at_timeout;
kevman 0:38ceb79fef03 287 _at_timeout = PROCESS_URC_TIME;
kevman 0:38ceb79fef03 288 while (true) {
kevman 0:38ceb79fef03 289 if (match_urc()) {
kevman 0:38ceb79fef03 290 if (!(_fileHandle->readable() || (_recv_pos < _recv_len))) {
kevman 0:38ceb79fef03 291 break; // we have nothing to read anymore
kevman 0:38ceb79fef03 292 }
kevman 0:38ceb79fef03 293 } else if (mem_str(_recv_buff, _recv_len, CRLF, CRLF_LENGTH)) { // If no match found, look for CRLF and consume everything up to CRLF
kevman 0:38ceb79fef03 294 consume_to_tag(CRLF, true);
kevman 0:38ceb79fef03 295 } else {
kevman 0:38ceb79fef03 296 if (!fill_buffer()) {
kevman 0:38ceb79fef03 297 reset_buffer(); // consume anything that could not be handled
kevman 0:38ceb79fef03 298 break;
kevman 0:38ceb79fef03 299 }
kevman 0:38ceb79fef03 300 _start_time = rtos::Kernel::get_ms_count();
kevman 0:38ceb79fef03 301 }
kevman 0:38ceb79fef03 302 }
kevman 0:38ceb79fef03 303 _at_timeout = timeout;
kevman 0:38ceb79fef03 304 }
kevman 0:38ceb79fef03 305 tr_debug("process_oob exit");
kevman 0:38ceb79fef03 306 unlock();
kevman 0:38ceb79fef03 307 }
kevman 0:38ceb79fef03 308
kevman 0:38ceb79fef03 309 void ATHandler::set_filehandle_sigio()
kevman 0:38ceb79fef03 310 {
kevman 0:38ceb79fef03 311 if (_fh_sigio_set) {
kevman 0:38ceb79fef03 312 return;
kevman 0:38ceb79fef03 313 }
kevman 0:38ceb79fef03 314 _fileHandle->sigio(mbed::Callback<void()>(this, &ATHandler::event));
kevman 0:38ceb79fef03 315 _fh_sigio_set = true;
kevman 0:38ceb79fef03 316 }
kevman 0:38ceb79fef03 317
kevman 0:38ceb79fef03 318 void ATHandler::reset_buffer()
kevman 0:38ceb79fef03 319 {
kevman 0:38ceb79fef03 320 _recv_pos = 0;
kevman 0:38ceb79fef03 321 _recv_len = 0;
kevman 0:38ceb79fef03 322 }
kevman 0:38ceb79fef03 323
kevman 0:38ceb79fef03 324 void ATHandler::rewind_buffer()
kevman 0:38ceb79fef03 325 {
kevman 0:38ceb79fef03 326 if (_recv_pos > 0 && _recv_len >= _recv_pos) {
kevman 0:38ceb79fef03 327 _recv_len -= _recv_pos;
kevman 0:38ceb79fef03 328 // move what is not read to beginning of buffer
kevman 0:38ceb79fef03 329 memmove(_recv_buff, _recv_buff + _recv_pos, _recv_len);
kevman 0:38ceb79fef03 330 _recv_pos = 0;
kevman 0:38ceb79fef03 331 }
kevman 0:38ceb79fef03 332 }
kevman 0:38ceb79fef03 333
kevman 0:38ceb79fef03 334 int ATHandler::poll_timeout(bool wait_for_timeout)
kevman 0:38ceb79fef03 335 {
kevman 0:38ceb79fef03 336 int timeout;
kevman 0:38ceb79fef03 337 if (wait_for_timeout) {
kevman 0:38ceb79fef03 338 uint64_t now = rtos::Kernel::get_ms_count();
kevman 0:38ceb79fef03 339 if (now >= _start_time + _at_timeout) {
kevman 0:38ceb79fef03 340 timeout = 0;
kevman 0:38ceb79fef03 341 } else if (_start_time + _at_timeout - now > INT_MAX) {
kevman 0:38ceb79fef03 342 timeout = INT_MAX;
kevman 0:38ceb79fef03 343 } else {
kevman 0:38ceb79fef03 344 timeout = _start_time + _at_timeout - now;
kevman 0:38ceb79fef03 345 }
kevman 0:38ceb79fef03 346 } else {
kevman 0:38ceb79fef03 347 timeout = 0;
kevman 0:38ceb79fef03 348 }
kevman 0:38ceb79fef03 349 return timeout;
kevman 0:38ceb79fef03 350 }
kevman 0:38ceb79fef03 351
kevman 0:38ceb79fef03 352 bool ATHandler::fill_buffer(bool wait_for_timeout)
kevman 0:38ceb79fef03 353 {
kevman 0:38ceb79fef03 354 // Reset buffer when full
kevman 0:38ceb79fef03 355 if (sizeof(_recv_buff) == _recv_len) {
kevman 0:38ceb79fef03 356 tr_error("AT overflow");
kevman 0:38ceb79fef03 357 reset_buffer();
kevman 0:38ceb79fef03 358 }
kevman 0:38ceb79fef03 359
kevman 0:38ceb79fef03 360 pollfh fhs;
kevman 0:38ceb79fef03 361 fhs.fh = _fileHandle;
kevman 0:38ceb79fef03 362 fhs.events = POLLIN;
kevman 0:38ceb79fef03 363 int count = poll(&fhs, 1, poll_timeout(wait_for_timeout));
kevman 0:38ceb79fef03 364 if (count > 0 && (fhs.revents & POLLIN)) {
kevman 0:38ceb79fef03 365 ssize_t len = _fileHandle->read(_recv_buff + _recv_len, sizeof(_recv_buff) - _recv_len);
kevman 0:38ceb79fef03 366 if (len > 0) {
kevman 0:38ceb79fef03 367 debug_print(_recv_buff + _recv_len, len);
kevman 0:38ceb79fef03 368 _recv_len += len;
kevman 0:38ceb79fef03 369 return true;
kevman 0:38ceb79fef03 370 }
kevman 0:38ceb79fef03 371 }
kevman 0:38ceb79fef03 372
kevman 0:38ceb79fef03 373 return false;
kevman 0:38ceb79fef03 374 }
kevman 0:38ceb79fef03 375
kevman 0:38ceb79fef03 376 int ATHandler::get_char()
kevman 0:38ceb79fef03 377 {
kevman 0:38ceb79fef03 378 if (_recv_pos == _recv_len) {
kevman 0:38ceb79fef03 379 reset_buffer(); // try to read as much as possible
kevman 0:38ceb79fef03 380 if (!fill_buffer()) {
kevman 0:38ceb79fef03 381 tr_warn("AT timeout");
kevman 0:38ceb79fef03 382 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 383 return -1; // timeout to read
kevman 0:38ceb79fef03 384 }
kevman 0:38ceb79fef03 385 }
kevman 0:38ceb79fef03 386
kevman 0:38ceb79fef03 387 return _recv_buff[_recv_pos++];
kevman 0:38ceb79fef03 388 }
kevman 0:38ceb79fef03 389
kevman 0:38ceb79fef03 390 void ATHandler::skip_param(uint32_t count)
kevman 0:38ceb79fef03 391 {
kevman 0:38ceb79fef03 392 if (_last_err || !_stop_tag || _stop_tag->found) {
kevman 0:38ceb79fef03 393 return;
kevman 0:38ceb79fef03 394 }
kevman 0:38ceb79fef03 395
kevman 0:38ceb79fef03 396 for (uint32_t i = 0; (i < count && !_stop_tag->found); i++) {
kevman 0:38ceb79fef03 397 size_t match_pos = 0;
kevman 0:38ceb79fef03 398 while (true) {
kevman 0:38ceb79fef03 399 int c = get_char();
kevman 0:38ceb79fef03 400 if (c == -1) {
kevman 0:38ceb79fef03 401 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 402 return;
kevman 0:38ceb79fef03 403 } else if (c == _delimiter) {
kevman 0:38ceb79fef03 404 break;
kevman 0:38ceb79fef03 405 } else if (_stop_tag->len && c == _stop_tag->tag[match_pos]) {
kevman 0:38ceb79fef03 406 match_pos++;
kevman 0:38ceb79fef03 407 if (match_pos == _stop_tag->len) {
kevman 0:38ceb79fef03 408 _stop_tag->found = true;
kevman 0:38ceb79fef03 409 break;
kevman 0:38ceb79fef03 410 }
kevman 0:38ceb79fef03 411 } else if (match_pos) {
kevman 0:38ceb79fef03 412 match_pos = 0;
kevman 0:38ceb79fef03 413 }
kevman 0:38ceb79fef03 414 }
kevman 0:38ceb79fef03 415 }
kevman 0:38ceb79fef03 416 return;
kevman 0:38ceb79fef03 417 }
kevman 0:38ceb79fef03 418
kevman 0:38ceb79fef03 419 void ATHandler::skip_param(ssize_t len, uint32_t count)
kevman 0:38ceb79fef03 420 {
kevman 0:38ceb79fef03 421 if (_last_err || !_stop_tag || _stop_tag->found) {
kevman 0:38ceb79fef03 422 return;
kevman 0:38ceb79fef03 423 }
kevman 0:38ceb79fef03 424
kevman 0:38ceb79fef03 425 for (uint32_t i = 0; i < count; i++) {
kevman 0:38ceb79fef03 426 ssize_t read_len = 0;
kevman 0:38ceb79fef03 427 while (read_len < len) {
kevman 0:38ceb79fef03 428 int c = get_char();
kevman 0:38ceb79fef03 429 if (c == -1) {
kevman 0:38ceb79fef03 430 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 431 return;
kevman 0:38ceb79fef03 432 }
kevman 0:38ceb79fef03 433 read_len++;
kevman 0:38ceb79fef03 434 }
kevman 0:38ceb79fef03 435 }
kevman 0:38ceb79fef03 436 return;
kevman 0:38ceb79fef03 437 }
kevman 0:38ceb79fef03 438
kevman 0:38ceb79fef03 439 ssize_t ATHandler::read_bytes(uint8_t *buf, size_t len)
kevman 0:38ceb79fef03 440 {
kevman 0:38ceb79fef03 441 if (_last_err) {
kevman 0:38ceb79fef03 442 return -1;
kevman 0:38ceb79fef03 443 }
kevman 0:38ceb79fef03 444
kevman 0:38ceb79fef03 445 size_t read_len = 0;
kevman 0:38ceb79fef03 446 for (; read_len < len; read_len++) {
kevman 0:38ceb79fef03 447 int c = get_char();
kevman 0:38ceb79fef03 448 if (c == -1) {
kevman 0:38ceb79fef03 449 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 450 return -1;
kevman 0:38ceb79fef03 451 }
kevman 0:38ceb79fef03 452 buf[read_len] = c;
kevman 0:38ceb79fef03 453 }
kevman 0:38ceb79fef03 454 return read_len;
kevman 0:38ceb79fef03 455 }
kevman 0:38ceb79fef03 456
kevman 0:38ceb79fef03 457 ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag)
kevman 0:38ceb79fef03 458 {
kevman 0:38ceb79fef03 459 if (_last_err || !_stop_tag || (_stop_tag->found && read_even_stop_tag == false)) {
kevman 0:38ceb79fef03 460 return -1;
kevman 0:38ceb79fef03 461 }
kevman 0:38ceb79fef03 462
kevman 0:38ceb79fef03 463 consume_char('\"');
kevman 0:38ceb79fef03 464
kevman 0:38ceb79fef03 465 if (_last_err) {
kevman 0:38ceb79fef03 466 return -1;
kevman 0:38ceb79fef03 467 }
kevman 0:38ceb79fef03 468
kevman 0:38ceb79fef03 469 size_t len = 0;
kevman 0:38ceb79fef03 470 size_t match_pos = 0;
kevman 0:38ceb79fef03 471
kevman 0:38ceb79fef03 472 for (; len < (size - 1 + match_pos); len++) {
kevman 0:38ceb79fef03 473 int c = get_char();
kevman 0:38ceb79fef03 474 if (c == -1) {
kevman 0:38ceb79fef03 475 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 476 return -1;
kevman 0:38ceb79fef03 477 } else if (c == _delimiter) {
kevman 0:38ceb79fef03 478 buf[len] = '\0';
kevman 0:38ceb79fef03 479 break;
kevman 0:38ceb79fef03 480 } else if (c == '\"') {
kevman 0:38ceb79fef03 481 match_pos = 0;
kevman 0:38ceb79fef03 482 len--;
kevman 0:38ceb79fef03 483 continue;
kevman 0:38ceb79fef03 484 } else if (_stop_tag->len && c == _stop_tag->tag[match_pos]) {
kevman 0:38ceb79fef03 485 match_pos++;
kevman 0:38ceb79fef03 486 if (match_pos == _stop_tag->len) {
kevman 0:38ceb79fef03 487 _stop_tag->found = true;
kevman 0:38ceb79fef03 488 // remove tag from string if it was matched
kevman 0:38ceb79fef03 489 len -= (_stop_tag->len - 1);
kevman 0:38ceb79fef03 490 buf[len] = '\0';
kevman 0:38ceb79fef03 491 break;
kevman 0:38ceb79fef03 492 }
kevman 0:38ceb79fef03 493 } else if (match_pos) {
kevman 0:38ceb79fef03 494 match_pos = 0;
kevman 0:38ceb79fef03 495 }
kevman 0:38ceb79fef03 496
kevman 0:38ceb79fef03 497 buf[len] = c;
kevman 0:38ceb79fef03 498 }
kevman 0:38ceb79fef03 499
kevman 0:38ceb79fef03 500 if (len && (len == size - 1 + match_pos)) {
kevman 0:38ceb79fef03 501 buf[len] = '\0';
kevman 0:38ceb79fef03 502 }
kevman 0:38ceb79fef03 503
kevman 0:38ceb79fef03 504 return len;
kevman 0:38ceb79fef03 505 }
kevman 0:38ceb79fef03 506
kevman 0:38ceb79fef03 507 ssize_t ATHandler::read_hex_string(char *buf, size_t size)
kevman 0:38ceb79fef03 508 {
kevman 0:38ceb79fef03 509 if (_last_err || !_stop_tag || _stop_tag->found) {
kevman 0:38ceb79fef03 510 return -1;
kevman 0:38ceb79fef03 511 }
kevman 0:38ceb79fef03 512
kevman 0:38ceb79fef03 513 size_t match_pos = 0;
kevman 0:38ceb79fef03 514
kevman 0:38ceb79fef03 515 consume_char('\"');
kevman 0:38ceb79fef03 516
kevman 0:38ceb79fef03 517 if (_last_err) {
kevman 0:38ceb79fef03 518 return -1;
kevman 0:38ceb79fef03 519 }
kevman 0:38ceb79fef03 520
kevman 0:38ceb79fef03 521 size_t read_idx = 0;
kevman 0:38ceb79fef03 522 size_t buf_idx = 0;
kevman 0:38ceb79fef03 523 char hexbuf[2];
kevman 0:38ceb79fef03 524
kevman 0:38ceb79fef03 525 for (; read_idx < size * 2 + match_pos; read_idx++) {
kevman 0:38ceb79fef03 526 int c = get_char();
kevman 0:38ceb79fef03 527
kevman 0:38ceb79fef03 528 if (match_pos) {
kevman 0:38ceb79fef03 529 buf_idx++;
kevman 0:38ceb79fef03 530 } else {
kevman 0:38ceb79fef03 531 buf_idx = read_idx / 2;
kevman 0:38ceb79fef03 532 }
kevman 0:38ceb79fef03 533
kevman 0:38ceb79fef03 534 if (c == -1) {
kevman 0:38ceb79fef03 535 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 536 return -1;
kevman 0:38ceb79fef03 537 }
kevman 0:38ceb79fef03 538 if (c == _delimiter) {
kevman 0:38ceb79fef03 539 break;
kevman 0:38ceb79fef03 540 } else if (c == '\"') {
kevman 0:38ceb79fef03 541 match_pos = 0;
kevman 0:38ceb79fef03 542 read_idx--;
kevman 0:38ceb79fef03 543 continue;
kevman 0:38ceb79fef03 544 } else if (_stop_tag->len && c == _stop_tag->tag[match_pos]) {
kevman 0:38ceb79fef03 545 match_pos++;
kevman 0:38ceb79fef03 546 if (match_pos == _stop_tag->len) {
kevman 0:38ceb79fef03 547 _stop_tag->found = true;
kevman 0:38ceb79fef03 548 // remove tag from string if it was matched
kevman 0:38ceb79fef03 549 buf_idx -= (_stop_tag->len - 1);
kevman 0:38ceb79fef03 550 break;
kevman 0:38ceb79fef03 551 }
kevman 0:38ceb79fef03 552 } else if (match_pos) {
kevman 0:38ceb79fef03 553 match_pos = 0;
kevman 0:38ceb79fef03 554 }
kevman 0:38ceb79fef03 555
kevman 0:38ceb79fef03 556 if (match_pos) {
kevman 0:38ceb79fef03 557 buf[buf_idx] = c;
kevman 0:38ceb79fef03 558 } else {
kevman 0:38ceb79fef03 559 hexbuf[read_idx % 2] = c;
kevman 0:38ceb79fef03 560 if (read_idx % 2 == 1) {
kevman 0:38ceb79fef03 561 hex_str_to_char_str(hexbuf, 2, buf + buf_idx);
kevman 0:38ceb79fef03 562 }
kevman 0:38ceb79fef03 563 }
kevman 0:38ceb79fef03 564 }
kevman 0:38ceb79fef03 565
kevman 0:38ceb79fef03 566 if (read_idx && (read_idx == size * 2 + match_pos)) {
kevman 0:38ceb79fef03 567 buf_idx++;
kevman 0:38ceb79fef03 568 }
kevman 0:38ceb79fef03 569
kevman 0:38ceb79fef03 570 return buf_idx;
kevman 0:38ceb79fef03 571 }
kevman 0:38ceb79fef03 572
kevman 0:38ceb79fef03 573 int32_t ATHandler::read_int()
kevman 0:38ceb79fef03 574 {
kevman 0:38ceb79fef03 575 if (_last_err || !_stop_tag || _stop_tag->found) {
kevman 0:38ceb79fef03 576 return -1;
kevman 0:38ceb79fef03 577 }
kevman 0:38ceb79fef03 578
kevman 0:38ceb79fef03 579 char buff[BUFF_SIZE];
kevman 0:38ceb79fef03 580 char *first_no_digit;
kevman 0:38ceb79fef03 581
kevman 0:38ceb79fef03 582 if (read_string(buff, (size_t)sizeof(buff)) == 0) {
kevman 0:38ceb79fef03 583 return -1;
kevman 0:38ceb79fef03 584 }
kevman 0:38ceb79fef03 585
kevman 0:38ceb79fef03 586 return std::strtol(buff, &first_no_digit, 10);
kevman 0:38ceb79fef03 587 }
kevman 0:38ceb79fef03 588
kevman 0:38ceb79fef03 589 void ATHandler::set_delimiter(char delimiter)
kevman 0:38ceb79fef03 590 {
kevman 0:38ceb79fef03 591 _delimiter = delimiter;
kevman 0:38ceb79fef03 592 }
kevman 0:38ceb79fef03 593
kevman 0:38ceb79fef03 594 void ATHandler::set_default_delimiter()
kevman 0:38ceb79fef03 595 {
kevman 0:38ceb79fef03 596 _delimiter = DEFAULT_DELIMITER;
kevman 0:38ceb79fef03 597 }
kevman 0:38ceb79fef03 598
kevman 0:38ceb79fef03 599 void ATHandler::set_tag(tag_t *tag_dst, const char *tag_seq)
kevman 0:38ceb79fef03 600 {
kevman 0:38ceb79fef03 601 if (tag_seq) {
kevman 0:38ceb79fef03 602 size_t tag_len = strlen(tag_seq);
kevman 0:38ceb79fef03 603 set_string(tag_dst->tag, tag_seq, tag_len);
kevman 0:38ceb79fef03 604 tag_dst->len = tag_len;
kevman 0:38ceb79fef03 605 tag_dst->found = false;
kevman 0:38ceb79fef03 606 } else {
kevman 0:38ceb79fef03 607 _stop_tag = NULL;
kevman 0:38ceb79fef03 608 }
kevman 0:38ceb79fef03 609 }
kevman 0:38ceb79fef03 610
kevman 0:38ceb79fef03 611 void ATHandler::set_stop_tag(const char *stop_tag_seq)
kevman 0:38ceb79fef03 612 {
kevman 0:38ceb79fef03 613 if (_last_err || !_stop_tag) {
kevman 0:38ceb79fef03 614 return;
kevman 0:38ceb79fef03 615 }
kevman 0:38ceb79fef03 616
kevman 0:38ceb79fef03 617 set_tag(_stop_tag, stop_tag_seq);
kevman 0:38ceb79fef03 618 }
kevman 0:38ceb79fef03 619
kevman 0:38ceb79fef03 620 void ATHandler::set_scope(ScopeType scope_type)
kevman 0:38ceb79fef03 621 {
kevman 0:38ceb79fef03 622 if (_current_scope != scope_type) {
kevman 0:38ceb79fef03 623 _current_scope = scope_type;
kevman 0:38ceb79fef03 624 switch (_current_scope) {
kevman 0:38ceb79fef03 625 case RespType:
kevman 0:38ceb79fef03 626 _stop_tag = &_resp_stop;
kevman 0:38ceb79fef03 627 _stop_tag->found = false;
kevman 0:38ceb79fef03 628 break;
kevman 0:38ceb79fef03 629 case InfoType:
kevman 0:38ceb79fef03 630 _stop_tag = &_info_stop;
kevman 0:38ceb79fef03 631 _stop_tag->found = false;
kevman 0:38ceb79fef03 632 consume_char(' ');
kevman 0:38ceb79fef03 633 break;
kevman 0:38ceb79fef03 634 case ElemType:
kevman 0:38ceb79fef03 635 _stop_tag = &_elem_stop;
kevman 0:38ceb79fef03 636 _stop_tag->found = false;
kevman 0:38ceb79fef03 637 break;
kevman 0:38ceb79fef03 638 case NotSet:
kevman 0:38ceb79fef03 639 _stop_tag = NULL;
kevman 0:38ceb79fef03 640 return;
kevman 0:38ceb79fef03 641 default:
kevman 0:38ceb79fef03 642 break;
kevman 0:38ceb79fef03 643 }
kevman 0:38ceb79fef03 644 }
kevman 0:38ceb79fef03 645 }
kevman 0:38ceb79fef03 646
kevman 0:38ceb79fef03 647 // should match from recv_pos?
kevman 0:38ceb79fef03 648 bool ATHandler::match(const char *str, size_t size)
kevman 0:38ceb79fef03 649 {
kevman 0:38ceb79fef03 650 rewind_buffer();
kevman 0:38ceb79fef03 651
kevman 0:38ceb79fef03 652 if ((_recv_len - _recv_pos) < size) {
kevman 0:38ceb79fef03 653 return false;
kevman 0:38ceb79fef03 654 }
kevman 0:38ceb79fef03 655
kevman 0:38ceb79fef03 656 if (str && memcmp(_recv_buff + _recv_pos, str, size) == 0) {
kevman 0:38ceb79fef03 657 // consume matching part
kevman 0:38ceb79fef03 658 _recv_pos += size;
kevman 0:38ceb79fef03 659 return true;
kevman 0:38ceb79fef03 660 }
kevman 0:38ceb79fef03 661 return false;
kevman 0:38ceb79fef03 662 }
kevman 0:38ceb79fef03 663
kevman 0:38ceb79fef03 664 bool ATHandler::match_urc()
kevman 0:38ceb79fef03 665 {
kevman 0:38ceb79fef03 666 rewind_buffer();
kevman 0:38ceb79fef03 667 size_t prefix_len = 0;
kevman 0:38ceb79fef03 668 for (struct oob_t *oob = _oobs; oob; oob = oob->next) {
kevman 0:38ceb79fef03 669 prefix_len = oob->prefix_len;
kevman 0:38ceb79fef03 670 if (_recv_len >= prefix_len) {
kevman 0:38ceb79fef03 671 if (match(oob->prefix, prefix_len)) {
kevman 0:38ceb79fef03 672 set_scope(InfoType);
kevman 0:38ceb79fef03 673 if (oob->cb) {
kevman 0:38ceb79fef03 674 oob->cb();
kevman 0:38ceb79fef03 675 }
kevman 0:38ceb79fef03 676 information_response_stop();
kevman 0:38ceb79fef03 677 return true;
kevman 0:38ceb79fef03 678 }
kevman 0:38ceb79fef03 679 }
kevman 0:38ceb79fef03 680 }
kevman 0:38ceb79fef03 681 return false;
kevman 0:38ceb79fef03 682 }
kevman 0:38ceb79fef03 683
kevman 0:38ceb79fef03 684 bool ATHandler::match_error()
kevman 0:38ceb79fef03 685 {
kevman 0:38ceb79fef03 686 if (match(CME_ERROR, CME_ERROR_LENGTH)) {
kevman 0:38ceb79fef03 687 at_error(true, DeviceErrorTypeErrorCME);
kevman 0:38ceb79fef03 688 return true;
kevman 0:38ceb79fef03 689 } else if (match(CMS_ERROR, CMS_ERROR_LENGTH)) {
kevman 0:38ceb79fef03 690 at_error(true, DeviceErrorTypeErrorCMS);
kevman 0:38ceb79fef03 691 return true;
kevman 0:38ceb79fef03 692 } else if (match(ERROR_, ERROR_LENGTH)) {
kevman 0:38ceb79fef03 693 at_error(false, DeviceErrorTypeNoError);
kevman 0:38ceb79fef03 694 return true;
kevman 0:38ceb79fef03 695 }
kevman 0:38ceb79fef03 696
kevman 0:38ceb79fef03 697 return false;
kevman 0:38ceb79fef03 698 }
kevman 0:38ceb79fef03 699
kevman 0:38ceb79fef03 700 void ATHandler::clear_error()
kevman 0:38ceb79fef03 701 {
kevman 0:38ceb79fef03 702 _last_err = NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 703 _last_at_err.errCode = 0;
kevman 0:38ceb79fef03 704 _last_at_err.errType = DeviceErrorTypeNoError;
kevman 0:38ceb79fef03 705 _last_3gpp_error = 0;
kevman 0:38ceb79fef03 706 }
kevman 0:38ceb79fef03 707
kevman 0:38ceb79fef03 708 nsapi_error_t ATHandler::get_last_error() const
kevman 0:38ceb79fef03 709 {
kevman 0:38ceb79fef03 710 return _last_err;
kevman 0:38ceb79fef03 711 }
kevman 0:38ceb79fef03 712
kevman 0:38ceb79fef03 713 device_err_t ATHandler::get_last_device_error() const
kevman 0:38ceb79fef03 714 {
kevman 0:38ceb79fef03 715 return _last_at_err;
kevman 0:38ceb79fef03 716 }
kevman 0:38ceb79fef03 717
kevman 0:38ceb79fef03 718 void ATHandler::set_error(nsapi_error_t err)
kevman 0:38ceb79fef03 719 {
kevman 0:38ceb79fef03 720 if (_last_err == NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 721 _last_err = err;
kevman 0:38ceb79fef03 722 }
kevman 0:38ceb79fef03 723
kevman 0:38ceb79fef03 724 if (_last_err != err) {
kevman 0:38ceb79fef03 725 tr_warn("AT error code changed from %d to %d!", _last_err, err);
kevman 0:38ceb79fef03 726 }
kevman 0:38ceb79fef03 727 }
kevman 0:38ceb79fef03 728
kevman 0:38ceb79fef03 729 int ATHandler::get_3gpp_error()
kevman 0:38ceb79fef03 730 {
kevman 0:38ceb79fef03 731 return _last_3gpp_error;
kevman 0:38ceb79fef03 732 }
kevman 0:38ceb79fef03 733
kevman 0:38ceb79fef03 734 void ATHandler::set_3gpp_error(int err, DeviceErrorType error_type)
kevman 0:38ceb79fef03 735 {
kevman 0:38ceb79fef03 736 if (_last_3gpp_error) { // don't overwrite likely root cause error
kevman 0:38ceb79fef03 737 return;
kevman 0:38ceb79fef03 738 }
kevman 0:38ceb79fef03 739
kevman 0:38ceb79fef03 740 if (error_type == DeviceErrorTypeErrorCMS && err < 128) {
kevman 0:38ceb79fef03 741 // CMS errors 0-127 maps straight to 3GPP errors
kevman 0:38ceb79fef03 742 _last_3gpp_error = err;
kevman 0:38ceb79fef03 743 } else {
kevman 0:38ceb79fef03 744 for (size_t i = 0; i < sizeof(map_3gpp_errors) / sizeof(map_3gpp_errors[0]); i++) {
kevman 0:38ceb79fef03 745 if (map_3gpp_errors[i][0] == err) {
kevman 0:38ceb79fef03 746 _last_3gpp_error = map_3gpp_errors[i][1];
kevman 0:38ceb79fef03 747 tr_debug("AT3GPP error code %d", get_3gpp_error());
kevman 0:38ceb79fef03 748 break;
kevman 0:38ceb79fef03 749 }
kevman 0:38ceb79fef03 750 }
kevman 0:38ceb79fef03 751 }
kevman 0:38ceb79fef03 752 }
kevman 0:38ceb79fef03 753
kevman 0:38ceb79fef03 754 void ATHandler::at_error(bool error_code_expected, DeviceErrorType error_type)
kevman 0:38ceb79fef03 755 {
kevman 0:38ceb79fef03 756 if (error_code_expected && (error_type == DeviceErrorTypeErrorCMS || error_type == DeviceErrorTypeErrorCME)) {
kevman 0:38ceb79fef03 757 set_scope(InfoType);
kevman 0:38ceb79fef03 758 int32_t err = read_int();
kevman 0:38ceb79fef03 759
kevman 0:38ceb79fef03 760 if (err != -1) {
kevman 0:38ceb79fef03 761 set_3gpp_error(err, error_type);
kevman 0:38ceb79fef03 762 _last_at_err.errCode = err;
kevman 0:38ceb79fef03 763 _last_at_err.errType = error_type;
kevman 0:38ceb79fef03 764 tr_error("AT error code %ld", err);
kevman 0:38ceb79fef03 765 } else {
kevman 0:38ceb79fef03 766 tr_warn("ATHandler ERROR reading failed");
kevman 0:38ceb79fef03 767 }
kevman 0:38ceb79fef03 768 }
kevman 0:38ceb79fef03 769
kevman 0:38ceb79fef03 770 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 771 }
kevman 0:38ceb79fef03 772
kevman 0:38ceb79fef03 773 void ATHandler::resp(const char *prefix, bool check_urc)
kevman 0:38ceb79fef03 774 {
kevman 0:38ceb79fef03 775 _prefix_matched = false;
kevman 0:38ceb79fef03 776 _urc_matched = false;
kevman 0:38ceb79fef03 777 _error_found = false;
kevman 0:38ceb79fef03 778
kevman 0:38ceb79fef03 779 while (!get_last_error()) {
kevman 0:38ceb79fef03 780
kevman 0:38ceb79fef03 781 match(CRLF, CRLF_LENGTH);
kevman 0:38ceb79fef03 782
kevman 0:38ceb79fef03 783 if (match(OK, OK_LENGTH)) {
kevman 0:38ceb79fef03 784 set_scope(RespType);
kevman 0:38ceb79fef03 785 _stop_tag->found = true;
kevman 0:38ceb79fef03 786 return;
kevman 0:38ceb79fef03 787 }
kevman 0:38ceb79fef03 788
kevman 0:38ceb79fef03 789 if (match_error()) {
kevman 0:38ceb79fef03 790 _error_found = true;
kevman 0:38ceb79fef03 791 return;
kevman 0:38ceb79fef03 792 }
kevman 0:38ceb79fef03 793
kevman 0:38ceb79fef03 794 if (prefix && match(prefix, strlen(prefix))) {
kevman 0:38ceb79fef03 795 _prefix_matched = true;
kevman 0:38ceb79fef03 796 return;
kevman 0:38ceb79fef03 797 }
kevman 0:38ceb79fef03 798
kevman 0:38ceb79fef03 799 if (check_urc && match_urc()) {
kevman 0:38ceb79fef03 800 _urc_matched = true;
kevman 0:38ceb79fef03 801 }
kevman 0:38ceb79fef03 802
kevman 0:38ceb79fef03 803 // If no match found, look for CRLF and consume everything up to and including CRLF
kevman 0:38ceb79fef03 804 if (mem_str(_recv_buff, _recv_len, CRLF, CRLF_LENGTH)) {
kevman 0:38ceb79fef03 805 // If no prefix, return on CRLF - means data to read
kevman 0:38ceb79fef03 806 if (!prefix) {
kevman 0:38ceb79fef03 807 return;
kevman 0:38ceb79fef03 808 }
kevman 0:38ceb79fef03 809 consume_to_tag(CRLF, true);
kevman 0:38ceb79fef03 810 } else {
kevman 0:38ceb79fef03 811 // If no prefix, no CRLF and no more chance to match for OK, ERROR or URC(since max resp length is already in buffer)
kevman 0:38ceb79fef03 812 // return so data could be read
kevman 0:38ceb79fef03 813 if (!prefix && ((_recv_len - _recv_pos) >= _max_resp_length)) {
kevman 0:38ceb79fef03 814 return;
kevman 0:38ceb79fef03 815 }
kevman 0:38ceb79fef03 816 if (!fill_buffer()) {
kevman 0:38ceb79fef03 817 // if we don't get any match and no data within timeout, set an error to indicate need for recovery
kevman 0:38ceb79fef03 818 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 819 }
kevman 0:38ceb79fef03 820 }
kevman 0:38ceb79fef03 821 }
kevman 0:38ceb79fef03 822
kevman 0:38ceb79fef03 823 return;
kevman 0:38ceb79fef03 824 // something went wrong so application need to recover and retry
kevman 0:38ceb79fef03 825 }
kevman 0:38ceb79fef03 826
kevman 0:38ceb79fef03 827 void ATHandler::resp_start(const char *prefix, bool stop)
kevman 0:38ceb79fef03 828 {
kevman 0:38ceb79fef03 829 if (_last_err) {
kevman 0:38ceb79fef03 830 return;
kevman 0:38ceb79fef03 831 }
kevman 0:38ceb79fef03 832
kevman 0:38ceb79fef03 833 // Try get as much data as possible
kevman 0:38ceb79fef03 834 rewind_buffer();
kevman 0:38ceb79fef03 835 (void)fill_buffer(false);
kevman 0:38ceb79fef03 836
kevman 0:38ceb79fef03 837 if (prefix) {
kevman 0:38ceb79fef03 838 MBED_ASSERT(strlen(prefix) < BUFF_SIZE);
kevman 0:38ceb79fef03 839 strcpy(_info_resp_prefix, prefix); // copy prefix so we can later use it without having to provide again for info_resp
kevman 0:38ceb79fef03 840 }
kevman 0:38ceb79fef03 841
kevman 0:38ceb79fef03 842 set_scope(RespType);
kevman 0:38ceb79fef03 843
kevman 0:38ceb79fef03 844 resp(prefix, true);
kevman 0:38ceb79fef03 845
kevman 0:38ceb79fef03 846 if (!stop && prefix && _prefix_matched) {
kevman 0:38ceb79fef03 847 set_scope(InfoType);
kevman 0:38ceb79fef03 848 }
kevman 0:38ceb79fef03 849 }
kevman 0:38ceb79fef03 850
kevman 0:38ceb79fef03 851 // check urc because of error as urc
kevman 0:38ceb79fef03 852 bool ATHandler::info_resp()
kevman 0:38ceb79fef03 853 {
kevman 0:38ceb79fef03 854 if (_last_err || _resp_stop.found) {
kevman 0:38ceb79fef03 855 return false;
kevman 0:38ceb79fef03 856 }
kevman 0:38ceb79fef03 857
kevman 0:38ceb79fef03 858 if (_prefix_matched) {
kevman 0:38ceb79fef03 859 _prefix_matched = false;
kevman 0:38ceb79fef03 860 return true;
kevman 0:38ceb79fef03 861 }
kevman 0:38ceb79fef03 862
kevman 0:38ceb79fef03 863 // If coming here after another info response was started(looping), stop the previous one.
kevman 0:38ceb79fef03 864 // Trying to handle stopping in this level instead of doing it in upper level.
kevman 0:38ceb79fef03 865 if (get_scope() == InfoType) {
kevman 0:38ceb79fef03 866 information_response_stop();
kevman 0:38ceb79fef03 867 }
kevman 0:38ceb79fef03 868
kevman 0:38ceb79fef03 869 resp(_info_resp_prefix, false);
kevman 0:38ceb79fef03 870
kevman 0:38ceb79fef03 871 if (_prefix_matched) {
kevman 0:38ceb79fef03 872 set_scope(InfoType);
kevman 0:38ceb79fef03 873 _prefix_matched = false;
kevman 0:38ceb79fef03 874 return true;
kevman 0:38ceb79fef03 875 }
kevman 0:38ceb79fef03 876
kevman 0:38ceb79fef03 877 // On mismatch go to response scope
kevman 0:38ceb79fef03 878 set_scope(RespType);
kevman 0:38ceb79fef03 879 return false;
kevman 0:38ceb79fef03 880 }
kevman 0:38ceb79fef03 881
kevman 0:38ceb79fef03 882 bool ATHandler::info_elem(char start_tag)
kevman 0:38ceb79fef03 883 {
kevman 0:38ceb79fef03 884 if (_last_err) {
kevman 0:38ceb79fef03 885 return false;
kevman 0:38ceb79fef03 886 }
kevman 0:38ceb79fef03 887
kevman 0:38ceb79fef03 888 // If coming here after another info response element was started(looping), stop the previous one.
kevman 0:38ceb79fef03 889 // Trying to handle stopping in this level instead of doing it in upper level.
kevman 0:38ceb79fef03 890 if (get_scope() == ElemType) {
kevman 0:38ceb79fef03 891 information_response_element_stop();
kevman 0:38ceb79fef03 892 }
kevman 0:38ceb79fef03 893
kevman 0:38ceb79fef03 894 consume_char(_delimiter);
kevman 0:38ceb79fef03 895
kevman 0:38ceb79fef03 896 if (consume_char(start_tag)) {
kevman 0:38ceb79fef03 897 _prefix_matched = true;
kevman 0:38ceb79fef03 898 set_scope(ElemType);
kevman 0:38ceb79fef03 899 return true;
kevman 0:38ceb79fef03 900 }
kevman 0:38ceb79fef03 901
kevman 0:38ceb79fef03 902 // On mismatch go to information response scope
kevman 0:38ceb79fef03 903 set_scope(InfoType);
kevman 0:38ceb79fef03 904 return false;
kevman 0:38ceb79fef03 905 }
kevman 0:38ceb79fef03 906
kevman 0:38ceb79fef03 907 bool ATHandler::consume_char(char ch)
kevman 0:38ceb79fef03 908 {
kevman 0:38ceb79fef03 909 int read_char = get_char();
kevman 0:38ceb79fef03 910 if (read_char == -1) {
kevman 0:38ceb79fef03 911 return false;
kevman 0:38ceb79fef03 912 }
kevman 0:38ceb79fef03 913 // If we read something else than ch, recover it
kevman 0:38ceb79fef03 914 if (read_char != ch) {
kevman 0:38ceb79fef03 915 _recv_pos--;
kevman 0:38ceb79fef03 916 return false;
kevman 0:38ceb79fef03 917 }
kevman 0:38ceb79fef03 918 return true;
kevman 0:38ceb79fef03 919 }
kevman 0:38ceb79fef03 920
kevman 0:38ceb79fef03 921 bool ATHandler::consume_to_tag(const char *tag, bool consume_tag)
kevman 0:38ceb79fef03 922 {
kevman 0:38ceb79fef03 923 size_t match_pos = 0;
kevman 0:38ceb79fef03 924
kevman 0:38ceb79fef03 925 while (true) {
kevman 0:38ceb79fef03 926 int c = get_char();
kevman 0:38ceb79fef03 927 if (c == -1) {
kevman 0:38ceb79fef03 928 break;
kevman 0:38ceb79fef03 929 // compares c against tag at current position and if this match fails
kevman 0:38ceb79fef03 930 // compares c against tag[0] and also resets match_pos to 0
kevman 0:38ceb79fef03 931 } else if (c == tag[match_pos] || ((match_pos = 1) && (c == tag[--match_pos]))) {
kevman 0:38ceb79fef03 932 match_pos++;
kevman 0:38ceb79fef03 933 if (match_pos == strlen(tag)) {
kevman 0:38ceb79fef03 934 if (!consume_tag) {
kevman 0:38ceb79fef03 935 _recv_pos -= strlen(tag);
kevman 0:38ceb79fef03 936 }
kevman 0:38ceb79fef03 937 return true;
kevman 0:38ceb79fef03 938 }
kevman 0:38ceb79fef03 939 }
kevman 0:38ceb79fef03 940 }
kevman 0:38ceb79fef03 941 tr_debug("consume_to_tag not found");
kevman 0:38ceb79fef03 942 return false;
kevman 0:38ceb79fef03 943 }
kevman 0:38ceb79fef03 944
kevman 0:38ceb79fef03 945 bool ATHandler::consume_to_stop_tag()
kevman 0:38ceb79fef03 946 {
kevman 0:38ceb79fef03 947 if (!_stop_tag || (_stop_tag && _stop_tag->found) || _error_found) {
kevman 0:38ceb79fef03 948 return true;
kevman 0:38ceb79fef03 949 }
kevman 0:38ceb79fef03 950
kevman 0:38ceb79fef03 951 if (consume_to_tag((const char *)_stop_tag->tag, true)) {
kevman 0:38ceb79fef03 952 return true;
kevman 0:38ceb79fef03 953 }
kevman 0:38ceb79fef03 954
kevman 0:38ceb79fef03 955 tr_warn("AT stop tag not found");
kevman 0:38ceb79fef03 956 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 957 return false;
kevman 0:38ceb79fef03 958 }
kevman 0:38ceb79fef03 959
kevman 0:38ceb79fef03 960 // consume by size needed?
kevman 0:38ceb79fef03 961
kevman 0:38ceb79fef03 962 void ATHandler::resp_stop()
kevman 0:38ceb79fef03 963 {
kevman 0:38ceb79fef03 964 // Do not return on error so that we can consume whatever there is in the buffer
kevman 0:38ceb79fef03 965
kevman 0:38ceb79fef03 966 if (_current_scope == ElemType) {
kevman 0:38ceb79fef03 967 information_response_element_stop();
kevman 0:38ceb79fef03 968 set_scope(InfoType);
kevman 0:38ceb79fef03 969 }
kevman 0:38ceb79fef03 970
kevman 0:38ceb79fef03 971 if (_current_scope == InfoType) {
kevman 0:38ceb79fef03 972 information_response_stop();
kevman 0:38ceb79fef03 973 }
kevman 0:38ceb79fef03 974
kevman 0:38ceb79fef03 975 // Go for response stop_tag
kevman 0:38ceb79fef03 976 if (consume_to_stop_tag()) {
kevman 0:38ceb79fef03 977 set_scope(NotSet);
kevman 0:38ceb79fef03 978 }
kevman 0:38ceb79fef03 979
kevman 0:38ceb79fef03 980 // Restore stop tag to OK
kevman 0:38ceb79fef03 981 set_tag(&_resp_stop, OK);
kevman 0:38ceb79fef03 982 // Reset info resp prefix
kevman 0:38ceb79fef03 983 memset(_info_resp_prefix, 0, sizeof(_info_resp_prefix));
kevman 0:38ceb79fef03 984
kevman 0:38ceb79fef03 985 _last_response_stop = rtos::Kernel::get_ms_count();
kevman 0:38ceb79fef03 986 }
kevman 0:38ceb79fef03 987
kevman 0:38ceb79fef03 988 void ATHandler::information_response_stop()
kevman 0:38ceb79fef03 989 {
kevman 0:38ceb79fef03 990 if (consume_to_stop_tag()) {
kevman 0:38ceb79fef03 991 set_scope(RespType);
kevman 0:38ceb79fef03 992 }
kevman 0:38ceb79fef03 993 }
kevman 0:38ceb79fef03 994
kevman 0:38ceb79fef03 995 void ATHandler::information_response_element_stop()
kevman 0:38ceb79fef03 996 {
kevman 0:38ceb79fef03 997 if (consume_to_stop_tag()) {
kevman 0:38ceb79fef03 998 set_scope(InfoType);
kevman 0:38ceb79fef03 999 }
kevman 0:38ceb79fef03 1000 }
kevman 0:38ceb79fef03 1001
kevman 0:38ceb79fef03 1002 ATHandler::ScopeType ATHandler::get_scope()
kevman 0:38ceb79fef03 1003 {
kevman 0:38ceb79fef03 1004 return _current_scope;
kevman 0:38ceb79fef03 1005 }
kevman 0:38ceb79fef03 1006
kevman 0:38ceb79fef03 1007 void ATHandler::set_string(char *dest, const char *src, size_t src_len)
kevman 0:38ceb79fef03 1008 {
kevman 0:38ceb79fef03 1009 memcpy(dest, src, src_len);
kevman 0:38ceb79fef03 1010 dest[src_len] = '\0';
kevman 0:38ceb79fef03 1011 }
kevman 0:38ceb79fef03 1012
kevman 0:38ceb79fef03 1013 const char *ATHandler::mem_str(const char *dest, size_t dest_len, const char *src, size_t src_len)
kevman 0:38ceb79fef03 1014 {
kevman 0:38ceb79fef03 1015 if (dest_len > src_len) {
kevman 0:38ceb79fef03 1016 for (size_t i = 0; i < dest_len - src_len + 1; ++i) {
kevman 0:38ceb79fef03 1017 if (memcmp(dest + i, src, src_len) == 0) {
kevman 0:38ceb79fef03 1018 return dest + i;
kevman 0:38ceb79fef03 1019 }
kevman 0:38ceb79fef03 1020 }
kevman 0:38ceb79fef03 1021 }
kevman 0:38ceb79fef03 1022 return NULL;
kevman 0:38ceb79fef03 1023 }
kevman 0:38ceb79fef03 1024
kevman 0:38ceb79fef03 1025 void ATHandler::cmd_start(const char *cmd)
kevman 0:38ceb79fef03 1026 {
kevman 0:38ceb79fef03 1027
kevman 0:38ceb79fef03 1028 if (_at_send_delay) {
kevman 0:38ceb79fef03 1029 rtos::Thread::wait_until(_last_response_stop + _at_send_delay);
kevman 0:38ceb79fef03 1030 }
kevman 0:38ceb79fef03 1031
kevman 0:38ceb79fef03 1032 if (_last_err != NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 1033 return;
kevman 0:38ceb79fef03 1034 }
kevman 0:38ceb79fef03 1035
kevman 0:38ceb79fef03 1036 (void)write(cmd, strlen(cmd));
kevman 0:38ceb79fef03 1037
kevman 0:38ceb79fef03 1038 _cmd_start = true;
kevman 0:38ceb79fef03 1039 }
kevman 0:38ceb79fef03 1040
kevman 0:38ceb79fef03 1041 void ATHandler::write_int(int32_t param)
kevman 0:38ceb79fef03 1042 {
kevman 0:38ceb79fef03 1043 // do common checks before sending subparameter
kevman 0:38ceb79fef03 1044 if (check_cmd_send() == false) {
kevman 0:38ceb79fef03 1045 return;
kevman 0:38ceb79fef03 1046 }
kevman 0:38ceb79fef03 1047
kevman 0:38ceb79fef03 1048 // write the integer subparameter
kevman 0:38ceb79fef03 1049 const int32_t str_len = 12;
kevman 0:38ceb79fef03 1050 char number_string[str_len];
kevman 0:38ceb79fef03 1051 int32_t result = sprintf(number_string, "%ld", param);
kevman 0:38ceb79fef03 1052 if (result > 0 && result < str_len) {
kevman 0:38ceb79fef03 1053 (void)write(number_string, strlen(number_string));
kevman 0:38ceb79fef03 1054 }
kevman 0:38ceb79fef03 1055 }
kevman 0:38ceb79fef03 1056
kevman 0:38ceb79fef03 1057 void ATHandler::write_string(const char *param, bool useQuotations)
kevman 0:38ceb79fef03 1058 {
kevman 0:38ceb79fef03 1059 // do common checks before sending subparameter
kevman 0:38ceb79fef03 1060 if (check_cmd_send() == false) {
kevman 0:38ceb79fef03 1061 return;
kevman 0:38ceb79fef03 1062 }
kevman 0:38ceb79fef03 1063
kevman 0:38ceb79fef03 1064 // we are writing string, surround it with quotes
kevman 0:38ceb79fef03 1065 if (useQuotations && write("\"", 1) != 1) {
kevman 0:38ceb79fef03 1066 return;
kevman 0:38ceb79fef03 1067 }
kevman 0:38ceb79fef03 1068
kevman 0:38ceb79fef03 1069 (void)write(param, strlen(param));
kevman 0:38ceb79fef03 1070
kevman 0:38ceb79fef03 1071 if (useQuotations) {
kevman 0:38ceb79fef03 1072 // we are writing string, surround it with quotes
kevman 0:38ceb79fef03 1073 (void)write("\"", 1);
kevman 0:38ceb79fef03 1074 }
kevman 0:38ceb79fef03 1075 }
kevman 0:38ceb79fef03 1076
kevman 0:38ceb79fef03 1077 void ATHandler::cmd_stop()
kevman 0:38ceb79fef03 1078 {
kevman 0:38ceb79fef03 1079 if (_last_err != NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 1080 return;
kevman 0:38ceb79fef03 1081 }
kevman 0:38ceb79fef03 1082 // Finish with CR
kevman 0:38ceb79fef03 1083 (void)write(_output_delimiter, strlen(_output_delimiter));
kevman 0:38ceb79fef03 1084 }
kevman 0:38ceb79fef03 1085
kevman 0:38ceb79fef03 1086 size_t ATHandler::write_bytes(const uint8_t *data, size_t len)
kevman 0:38ceb79fef03 1087 {
kevman 0:38ceb79fef03 1088 if (_last_err != NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 1089 return 0;
kevman 0:38ceb79fef03 1090 }
kevman 0:38ceb79fef03 1091
kevman 0:38ceb79fef03 1092 return write(data, len);
kevman 0:38ceb79fef03 1093 }
kevman 0:38ceb79fef03 1094
kevman 0:38ceb79fef03 1095 size_t ATHandler::write(const void *data, size_t len)
kevman 0:38ceb79fef03 1096 {
kevman 0:38ceb79fef03 1097 pollfh fhs;
kevman 0:38ceb79fef03 1098 fhs.fh = _fileHandle;
kevman 0:38ceb79fef03 1099 fhs.events = POLLOUT;
kevman 0:38ceb79fef03 1100 size_t write_len = 0;
kevman 0:38ceb79fef03 1101 for (; write_len < len;) {
kevman 0:38ceb79fef03 1102 int count = poll(&fhs, 1, poll_timeout());
kevman 0:38ceb79fef03 1103 if (count <= 0 || !(fhs.revents & POLLOUT)) {
kevman 0:38ceb79fef03 1104 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 1105 return 0;
kevman 0:38ceb79fef03 1106 }
kevman 0:38ceb79fef03 1107 ssize_t ret = _fileHandle->write((uint8_t *)data + write_len, len - write_len);
kevman 0:38ceb79fef03 1108 if (ret < 0) {
kevman 0:38ceb79fef03 1109 set_error(NSAPI_ERROR_DEVICE_ERROR);
kevman 0:38ceb79fef03 1110 return 0;
kevman 0:38ceb79fef03 1111 }
kevman 0:38ceb79fef03 1112 debug_print((char *)data + write_len, ret);
kevman 0:38ceb79fef03 1113 write_len += (size_t)ret;
kevman 0:38ceb79fef03 1114 }
kevman 0:38ceb79fef03 1115
kevman 0:38ceb79fef03 1116 return write_len;
kevman 0:38ceb79fef03 1117 }
kevman 0:38ceb79fef03 1118
kevman 0:38ceb79fef03 1119 // do common checks before sending subparameters
kevman 0:38ceb79fef03 1120 bool ATHandler::check_cmd_send()
kevman 0:38ceb79fef03 1121 {
kevman 0:38ceb79fef03 1122 if (_last_err != NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 1123 return false;
kevman 0:38ceb79fef03 1124 }
kevman 0:38ceb79fef03 1125
kevman 0:38ceb79fef03 1126 // Don't write delimiter if this is the first subparameter
kevman 0:38ceb79fef03 1127 if (_cmd_start) {
kevman 0:38ceb79fef03 1128 _cmd_start = false;
kevman 0:38ceb79fef03 1129 } else {
kevman 0:38ceb79fef03 1130 if (write(&_delimiter, 1) != 1) {
kevman 0:38ceb79fef03 1131 // writing of delimiter failed, return. write() already have set the _last_err
kevman 0:38ceb79fef03 1132 return false;
kevman 0:38ceb79fef03 1133 }
kevman 0:38ceb79fef03 1134 }
kevman 0:38ceb79fef03 1135
kevman 0:38ceb79fef03 1136 return true;
kevman 0:38ceb79fef03 1137 }
kevman 0:38ceb79fef03 1138
kevman 0:38ceb79fef03 1139 void ATHandler::flush()
kevman 0:38ceb79fef03 1140 {
kevman 0:38ceb79fef03 1141 reset_buffer();
kevman 0:38ceb79fef03 1142 while (fill_buffer(false)) {
kevman 0:38ceb79fef03 1143 reset_buffer();
kevman 0:38ceb79fef03 1144 }
kevman 0:38ceb79fef03 1145 }
kevman 0:38ceb79fef03 1146
kevman 0:38ceb79fef03 1147 void ATHandler::debug_print(char *p, int len)
kevman 0:38ceb79fef03 1148 {
kevman 0:38ceb79fef03 1149 #if MBED_CONF_CELLULAR_DEBUG_AT
kevman 0:38ceb79fef03 1150 if (_debug_on) {
kevman 0:38ceb79fef03 1151 #if MBED_CONF_MBED_TRACE_ENABLE
kevman 0:38ceb79fef03 1152 mbed_cellular_trace::mutex_wait();
kevman 0:38ceb79fef03 1153 #endif
kevman 0:38ceb79fef03 1154 for (ssize_t i = 0; i < len; i++) {
kevman 0:38ceb79fef03 1155 char c = *p++;
kevman 0:38ceb79fef03 1156 if (!isprint(c)) {
kevman 0:38ceb79fef03 1157 if (c == '\r') {
kevman 0:38ceb79fef03 1158 debug("\n");
kevman 0:38ceb79fef03 1159 } else if (c == '\n') {
kevman 0:38ceb79fef03 1160 } else {
kevman 0:38ceb79fef03 1161 debug("[%d]", c);
kevman 0:38ceb79fef03 1162 }
kevman 0:38ceb79fef03 1163 } else {
kevman 0:38ceb79fef03 1164 debug("%c", c);
kevman 0:38ceb79fef03 1165 }
kevman 0:38ceb79fef03 1166 }
kevman 0:38ceb79fef03 1167 #if MBED_CONF_MBED_TRACE_ENABLE
kevman 0:38ceb79fef03 1168 mbed_cellular_trace::mutex_release();
kevman 0:38ceb79fef03 1169 #endif
kevman 0:38ceb79fef03 1170 }
kevman 0:38ceb79fef03 1171 #endif // MBED_CONF_CELLULAR_DEBUG_AT
kevman 0:38ceb79fef03 1172 }