mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

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