This class provides SMS, USSD and modem file system support for u-blox modules on the C027 and C030 boards (excepting the C030 N2xx flavour) from mbed 5.5 onwards.
Dependents: example-ublox-at-cellular-interface-ext example-ublox-cellular-driver-gen HelloMQTT ublox_new_driver_test ... more
UbloxCellularDriverGen.cpp
00001 /* Copyright (c) 2017 ublox 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 00016 #include "UbloxCellularDriverGen.h" 00017 #include "string.h" 00018 #if defined(FEATURE_COMMON_PAL) 00019 #include "mbed_trace.h" 00020 #define TRACE_GROUP "UCID" 00021 #else 00022 #define tr_debug(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00023 #define tr_info(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00024 #define tr_warn(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00025 #define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00026 #endif 00027 00028 /********************************************************************** 00029 * PROTECTED METHODS: Short Message Service 00030 **********************************************************************/ 00031 00032 // URC for Short Message listing. 00033 void UbloxCellularDriverGen::CMGL_URC() 00034 { 00035 char buf[64]; 00036 int index; 00037 00038 // Note: not calling _at->recv() from here as we're 00039 // already in an _at->recv() 00040 // +CMGL: <ix>,... 00041 *buf = 0; 00042 if (read_at_to_char(buf, sizeof(buf), '\n') > 0) { 00043 // Now also read out the text message, so that we don't 00044 // accidentally trigger URCs or the like on any of 00045 // its contents 00046 *_smsBuf = 0; 00047 read_at_to_char(_smsBuf, sizeof(_smsBuf), '\n'); 00048 // Note: don't put any debug in here, this URC is being 00049 // called multiple times and debug may cause it to 00050 // miss characters 00051 if (sscanf(buf, ": %d,", &index) == 1) { 00052 _smsCount++; 00053 if ((_userSmsIndex != NULL) && (_userSmsNum > 0)) { 00054 *_userSmsIndex = index; 00055 _userSmsIndex++; 00056 _userSmsNum--; 00057 } 00058 } 00059 } 00060 } 00061 00062 // URC for new SMS messages. 00063 void UbloxCellularDriverGen::CMTI_URC() 00064 { 00065 char buf[32]; 00066 00067 // Note: not calling _at->recv() from here as we're 00068 // already in an _at->recv() 00069 *buf = 0; 00070 if (read_at_to_char(buf, sizeof (buf), '\n') > 0) { 00071 // No need to parse, any content is good 00072 tr_info("New SMS received"); 00073 } 00074 } 00075 00076 /********************************************************************** 00077 * PROTECTED METHODS: Unstructured Supplementary Service Data 00078 **********************************************************************/ 00079 00080 // URC for call waiting. 00081 void UbloxCellularDriverGen::CCWA_URC() 00082 { 00083 char buf[32]; 00084 int numChars; 00085 int a; 00086 int b = 0; 00087 00088 // Note: not calling _at->recv() from here as we're 00089 // already in an _at->recv() 00090 // +CCWA: <status>[, <class>] 00091 numChars = read_at_to_char(buf, sizeof (buf), '\n'); 00092 if (numChars > 0) { 00093 if (sscanf(buf, ": %d,%d", &a, &b) > 0) { 00094 if (_ssUrcBuf == NULL) { 00095 _ssUrcBuf = (char *) malloc(numChars + 5 + 1); 00096 if (_ssUrcBuf != NULL) { 00097 memcpy (_ssUrcBuf, "+CCWA", 5); 00098 memcpy (_ssUrcBuf + 5, buf, numChars); 00099 *(_ssUrcBuf + numChars + 5) = 0; 00100 if (a > 0) { 00101 debug_if(_debug_trace_on, "Calling Waiting is active"); 00102 } else { 00103 debug_if(_debug_trace_on, "Calling Waiting is not active"); 00104 } 00105 if (b > 0) { 00106 if (b & 0x01) { 00107 debug_if(_debug_trace_on, " for voice\n"); 00108 } 00109 if (b & 0x02) { 00110 debug_if(_debug_trace_on, " for data\n"); 00111 } 00112 if (b & 0x04) { 00113 debug_if(_debug_trace_on, " for fax\n"); 00114 } 00115 if (b & 0x08) { 00116 debug_if(_debug_trace_on, " for SMS\n"); 00117 } 00118 if (b & 0x10) { 00119 debug_if(_debug_trace_on, " for data circuit sync\n"); 00120 } 00121 if (b & 0x20) { 00122 debug_if(_debug_trace_on, " for data circuit async\n"); 00123 } 00124 if (b & 0x40) { 00125 debug_if(_debug_trace_on, " for dedicated packet access\n"); 00126 } 00127 if (b & 0x80) { 00128 debug_if(_debug_trace_on, " for dedicated PAD access\n"); 00129 } 00130 } 00131 } 00132 } 00133 } 00134 } 00135 } 00136 00137 // URC for call forwarding. 00138 void UbloxCellularDriverGen::CCFC_URC() 00139 { 00140 char buf[32]; 00141 int numChars; 00142 char num[32]; 00143 int a, b; 00144 int numValues; 00145 00146 // Note: not calling _at->recv() from here as we're 00147 // already in an _at->recv() 00148 // +CCFC: <status>[, <class>] 00149 numChars = read_at_to_char(buf, sizeof (buf), '\n'); 00150 if (numChars > 0) { 00151 memset (num, 0, sizeof (num)); 00152 numValues = sscanf(buf, ": %d,%d,\"%32[^\"][\"]", &a, &b, num); 00153 if (numValues > 0) { 00154 if (_ssUrcBuf == NULL) { 00155 _ssUrcBuf = (char *) malloc(numChars + 5 + 1); 00156 if (_ssUrcBuf != NULL) { 00157 memcpy (_ssUrcBuf, "+CCFC", 5); 00158 memcpy (_ssUrcBuf + 5, buf, numChars); 00159 *(_ssUrcBuf + numChars + 5) = 0; 00160 if (a > 0) { 00161 debug_if(_debug_trace_on, "Calling Forwarding is active "); 00162 } else { 00163 debug_if(_debug_trace_on, "Calling Forwarding is not active "); 00164 } 00165 if (numValues > 1) { 00166 if (b > 0) { 00167 if (b & 0x01) { 00168 debug_if(_debug_trace_on, " for voice"); 00169 } 00170 if (b & 0x02) { 00171 debug_if(_debug_trace_on, " for data"); 00172 } 00173 if (b & 0x04) { 00174 debug_if(_debug_trace_on, " for fax"); 00175 } 00176 if (b & 0x08) { 00177 debug_if(_debug_trace_on, " for SMS"); 00178 } 00179 if (b & 0x10) { 00180 debug_if(_debug_trace_on, " for data circuit sync"); 00181 } 00182 if (b & 0x20) { 00183 debug_if(_debug_trace_on, " for data circuit async"); 00184 } 00185 if (b & 0x40) { 00186 debug_if(_debug_trace_on, " for dedicated packet access"); 00187 } 00188 if (b & 0x80) { 00189 debug_if(_debug_trace_on, " for dedicated PAD access"); 00190 } 00191 } 00192 } 00193 if (numValues > 2) { 00194 debug_if(_debug_trace_on, " for %s\n", num); 00195 } else { 00196 debug_if(_debug_trace_on, "\n"); 00197 } 00198 } 00199 } 00200 } 00201 } 00202 } 00203 00204 00205 // URC for calling line ID restriction. 00206 void UbloxCellularDriverGen::CLIR_URC() 00207 { 00208 char buf[32]; 00209 int numChars; 00210 int a, b; 00211 int numValues; 00212 00213 // Note: not calling _at->recv() from here as we're 00214 // already in an _at->recv() 00215 // +CLIR: <n>[, <m>] 00216 numChars = read_at_to_char(buf, sizeof (buf), '\n'); 00217 if (numChars > 0) { 00218 numValues = sscanf(buf, ": %d,%d", &a, &b); 00219 if (numValues > 0) { 00220 if (_ssUrcBuf == NULL) { 00221 _ssUrcBuf = (char *) malloc(numChars + 5 + 1); 00222 if (_ssUrcBuf != NULL) { 00223 memcpy (_ssUrcBuf, "+CLIR", 5); 00224 memcpy (_ssUrcBuf + 5, buf, numChars); 00225 *(_ssUrcBuf + numChars + 5) = 0; 00226 switch (a) { 00227 case 0: 00228 debug_if(_debug_trace_on, "Calling Line ID restriction is as subscribed\n"); 00229 break; 00230 case 1: 00231 debug_if(_debug_trace_on, "Calling Line ID invocation "); 00232 break; 00233 case 2: 00234 debug_if(_debug_trace_on, "Calling Line ID suppression "); 00235 break; 00236 } 00237 if (numValues > 2) { 00238 switch (b) { 00239 case 0: 00240 debug_if(_debug_trace_on, " is not provisioned\n"); 00241 break; 00242 case 1: 00243 debug_if(_debug_trace_on, " is provisioned permanently\n"); 00244 break; 00245 case 2: 00246 debug_if(_debug_trace_on, " is unknown\n"); 00247 break; 00248 case 3: 00249 debug_if(_debug_trace_on, " is in temporary mode, presentation restricted\n"); 00250 break; 00251 case 4: 00252 debug_if(_debug_trace_on, " is in temporary mode, presentation allowed\n"); 00253 break; 00254 } 00255 } 00256 } 00257 } 00258 } 00259 } 00260 } 00261 00262 // URC for calling line ID presentation. 00263 void UbloxCellularDriverGen::CLIP_URC() 00264 { 00265 char buf[32]; 00266 int numChars; 00267 int a, b; 00268 int numValues; 00269 00270 // Note: not calling _at->recv() from here as we're 00271 // already in an _at->recv() 00272 // +CLIP: <n>[, <m>] 00273 numChars = read_at_to_char(buf, sizeof (buf), '\n'); 00274 if (numChars > 0) { 00275 numValues = sscanf(buf, ": %d,%d", &a, &b); 00276 if (numValues > 0) { 00277 if (_ssUrcBuf == NULL) { 00278 _ssUrcBuf = (char *) malloc(numChars + 5 + 1); 00279 if (_ssUrcBuf != NULL) { 00280 memcpy (_ssUrcBuf, "+CLIP", 5); 00281 memcpy (_ssUrcBuf + 5, buf, numChars); 00282 *(_ssUrcBuf + numChars + 5) = 0; 00283 switch (a) { 00284 case 0: 00285 debug_if(_debug_trace_on, "Calling Line ID disable "); 00286 break; 00287 case 1: 00288 debug_if(_debug_trace_on, "Calling Line ID enable "); 00289 break; 00290 } 00291 if (numValues > 1) { 00292 switch (b) { 00293 case 0: 00294 debug_if(_debug_trace_on, " is not provisioned\n"); 00295 break; 00296 case 1: 00297 debug_if(_debug_trace_on, " is provisioned\n"); 00298 break; 00299 case 2: 00300 debug_if(_debug_trace_on, " is unknown\n"); 00301 break; 00302 } 00303 } 00304 } 00305 } 00306 } 00307 } 00308 } 00309 00310 // URC for connected line ID presentation. 00311 void UbloxCellularDriverGen::COLP_URC() 00312 { 00313 char buf[32]; 00314 int numChars; 00315 int a, b; 00316 int numValues; 00317 00318 // Note: not calling _at->recv() from here as we're 00319 // already in an _at->recv() 00320 // +COLP: <n>[, <m>] 00321 numChars = read_at_to_char(buf, sizeof (buf), '\n'); 00322 if (numChars > 0) { 00323 numValues = sscanf(buf, ": %d,%d", &a, &b); 00324 if (numValues > 0) { 00325 if (_ssUrcBuf == NULL) { 00326 _ssUrcBuf = (char *) malloc(numChars + 5 + 1); 00327 if (_ssUrcBuf != NULL) { 00328 memcpy (_ssUrcBuf, "+COLP", 5); 00329 memcpy (_ssUrcBuf + 5, buf, numChars); 00330 *(_ssUrcBuf + numChars + 5) = 0; 00331 switch (a) { 00332 case 0: 00333 debug_if(_debug_trace_on, "Connected Line ID disable "); 00334 break; 00335 case 1: 00336 debug_if(_debug_trace_on, "Connected Line ID enable "); 00337 break; 00338 } 00339 if (numValues > 1) { 00340 switch (b) { 00341 case 0: 00342 debug_if(_debug_trace_on, " is not provisioned\n"); 00343 break; 00344 case 1: 00345 debug_if(_debug_trace_on, " is provisioned\n"); 00346 break; 00347 case 2: 00348 debug_if(_debug_trace_on, " is unknown\n"); 00349 break; 00350 } 00351 } 00352 } 00353 } 00354 } 00355 } 00356 } 00357 00358 // URC for connected line ID restriction. 00359 void UbloxCellularDriverGen::COLR_URC() 00360 { 00361 char buf[32]; 00362 int numChars; 00363 int a; 00364 00365 // Note: not calling _at->recv() from here as we're 00366 // already in an _at->recv() 00367 // +COLR: <status> 00368 numChars = read_at_to_char(buf, sizeof (buf), '\n'); 00369 if (numChars > 0) { 00370 if (sscanf(buf, ": %d", &a) > 0) { 00371 if (_ssUrcBuf == NULL) { 00372 _ssUrcBuf = (char *) malloc(numChars + 5 + 1); 00373 if (_ssUrcBuf != NULL) { 00374 memcpy (_ssUrcBuf, "+COLR", 5); 00375 memcpy (_ssUrcBuf + 5, buf, numChars); 00376 *(_ssUrcBuf + numChars + 5) = 0; 00377 switch (a) { 00378 case 0: 00379 debug_if(_debug_trace_on, "Connected Line ID restriction is not provisioned\n"); 00380 break; 00381 case 1: 00382 debug_if(_debug_trace_on, "Connected Line ID restriction is provisioned\n"); 00383 break; 00384 case 2: 00385 debug_if(_debug_trace_on, "Connected Line ID restriction is unknown\n"); 00386 break; 00387 } 00388 } 00389 } 00390 } 00391 } 00392 } 00393 00394 /********************************************************************** 00395 * PUBLIC METHODS: Generic 00396 **********************************************************************/ 00397 00398 // Constructor. 00399 UbloxCellularDriverGen::UbloxCellularDriverGen(PinName tx, PinName rx, 00400 int baud, bool debug_on) 00401 { 00402 _userSmsIndex = NULL; 00403 _userSmsNum = 0; 00404 _smsCount = 0; 00405 _ssUrcBuf = NULL; 00406 00407 // Initialise the base class, which starts the AT parser 00408 baseClassInit(tx, rx, baud, debug_on); 00409 00410 // URCs related to SMS 00411 _at->oob("+CMGL", callback(this, &UbloxCellularDriverGen::CMGL_URC)); 00412 // Include the colon with this one as otherwise it could be found 00413 // by +CMT, should it ever occur 00414 _at->oob("+CMTI:", callback(this, &UbloxCellularDriverGen::CMTI_URC)); 00415 00416 // URCs related to supplementary services 00417 _at->oob("+CCWA", callback(this, &UbloxCellularDriverGen::CCWA_URC)); 00418 _at->oob("+CCFC", callback(this, &UbloxCellularDriverGen::CCFC_URC)); 00419 _at->oob("+CLIR", callback(this, &UbloxCellularDriverGen::CLIR_URC)); 00420 _at->oob("+CLIP", callback(this, &UbloxCellularDriverGen::CLIP_URC)); 00421 _at->oob("+COLP", callback(this, &UbloxCellularDriverGen::COLP_URC)); 00422 _at->oob("+COLR", callback(this, &UbloxCellularDriverGen::COLR_URC)); 00423 } 00424 00425 // Destructor. 00426 UbloxCellularDriverGen::~UbloxCellularDriverGen() 00427 { 00428 } 00429 00430 /********************************************************************** 00431 * PUBLIC METHODS: Short Message Service 00432 **********************************************************************/ 00433 00434 // Count the number of messages on the module. 00435 int UbloxCellularDriverGen::smsList(const char* stat, int* index, int num) 00436 { 00437 int numMessages = -1; 00438 LOCK(); 00439 00440 _userSmsIndex = index; 00441 _userSmsNum = num; 00442 _smsCount = 0; 00443 // There is a callback to capture the result 00444 // +CMGL: <ix>,... 00445 _at->debug_on(false); // No time for AT interface debug 00446 // as the list comes out in one long 00447 // stream and we can lose characters if we 00448 // pause to do printfs 00449 if (_at->send("AT+CMGL=\"%s\"", stat) && _at->recv("OK\n")) { 00450 numMessages = _smsCount; 00451 } 00452 _at->debug_on(_debug_trace_on); 00453 00454 // Set this back to null so that the URC won't trample 00455 _userSmsIndex = NULL; 00456 00457 UNLOCK(); 00458 return numMessages; 00459 } 00460 00461 // Send an SMS message. 00462 bool UbloxCellularDriverGen::smsSend(const char* num, const char* buf) 00463 { 00464 bool success = false; 00465 char typeOfAddress = TYPE_OF_ADDRESS_NATIONAL; 00466 LOCK(); 00467 00468 if ((strlen (num) > 0) && (*(num) == '+')) { 00469 typeOfAddress = TYPE_OF_ADDRESS_INTERNATIONAL; 00470 } 00471 if (_at->send("AT+CMGS=\"%s\",%d", num, typeOfAddress) && _at->recv(">")) { 00472 if ((_at->write(buf, (int) strlen(buf)) >= (int) strlen(buf)) && 00473 (_at->putc(0x1A) == 0) && // CTRL-Z 00474 _at->recv("OK")) { 00475 success = true; 00476 } 00477 } 00478 00479 UNLOCK(); 00480 return success; 00481 } 00482 00483 bool UbloxCellularDriverGen::smsDelete(int index) 00484 { 00485 bool success; 00486 LOCK(); 00487 00488 success = _at->send("AT+CMGD=%d", index) && _at->recv("OK"); 00489 00490 UNLOCK(); 00491 return success; 00492 } 00493 00494 bool UbloxCellularDriverGen::smsRead(int index, char* num, char* buf, int len) 00495 { 00496 bool success = false; 00497 char * endOfString; 00498 int smsReadLength = 0; 00499 LOCK(); 00500 00501 if (len > 0) { 00502 //+CMGR: "REC READ", "+393488535999",,"07/04/05,18:02:28+08",145,4,0,0,"+393492000466",145,93 00503 // The text of the message. 00504 // OK 00505 memset (_smsBuf, 0, sizeof (SMS_BUFFER_SIZE)); // Ensure terminator 00506 if (_at->send("AT+CMGR=%d", index) && 00507 _at->recv("+CMGR: \"%*[^\"]\",\"%15[^\"]\"%*[^\n]\n", num) && 00508 _at->recv("%" stringify(SMS_BUFFER_SIZE) "[^\n]\n", _smsBuf) && 00509 _at->recv("OK")) { 00510 endOfString = strchr(_smsBuf, 0); 00511 if (endOfString != NULL) { 00512 smsReadLength = endOfString - _smsBuf; 00513 if (smsReadLength + 1 > len) { // +1 for terminator 00514 smsReadLength = len - 1; 00515 } 00516 memcpy(buf, _smsBuf, smsReadLength); 00517 *(buf + smsReadLength) = 0; // Add terminator 00518 success = true; 00519 } 00520 } 00521 } 00522 00523 UNLOCK(); 00524 return success; 00525 } 00526 00527 /********************************************************************** 00528 * PUBLIC METHODS: Unstructured Supplementary Service Data 00529 **********************************************************************/ 00530 00531 // Perform a USSD command. 00532 bool UbloxCellularDriverGen::ussdCommand(const char* cmd, char* buf, int len) 00533 { 00534 bool success = false; 00535 char * tmpBuf; 00536 int atTimeout; 00537 int x; 00538 Timer timer; 00539 LOCK(); 00540 atTimeout = _at_timeout; // Has to be inside LOCK()s 00541 00542 if (len > 0) { 00543 *buf = 0; 00544 if (len > USSD_STRING_LENGTH + 1) { 00545 len = USSD_STRING_LENGTH + 1; 00546 } 00547 00548 tmpBuf = (char *) malloc(USSD_STRING_LENGTH + 1); 00549 00550 if (tmpBuf != NULL) { 00551 memset (tmpBuf, 0, USSD_STRING_LENGTH + 1); 00552 // +CUSD: \"%*d, \"%128[^\"]\",%*d" 00553 if (_at->send("AT+CUSD=1,\"%s\"", cmd)) { 00554 // Wait for either +CUSD to come back or 00555 // one of the other SS related URCs to trigger 00556 if (_ssUrcBuf != NULL) { 00557 free(_ssUrcBuf); 00558 _ssUrcBuf = NULL; 00559 } 00560 timer.start(); 00561 _at->set_timeout(1000); 00562 while (!success && (timer.read_ms() < 30000)) { 00563 if (_at->recv("+CUSD: %*d,\"")) { 00564 // Note: don't wait for "OK" here as the +CUSD response may come 00565 // before or after the OK 00566 // Also, the return string may include newlines so can't just use 00567 // recv() to capture it as recv() will stop capturing at a newline. 00568 if (read_at_to_char(tmpBuf, USSD_STRING_LENGTH, '\"') > 0) { 00569 success = true; 00570 memcpy (buf, tmpBuf, len); 00571 *(buf + len - 1) = 0; 00572 } 00573 } else { 00574 // Some of the return values do not appear as +CUSD but 00575 // instead as the relevant URC for call waiting, call forwarding, 00576 // etc. Test those here. 00577 if (_ssUrcBuf != NULL) { 00578 success = true; 00579 x = strlen (_ssUrcBuf); 00580 if (x > len - 1 ) { 00581 x = len - 1; 00582 } 00583 memcpy (buf, _ssUrcBuf, x); 00584 *(buf + x) = 0; 00585 free (_ssUrcBuf); 00586 _ssUrcBuf = NULL; 00587 } 00588 } 00589 } 00590 at_set_timeout(atTimeout); 00591 timer.stop(); 00592 } 00593 } 00594 } 00595 00596 UNLOCK(); 00597 return success; 00598 } 00599 00600 /********************************************************************** 00601 * PUBLIC: Module File System 00602 **********************************************************************/ 00603 00604 // Delete a file from the module's file system. 00605 bool UbloxCellularDriverGen::delFile(const char* filename) 00606 { 00607 bool success; 00608 LOCK(); 00609 00610 success = _at->send("AT+UDELFILE=\"%s\"", filename) && _at->recv("OK"); 00611 00612 UNLOCK(); 00613 return success; 00614 } 00615 00616 // Write a buffer of data to a file in the module's file system. 00617 int UbloxCellularDriverGen::writeFile(const char* filename, const char* buf, int len) 00618 { 00619 int bytesWritten = -1; 00620 LOCK(); 00621 00622 if (_at->send("AT+UDWNFILE=\"%s\",%d", filename, len) && _at->recv(">")) { 00623 if ((_at->write(buf, len) >= len) && _at->recv("OK")) { 00624 bytesWritten = len; 00625 } 00626 } 00627 00628 UNLOCK(); 00629 return bytesWritten; 00630 } 00631 00632 // Read a file from the module's file system 00633 // Note: this is implemented with block reads since UARTSerial 00634 // does not currently allow flow control and there is a danger 00635 // of character loss with large whole-file reads 00636 int UbloxCellularDriverGen::readFile(const char* filename, char* buf, int len) 00637 { 00638 int countBytes = -1; // Counter for file reading (default value) 00639 int bytesToRead = fileSize(filename); // Retrieve the size of the file 00640 int offset = 0; 00641 int blockSize = FILE_BUFFER_SIZE; 00642 char respFilename[48 + 1]; 00643 int sz, sz_read; 00644 bool success = true; 00645 int ch = 0; 00646 int timeLimit; 00647 Timer timer; 00648 00649 debug_if(_debug_trace_on, "readFile: filename is %s; size is %d\n", filename, bytesToRead); 00650 00651 memset(respFilename, 0, sizeof (respFilename)); // Ensure terminator 00652 if (bytesToRead > 0) 00653 { 00654 if (bytesToRead > len) { 00655 bytesToRead = len; 00656 } 00657 00658 while (success && (bytesToRead > 0)) { 00659 00660 if (bytesToRead < blockSize) { 00661 blockSize = bytesToRead; 00662 } 00663 LOCK(); 00664 00665 if (blockSize > 0) { 00666 if (_at->send("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize) && 00667 _at->recv("+URDBLOCK:%48[^,],%d,\"", respFilename, &sz)) { 00668 // Note: not checking respFilename as some modules (e.g. Sara-G350 00S-00) 00669 // doesn't always include it. 00670 // Would use _at->read() here, but if it runs ahead of the 00671 // serial stream it returns -1 instead of the number of characters 00672 // read so far, which is not very helpful so instead use _at->getc() and 00673 // a time limit. The time limit is four times the amount of time it 00674 // should take to read the block at the working baud rate with a minimum 00675 // of 100 ms (for short files) 00676 timer.reset(); 00677 timer.start(); 00678 00679 // Add startup delay 00680 timeLimit = 200+ FILE_BUFFER_SIZE * 4 / ((MBED_CONF_UBLOX_CELL_BAUD_RATE / 8) / 1000); 00681 00682 sz_read = 0; 00683 00684 while ((sz_read < blockSize) && (timer.read_ms() < timeLimit)) { 00685 ch = _at->getc(); 00686 if (ch >= 0) { 00687 *buf = ch; 00688 buf++; 00689 sz_read++; 00690 } 00691 } 00692 timer.stop(); 00693 00694 if (sz_read == blockSize) { 00695 bytesToRead -= sz_read; 00696 offset += sz_read; 00697 _at->recv("OK"); 00698 } else { 00699 debug_if(_debug_trace_on, "blockSize %d but only received %d bytes, configured retry\n", blockSize, sz_read); 00700 //success = false; 00701 } 00702 } else { 00703 success = false; 00704 } 00705 } 00706 00707 UNLOCK(); 00708 } 00709 00710 if (success) { 00711 countBytes = offset; 00712 } 00713 } 00714 00715 return countBytes; 00716 } 00717 00718 // Return the size of a file. 00719 int UbloxCellularDriverGen::fileSize(const char* filename) 00720 { 00721 int returnValue = -1; 00722 int fileSize; 00723 LOCK(); 00724 00725 if (_at->send("AT+ULSTFILE=2,\"%s\"", filename) && 00726 _at->recv("+ULSTFILE: %d\n", &fileSize) && 00727 _at->recv("OK")) { 00728 returnValue = fileSize; 00729 } 00730 00731 UNLOCK(); 00732 return returnValue; 00733 } 00734 00735 // End of file 00736
Generated on Tue Jul 12 2022 17:22:58 by 1.7.2