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