Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

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