The driver for the ESP8266 WiFi module

Dependents:   Datarecorder2

Fork of esp8266-driver by ESP8266

Committer:
group-ESP8266
Date:
Thu Jan 12 21:57:48 2017 +0000
Revision:
0:6946b0b9e323
Initial commit

Who changed what in which revision?

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