init

Dependencies:   mbed

Committer:
Nathan Yonkee
Date:
Fri Mar 02 07:16:49 2018 -0700
Revision:
10:46a4cf51ee38
Parent:
9:d58e77ebd769
remove mbed-os

Who changed what in which revision?

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