Parser for AT commands and similar protocols
Diff: ATParser.cpp
- Revision:
- 10:553f9ffaf657
- Parent:
- 9:9bcb87c27208
- Child:
- 11:fd406d4c4227
--- a/ATParser.cpp Mon Jul 20 21:28:39 2015 +0000 +++ b/ATParser.cpp Sun Jul 26 21:53:28 2015 +0000 @@ -17,97 +17,102 @@ * Parser for the AT command syntax * */ - + #include "ATParser.h" - -// This can be defined to assist in debugging -#define AT_ECHO 1 +#include "mbed_debug.h" // getc/putc handling with timeouts -int ATParser::putc(char c) { +int ATParser::putc(char c) +{ Timer timer; timer.start(); - + while (true) { - if (_serial->writeable()) + if (_serial->writeable()) { return _serial->putc(c); - - if (timer.read_ms() > _timeout) + } + if (timer.read_ms() > _timeout) { return -1; + } } } -int ATParser::getc() { +int ATParser::getc() +{ Timer timer; timer.start(); - + while (true) { - if (_serial->readable()) + if (_serial->readable()) { return _serial->getc(); - - if (timer.read_ms() > _timeout) + } + if (timer.read_ms() > _timeout) { return -1; + } } } -void ATParser::flush() { - while (_serial->readable()) +void ATParser::flush() +{ + while (_serial->readable()) { _serial->getc(); + } } // read/write handling with timeouts -int ATParser::write(const char *data, int size) { - int i; - for (i = 0; i < size; i++) { - if (putc(data[i]) < 0) +int ATParser::write(const char *data, int size) +{ + int i = 0; + for ( ; i < size; i++) { + if (putc(data[i]) < 0) { return -1; + } } - return i; } -int ATParser::read(char *data, int size) { - int i; - for (i = 0; i < size; i++) { +int ATParser::read(char *data, int size) +{ + int i = 0; + for ( ; i < size; i++) { int c = getc(); - if (c < 0) + if (c < 0) { return -1; - + } data[i] = c; } - return i; } // printf/scanf handling -int ATParser::vprintf(const char *format, va_list args) { - if (vsprintf(_buffer, format, args) < 0) +int ATParser::vprintf(const char *format, va_list args) +{ + if (vsprintf(_buffer, format, args) < 0) { return false; - - int i; - for (i = 0; _buffer[i]; i++) { - if (putc(_buffer[i]) < 0) + } + int i = 0; + for ( ; _buffer[i]; i++) { + if (putc(_buffer[i]) < 0) { return -1; + } } - return i; } -int ATParser::vscanf(const char *format, va_list args) { +int ATParser::vscanf(const char *format, va_list args) +{ // Since format is const, we need to copy it into our buffer to // add the line's null terminator and clobber value-matches with asterisks. // // We just use the beginning of the buffer to avoid unnecessary allocations. int i = 0; int offset = 0; - + while (format[i]) { - if (format[i] == '%' && - format[i+1] != '%' && - format[i+1] != '*') { + if (format[i] == '%' && format[i+1] != '%' && format[i+1] != '*') { _buffer[offset++] = '%'; _buffer[offset++] = '*'; i++; @@ -115,40 +120,40 @@ _buffer[offset++] = format[i++]; } } - + // Scanf has very poor support for catching errors // fortunately, we can abuse the %n specifier to determine // if the entire string was matched. _buffer[offset++] = '%'; _buffer[offset++] = 'n'; _buffer[offset++] = 0; - + // To workaround scanf's lack of error reporting, we actually // make two passes. One checks the validity with the modified - // format string that only stores the matched characters (%n). + // format string that only stores the matched characters (%n). // The other reads in the actual matched values. // // We keep trying the match until we succeed or some other error // derails us. int j = 0; - + while (true) { // Ran out of space - if (j+1 >= _buffer_size - offset) + if (j+1 >= _buffer_size - offset) { return false; - + } // Recieve next character int c = getc(); - if (c < 0) + if (c < 0) { return -1; - + } _buffer[offset + j++] = c; _buffer[offset + j] = 0; - + // Check for match int count = -1; sscanf(_buffer+offset, _buffer, &count); - + // We only succeed if all characters in the response are matched if (count == j) { // Store the found results @@ -160,30 +165,31 @@ // Command parsing with line handling -bool ATParser::vsend(const char *command, va_list args) { +bool ATParser::vsend(const char *command, va_list args) +{ // Create and send command - if (vsprintf(_buffer, command, args) < 0) + if (vsprintf(_buffer, command, args) < 0) { return false; - + } for (int i = 0; _buffer[i]; i++) { - if (putc(_buffer[i]) < 0) + if (putc(_buffer[i]) < 0) { return false; + } } - + // Finish with newline for (int i = 0; _delimiter[i]; i++) { - if (putc(_delimiter[i]) < 0) + if (putc(_delimiter[i]) < 0) { return false; + } } - -#ifdef AT_ECHO - ::printf("AT> %s\r\n", _buffer); -#endif - + + debug_if(at_echo, "AT> %s\r\n", _buffer); return true; } -bool ATParser::vrecv(const char *response, va_list args) { +bool ATParser::vrecv(const char *response, va_list args) +{ // Iterate through each line in the expected response while (response[0]) { // Since response is const, we need to copy it into our buffer to @@ -192,14 +198,12 @@ // We just use the beginning of the buffer to avoid unnecessary allocations. int i = 0; int offset = 0; - + while (response[i]) { if (memcmp(&response[i+1-_delim_size], _delimiter, _delim_size) == 0) { i++; break; - } else if (response[i] == '%' && - response[i+1] != '%' && - response[i+1] != '*') { + } else if (response[i] == '%' && response[i+1] != '%' && response[i+1] != '*') { _buffer[offset++] = '%'; _buffer[offset++] = '*'; i++; @@ -207,73 +211,70 @@ _buffer[offset++] = response[i++]; } } - + // Scanf has very poor support for catching errors // fortunately, we can abuse the %n specifier to determine // if the entire string was matched. _buffer[offset++] = '%'; _buffer[offset++] = 'n'; _buffer[offset++] = 0; - + // To workaround scanf's lack of error reporting, we actually // make two passes. One checks the validity with the modified - // format string that only stores the matched characters (%n). + // format string that only stores the matched characters (%n). // The other reads in the actual matched values. // // We keep trying the match until we succeed or some other error // derails us. int j = 0; - + while (true) { // Ran out of space - if (j+1 >= _buffer_size - offset) + if (j+1 >= _buffer_size - offset) { return false; - + } // Recieve next character int c = getc(); - if (c < 0) + if (c < 0) { return false; - + } _buffer[offset + j++] = c; _buffer[offset + j] = 0; - + // Check for match int count = -1; sscanf(_buffer+offset, _buffer, &count); - + // We only succeed if all characters in the response are matched if (count == j) { -#ifdef AT_ECHO - ::printf("AT= %s\r\n", _buffer+offset); -#endif + debug_if(at_echo, "AT= %s\r\n", _buffer+offset); // Reuse the front end of the buffer memcpy(_buffer, response, i); _buffer[i] = 0; - + // Store the found results vsscanf(_buffer+offset, _buffer, args); - + // Jump to next line and continue parsing response += i; break; } - + // Clear the buffer when we hit a newline if (strcmp(&_buffer[offset + j-_delim_size], _delimiter) == 0) { -#ifdef AT_ECHO - ::printf("AT< %s", _buffer+offset); -#endif + debug_if(at_echo, "AT< %s", _buffer+offset); j = 0; } } } - + return true; } // Mapping to vararg functions -int ATParser::printf(const char *format, ...) { +int ATParser::printf(const char *format, ...) +{ va_list args; va_start(args, format); int res = vprintf(format, args); @@ -281,7 +282,8 @@ return res; } -int ATParser::scanf(const char *format, ...) { +int ATParser::scanf(const char *format, ...) +{ va_list args; va_start(args, format); int res = vscanf(format, args); @@ -289,7 +291,8 @@ return res; } -bool ATParser::send(const char *command, ...) { +bool ATParser::send(const char *command, ...) +{ va_list args; va_start(args, command); bool res = vsend(command, args); @@ -297,7 +300,8 @@ return res; } -bool ATParser::recv(const char *response, ...) { +bool ATParser::recv(const char *response, ...) +{ va_list args; va_start(args, response); bool res = vrecv(response, args);