inport from local

Dependents:   Hobbyking_Cheetah_0511

Committer:
NYX
Date:
Mon Mar 16 06:35:48 2020 +0000
Revision:
0:85b3fd62ea1a
reinport to mbed;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
NYX 0:85b3fd62ea1a 1 /* Copyright (c) 2017 ARM Limited
NYX 0:85b3fd62ea1a 2 *
NYX 0:85b3fd62ea1a 3 * Licensed under the Apache License, Version 2.0 (the "License");
NYX 0:85b3fd62ea1a 4 * you may not use this file except in compliance with the License.
NYX 0:85b3fd62ea1a 5 * You may obtain a copy of the License at
NYX 0:85b3fd62ea1a 6 *
NYX 0:85b3fd62ea1a 7 * http://www.apache.org/licenses/LICENSE-2.0
NYX 0:85b3fd62ea1a 8 *
NYX 0:85b3fd62ea1a 9 * Unless required by applicable law or agreed to in writing, software
NYX 0:85b3fd62ea1a 10 * distributed under the License is distributed on an "AS IS" BASIS,
NYX 0:85b3fd62ea1a 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
NYX 0:85b3fd62ea1a 12 * See the License for the specific language governing permissions and
NYX 0:85b3fd62ea1a 13 * limitations under the License.
NYX 0:85b3fd62ea1a 14 *
NYX 0:85b3fd62ea1a 15 * @section DESCRIPTION
NYX 0:85b3fd62ea1a 16 *
NYX 0:85b3fd62ea1a 17 * Parser for the AT command syntax
NYX 0:85b3fd62ea1a 18 *
NYX 0:85b3fd62ea1a 19 */
NYX 0:85b3fd62ea1a 20
NYX 0:85b3fd62ea1a 21 #include "ATCmdParser.h"
NYX 0:85b3fd62ea1a 22 #include "mbed_poll.h"
NYX 0:85b3fd62ea1a 23 #include "mbed_debug.h"
NYX 0:85b3fd62ea1a 24
NYX 0:85b3fd62ea1a 25 #ifdef LF
NYX 0:85b3fd62ea1a 26 #undef LF
NYX 0:85b3fd62ea1a 27 #define LF 10
NYX 0:85b3fd62ea1a 28 #else
NYX 0:85b3fd62ea1a 29 #define LF 10
NYX 0:85b3fd62ea1a 30 #endif
NYX 0:85b3fd62ea1a 31
NYX 0:85b3fd62ea1a 32 #ifdef CR
NYX 0:85b3fd62ea1a 33 #undef CR
NYX 0:85b3fd62ea1a 34 #define CR 13
NYX 0:85b3fd62ea1a 35 #else
NYX 0:85b3fd62ea1a 36 #define CR 13
NYX 0:85b3fd62ea1a 37 #endif
NYX 0:85b3fd62ea1a 38
NYX 0:85b3fd62ea1a 39 // getc/putc handling with timeouts
NYX 0:85b3fd62ea1a 40 int ATCmdParser::putc(char c)
NYX 0:85b3fd62ea1a 41 {
NYX 0:85b3fd62ea1a 42 pollfh fhs;
NYX 0:85b3fd62ea1a 43 fhs.fh = _fh;
NYX 0:85b3fd62ea1a 44 fhs.events = POLLOUT;
NYX 0:85b3fd62ea1a 45
NYX 0:85b3fd62ea1a 46 int count = poll(&fhs, 1, _timeout);
NYX 0:85b3fd62ea1a 47 if (count > 0 && (fhs.revents & POLLOUT)) {
NYX 0:85b3fd62ea1a 48 return _fh->write(&c, 1) == 1 ? 0 : -1;
NYX 0:85b3fd62ea1a 49 } else {
NYX 0:85b3fd62ea1a 50 return -1;
NYX 0:85b3fd62ea1a 51 }
NYX 0:85b3fd62ea1a 52 }
NYX 0:85b3fd62ea1a 53
NYX 0:85b3fd62ea1a 54 int ATCmdParser::getc()
NYX 0:85b3fd62ea1a 55 {
NYX 0:85b3fd62ea1a 56 pollfh fhs;
NYX 0:85b3fd62ea1a 57 fhs.fh = _fh;
NYX 0:85b3fd62ea1a 58 fhs.events = POLLIN;
NYX 0:85b3fd62ea1a 59
NYX 0:85b3fd62ea1a 60 int count = poll(&fhs, 1, _timeout);
NYX 0:85b3fd62ea1a 61 if (count > 0 && (fhs.revents & POLLIN)) {
NYX 0:85b3fd62ea1a 62 unsigned char ch;
NYX 0:85b3fd62ea1a 63 return _fh->read(&ch, 1) == 1 ? ch : -1;
NYX 0:85b3fd62ea1a 64 } else {
NYX 0:85b3fd62ea1a 65 return -1;
NYX 0:85b3fd62ea1a 66 }
NYX 0:85b3fd62ea1a 67 }
NYX 0:85b3fd62ea1a 68
NYX 0:85b3fd62ea1a 69 void ATCmdParser::flush()
NYX 0:85b3fd62ea1a 70 {
NYX 0:85b3fd62ea1a 71 while (_fh->readable()) {
NYX 0:85b3fd62ea1a 72 unsigned char ch;
NYX 0:85b3fd62ea1a 73 _fh->read(&ch, 1);
NYX 0:85b3fd62ea1a 74 }
NYX 0:85b3fd62ea1a 75 }
NYX 0:85b3fd62ea1a 76
NYX 0:85b3fd62ea1a 77
NYX 0:85b3fd62ea1a 78 // read/write handling with timeouts
NYX 0:85b3fd62ea1a 79 int ATCmdParser::write(const char *data, int size)
NYX 0:85b3fd62ea1a 80 {
NYX 0:85b3fd62ea1a 81 int i = 0;
NYX 0:85b3fd62ea1a 82 for ( ; i < size; i++) {
NYX 0:85b3fd62ea1a 83 if (putc(data[i]) < 0) {
NYX 0:85b3fd62ea1a 84 return -1;
NYX 0:85b3fd62ea1a 85 }
NYX 0:85b3fd62ea1a 86 }
NYX 0:85b3fd62ea1a 87 return i;
NYX 0:85b3fd62ea1a 88 }
NYX 0:85b3fd62ea1a 89
NYX 0:85b3fd62ea1a 90 int ATCmdParser::read(char *data, int size)
NYX 0:85b3fd62ea1a 91 {
NYX 0:85b3fd62ea1a 92 int i = 0;
NYX 0:85b3fd62ea1a 93 for ( ; i < size; i++) {
NYX 0:85b3fd62ea1a 94 int c = getc();
NYX 0:85b3fd62ea1a 95 if (c < 0) {
NYX 0:85b3fd62ea1a 96 return -1;
NYX 0:85b3fd62ea1a 97 }
NYX 0:85b3fd62ea1a 98 data[i] = c;
NYX 0:85b3fd62ea1a 99 }
NYX 0:85b3fd62ea1a 100 return i;
NYX 0:85b3fd62ea1a 101 }
NYX 0:85b3fd62ea1a 102
NYX 0:85b3fd62ea1a 103
NYX 0:85b3fd62ea1a 104 // printf/scanf handling
NYX 0:85b3fd62ea1a 105 int ATCmdParser::vprintf(const char *format, va_list args)
NYX 0:85b3fd62ea1a 106 {
NYX 0:85b3fd62ea1a 107
NYX 0:85b3fd62ea1a 108 if (vsprintf(_buffer, format, args) < 0) {
NYX 0:85b3fd62ea1a 109 return false;
NYX 0:85b3fd62ea1a 110 }
NYX 0:85b3fd62ea1a 111
NYX 0:85b3fd62ea1a 112 int i = 0;
NYX 0:85b3fd62ea1a 113 for ( ; _buffer[i]; i++) {
NYX 0:85b3fd62ea1a 114 if (putc(_buffer[i]) < 0) {
NYX 0:85b3fd62ea1a 115 return -1;
NYX 0:85b3fd62ea1a 116 }
NYX 0:85b3fd62ea1a 117 }
NYX 0:85b3fd62ea1a 118 return i;
NYX 0:85b3fd62ea1a 119 }
NYX 0:85b3fd62ea1a 120
NYX 0:85b3fd62ea1a 121 int ATCmdParser::vscanf(const char *format, va_list args)
NYX 0:85b3fd62ea1a 122 {
NYX 0:85b3fd62ea1a 123 // Since format is const, we need to copy it into our buffer to
NYX 0:85b3fd62ea1a 124 // add the line's null terminator and clobber value-matches with asterisks.
NYX 0:85b3fd62ea1a 125 //
NYX 0:85b3fd62ea1a 126 // We just use the beginning of the buffer to avoid unnecessary allocations.
NYX 0:85b3fd62ea1a 127 int i = 0;
NYX 0:85b3fd62ea1a 128 int offset = 0;
NYX 0:85b3fd62ea1a 129
NYX 0:85b3fd62ea1a 130 while (format[i]) {
NYX 0:85b3fd62ea1a 131 if (format[i] == '%' && format[i+1] != '%' && format[i+1] != '*') {
NYX 0:85b3fd62ea1a 132 _buffer[offset++] = '%';
NYX 0:85b3fd62ea1a 133 _buffer[offset++] = '*';
NYX 0:85b3fd62ea1a 134 i++;
NYX 0:85b3fd62ea1a 135 } else {
NYX 0:85b3fd62ea1a 136 _buffer[offset++] = format[i++];
NYX 0:85b3fd62ea1a 137 }
NYX 0:85b3fd62ea1a 138 }
NYX 0:85b3fd62ea1a 139
NYX 0:85b3fd62ea1a 140 // Scanf has very poor support for catching errors
NYX 0:85b3fd62ea1a 141 // fortunately, we can abuse the %n specifier to determine
NYX 0:85b3fd62ea1a 142 // if the entire string was matched.
NYX 0:85b3fd62ea1a 143 _buffer[offset++] = '%';
NYX 0:85b3fd62ea1a 144 _buffer[offset++] = 'n';
NYX 0:85b3fd62ea1a 145 _buffer[offset++] = 0;
NYX 0:85b3fd62ea1a 146
NYX 0:85b3fd62ea1a 147 // To workaround scanf's lack of error reporting, we actually
NYX 0:85b3fd62ea1a 148 // make two passes. One checks the validity with the modified
NYX 0:85b3fd62ea1a 149 // format string that only stores the matched characters (%n).
NYX 0:85b3fd62ea1a 150 // The other reads in the actual matched values.
NYX 0:85b3fd62ea1a 151 //
NYX 0:85b3fd62ea1a 152 // We keep trying the match until we succeed or some other error
NYX 0:85b3fd62ea1a 153 // derails us.
NYX 0:85b3fd62ea1a 154 int j = 0;
NYX 0:85b3fd62ea1a 155
NYX 0:85b3fd62ea1a 156 while (true) {
NYX 0:85b3fd62ea1a 157 // Ran out of space
NYX 0:85b3fd62ea1a 158 if (j+1 >= _buffer_size - offset) {
NYX 0:85b3fd62ea1a 159 return false;
NYX 0:85b3fd62ea1a 160 }
NYX 0:85b3fd62ea1a 161 // Recieve next character
NYX 0:85b3fd62ea1a 162 int c = getc();
NYX 0:85b3fd62ea1a 163 if (c < 0) {
NYX 0:85b3fd62ea1a 164 return -1;
NYX 0:85b3fd62ea1a 165 }
NYX 0:85b3fd62ea1a 166 _buffer[offset + j++] = c;
NYX 0:85b3fd62ea1a 167 _buffer[offset + j] = 0;
NYX 0:85b3fd62ea1a 168
NYX 0:85b3fd62ea1a 169 // Check for match
NYX 0:85b3fd62ea1a 170 int count = -1;
NYX 0:85b3fd62ea1a 171 sscanf(_buffer+offset, _buffer, &count);
NYX 0:85b3fd62ea1a 172
NYX 0:85b3fd62ea1a 173 // We only succeed if all characters in the response are matched
NYX 0:85b3fd62ea1a 174 if (count == j) {
NYX 0:85b3fd62ea1a 175 // Store the found results
NYX 0:85b3fd62ea1a 176 vsscanf(_buffer+offset, format, args);
NYX 0:85b3fd62ea1a 177 return j;
NYX 0:85b3fd62ea1a 178 }
NYX 0:85b3fd62ea1a 179 }
NYX 0:85b3fd62ea1a 180 }
NYX 0:85b3fd62ea1a 181
NYX 0:85b3fd62ea1a 182
NYX 0:85b3fd62ea1a 183 // Command parsing with line handling
NYX 0:85b3fd62ea1a 184 bool ATCmdParser::vsend(const char *command, va_list args)
NYX 0:85b3fd62ea1a 185 {
NYX 0:85b3fd62ea1a 186 // Create and send command
NYX 0:85b3fd62ea1a 187 if (vsprintf(_buffer, command, args) < 0) {
NYX 0:85b3fd62ea1a 188 return false;
NYX 0:85b3fd62ea1a 189 }
NYX 0:85b3fd62ea1a 190
NYX 0:85b3fd62ea1a 191 for (int i = 0; _buffer[i]; i++) {
NYX 0:85b3fd62ea1a 192 if (putc(_buffer[i]) < 0) {
NYX 0:85b3fd62ea1a 193 return false;
NYX 0:85b3fd62ea1a 194 }
NYX 0:85b3fd62ea1a 195 }
NYX 0:85b3fd62ea1a 196
NYX 0:85b3fd62ea1a 197 // Finish with newline
NYX 0:85b3fd62ea1a 198 for (size_t i = 0; _output_delimiter[i]; i++) {
NYX 0:85b3fd62ea1a 199 if (putc(_output_delimiter[i]) < 0) {
NYX 0:85b3fd62ea1a 200 return false;
NYX 0:85b3fd62ea1a 201 }
NYX 0:85b3fd62ea1a 202 }
NYX 0:85b3fd62ea1a 203
NYX 0:85b3fd62ea1a 204 debug_if(_dbg_on, "AT> %s\n", _buffer);
NYX 0:85b3fd62ea1a 205 return true;
NYX 0:85b3fd62ea1a 206 }
NYX 0:85b3fd62ea1a 207
NYX 0:85b3fd62ea1a 208 bool ATCmdParser::vrecv(const char *response, va_list args)
NYX 0:85b3fd62ea1a 209 {
NYX 0:85b3fd62ea1a 210 restart:
NYX 0:85b3fd62ea1a 211 _aborted = false;
NYX 0:85b3fd62ea1a 212 // Iterate through each line in the expected response
NYX 0:85b3fd62ea1a 213 while (response[0]) {
NYX 0:85b3fd62ea1a 214 // Since response is const, we need to copy it into our buffer to
NYX 0:85b3fd62ea1a 215 // add the line's null terminator and clobber value-matches with asterisks.
NYX 0:85b3fd62ea1a 216 //
NYX 0:85b3fd62ea1a 217 // We just use the beginning of the buffer to avoid unnecessary allocations.
NYX 0:85b3fd62ea1a 218 int i = 0;
NYX 0:85b3fd62ea1a 219 int offset = 0;
NYX 0:85b3fd62ea1a 220 bool whole_line_wanted = false;
NYX 0:85b3fd62ea1a 221
NYX 0:85b3fd62ea1a 222 while (response[i]) {
NYX 0:85b3fd62ea1a 223 if (response[i] == '%' && response[i+1] != '%' && response[i+1] != '*') {
NYX 0:85b3fd62ea1a 224 _buffer[offset++] = '%';
NYX 0:85b3fd62ea1a 225 _buffer[offset++] = '*';
NYX 0:85b3fd62ea1a 226 i++;
NYX 0:85b3fd62ea1a 227 } else {
NYX 0:85b3fd62ea1a 228 _buffer[offset++] = response[i++];
NYX 0:85b3fd62ea1a 229 // Find linebreaks, taking care not to be fooled if they're in a %[^\n] conversion specification
NYX 0:85b3fd62ea1a 230 if (response[i - 1] == '\n' && !(i >= 3 && response[i-3] == '[' && response[i-2] == '^')) {
NYX 0:85b3fd62ea1a 231 whole_line_wanted = true;
NYX 0:85b3fd62ea1a 232 break;
NYX 0:85b3fd62ea1a 233 }
NYX 0:85b3fd62ea1a 234 }
NYX 0:85b3fd62ea1a 235 }
NYX 0:85b3fd62ea1a 236
NYX 0:85b3fd62ea1a 237 // Scanf has very poor support for catching errors
NYX 0:85b3fd62ea1a 238 // fortunately, we can abuse the %n specifier to determine
NYX 0:85b3fd62ea1a 239 // if the entire string was matched.
NYX 0:85b3fd62ea1a 240 _buffer[offset++] = '%';
NYX 0:85b3fd62ea1a 241 _buffer[offset++] = 'n';
NYX 0:85b3fd62ea1a 242 _buffer[offset++] = 0;
NYX 0:85b3fd62ea1a 243
NYX 0:85b3fd62ea1a 244 debug_if(_dbg_on, "AT? %s\n", _buffer);
NYX 0:85b3fd62ea1a 245 // To workaround scanf's lack of error reporting, we actually
NYX 0:85b3fd62ea1a 246 // make two passes. One checks the validity with the modified
NYX 0:85b3fd62ea1a 247 // format string that only stores the matched characters (%n).
NYX 0:85b3fd62ea1a 248 // The other reads in the actual matched values.
NYX 0:85b3fd62ea1a 249 //
NYX 0:85b3fd62ea1a 250 // We keep trying the match until we succeed or some other error
NYX 0:85b3fd62ea1a 251 // derails us.
NYX 0:85b3fd62ea1a 252 int j = 0;
NYX 0:85b3fd62ea1a 253
NYX 0:85b3fd62ea1a 254 while (true) {
NYX 0:85b3fd62ea1a 255 // Receive next character
NYX 0:85b3fd62ea1a 256 int c = getc();
NYX 0:85b3fd62ea1a 257 if (c < 0) {
NYX 0:85b3fd62ea1a 258 debug_if(_dbg_on, "AT(Timeout)\n");
NYX 0:85b3fd62ea1a 259 return false;
NYX 0:85b3fd62ea1a 260 }
NYX 0:85b3fd62ea1a 261 // Simplify newlines (borrowed from retarget.cpp)
NYX 0:85b3fd62ea1a 262 if ((c == CR && _in_prev != LF) ||
NYX 0:85b3fd62ea1a 263 (c == LF && _in_prev != CR)) {
NYX 0:85b3fd62ea1a 264 _in_prev = c;
NYX 0:85b3fd62ea1a 265 c = '\n';
NYX 0:85b3fd62ea1a 266 } else if ((c == CR && _in_prev == LF) ||
NYX 0:85b3fd62ea1a 267 (c == LF && _in_prev == CR)) {
NYX 0:85b3fd62ea1a 268 _in_prev = c;
NYX 0:85b3fd62ea1a 269 // onto next character
NYX 0:85b3fd62ea1a 270 continue;
NYX 0:85b3fd62ea1a 271 } else {
NYX 0:85b3fd62ea1a 272 _in_prev = c;
NYX 0:85b3fd62ea1a 273 }
NYX 0:85b3fd62ea1a 274 _buffer[offset + j++] = c;
NYX 0:85b3fd62ea1a 275 _buffer[offset + j] = 0;
NYX 0:85b3fd62ea1a 276
NYX 0:85b3fd62ea1a 277 // Check for oob data
NYX 0:85b3fd62ea1a 278 for (struct oob *oob = _oobs; oob; oob = oob->next) {
NYX 0:85b3fd62ea1a 279 if ((unsigned)j == oob->len && memcmp(
NYX 0:85b3fd62ea1a 280 oob->prefix, _buffer+offset, oob->len) == 0) {
NYX 0:85b3fd62ea1a 281 debug_if(_dbg_on, "AT! %s\n", oob->prefix);
NYX 0:85b3fd62ea1a 282 oob->cb();
NYX 0:85b3fd62ea1a 283
NYX 0:85b3fd62ea1a 284 if (_aborted) {
NYX 0:85b3fd62ea1a 285 debug_if(_dbg_on, "AT(Aborted)\n");
NYX 0:85b3fd62ea1a 286 return false;
NYX 0:85b3fd62ea1a 287 }
NYX 0:85b3fd62ea1a 288 // oob may have corrupted non-reentrant buffer,
NYX 0:85b3fd62ea1a 289 // so we need to set it up again
NYX 0:85b3fd62ea1a 290 goto restart;
NYX 0:85b3fd62ea1a 291 }
NYX 0:85b3fd62ea1a 292 }
NYX 0:85b3fd62ea1a 293
NYX 0:85b3fd62ea1a 294 // Check for match
NYX 0:85b3fd62ea1a 295 int count = -1;
NYX 0:85b3fd62ea1a 296 if (whole_line_wanted && c != '\n') {
NYX 0:85b3fd62ea1a 297 // Don't attempt scanning until we get delimiter if they included it in format
NYX 0:85b3fd62ea1a 298 // This allows recv("Foo: %s\n") to work, and not match with just the first character of a string
NYX 0:85b3fd62ea1a 299 // (scanf does not itself match whitespace in its format string, so \n is not significant to it)
NYX 0:85b3fd62ea1a 300 } else {
NYX 0:85b3fd62ea1a 301 sscanf(_buffer+offset, _buffer, &count);
NYX 0:85b3fd62ea1a 302 }
NYX 0:85b3fd62ea1a 303
NYX 0:85b3fd62ea1a 304 // We only succeed if all characters in the response are matched
NYX 0:85b3fd62ea1a 305 if (count == j) {
NYX 0:85b3fd62ea1a 306 debug_if(_dbg_on, "AT= %s\n", _buffer+offset);
NYX 0:85b3fd62ea1a 307 // Reuse the front end of the buffer
NYX 0:85b3fd62ea1a 308 memcpy(_buffer, response, i);
NYX 0:85b3fd62ea1a 309 _buffer[i] = 0;
NYX 0:85b3fd62ea1a 310
NYX 0:85b3fd62ea1a 311 // Store the found results
NYX 0:85b3fd62ea1a 312 vsscanf(_buffer+offset, _buffer, args);
NYX 0:85b3fd62ea1a 313
NYX 0:85b3fd62ea1a 314 // Jump to next line and continue parsing
NYX 0:85b3fd62ea1a 315 response += i;
NYX 0:85b3fd62ea1a 316 break;
NYX 0:85b3fd62ea1a 317 }
NYX 0:85b3fd62ea1a 318
NYX 0:85b3fd62ea1a 319 // Clear the buffer when we hit a newline or ran out of space
NYX 0:85b3fd62ea1a 320 // running out of space usually means we ran into binary data
NYX 0:85b3fd62ea1a 321 if (c == '\n' || j+1 >= _buffer_size - offset) {
NYX 0:85b3fd62ea1a 322 debug_if(_dbg_on, "AT< %s", _buffer+offset);
NYX 0:85b3fd62ea1a 323 j = 0;
NYX 0:85b3fd62ea1a 324 }
NYX 0:85b3fd62ea1a 325 }
NYX 0:85b3fd62ea1a 326 }
NYX 0:85b3fd62ea1a 327
NYX 0:85b3fd62ea1a 328 return true;
NYX 0:85b3fd62ea1a 329 }
NYX 0:85b3fd62ea1a 330
NYX 0:85b3fd62ea1a 331 // Mapping to vararg functions
NYX 0:85b3fd62ea1a 332 int ATCmdParser::printf(const char *format, ...)
NYX 0:85b3fd62ea1a 333 {
NYX 0:85b3fd62ea1a 334 va_list args;
NYX 0:85b3fd62ea1a 335 va_start(args, format);
NYX 0:85b3fd62ea1a 336 int res = vprintf(format, args);
NYX 0:85b3fd62ea1a 337 va_end(args);
NYX 0:85b3fd62ea1a 338 return res;
NYX 0:85b3fd62ea1a 339 }
NYX 0:85b3fd62ea1a 340
NYX 0:85b3fd62ea1a 341 int ATCmdParser::scanf(const char *format, ...)
NYX 0:85b3fd62ea1a 342 {
NYX 0:85b3fd62ea1a 343 va_list args;
NYX 0:85b3fd62ea1a 344 va_start(args, format);
NYX 0:85b3fd62ea1a 345 int res = vscanf(format, args);
NYX 0:85b3fd62ea1a 346 va_end(args);
NYX 0:85b3fd62ea1a 347 return res;
NYX 0:85b3fd62ea1a 348 }
NYX 0:85b3fd62ea1a 349
NYX 0:85b3fd62ea1a 350 bool ATCmdParser::send(const char *command, ...)
NYX 0:85b3fd62ea1a 351 {
NYX 0:85b3fd62ea1a 352 va_list args;
NYX 0:85b3fd62ea1a 353 va_start(args, command);
NYX 0:85b3fd62ea1a 354 bool res = vsend(command, args);
NYX 0:85b3fd62ea1a 355 va_end(args);
NYX 0:85b3fd62ea1a 356 return res;
NYX 0:85b3fd62ea1a 357 }
NYX 0:85b3fd62ea1a 358
NYX 0:85b3fd62ea1a 359 bool ATCmdParser::recv(const char *response, ...)
NYX 0:85b3fd62ea1a 360 {
NYX 0:85b3fd62ea1a 361 va_list args;
NYX 0:85b3fd62ea1a 362 va_start(args, response);
NYX 0:85b3fd62ea1a 363 bool res = vrecv(response, args);
NYX 0:85b3fd62ea1a 364 va_end(args);
NYX 0:85b3fd62ea1a 365 return res;
NYX 0:85b3fd62ea1a 366 }
NYX 0:85b3fd62ea1a 367
NYX 0:85b3fd62ea1a 368 // oob registration
NYX 0:85b3fd62ea1a 369 void ATCmdParser::oob(const char *prefix, Callback<void()> cb)
NYX 0:85b3fd62ea1a 370 {
NYX 0:85b3fd62ea1a 371 struct oob *oob = new struct oob;
NYX 0:85b3fd62ea1a 372 oob->len = strlen(prefix);
NYX 0:85b3fd62ea1a 373 oob->prefix = prefix;
NYX 0:85b3fd62ea1a 374 oob->cb = cb;
NYX 0:85b3fd62ea1a 375 oob->next = _oobs;
NYX 0:85b3fd62ea1a 376 _oobs = oob;
NYX 0:85b3fd62ea1a 377 }
NYX 0:85b3fd62ea1a 378
NYX 0:85b3fd62ea1a 379 void ATCmdParser::abort()
NYX 0:85b3fd62ea1a 380 {
NYX 0:85b3fd62ea1a 381 _aborted = true;
NYX 0:85b3fd62ea1a 382 }