Nicolas Borla / Mbed OS BBR_1Ebene
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ATHandler.cpp Source File

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