Biomimetics MBED Library w/ Added Support for CAN3

Dependents:   CAN_TEST SPIne_Plus_DYNO_SENSORS SPIne_Plus_v2 SPIne_Plus_Dyno_v2

Committer:
adimmit
Date:
Tue Mar 09 20:33:24 2021 +0000
Revision:
3:993b4d6ff61e
Parent:
0:083111ae2a11
added CAN3

Who changed what in which revision?

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