ESP8266 driver from ARM

Dependents:   8-0_OneNet_IoT_demo STM32F103C8T6_OneNet_IoT

Committer:
TaylorGy
Date:
Wed Mar 29 03:09:15 2017 +0000
Revision:
0:dfb22bd0e039
ESP8266 driver from ARM

Who changed what in which revision?

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