Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
features/cellular/framework/AT/ATHandler.h@1:9db0e321a9f4, 2019-12-31 (annotated)
- Committer:
- kenjiArai
- Date:
- Tue Dec 31 06:02:27 2019 +0000
- Revision:
- 1:9db0e321a9f4
- Parent:
- 0:5b88d5760320
updated based on mbed-os5.15.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kenjiArai | 0:5b88d5760320 | 1 | /* |
kenjiArai | 0:5b88d5760320 | 2 | * Copyright (c) 2017, Arm Limited and affiliates. |
kenjiArai | 0:5b88d5760320 | 3 | * SPDX-License-Identifier: Apache-2.0 |
kenjiArai | 0:5b88d5760320 | 4 | * |
kenjiArai | 0:5b88d5760320 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
kenjiArai | 0:5b88d5760320 | 6 | * you may not use this file except in compliance with the License. |
kenjiArai | 0:5b88d5760320 | 7 | * You may obtain a copy of the License at |
kenjiArai | 0:5b88d5760320 | 8 | * |
kenjiArai | 0:5b88d5760320 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
kenjiArai | 0:5b88d5760320 | 10 | * |
kenjiArai | 0:5b88d5760320 | 11 | * Unless required by applicable law or agreed to in writing, software |
kenjiArai | 0:5b88d5760320 | 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
kenjiArai | 0:5b88d5760320 | 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
kenjiArai | 0:5b88d5760320 | 14 | * See the License for the specific language governing permissions and |
kenjiArai | 0:5b88d5760320 | 15 | * limitations under the License. |
kenjiArai | 0:5b88d5760320 | 16 | */ |
kenjiArai | 0:5b88d5760320 | 17 | |
kenjiArai | 0:5b88d5760320 | 18 | #ifndef AT_HANDLER_H_ |
kenjiArai | 0:5b88d5760320 | 19 | #define AT_HANDLER_H_ |
kenjiArai | 0:5b88d5760320 | 20 | |
kenjiArai | 0:5b88d5760320 | 21 | #include "platform/mbed_retarget.h" |
kenjiArai | 0:5b88d5760320 | 22 | |
kenjiArai | 0:5b88d5760320 | 23 | #include "events/EventQueue.h" |
kenjiArai | 0:5b88d5760320 | 24 | #include "nsapi_types.h" |
kenjiArai | 0:5b88d5760320 | 25 | |
kenjiArai | 0:5b88d5760320 | 26 | #include "Callback.h" |
kenjiArai | 0:5b88d5760320 | 27 | |
kenjiArai | 0:5b88d5760320 | 28 | #include <cstdarg> |
kenjiArai | 0:5b88d5760320 | 29 | |
kenjiArai | 1:9db0e321a9f4 | 30 | #include "UARTSerial.h" |
kenjiArai | 0:5b88d5760320 | 31 | |
kenjiArai | 0:5b88d5760320 | 32 | /** |
kenjiArai | 0:5b88d5760320 | 33 | * If application calls associated FileHandle only from single thread context |
kenjiArai | 0:5b88d5760320 | 34 | * then locking between AT command and response is not needed. However, |
kenjiArai | 0:5b88d5760320 | 35 | * note that many cellular functions are called indirectly, for example with the socket API. |
kenjiArai | 0:5b88d5760320 | 36 | * If you are unsure, then AT_HANDLER_MUTEX must be defined. |
kenjiArai | 0:5b88d5760320 | 37 | */ |
kenjiArai | 0:5b88d5760320 | 38 | #define AT_HANDLER_MUTEX |
kenjiArai | 0:5b88d5760320 | 39 | |
kenjiArai | 1:9db0e321a9f4 | 40 | #if defined AT_HANDLER_MUTEX && defined MBED_CONF_RTOS_PRESENT |
kenjiArai | 1:9db0e321a9f4 | 41 | #include "ConditionVariable.h" |
kenjiArai | 1:9db0e321a9f4 | 42 | #endif |
kenjiArai | 1:9db0e321a9f4 | 43 | |
kenjiArai | 1:9db0e321a9f4 | 44 | namespace mbed { |
kenjiArai | 1:9db0e321a9f4 | 45 | |
kenjiArai | 1:9db0e321a9f4 | 46 | class FileHandle; |
kenjiArai | 1:9db0e321a9f4 | 47 | |
kenjiArai | 0:5b88d5760320 | 48 | extern const char *OK; |
kenjiArai | 0:5b88d5760320 | 49 | extern const char *CRLF; |
kenjiArai | 0:5b88d5760320 | 50 | |
kenjiArai | 0:5b88d5760320 | 51 | #define BUFF_SIZE 32 |
kenjiArai | 0:5b88d5760320 | 52 | |
kenjiArai | 0:5b88d5760320 | 53 | /* AT Error types enumeration */ |
kenjiArai | 0:5b88d5760320 | 54 | enum DeviceErrorType { |
kenjiArai | 0:5b88d5760320 | 55 | DeviceErrorTypeNoError = 0, |
kenjiArai | 0:5b88d5760320 | 56 | DeviceErrorTypeError, // AT ERROR |
kenjiArai | 0:5b88d5760320 | 57 | DeviceErrorTypeErrorCMS, // AT ERROR CMS |
kenjiArai | 0:5b88d5760320 | 58 | DeviceErrorTypeErrorCME // AT ERROR CME |
kenjiArai | 0:5b88d5760320 | 59 | }; |
kenjiArai | 0:5b88d5760320 | 60 | |
kenjiArai | 0:5b88d5760320 | 61 | /** AT response error with error code and type */ |
kenjiArai | 0:5b88d5760320 | 62 | struct device_err_t { |
kenjiArai | 0:5b88d5760320 | 63 | DeviceErrorType errType; |
kenjiArai | 0:5b88d5760320 | 64 | int errCode; |
kenjiArai | 0:5b88d5760320 | 65 | }; |
kenjiArai | 0:5b88d5760320 | 66 | |
kenjiArai | 0:5b88d5760320 | 67 | /// Class for sending AT commands and parsing AT responses. |
kenjiArai | 0:5b88d5760320 | 68 | class ATHandler { |
kenjiArai | 0:5b88d5760320 | 69 | |
kenjiArai | 0:5b88d5760320 | 70 | public: |
kenjiArai | 0:5b88d5760320 | 71 | /** Constructor |
kenjiArai | 0:5b88d5760320 | 72 | * |
kenjiArai | 0:5b88d5760320 | 73 | * @param fh file handle used for reading AT responses and writing AT commands |
kenjiArai | 0:5b88d5760320 | 74 | * @param queue Event queue used to transfer sigio events to this thread |
kenjiArai | 0:5b88d5760320 | 75 | * @param timeout Timeout when reading for AT response |
kenjiArai | 0:5b88d5760320 | 76 | * @param output_delimiter delimiter used when parsing at responses, "\r" should be used as output_delimiter |
kenjiArai | 0:5b88d5760320 | 77 | * @param send_delay the minimum delay in ms between the end of last response and the beginning of a new command |
kenjiArai | 0:5b88d5760320 | 78 | */ |
kenjiArai | 0:5b88d5760320 | 79 | ATHandler(FileHandle *fh, events::EventQueue &queue, uint32_t timeout, const char *output_delimiter, uint16_t send_delay = 0); |
kenjiArai | 0:5b88d5760320 | 80 | virtual ~ATHandler(); |
kenjiArai | 0:5b88d5760320 | 81 | |
kenjiArai | 0:5b88d5760320 | 82 | /** Return used file handle. |
kenjiArai | 0:5b88d5760320 | 83 | * |
kenjiArai | 0:5b88d5760320 | 84 | * @return used file handle |
kenjiArai | 0:5b88d5760320 | 85 | */ |
kenjiArai | 0:5b88d5760320 | 86 | FileHandle *get_file_handle(); |
kenjiArai | 0:5b88d5760320 | 87 | |
kenjiArai | 0:5b88d5760320 | 88 | /** Get a new ATHandler instance, and update the linked list. Once the use of the ATHandler |
kenjiArai | 0:5b88d5760320 | 89 | * has finished, call to close() has to be made |
kenjiArai | 0:5b88d5760320 | 90 | * |
kenjiArai | 0:5b88d5760320 | 91 | * @param fileHandle filehandle used for reading AT responses and writing AT commands. |
kenjiArai | 0:5b88d5760320 | 92 | * If there is already an ATHandler with the same fileHandle pointer, |
kenjiArai | 0:5b88d5760320 | 93 | * then a pointer to that ATHandler instance will be returned with |
kenjiArai | 0:5b88d5760320 | 94 | * that ATHandler's queue, timeout, delimiter, send_delay and debug_on |
kenjiArai | 0:5b88d5760320 | 95 | * values |
kenjiArai | 0:5b88d5760320 | 96 | * @param queue Event queue used to transfer sigio events to this thread |
kenjiArai | 0:5b88d5760320 | 97 | * @param timeout Timeout when reading for AT response |
kenjiArai | 0:5b88d5760320 | 98 | * @param delimiter delimiter used when parsing at responses, "\r" should be used as output_delimiter |
kenjiArai | 0:5b88d5760320 | 99 | * @param send_delay the minimum delay in ms between the end of last response and the beginning of a new command |
kenjiArai | 0:5b88d5760320 | 100 | * @param debug_on Set true to enable debug traces |
kenjiArai | 0:5b88d5760320 | 101 | * @return NULL, if fileHandle is not set, or a pointer to an existing ATHandler, if the fileHandle is |
kenjiArai | 0:5b88d5760320 | 102 | * already in use. Otherwise a pointer to a new ATHandler instance is returned |
kenjiArai | 0:5b88d5760320 | 103 | */ |
kenjiArai | 0:5b88d5760320 | 104 | static ATHandler *get_instance(FileHandle *fileHandle, events::EventQueue &queue, uint32_t timeout, |
kenjiArai | 0:5b88d5760320 | 105 | const char *delimiter, uint16_t send_delay, bool debug_on); |
kenjiArai | 0:5b88d5760320 | 106 | |
kenjiArai | 0:5b88d5760320 | 107 | /** Close and delete the current ATHandler instance, if the reference count to it is 0. |
kenjiArai | 0:5b88d5760320 | 108 | * Close() can be only called, if the ATHandler was opened with get_instance() |
kenjiArai | 0:5b88d5760320 | 109 | * |
kenjiArai | 0:5b88d5760320 | 110 | * @return NSAPI_ERROR_OK on success, NSAPI_ERROR_PARAMETER on failure |
kenjiArai | 0:5b88d5760320 | 111 | */ |
kenjiArai | 0:5b88d5760320 | 112 | nsapi_error_t close(); |
kenjiArai | 0:5b88d5760320 | 113 | |
kenjiArai | 0:5b88d5760320 | 114 | /** Locks the mutex for file handle if AT_HANDLER_MUTEX is defined. |
kenjiArai | 0:5b88d5760320 | 115 | */ |
kenjiArai | 0:5b88d5760320 | 116 | void lock(); |
kenjiArai | 0:5b88d5760320 | 117 | |
kenjiArai | 0:5b88d5760320 | 118 | /** Unlocks the mutex for file handle if AT_HANDLER_MUTEX is defined. |
kenjiArai | 0:5b88d5760320 | 119 | */ |
kenjiArai | 0:5b88d5760320 | 120 | void unlock(); |
kenjiArai | 0:5b88d5760320 | 121 | |
kenjiArai | 0:5b88d5760320 | 122 | /** Locks the mutex for file handle if AT_HANDLER_MUTEX is defined and returns the last error. |
kenjiArai | 0:5b88d5760320 | 123 | * |
kenjiArai | 0:5b88d5760320 | 124 | * @return last error that happened when parsing AT responses |
kenjiArai | 0:5b88d5760320 | 125 | */ |
kenjiArai | 0:5b88d5760320 | 126 | nsapi_error_t unlock_return_error(); |
kenjiArai | 0:5b88d5760320 | 127 | |
kenjiArai | 0:5b88d5760320 | 128 | /** Set callback function for URC |
kenjiArai | 0:5b88d5760320 | 129 | * |
kenjiArai | 0:5b88d5760320 | 130 | * @param prefix URC text to look for, e.g. "+CMTI:". Maximum length is BUFF_SIZE. |
kenjiArai | 0:5b88d5760320 | 131 | * @param callback function to call on prefix, or 0 to remove callback |
kenjiArai | 0:5b88d5760320 | 132 | */ |
kenjiArai | 0:5b88d5760320 | 133 | void set_urc_handler(const char *prefix, Callback<void()> callback); |
kenjiArai | 0:5b88d5760320 | 134 | |
kenjiArai | 0:5b88d5760320 | 135 | ATHandler *_nextATHandler; // linked list |
kenjiArai | 0:5b88d5760320 | 136 | |
kenjiArai | 0:5b88d5760320 | 137 | /** returns the last error while parsing AT responses. |
kenjiArai | 0:5b88d5760320 | 138 | * |
kenjiArai | 0:5b88d5760320 | 139 | * @return last error |
kenjiArai | 0:5b88d5760320 | 140 | */ |
kenjiArai | 0:5b88d5760320 | 141 | nsapi_error_t get_last_error() const; |
kenjiArai | 0:5b88d5760320 | 142 | |
kenjiArai | 0:5b88d5760320 | 143 | /** returns the last device error while parsing AT responses. Actually AT error (CME/CMS). |
kenjiArai | 0:5b88d5760320 | 144 | * |
kenjiArai | 0:5b88d5760320 | 145 | * @return last error struct device_err_t |
kenjiArai | 0:5b88d5760320 | 146 | */ |
kenjiArai | 0:5b88d5760320 | 147 | device_err_t get_last_device_error() const; |
kenjiArai | 0:5b88d5760320 | 148 | |
kenjiArai | 0:5b88d5760320 | 149 | /** Increase reference count. Used for counting references to this instance. |
kenjiArai | 0:5b88d5760320 | 150 | * Note that this should be used with care, if the ATHandler was taken into use |
kenjiArai | 0:5b88d5760320 | 151 | * with get_instance() |
kenjiArai | 0:5b88d5760320 | 152 | */ |
kenjiArai | 0:5b88d5760320 | 153 | void inc_ref_count(); |
kenjiArai | 0:5b88d5760320 | 154 | |
kenjiArai | 0:5b88d5760320 | 155 | /** Decrease reference count. Used for counting references to this instance. |
kenjiArai | 0:5b88d5760320 | 156 | * Note that this should be used with care, if the ATHandler was taken into use |
kenjiArai | 0:5b88d5760320 | 157 | * with get_instance() |
kenjiArai | 0:5b88d5760320 | 158 | */ |
kenjiArai | 0:5b88d5760320 | 159 | void dec_ref_count(); |
kenjiArai | 0:5b88d5760320 | 160 | |
kenjiArai | 0:5b88d5760320 | 161 | /** Get the current reference count. Used for counting references to this instance. |
kenjiArai | 0:5b88d5760320 | 162 | * |
kenjiArai | 0:5b88d5760320 | 163 | * @return current reference count |
kenjiArai | 0:5b88d5760320 | 164 | */ |
kenjiArai | 0:5b88d5760320 | 165 | int get_ref_count(); |
kenjiArai | 0:5b88d5760320 | 166 | |
kenjiArai | 0:5b88d5760320 | 167 | /** Set timeout in milliseconds for AT commands |
kenjiArai | 0:5b88d5760320 | 168 | * |
kenjiArai | 0:5b88d5760320 | 169 | * @param timeout_milliseconds Timeout in milliseconds |
kenjiArai | 0:5b88d5760320 | 170 | * @param default_timeout Store as default timeout |
kenjiArai | 0:5b88d5760320 | 171 | */ |
kenjiArai | 0:5b88d5760320 | 172 | void set_at_timeout(uint32_t timeout_milliseconds, bool default_timeout = false); |
kenjiArai | 0:5b88d5760320 | 173 | |
kenjiArai | 0:5b88d5760320 | 174 | /** Set timeout in milliseconds for all ATHandlers in the _atHandlers list |
kenjiArai | 0:5b88d5760320 | 175 | * |
kenjiArai | 0:5b88d5760320 | 176 | * @param timeout_milliseconds Timeout in milliseconds |
kenjiArai | 0:5b88d5760320 | 177 | * @param default_timeout Store as default timeout |
kenjiArai | 0:5b88d5760320 | 178 | */ |
kenjiArai | 0:5b88d5760320 | 179 | static void set_at_timeout_list(uint32_t timeout_milliseconds, bool default_timeout = false); |
kenjiArai | 0:5b88d5760320 | 180 | |
kenjiArai | 0:5b88d5760320 | 181 | /** Restore timeout to previous timeout. Handy if there is a need to change timeout temporarily. |
kenjiArai | 0:5b88d5760320 | 182 | */ |
kenjiArai | 0:5b88d5760320 | 183 | void restore_at_timeout(); |
kenjiArai | 0:5b88d5760320 | 184 | |
kenjiArai | 0:5b88d5760320 | 185 | /** Clear pending error flag. By default, error is cleared only in lock(). |
kenjiArai | 0:5b88d5760320 | 186 | */ |
kenjiArai | 0:5b88d5760320 | 187 | void clear_error(); |
kenjiArai | 0:5b88d5760320 | 188 | |
kenjiArai | 0:5b88d5760320 | 189 | /** |
kenjiArai | 0:5b88d5760320 | 190 | * Flushes the underlying stream |
kenjiArai | 0:5b88d5760320 | 191 | */ |
kenjiArai | 0:5b88d5760320 | 192 | void flush(); |
kenjiArai | 0:5b88d5760320 | 193 | |
kenjiArai | 0:5b88d5760320 | 194 | /** Tries to find oob's from the AT response. Call the urc callback if one is found. |
kenjiArai | 0:5b88d5760320 | 195 | */ |
kenjiArai | 0:5b88d5760320 | 196 | void process_oob(); |
kenjiArai | 0:5b88d5760320 | 197 | |
kenjiArai | 0:5b88d5760320 | 198 | /** Set file handle, which is used for reading AT responses and writing AT commands |
kenjiArai | 0:5b88d5760320 | 199 | * |
kenjiArai | 0:5b88d5760320 | 200 | * @param fh file handle used for reading AT responses and writing AT commands |
kenjiArai | 0:5b88d5760320 | 201 | */ |
kenjiArai | 0:5b88d5760320 | 202 | void set_file_handle(FileHandle *fh); |
kenjiArai | 0:5b88d5760320 | 203 | |
kenjiArai | 0:5b88d5760320 | 204 | /** Set is file handle usable. Some situations like after going to data mode, file handle is not usable anymore. |
kenjiArai | 0:5b88d5760320 | 205 | * Any items in queue are not to be processed. |
kenjiArai | 0:5b88d5760320 | 206 | * |
kenjiArai | 0:5b88d5760320 | 207 | * @param usable true for usable filehandle |
kenjiArai | 0:5b88d5760320 | 208 | */ |
kenjiArai | 0:5b88d5760320 | 209 | void set_is_filehandle_usable(bool usable); |
kenjiArai | 0:5b88d5760320 | 210 | |
kenjiArai | 0:5b88d5760320 | 211 | /** Synchronize AT command and response handling to modem. |
kenjiArai | 0:5b88d5760320 | 212 | * |
kenjiArai | 0:5b88d5760320 | 213 | * @param timeout_ms ATHandler timeout when trying to sync. Will be restored when function returns. |
kenjiArai | 0:5b88d5760320 | 214 | * @return true is synchronization was successful, false in case of failure |
kenjiArai | 0:5b88d5760320 | 215 | */ |
kenjiArai | 0:5b88d5760320 | 216 | bool sync(int timeout_ms); |
kenjiArai | 0:5b88d5760320 | 217 | |
kenjiArai | 1:9db0e321a9f4 | 218 | /** Sets the delay to be applied before sending any AT command. |
kenjiArai | 1:9db0e321a9f4 | 219 | * |
kenjiArai | 1:9db0e321a9f4 | 220 | * @param send_delay the minimum delay in ms between the end of last response and the beginning of a new command |
kenjiArai | 1:9db0e321a9f4 | 221 | */ |
kenjiArai | 1:9db0e321a9f4 | 222 | void set_send_delay(uint16_t send_delay); |
kenjiArai | 1:9db0e321a9f4 | 223 | |
kenjiArai | 1:9db0e321a9f4 | 224 | /** Sets UARTSerial filehandle to given baud rate |
kenjiArai | 1:9db0e321a9f4 | 225 | * |
kenjiArai | 1:9db0e321a9f4 | 226 | * @param baud_rate |
kenjiArai | 1:9db0e321a9f4 | 227 | */ |
kenjiArai | 1:9db0e321a9f4 | 228 | void set_baud(int baud_rate); |
kenjiArai | 1:9db0e321a9f4 | 229 | |
kenjiArai | 0:5b88d5760320 | 230 | protected: |
kenjiArai | 0:5b88d5760320 | 231 | void event(); |
kenjiArai | 1:9db0e321a9f4 | 232 | #if defined AT_HANDLER_MUTEX && defined MBED_CONF_RTOS_PRESENT |
kenjiArai | 1:9db0e321a9f4 | 233 | rtos::Mutex _fileHandleMutex; |
kenjiArai | 1:9db0e321a9f4 | 234 | rtos::ConditionVariable _oobCv; |
kenjiArai | 0:5b88d5760320 | 235 | #endif |
kenjiArai | 0:5b88d5760320 | 236 | FileHandle *_fileHandle; |
kenjiArai | 0:5b88d5760320 | 237 | private: |
kenjiArai | 0:5b88d5760320 | 238 | /** Remove urc handler from linked list of urc's |
kenjiArai | 0:5b88d5760320 | 239 | * |
kenjiArai | 0:5b88d5760320 | 240 | * @param prefix Register urc prefix for callback. Urc could be for example "+CMTI: " |
kenjiArai | 0:5b88d5760320 | 241 | */ |
kenjiArai | 0:5b88d5760320 | 242 | void remove_urc_handler(const char *prefix); |
kenjiArai | 0:5b88d5760320 | 243 | |
kenjiArai | 0:5b88d5760320 | 244 | void set_error(nsapi_error_t err); |
kenjiArai | 0:5b88d5760320 | 245 | |
kenjiArai | 0:5b88d5760320 | 246 | events::EventQueue &_queue; |
kenjiArai | 0:5b88d5760320 | 247 | nsapi_error_t _last_err; |
kenjiArai | 0:5b88d5760320 | 248 | int _last_3gpp_error; |
kenjiArai | 0:5b88d5760320 | 249 | device_err_t _last_at_err; |
kenjiArai | 0:5b88d5760320 | 250 | uint16_t _oob_string_max_length; |
kenjiArai | 0:5b88d5760320 | 251 | char *_output_delimiter; |
kenjiArai | 0:5b88d5760320 | 252 | |
kenjiArai | 0:5b88d5760320 | 253 | struct oob_t { |
kenjiArai | 0:5b88d5760320 | 254 | const char *prefix; |
kenjiArai | 0:5b88d5760320 | 255 | int prefix_len; |
kenjiArai | 0:5b88d5760320 | 256 | Callback<void()> cb; |
kenjiArai | 0:5b88d5760320 | 257 | oob_t *next; |
kenjiArai | 0:5b88d5760320 | 258 | }; |
kenjiArai | 0:5b88d5760320 | 259 | oob_t *_oobs; |
kenjiArai | 0:5b88d5760320 | 260 | uint32_t _at_timeout; |
kenjiArai | 0:5b88d5760320 | 261 | uint32_t _previous_at_timeout; |
kenjiArai | 0:5b88d5760320 | 262 | |
kenjiArai | 0:5b88d5760320 | 263 | uint16_t _at_send_delay; |
kenjiArai | 0:5b88d5760320 | 264 | uint64_t _last_response_stop; |
kenjiArai | 0:5b88d5760320 | 265 | |
kenjiArai | 0:5b88d5760320 | 266 | int32_t _ref_count; |
kenjiArai | 0:5b88d5760320 | 267 | bool _is_fh_usable; |
kenjiArai | 0:5b88d5760320 | 268 | |
kenjiArai | 0:5b88d5760320 | 269 | static ATHandler *_atHandlers; |
kenjiArai | 0:5b88d5760320 | 270 | |
kenjiArai | 0:5b88d5760320 | 271 | //************************************* |
kenjiArai | 0:5b88d5760320 | 272 | public: |
kenjiArai | 0:5b88d5760320 | 273 | |
kenjiArai | 0:5b88d5760320 | 274 | /** Starts the command writing by clearing the last error and writing the given command. |
kenjiArai | 0:5b88d5760320 | 275 | * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. |
kenjiArai | 0:5b88d5760320 | 276 | * |
kenjiArai | 0:5b88d5760320 | 277 | * @param cmd AT command to be written to modem |
kenjiArai | 0:5b88d5760320 | 278 | */ |
kenjiArai | 0:5b88d5760320 | 279 | virtual void cmd_start(const char *cmd); |
kenjiArai | 0:5b88d5760320 | 280 | |
kenjiArai | 0:5b88d5760320 | 281 | /** |
kenjiArai | 0:5b88d5760320 | 282 | * @brief cmd_start_stop Starts an AT command, writes given variadic arguments and stops the command. Use this |
kenjiArai | 0:5b88d5760320 | 283 | * command when you need multiple response parameters to be handled. |
kenjiArai | 0:5b88d5760320 | 284 | * NOTE: Does not lock ATHandler for process! |
kenjiArai | 0:5b88d5760320 | 285 | * |
kenjiArai | 0:5b88d5760320 | 286 | * @param cmd AT command in form +<CMD> (will be used also in response reading, no extra chars allowed) |
kenjiArai | 0:5b88d5760320 | 287 | * @param cmd_chr Char to be added to specific AT command: '?', '=' or ''. Will be used as such so '=1' is valid as well. |
kenjiArai | 0:5b88d5760320 | 288 | * @param format Format string for variadic arguments to be added to AT command; No separator needed. |
kenjiArai | 0:5b88d5760320 | 289 | * Use %d for integer, %s for string and %b for byte string (requires 2 arguments: string and length) |
kenjiArai | 0:5b88d5760320 | 290 | */ |
kenjiArai | 0:5b88d5760320 | 291 | void cmd_start_stop(const char *cmd, const char *cmd_chr, const char *format = "", ...); |
kenjiArai | 0:5b88d5760320 | 292 | |
kenjiArai | 0:5b88d5760320 | 293 | /** |
kenjiArai | 0:5b88d5760320 | 294 | * @brief at_cmd_str Send an AT command and read a single string response. Locks and unlocks ATHandler for operation |
kenjiArai | 0:5b88d5760320 | 295 | * @param cmd AT command in form +<CMD> (will be used also in response reading, no extra chars allowed) |
kenjiArai | 0:5b88d5760320 | 296 | * @param cmd_chr Char to be added to specific AT command: '?', '=' or ''. Will be used as such so '=1' is valid as well. |
kenjiArai | 0:5b88d5760320 | 297 | * @param resp_buf Response buffer |
kenjiArai | 0:5b88d5760320 | 298 | * @param resp_buf_size Response buffer size |
kenjiArai | 0:5b88d5760320 | 299 | * @param format Format string for variadic arguments to be added to AT command; No separator needed. |
kenjiArai | 0:5b88d5760320 | 300 | * Use %d for integer, %s for string and %b for byte string (requires 2 arguments: string and length) |
kenjiArai | 0:5b88d5760320 | 301 | * @return last error that happened when parsing AT responses |
kenjiArai | 0:5b88d5760320 | 302 | */ |
kenjiArai | 0:5b88d5760320 | 303 | nsapi_error_t at_cmd_str(const char *cmd, const char *cmd_chr, char *resp_buf, size_t resp_buf_size, const char *format = "", ...); |
kenjiArai | 0:5b88d5760320 | 304 | |
kenjiArai | 0:5b88d5760320 | 305 | /** |
kenjiArai | 0:5b88d5760320 | 306 | * @brief at_cmd_int Send an AT command and read a single integer response. Locks and unlocks ATHandler for operation |
kenjiArai | 0:5b88d5760320 | 307 | * @param cmd AT command in form +<CMD> (will be used also in response reading, no extra chars allowed) |
kenjiArai | 0:5b88d5760320 | 308 | * @param cmd_chr Char to be added to specific AT command: '?', '=' or ''. Will be used as such so '=1' is valid as well. |
kenjiArai | 0:5b88d5760320 | 309 | * @param resp Integer to hold response |
kenjiArai | 0:5b88d5760320 | 310 | * @param format Format string for variadic arguments to be added to AT command; No separator needed. |
kenjiArai | 0:5b88d5760320 | 311 | * Use %d for integer, %s for string and %b for byte string (requires 2 arguments: string and length) |
kenjiArai | 0:5b88d5760320 | 312 | * @return last error that happened when parsing AT responses |
kenjiArai | 0:5b88d5760320 | 313 | */ |
kenjiArai | 0:5b88d5760320 | 314 | nsapi_error_t at_cmd_int(const char *cmd, const char *cmd_chr, int &resp, const char *format = "", ...); |
kenjiArai | 0:5b88d5760320 | 315 | |
kenjiArai | 0:5b88d5760320 | 316 | /** |
kenjiArai | 0:5b88d5760320 | 317 | * @brief at_cmd_discard Send an AT command and read and discard a response. Locks and unlocks ATHandler for operation |
kenjiArai | 0:5b88d5760320 | 318 | * @param cmd AT command in form +<CMD> (will be used also in response reading, no extra chars allowed) |
kenjiArai | 0:5b88d5760320 | 319 | * @param cmd_chr Char to be added to specific AT command: '?', '=' or ''. Will be used as such so '=1' is valid as well. |
kenjiArai | 0:5b88d5760320 | 320 | * @param format Format string for variadic arguments to be added to AT command; No separator needed. |
kenjiArai | 0:5b88d5760320 | 321 | * Use %d for integer, %s for string and %b for byte string (requires 2 arguments: string and length) |
kenjiArai | 0:5b88d5760320 | 322 | * @return last error that happened when parsing AT responses |
kenjiArai | 0:5b88d5760320 | 323 | */ |
kenjiArai | 0:5b88d5760320 | 324 | nsapi_error_t at_cmd_discard(const char *cmd, const char *cmd_chr, const char *format = "", ...); |
kenjiArai | 0:5b88d5760320 | 325 | |
kenjiArai | 0:5b88d5760320 | 326 | public: |
kenjiArai | 0:5b88d5760320 | 327 | |
kenjiArai | 0:5b88d5760320 | 328 | /** Writes integer type AT command subparameter. Starts with the delimiter if not the first param after cmd_start. |
kenjiArai | 0:5b88d5760320 | 329 | * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. |
kenjiArai | 0:5b88d5760320 | 330 | * |
kenjiArai | 0:5b88d5760320 | 331 | * @param param int to be written to modem as AT command subparameter |
kenjiArai | 0:5b88d5760320 | 332 | */ |
kenjiArai | 0:5b88d5760320 | 333 | void write_int(int32_t param); |
kenjiArai | 0:5b88d5760320 | 334 | |
kenjiArai | 0:5b88d5760320 | 335 | /** Writes string type AT command subparamater. Quotes are added to surround the given string. |
kenjiArai | 0:5b88d5760320 | 336 | * Starts with the delimiter if not the first param after cmd_start. |
kenjiArai | 0:5b88d5760320 | 337 | * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. |
kenjiArai | 0:5b88d5760320 | 338 | * |
kenjiArai | 0:5b88d5760320 | 339 | * @param param string to be written to modem as AT command subparameter |
kenjiArai | 0:5b88d5760320 | 340 | * @param useQuotations flag indicating whether the string should be included in quotation marks |
kenjiArai | 0:5b88d5760320 | 341 | */ |
kenjiArai | 0:5b88d5760320 | 342 | void write_string(const char *param, bool useQuotations = true); |
kenjiArai | 0:5b88d5760320 | 343 | |
kenjiArai | 0:5b88d5760320 | 344 | /** Stops the AT command by writing command-line terminator CR to mark command as finished. |
kenjiArai | 0:5b88d5760320 | 345 | */ |
kenjiArai | 0:5b88d5760320 | 346 | void cmd_stop(); |
kenjiArai | 0:5b88d5760320 | 347 | |
kenjiArai | 0:5b88d5760320 | 348 | /** Stops the AT command by writing command-line terminator CR to mark command as finished and reads the OK/ERROR response. |
kenjiArai | 0:5b88d5760320 | 349 | * |
kenjiArai | 0:5b88d5760320 | 350 | */ |
kenjiArai | 0:5b88d5760320 | 351 | void cmd_stop_read_resp(); |
kenjiArai | 0:5b88d5760320 | 352 | |
kenjiArai | 0:5b88d5760320 | 353 | /** Write bytes without any subparameter delimiters, such as comma. |
kenjiArai | 0:5b88d5760320 | 354 | * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. |
kenjiArai | 0:5b88d5760320 | 355 | * |
kenjiArai | 0:5b88d5760320 | 356 | * @param data bytes to be written to modem |
kenjiArai | 0:5b88d5760320 | 357 | * @param len length of data string |
kenjiArai | 0:5b88d5760320 | 358 | * |
kenjiArai | 0:5b88d5760320 | 359 | * @return number of characters successfully written |
kenjiArai | 0:5b88d5760320 | 360 | */ |
kenjiArai | 0:5b88d5760320 | 361 | size_t write_bytes(const uint8_t *data, size_t len); |
kenjiArai | 0:5b88d5760320 | 362 | |
kenjiArai | 0:5b88d5760320 | 363 | /** Sets the stop tag for the current scope (response/information response/element) |
kenjiArai | 0:5b88d5760320 | 364 | * Parameter's reading routines will stop the reading when such tag is found and will set the found flag. |
kenjiArai | 0:5b88d5760320 | 365 | * Consume routines will read everything until such tag is found. |
kenjiArai | 0:5b88d5760320 | 366 | * |
kenjiArai | 0:5b88d5760320 | 367 | * @param stop_tag_seq string to be set as stop tag |
kenjiArai | 0:5b88d5760320 | 368 | */ |
kenjiArai | 0:5b88d5760320 | 369 | void set_stop_tag(const char *stop_tag_seq); |
kenjiArai | 0:5b88d5760320 | 370 | |
kenjiArai | 0:5b88d5760320 | 371 | /** Sets the delimiter between parameters or between elements of the information response. |
kenjiArai | 0:5b88d5760320 | 372 | * Parameter's reading routines will stop when such char is read. |
kenjiArai | 0:5b88d5760320 | 373 | * |
kenjiArai | 0:5b88d5760320 | 374 | * @param delimiter char to be set as _delimiter |
kenjiArai | 0:5b88d5760320 | 375 | */ |
kenjiArai | 0:5b88d5760320 | 376 | void set_delimiter(char delimiter); |
kenjiArai | 0:5b88d5760320 | 377 | |
kenjiArai | 0:5b88d5760320 | 378 | /** Sets the delimiter to default value defined by DEFAULT_DELIMITER. |
kenjiArai | 0:5b88d5760320 | 379 | */ |
kenjiArai | 0:5b88d5760320 | 380 | void set_default_delimiter(); |
kenjiArai | 0:5b88d5760320 | 381 | |
kenjiArai | 0:5b88d5760320 | 382 | /** Defines behaviour for using or ignoring the delimiter within an AT command |
kenjiArai | 0:5b88d5760320 | 383 | * |
kenjiArai | 0:5b88d5760320 | 384 | * @param use_delimiter indicating if delimiter should be used or not |
kenjiArai | 0:5b88d5760320 | 385 | */ |
kenjiArai | 0:5b88d5760320 | 386 | void use_delimiter(bool use_delimiter); |
kenjiArai | 0:5b88d5760320 | 387 | |
kenjiArai | 0:5b88d5760320 | 388 | /** Consumes the reading buffer up to the delimiter or stop_tag |
kenjiArai | 0:5b88d5760320 | 389 | * |
kenjiArai | 0:5b88d5760320 | 390 | * @param count number of parameters to be skipped |
kenjiArai | 0:5b88d5760320 | 391 | */ |
kenjiArai | 0:5b88d5760320 | 392 | void skip_param(uint32_t count = 1); |
kenjiArai | 0:5b88d5760320 | 393 | |
kenjiArai | 0:5b88d5760320 | 394 | /** Consumes the given length from the reading buffer |
kenjiArai | 0:5b88d5760320 | 395 | * |
kenjiArai | 0:5b88d5760320 | 396 | * @param len length to be consumed from reading buffer |
kenjiArai | 0:5b88d5760320 | 397 | * @param count number of parameters to be skipped |
kenjiArai | 0:5b88d5760320 | 398 | */ |
kenjiArai | 0:5b88d5760320 | 399 | void skip_param(ssize_t len, uint32_t count); |
kenjiArai | 0:5b88d5760320 | 400 | |
kenjiArai | 0:5b88d5760320 | 401 | /** Reads given number of bytes from receiving buffer without checking any subparameter delimiters, such as comma. |
kenjiArai | 0:5b88d5760320 | 402 | * |
kenjiArai | 0:5b88d5760320 | 403 | * @param buf output buffer for the read |
kenjiArai | 0:5b88d5760320 | 404 | * @param len maximum number of bytes to read |
kenjiArai | 0:5b88d5760320 | 405 | * @return number of successfully read bytes or -1 in case of error |
kenjiArai | 0:5b88d5760320 | 406 | */ |
kenjiArai | 0:5b88d5760320 | 407 | ssize_t read_bytes(uint8_t *buf, size_t len); |
kenjiArai | 0:5b88d5760320 | 408 | |
kenjiArai | 0:5b88d5760320 | 409 | /** Reads chars from reading buffer. Terminates with null. Skips the quotation marks. |
kenjiArai | 0:5b88d5760320 | 410 | * Stops on delimiter or stop tag. |
kenjiArai | 0:5b88d5760320 | 411 | * |
kenjiArai | 0:5b88d5760320 | 412 | * @param str output buffer for the read |
kenjiArai | 0:5b88d5760320 | 413 | * @param size maximum number of chars to output including NULL |
kenjiArai | 0:5b88d5760320 | 414 | * @param read_even_stop_tag if true then try to read even if the stop tag was found previously |
kenjiArai | 0:5b88d5760320 | 415 | * @return length of output string or -1 in case of read timeout before delimiter or stop tag is found |
kenjiArai | 0:5b88d5760320 | 416 | */ |
kenjiArai | 0:5b88d5760320 | 417 | ssize_t read_string(char *str, size_t size, bool read_even_stop_tag = false); |
kenjiArai | 0:5b88d5760320 | 418 | |
kenjiArai | 0:5b88d5760320 | 419 | /** Reads chars representing hex ascii values and converts them to the corresponding chars. |
kenjiArai | 0:5b88d5760320 | 420 | * For example: "4156" to "AV". |
kenjiArai | 0:5b88d5760320 | 421 | * Terminates with null. Skips the quotation marks. |
kenjiArai | 0:5b88d5760320 | 422 | * Stops on delimiter or stop tag. |
kenjiArai | 0:5b88d5760320 | 423 | * |
kenjiArai | 0:5b88d5760320 | 424 | * @param str output buffer for the read |
kenjiArai | 0:5b88d5760320 | 425 | * @param size maximum number of chars to output |
kenjiArai | 0:5b88d5760320 | 426 | * @return length of output string or -1 in case of read timeout before delimiter or stop tag is found |
kenjiArai | 0:5b88d5760320 | 427 | */ |
kenjiArai | 0:5b88d5760320 | 428 | ssize_t read_hex_string(char *str, size_t size); |
kenjiArai | 0:5b88d5760320 | 429 | |
kenjiArai | 1:9db0e321a9f4 | 430 | /** Converts contained chars to their hex ascii value and writes the resulting string to the file handle |
kenjiArai | 1:9db0e321a9f4 | 431 | * For example: "AV" to "4156". |
kenjiArai | 0:5b88d5760320 | 432 | * |
kenjiArai | 1:9db0e321a9f4 | 433 | * @param str input buffer to be converted to hex ascii |
kenjiArai | 1:9db0e321a9f4 | 434 | * @param size of the input param str |
kenjiArai | 1:9db0e321a9f4 | 435 | */ |
kenjiArai | 1:9db0e321a9f4 | 436 | void write_hex_string(char *str, size_t size); |
kenjiArai | 1:9db0e321a9f4 | 437 | |
kenjiArai | 1:9db0e321a9f4 | 438 | /** Reads as string and converts result to integer. Supports only non-negative integers. |
kenjiArai | 1:9db0e321a9f4 | 439 | * |
kenjiArai | 1:9db0e321a9f4 | 440 | * @return the non-negative integer or -1 in case of error. |
kenjiArai | 0:5b88d5760320 | 441 | */ |
kenjiArai | 0:5b88d5760320 | 442 | int32_t read_int(); |
kenjiArai | 0:5b88d5760320 | 443 | |
kenjiArai | 0:5b88d5760320 | 444 | /** This looks for necessary matches: prefix, OK, ERROR, URCs and sets the correct scope. |
kenjiArai | 0:5b88d5760320 | 445 | * |
kenjiArai | 0:5b88d5760320 | 446 | * @param prefix string to be matched from receiving buffer. If not NULL and match succeeds, then scope |
kenjiArai | 0:5b88d5760320 | 447 | * will be set as information response(info_type) |
kenjiArai | 0:5b88d5760320 | 448 | * @param stop flag to indicate if we go to information response scope or not. |
kenjiArai | 0:5b88d5760320 | 449 | * (needed when nothing is expected to be received anymore after the prefix match: |
kenjiArai | 0:5b88d5760320 | 450 | * sms case: "> ", bc95 reboot case) |
kenjiArai | 0:5b88d5760320 | 451 | */ |
kenjiArai | 0:5b88d5760320 | 452 | void resp_start(const char *prefix = NULL, bool stop = false); |
kenjiArai | 0:5b88d5760320 | 453 | |
kenjiArai | 0:5b88d5760320 | 454 | /** Ends all scopes starting from current scope. |
kenjiArai | 0:5b88d5760320 | 455 | * Consumes everything until the scope's stop tag is found, then |
kenjiArai | 0:5b88d5760320 | 456 | * goes to next scope until response scope is ending. |
kenjiArai | 0:5b88d5760320 | 457 | * URC match is checked during response scope ending, |
kenjiArai | 0:5b88d5760320 | 458 | * for every new line / CRLF. |
kenjiArai | 0:5b88d5760320 | 459 | * |
kenjiArai | 0:5b88d5760320 | 460 | * |
kenjiArai | 0:5b88d5760320 | 461 | * Possible sequence: |
kenjiArai | 0:5b88d5760320 | 462 | * element scope -> information response scope -> response scope |
kenjiArai | 0:5b88d5760320 | 463 | */ |
kenjiArai | 0:5b88d5760320 | 464 | void resp_stop(); |
kenjiArai | 0:5b88d5760320 | 465 | |
kenjiArai | 0:5b88d5760320 | 466 | /** Looks for matching the prefix given to resp_start() call. |
kenjiArai | 0:5b88d5760320 | 467 | * If needed, it ends the scope of a previous information response. |
kenjiArai | 0:5b88d5760320 | 468 | * Sets the information response scope if new prefix is found and response scope if prefix is not found. |
kenjiArai | 0:5b88d5760320 | 469 | * |
kenjiArai | 0:5b88d5760320 | 470 | * @return true if prefix defined for information response is not empty string and is found, |
kenjiArai | 0:5b88d5760320 | 471 | * false otherwise. |
kenjiArai | 0:5b88d5760320 | 472 | */ |
kenjiArai | 0:5b88d5760320 | 473 | bool info_resp(); |
kenjiArai | 0:5b88d5760320 | 474 | |
kenjiArai | 0:5b88d5760320 | 475 | /** Looks for matching the start tag. |
kenjiArai | 0:5b88d5760320 | 476 | * If needed, it ends the scope of a previous element. |
kenjiArai | 0:5b88d5760320 | 477 | * Sets the element scope if start tag is found and information response scope if start tag is not found. |
kenjiArai | 0:5b88d5760320 | 478 | * |
kenjiArai | 0:5b88d5760320 | 479 | * @param start_tag tag to be matched to begin parsing an element of an information response |
kenjiArai | 0:5b88d5760320 | 480 | * @return true if new element is found, false otherwise |
kenjiArai | 0:5b88d5760320 | 481 | */ |
kenjiArai | 0:5b88d5760320 | 482 | bool info_elem(char start_tag); |
kenjiArai | 0:5b88d5760320 | 483 | |
kenjiArai | 0:5b88d5760320 | 484 | /** Consumes the received content until current stop tag is found. |
kenjiArai | 0:5b88d5760320 | 485 | * |
kenjiArai | 0:5b88d5760320 | 486 | * @return true if stop tag is found, false otherwise |
kenjiArai | 0:5b88d5760320 | 487 | */ |
kenjiArai | 0:5b88d5760320 | 488 | bool consume_to_stop_tag(); |
kenjiArai | 0:5b88d5760320 | 489 | |
kenjiArai | 0:5b88d5760320 | 490 | /** Return the last 3GPP error code. |
kenjiArai | 0:5b88d5760320 | 491 | * @return last 3GPP error code |
kenjiArai | 0:5b88d5760320 | 492 | */ |
kenjiArai | 0:5b88d5760320 | 493 | int get_3gpp_error(); |
kenjiArai | 0:5b88d5760320 | 494 | |
kenjiArai | 0:5b88d5760320 | 495 | public: // just for debugging |
kenjiArai | 0:5b88d5760320 | 496 | /** |
kenjiArai | 0:5b88d5760320 | 497 | * AT debugging, when enabled will print all data read and written, |
kenjiArai | 0:5b88d5760320 | 498 | * non-printable chars are printed as "[%d]". |
kenjiArai | 0:5b88d5760320 | 499 | * |
kenjiArai | 0:5b88d5760320 | 500 | * AT debug can be enabled at compile time using MBED_CONF_CELLULAR_DEBUG_AT flag or at runtime |
kenjiArai | 0:5b88d5760320 | 501 | * calling set_debug(). Note that MBED_CONF_MBED_TRACE_ENABLE must also be enabled. |
kenjiArai | 0:5b88d5760320 | 502 | * |
kenjiArai | 0:5b88d5760320 | 503 | * @param debug_on Enable/disable debugging |
kenjiArai | 0:5b88d5760320 | 504 | */ |
kenjiArai | 0:5b88d5760320 | 505 | void set_debug(bool debug_on); |
kenjiArai | 0:5b88d5760320 | 506 | |
kenjiArai | 0:5b88d5760320 | 507 | /** |
kenjiArai | 0:5b88d5760320 | 508 | * Get degug state set by @ref set_debug |
kenjiArai | 0:5b88d5760320 | 509 | * |
kenjiArai | 0:5b88d5760320 | 510 | * @return current state of debug |
kenjiArai | 0:5b88d5760320 | 511 | */ |
kenjiArai | 0:5b88d5760320 | 512 | bool get_debug() const; |
kenjiArai | 0:5b88d5760320 | 513 | |
kenjiArai | 0:5b88d5760320 | 514 | /** Set debug_on for all ATHandlers in the _atHandlers list |
kenjiArai | 0:5b88d5760320 | 515 | * |
kenjiArai | 0:5b88d5760320 | 516 | * @param debug_on Set true to enable debug traces |
kenjiArai | 0:5b88d5760320 | 517 | */ |
kenjiArai | 0:5b88d5760320 | 518 | static void set_debug_list(bool debug_on); |
kenjiArai | 0:5b88d5760320 | 519 | |
kenjiArai | 0:5b88d5760320 | 520 | private: |
kenjiArai | 0:5b88d5760320 | 521 | |
kenjiArai | 0:5b88d5760320 | 522 | // should fit any prefix and int |
kenjiArai | 0:5b88d5760320 | 523 | char _recv_buff[BUFF_SIZE]; |
kenjiArai | 0:5b88d5760320 | 524 | // reading position |
kenjiArai | 0:5b88d5760320 | 525 | size_t _recv_len; |
kenjiArai | 0:5b88d5760320 | 526 | // reading length |
kenjiArai | 0:5b88d5760320 | 527 | size_t _recv_pos; |
kenjiArai | 0:5b88d5760320 | 528 | |
kenjiArai | 0:5b88d5760320 | 529 | // resp_type: the part of the response that doesn't include the information response (+CMD1,+CMD2..) |
kenjiArai | 0:5b88d5760320 | 530 | // ends with OK or (CME)(CMS)ERROR |
kenjiArai | 0:5b88d5760320 | 531 | // info_type: the information response part of the response: starts with +CMD1 and ends with CRLF |
kenjiArai | 0:5b88d5760320 | 532 | // information response contains parameters or subsets of parameters (elements), both separated by comma |
kenjiArai | 0:5b88d5760320 | 533 | // elem_type: subsets of parameters that are part of information response, its parameters are separated by comma |
kenjiArai | 0:5b88d5760320 | 534 | enum ScopeType {RespType, InfoType, ElemType, NotSet}; |
kenjiArai | 0:5b88d5760320 | 535 | void set_scope(ScopeType scope_type); |
kenjiArai | 0:5b88d5760320 | 536 | ScopeType _current_scope; |
kenjiArai | 0:5b88d5760320 | 537 | |
kenjiArai | 0:5b88d5760320 | 538 | struct tag_t { |
kenjiArai | 0:5b88d5760320 | 539 | char tag[7]; |
kenjiArai | 0:5b88d5760320 | 540 | size_t len; |
kenjiArai | 0:5b88d5760320 | 541 | bool found; |
kenjiArai | 0:5b88d5760320 | 542 | }; |
kenjiArai | 0:5b88d5760320 | 543 | |
kenjiArai | 0:5b88d5760320 | 544 | // tag to stop response scope |
kenjiArai | 0:5b88d5760320 | 545 | tag_t _resp_stop; |
kenjiArai | 0:5b88d5760320 | 546 | // tag to stop information response scope |
kenjiArai | 0:5b88d5760320 | 547 | tag_t _info_stop; |
kenjiArai | 0:5b88d5760320 | 548 | // tag to stop element scope |
kenjiArai | 0:5b88d5760320 | 549 | tag_t _elem_stop; |
kenjiArai | 0:5b88d5760320 | 550 | // reference to the stop tag of current scope (resp/info/elem) |
kenjiArai | 0:5b88d5760320 | 551 | tag_t *_stop_tag; |
kenjiArai | 0:5b88d5760320 | 552 | |
kenjiArai | 0:5b88d5760320 | 553 | // delimiter between parameters and also used for delimiting elements of information response |
kenjiArai | 0:5b88d5760320 | 554 | char _delimiter; |
kenjiArai | 0:5b88d5760320 | 555 | // set true on prefix match -> indicates start of an information response or of an element |
kenjiArai | 0:5b88d5760320 | 556 | bool _prefix_matched; |
kenjiArai | 0:5b88d5760320 | 557 | // set true on urc match |
kenjiArai | 0:5b88d5760320 | 558 | bool _urc_matched; |
kenjiArai | 0:5b88d5760320 | 559 | // set true on (CME)(CMS)ERROR |
kenjiArai | 0:5b88d5760320 | 560 | bool _error_found; |
kenjiArai | 0:5b88d5760320 | 561 | // Max length of OK,(CME)(CMS)ERROR and URCs |
kenjiArai | 0:5b88d5760320 | 562 | size_t _max_resp_length; |
kenjiArai | 0:5b88d5760320 | 563 | |
kenjiArai | 0:5b88d5760320 | 564 | // prefix set during resp_start and used to try matching possible information responses |
kenjiArai | 0:5b88d5760320 | 565 | char _info_resp_prefix[BUFF_SIZE]; |
kenjiArai | 0:5b88d5760320 | 566 | bool _debug_on; |
kenjiArai | 0:5b88d5760320 | 567 | bool _cmd_start; |
kenjiArai | 0:5b88d5760320 | 568 | bool _use_delimiter; |
kenjiArai | 0:5b88d5760320 | 569 | |
kenjiArai | 0:5b88d5760320 | 570 | // time when a command or an URC processing was started |
kenjiArai | 0:5b88d5760320 | 571 | uint64_t _start_time; |
kenjiArai | 1:9db0e321a9f4 | 572 | // eventqueue event id |
kenjiArai | 1:9db0e321a9f4 | 573 | int _event_id; |
kenjiArai | 0:5b88d5760320 | 574 | |
kenjiArai | 0:5b88d5760320 | 575 | char _cmd_buffer[BUFF_SIZE]; |
kenjiArai | 0:5b88d5760320 | 576 | |
kenjiArai | 0:5b88d5760320 | 577 | private: |
kenjiArai | 0:5b88d5760320 | 578 | //Handles the arguments from given variadic list |
kenjiArai | 0:5b88d5760320 | 579 | void handle_args(const char *format, std::va_list list); |
kenjiArai | 0:5b88d5760320 | 580 | |
kenjiArai | 0:5b88d5760320 | 581 | //Starts an AT command based on given parameters |
kenjiArai | 0:5b88d5760320 | 582 | void handle_start(const char *cmd, const char *cmd_chr); |
kenjiArai | 0:5b88d5760320 | 583 | |
kenjiArai | 0:5b88d5760320 | 584 | //Checks that ATHandler does not have a pending error condition and filehandle is usable |
kenjiArai | 0:5b88d5760320 | 585 | bool ok_to_proceed(); |
kenjiArai | 0:5b88d5760320 | 586 | |
kenjiArai | 0:5b88d5760320 | 587 | private: |
kenjiArai | 0:5b88d5760320 | 588 | // Gets char from receiving buffer. |
kenjiArai | 0:5b88d5760320 | 589 | // Resets and fills the buffer if all are already read (receiving position equals receiving length). |
kenjiArai | 0:5b88d5760320 | 590 | // Returns a next char or -1 on failure (also sets error flag) |
kenjiArai | 0:5b88d5760320 | 591 | int get_char(); |
kenjiArai | 0:5b88d5760320 | 592 | // Sets to 0 the reading position, reading length and the whole buffer content. |
kenjiArai | 0:5b88d5760320 | 593 | void reset_buffer(); |
kenjiArai | 0:5b88d5760320 | 594 | // Reading position set to 0 and buffer's unread content moved to beginning |
kenjiArai | 0:5b88d5760320 | 595 | void rewind_buffer(); |
kenjiArai | 0:5b88d5760320 | 596 | // Calculate remaining time for polling based on request start time and AT timeout. |
kenjiArai | 0:5b88d5760320 | 597 | // Returns 0 or time in ms for polling. |
kenjiArai | 0:5b88d5760320 | 598 | int poll_timeout(bool wait_for_timeout = true); |
kenjiArai | 0:5b88d5760320 | 599 | // Reads from serial to receiving buffer. |
kenjiArai | 0:5b88d5760320 | 600 | // Returns true on successful read OR false on timeout. |
kenjiArai | 0:5b88d5760320 | 601 | bool fill_buffer(bool wait_for_timeout = true); |
kenjiArai | 0:5b88d5760320 | 602 | |
kenjiArai | 0:5b88d5760320 | 603 | void set_tag(tag_t *tag_dest, const char *tag_seq); |
kenjiArai | 0:5b88d5760320 | 604 | |
kenjiArai | 0:5b88d5760320 | 605 | // Rewinds the receiving buffer and compares it against given str. |
kenjiArai | 0:5b88d5760320 | 606 | bool match(const char *str, size_t size); |
kenjiArai | 0:5b88d5760320 | 607 | // Iterates URCs and checks if they match the receiving buffer content. |
kenjiArai | 0:5b88d5760320 | 608 | // If URC match sets the scope to information response and after urc's cb returns |
kenjiArai | 0:5b88d5760320 | 609 | // finishes the information response scope(consumes to CRLF). |
kenjiArai | 0:5b88d5760320 | 610 | bool match_urc(); |
kenjiArai | 0:5b88d5760320 | 611 | // Checks if any of the error strings are matching the receiving buffer content. |
kenjiArai | 0:5b88d5760320 | 612 | bool match_error(); |
kenjiArai | 0:5b88d5760320 | 613 | // Checks if current char in buffer matches ch and consumes it, |
kenjiArai | 0:5b88d5760320 | 614 | // if no match lets the buffer unchanged. |
kenjiArai | 0:5b88d5760320 | 615 | bool consume_char(char ch); |
kenjiArai | 0:5b88d5760320 | 616 | // Consumes the received content until tag is found. |
kenjiArai | 0:5b88d5760320 | 617 | // Consumes the tag only if consume_tag flag is true. |
kenjiArai | 0:5b88d5760320 | 618 | bool consume_to_tag(const char *tag, bool consume_tag); |
kenjiArai | 0:5b88d5760320 | 619 | // Checks if receiving buffer contains OK, ERROR, URC or given prefix. |
kenjiArai | 0:5b88d5760320 | 620 | void resp(const char *prefix, bool check_urc); |
kenjiArai | 0:5b88d5760320 | 621 | |
kenjiArai | 0:5b88d5760320 | 622 | |
kenjiArai | 0:5b88d5760320 | 623 | ScopeType get_scope(); |
kenjiArai | 0:5b88d5760320 | 624 | |
kenjiArai | 0:5b88d5760320 | 625 | // Consumes to information response stop tag which is CRLF. Sets scope to response. |
kenjiArai | 0:5b88d5760320 | 626 | void information_response_stop(); |
kenjiArai | 0:5b88d5760320 | 627 | // Consumes to element stop tag. Sets scope to information response |
kenjiArai | 0:5b88d5760320 | 628 | void information_response_element_stop(); |
kenjiArai | 0:5b88d5760320 | 629 | |
kenjiArai | 0:5b88d5760320 | 630 | // Reads the error code if expected and sets it as last error. |
kenjiArai | 0:5b88d5760320 | 631 | void at_error(bool error_code, DeviceErrorType error_type); |
kenjiArai | 0:5b88d5760320 | 632 | |
kenjiArai | 0:5b88d5760320 | 633 | /** Convert AT error code to 3GPP error codes |
kenjiArai | 0:5b88d5760320 | 634 | * @param err AT error code read from CME/CMS ERROR responses |
kenjiArai | 0:5b88d5760320 | 635 | * @param error_type error type (CMS/CME/ERROR) |
kenjiArai | 0:5b88d5760320 | 636 | */ |
kenjiArai | 0:5b88d5760320 | 637 | void set_3gpp_error(int err, DeviceErrorType error_type); |
kenjiArai | 0:5b88d5760320 | 638 | |
kenjiArai | 0:5b88d5760320 | 639 | bool check_cmd_send(); |
kenjiArai | 0:5b88d5760320 | 640 | size_t write(const void *data, size_t len); |
kenjiArai | 0:5b88d5760320 | 641 | |
kenjiArai | 0:5b88d5760320 | 642 | /** Finds occurrence of one char buffer inside another char buffer. |
kenjiArai | 0:5b88d5760320 | 643 | * |
kenjiArai | 0:5b88d5760320 | 644 | * @param dest destination char buffer |
kenjiArai | 0:5b88d5760320 | 645 | * @param dest_len length of dest |
kenjiArai | 0:5b88d5760320 | 646 | * @param src string to be searched for |
kenjiArai | 0:5b88d5760320 | 647 | * @param src_len length of string to be searched for |
kenjiArai | 0:5b88d5760320 | 648 | * |
kenjiArai | 0:5b88d5760320 | 649 | * @return pointer to first occurrence of src in dest |
kenjiArai | 0:5b88d5760320 | 650 | */ |
kenjiArai | 0:5b88d5760320 | 651 | const char *mem_str(const char *dest, size_t dest_len, const char *src, size_t src_len); |
kenjiArai | 0:5b88d5760320 | 652 | |
kenjiArai | 0:5b88d5760320 | 653 | // check is urc is already added |
kenjiArai | 0:5b88d5760320 | 654 | bool find_urc_handler(const char *prefix); |
kenjiArai | 0:5b88d5760320 | 655 | |
kenjiArai | 0:5b88d5760320 | 656 | // print contents of a buffer to trace log |
kenjiArai | 0:5b88d5760320 | 657 | enum ATType { |
kenjiArai | 0:5b88d5760320 | 658 | AT_ERR, |
kenjiArai | 0:5b88d5760320 | 659 | AT_RX, |
kenjiArai | 0:5b88d5760320 | 660 | AT_TX |
kenjiArai | 0:5b88d5760320 | 661 | }; |
kenjiArai | 0:5b88d5760320 | 662 | void debug_print(const char *p, int len, ATType type); |
kenjiArai | 0:5b88d5760320 | 663 | }; |
kenjiArai | 0:5b88d5760320 | 664 | |
kenjiArai | 0:5b88d5760320 | 665 | } // namespace mbed |
kenjiArai | 0:5b88d5760320 | 666 | |
kenjiArai | 0:5b88d5760320 | 667 | #endif //AT_HANDLER_H_ |