emw3162 driver for mbed os 5

Fork of emw3162-driver by Maggie Mei

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ATParser.cpp Source File

ATParser.cpp

00001 /* Copyright (c) 2015 ARM Limited
00002  *
00003  * Licensed under the Apache License, Version 2.0 (the "License");
00004  * you may not use this file except in compliance with the License.
00005  * You may obtain a copy of the License at
00006  *
00007  *     http://www.apache.org/licenses/LICENSE-2.0
00008  *
00009  * Unless required by applicable law or agreed to in writing, software
00010  * distributed under the License is distributed on an "AS IS" BASIS,
00011  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012  * See the License for the specific language governing permissions and
00013  * limitations under the License.
00014  *
00015  * @section DESCRIPTION
00016  *
00017  * Parser for the AT command syntax
00018  *
00019  */
00020 
00021 #include "ATParser.h"
00022 #include "mbed_debug.h"
00023 
00024 
00025 // getc/putc handling with timeouts
00026 int ATParser::putc(char c)
00027 {
00028     Timer timer;
00029     timer.start();
00030 
00031     while (true) {
00032         if (_serial->writeable()) {
00033             return _serial->putc(c);
00034         }
00035         if (timer.read_ms() > _timeout) {
00036             return -1;
00037         }
00038     }
00039 }
00040 
00041 int ATParser::getc()
00042 {
00043     Timer timer;
00044     timer.start();
00045 
00046     while (true) {
00047         if (_serial->readable()) {
00048             return _serial->getc();
00049         }
00050         if (timer.read_ms() > _timeout) {
00051             return -1;
00052         }
00053     }
00054 }
00055 
00056 void ATParser::flush()
00057 {
00058     while (_serial->readable()) {
00059         _serial->getc();
00060     }
00061 }
00062 
00063 
00064 // read/write handling with timeouts
00065 int ATParser::write(const char *data, int size)
00066 {
00067     int i = 0;
00068     for ( ; i < size; i++) {
00069         if (putc(data[i]) < 0) {
00070             return -1;
00071         }
00072     }
00073     return i;
00074 }
00075 
00076 int ATParser::read(char *data, int size)
00077 {
00078     int i = 0;
00079     for ( ; i < size; i++) {
00080         int c = getc();
00081         if (c < 0) {
00082             return -1;
00083         }
00084         data[i] = c;
00085     }
00086     return i;
00087 }
00088 
00089 
00090 // printf/scanf handling
00091 int ATParser::vprintf(const char *format, va_list args)
00092 {
00093     if (vsprintf(_buffer, format, args) < 0) {
00094         return false;
00095     }
00096     int i = 0;
00097     for ( ; _buffer[i]; i++) {
00098         if (putc(_buffer[i]) < 0) {
00099             return -1;
00100         }
00101     }
00102     return i;
00103 }
00104 
00105 int ATParser::vscanf(const char *format, va_list args)
00106 {
00107     // Since format is const, we need to copy it into our buffer to
00108     // add the line's null terminator and clobber value-matches with asterisks.
00109     //
00110     // We just use the beginning of the buffer to avoid unnecessary allocations.
00111     int i = 0;
00112     int offset = 0;
00113 
00114     while (format[i]) {
00115         if (format[i] == '%' && format[i+1] != '%' && format[i+1] != '*') {
00116             _buffer[offset++] = '%';
00117             _buffer[offset++] = '*';
00118             i++;
00119         } else {
00120             _buffer[offset++] = format[i++];
00121         }
00122     }
00123 
00124     // Scanf has very poor support for catching errors
00125     // fortunately, we can abuse the %n specifier to determine
00126     // if the entire string was matched.
00127     _buffer[offset++] = '%';
00128     _buffer[offset++] = 'n';
00129     _buffer[offset++] = 0;
00130 
00131     // To workaround scanf's lack of error reporting, we actually
00132     // make two passes. One checks the validity with the modified
00133     // format string that only stores the matched characters (%n).
00134     // The other reads in the actual matched values.
00135     //
00136     // We keep trying the match until we succeed or some other error
00137     // derails us.
00138     int j = 0;
00139 
00140     while (true) {
00141         // Ran out of space
00142         if (j+1 >= _buffer_size - offset) {
00143             return false;
00144         }
00145         // Recieve next character
00146         int c = getc();
00147         if (c < 0) {
00148             return -1;
00149         }
00150         _buffer[offset + j++] = c;
00151         _buffer[offset + j] = 0;
00152 
00153         // Check for match
00154         int count = -1;
00155         sscanf(_buffer+offset, _buffer, &count);
00156 
00157         // We only succeed if all characters in the response are matched
00158         if (count == j) {
00159             // Store the found results
00160             vsscanf(_buffer+offset, format, args);
00161             return j;
00162         }
00163     }
00164 }
00165 
00166 
00167 // Command parsing with line handling
00168 bool ATParser::vsend(const char *command, va_list args)
00169 {
00170     // Create and send command
00171     if (vsprintf(_buffer, command, args) < 0) {
00172         return false;
00173     }
00174 
00175     for (int i = 0; _buffer[i]; i++) {
00176         if (putc(_buffer[i]) < 0) {
00177             return false;
00178         }
00179     }
00180 
00181     // Finish with newline//
00182     char s[] = "\x0d";
00183     for (int i = 0; s[i]; i++){
00184         if(putc(s[i]) < 0)
00185             printf("send <CR> error\n");
00186     }
00187     
00188     debug_if(dbg_on, "AT> %s\r\n", _buffer);
00189     return true;
00190 }
00191 
00192 bool ATParser::vrecv(const char *response, va_list args)
00193 {
00194     // Iterate through each line in the expected response
00195     while (response[0]) {
00196         // Since response is const, we need to copy it into our buffer to
00197         // add the line's null terminator and clobber value-matches with asterisks.
00198         //
00199         // We just use the beginning of the buffer to avoid unnecessary allocations.
00200         int i = 0;
00201         int offset = 0;
00202 
00203         while (response[i]) {
00204             if (memcmp(&response[i+1-_delim_size], _delimiter, _delim_size) == 0) {
00205                 i++;
00206                 break;
00207             } else if (response[i] == '%' && response[i+1] != '%' && response[i+1] != '*') {
00208                 _buffer[offset++] = '%';
00209                 _buffer[offset++] = '*';
00210                 i++;
00211             } else {
00212                 _buffer[offset++] = response[i++];
00213             }
00214         }
00215 
00216         // Scanf has very poor support for catching errors
00217         // fortunately, we can abuse the %n specifier to determine
00218         // if the entire string was matched.
00219         _buffer[offset++] = '%';
00220         _buffer[offset++] = 'n';
00221         _buffer[offset++] = 0;
00222 
00223         // To workaround scanf's lack of error reporting, we actually
00224         // make two passes. One checks the validity with the modified
00225         // format string that only stores the matched characters (%n).
00226         // The other reads in the actual matched values.
00227         //
00228         // We keep trying the match until we succeed or some other error
00229         // derails us.
00230         int j = 0;
00231 
00232         while (true) {
00233             // Recieve next character
00234             int c = getc();
00235             //printf("111111111c= %d\n", c);
00236             if (c < 0) {
00237                 return false;
00238             }
00239             
00240             if (c == 0x0d)
00241                 c = '#';
00242                 
00243             _buffer[offset + j++] = c;
00244             _buffer[offset + j] = 0;
00245 
00246             // Check for oob data
00247             for (int k = 0; k < _oobs.size(); k++) {
00248                 if (j == _oobs[k].len && memcmp(
00249                         _oobs[k].prefix, _buffer+offset, _oobs[k].len) == 0) {
00250                     debug_if(dbg_on, "AT! %s\r\n", _oobs[k].prefix);
00251                     _oobs[k].cb();
00252 
00253                     // oob may have corrupted non-reentrant buffer,
00254                     // so we need to set it up again
00255                     return vrecv(response, args);
00256                 }
00257             }
00258 
00259             // Check for match
00260             int count = -1;
00261             sscanf(_buffer+offset, _buffer, &count);
00262             //printf("_buffer+offset is %s, _buffer is %s\n", _buffer+offset, _buffer);
00263 
00264             // We only succeed if all characters in the response are matched
00265             if (count == j) {
00266                 debug_if(dbg_on, "AT= %s\r\n", _buffer+offset);
00267                 // Reuse the front end of the buffer
00268                 memcpy(_buffer, response, i);
00269                 _buffer[i] = 0;
00270 
00271                 // Store the found results
00272                 vsscanf(_buffer+offset, _buffer, args);
00273 
00274                 // Jump to next line and continue parsing
00275                 response += i;
00276                 break;
00277             }
00278 
00279             // Clear the buffer when we hit a newline or ran out of space
00280             // running out of space usually means we ran into binary data
00281             if (c == '\n' || j+1 >= _buffer_size - offset ||
00282                 strcmp(&_buffer[offset + j-_delim_size], _delimiter) == 0) {
00283                 
00284                 debug_if(dbg_on, "AT< %s", _buffer+offset);
00285                 j = 0;
00286             }
00287         }
00288     }
00289 
00290     return true;
00291 }
00292 
00293 
00294 //// Mapping to vararg functions
00295 //int ATParser::printf(const char *format, ...)
00296 //{
00297 //    va_list args;
00298 //    va_start(args, format);
00299 //    int res = vprintf(format, args);
00300 //    va_end(args);
00301 //    return res;
00302 //}
00303 
00304 int ATParser::scanf(const char *format, ...)
00305 {
00306     va_list args;
00307     va_start(args, format);
00308     int res = vscanf(format, args);
00309     va_end(args);
00310     return res;
00311 }
00312 
00313 bool ATParser::send(const char *command, ...)
00314 {
00315     va_list args;
00316     va_start(args, command);
00317     bool res = vsend(command, args);
00318     va_end(args);
00319     return res;
00320 }
00321 
00322 bool ATParser::recv(const char *response, ...)
00323 {
00324     va_list args;
00325     va_start(args, response);
00326     bool res = vrecv(response, args);
00327     va_end(args);
00328     return res;
00329 }
00330 
00331 
00332 // oob registration
00333 void ATParser::oob(const char *prefix, Callback<void()> cb)
00334 {
00335     struct oob oob;
00336     oob.len = strlen(prefix);
00337     oob.prefix = prefix;
00338     oob.cb = cb;
00339     _oobs.push_back(oob);
00340 }