Nicolas Borla / Mbed OS ROME2_Robot_Firmware
Committer:
boro
Date:
Tue Mar 09 13:10:40 2021 +0000
Revision:
3:6fe17b8a6d62
Parent:
0:4beb2ea291ec
SDBlockDevice added

Who changed what in which revision?

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