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

Committer:
rob.meades@u-blox.com
Date:
Fri Jun 16 00:49:52 2017 +0100
Revision:
7:a9eea2dbdd68
Parent:
5:b935404dcf7c
Child:
8:e6f6bf43a5d1
C027 compatibility: don't check the response filename when doing a block read as teh Sara-G350 module doesn't always return it. Increase the minimum wait time for a read response and the maximum wait time as well, again 'cos Sara-G350 is not as responsive as Sara-U201.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RobMeades 0:bb5fabac67ab 1 /* Copyright (c) 2017 ublox Limited
RobMeades 0:bb5fabac67ab 2 *
RobMeades 0:bb5fabac67ab 3 * Licensed under the Apache License, Version 2.0 (the "License");
RobMeades 0:bb5fabac67ab 4 * you may not use this file except in compliance with the License.
RobMeades 0:bb5fabac67ab 5 * You may obtain a copy of the License at
RobMeades 0:bb5fabac67ab 6 *
RobMeades 0:bb5fabac67ab 7 * http://www.apache.org/licenses/LICENSE-2.0
RobMeades 0:bb5fabac67ab 8 *
RobMeades 0:bb5fabac67ab 9 * Unless required by applicable law or agreed to in writing, software
RobMeades 0:bb5fabac67ab 10 * distributed under the License is distributed on an "AS IS" BASIS,
RobMeades 0:bb5fabac67ab 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
RobMeades 0:bb5fabac67ab 12 * See the License for the specific language governing permissions and
RobMeades 0:bb5fabac67ab 13 * limitations under the License.
RobMeades 0:bb5fabac67ab 14 */
RobMeades 0:bb5fabac67ab 15
RobMeades 0:bb5fabac67ab 16 #include "UbloxCellularDriverGen.h"
RobMeades 0:bb5fabac67ab 17 #include "string.h"
RobMeades 0:bb5fabac67ab 18 #if defined(FEATURE_COMMON_PAL)
RobMeades 0:bb5fabac67ab 19 #include "mbed_trace.h"
RobMeades 0:bb5fabac67ab 20 #define TRACE_GROUP "UCID"
RobMeades 0:bb5fabac67ab 21 #else
rob.meades@u-blox.com 4:4f2c12992e17 22 #define tr_debug(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
rob.meades@u-blox.com 4:4f2c12992e17 23 #define tr_info(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
rob.meades@u-blox.com 4:4f2c12992e17 24 #define tr_warn(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
rob.meades@u-blox.com 4:4f2c12992e17 25 #define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
RobMeades 0:bb5fabac67ab 26 #endif
RobMeades 0:bb5fabac67ab 27
RobMeades 0:bb5fabac67ab 28 /**********************************************************************
RobMeades 0:bb5fabac67ab 29 * PROTECTED METHODS: Short Message Service
RobMeades 0:bb5fabac67ab 30 **********************************************************************/
RobMeades 0:bb5fabac67ab 31
RobMeades 0:bb5fabac67ab 32 // URC for Short Message listing.
RobMeades 0:bb5fabac67ab 33 void UbloxCellularDriverGen::CMGL_URC()
RobMeades 0:bb5fabac67ab 34 {
RobMeades 0:bb5fabac67ab 35 char buf[64];
RobMeades 0:bb5fabac67ab 36 int index;
RobMeades 0:bb5fabac67ab 37
RobMeades 0:bb5fabac67ab 38 // Note: not calling _at->recv() from here as we're
RobMeades 0:bb5fabac67ab 39 // already in an _at->recv()
RobMeades 0:bb5fabac67ab 40 // +CMGL: <ix>,...
RobMeades 0:bb5fabac67ab 41 *buf = 0;
RobMeades 0:bb5fabac67ab 42 if (read_at_to_char(buf, sizeof(buf), '\n') > 0) {
RobMeades 0:bb5fabac67ab 43 // Now also read out the text message, so that we don't
RobMeades 0:bb5fabac67ab 44 // accidentally trigger URCs or the like on any of
RobMeades 0:bb5fabac67ab 45 // its contents
RobMeades 0:bb5fabac67ab 46 *_smsBuf = 0;
RobMeades 0:bb5fabac67ab 47 read_at_to_char(_smsBuf, sizeof(_smsBuf), '\n');
RobMeades 0:bb5fabac67ab 48 // Note: don't put any debug in here, this URC is being
RobMeades 0:bb5fabac67ab 49 // called multiple times and debug may cause it to
RobMeades 0:bb5fabac67ab 50 // miss characters
RobMeades 0:bb5fabac67ab 51 if (sscanf(buf, ": %d,", &index) == 1) {
RobMeades 0:bb5fabac67ab 52 _smsCount++;
RobMeades 0:bb5fabac67ab 53 if ((_userSmsIndex != NULL) && (_userSmsNum > 0)) {
RobMeades 0:bb5fabac67ab 54 *_userSmsIndex = index;
RobMeades 0:bb5fabac67ab 55 _userSmsIndex++;
RobMeades 0:bb5fabac67ab 56 _userSmsNum--;
RobMeades 0:bb5fabac67ab 57 }
RobMeades 0:bb5fabac67ab 58 }
RobMeades 0:bb5fabac67ab 59 }
RobMeades 0:bb5fabac67ab 60 }
RobMeades 0:bb5fabac67ab 61
RobMeades 0:bb5fabac67ab 62 // URC for new SMS messages.
RobMeades 0:bb5fabac67ab 63 void UbloxCellularDriverGen::CMTI_URC()
RobMeades 0:bb5fabac67ab 64 {
RobMeades 0:bb5fabac67ab 65 char buf[32];
RobMeades 0:bb5fabac67ab 66
RobMeades 0:bb5fabac67ab 67 // Note: not calling _at->recv() from here as we're
RobMeades 0:bb5fabac67ab 68 // already in an _at->recv()
RobMeades 0:bb5fabac67ab 69 *buf = 0;
RobMeades 0:bb5fabac67ab 70 if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
RobMeades 0:bb5fabac67ab 71 // No need to parse, any content is good
RobMeades 0:bb5fabac67ab 72 tr_info("New SMS received");
RobMeades 0:bb5fabac67ab 73 }
RobMeades 0:bb5fabac67ab 74 }
RobMeades 0:bb5fabac67ab 75
RobMeades 0:bb5fabac67ab 76 /**********************************************************************
RobMeades 0:bb5fabac67ab 77 * PROTECTED METHODS: Unstructured Supplementary Service Data
RobMeades 0:bb5fabac67ab 78 **********************************************************************/
RobMeades 0:bb5fabac67ab 79
RobMeades 0:bb5fabac67ab 80 // URC for call waiting.
RobMeades 0:bb5fabac67ab 81 void UbloxCellularDriverGen::CCWA_URC()
RobMeades 0:bb5fabac67ab 82 {
RobMeades 0:bb5fabac67ab 83 char buf[32];
RobMeades 0:bb5fabac67ab 84 int numChars;
RobMeades 0:bb5fabac67ab 85 int a;
RobMeades 0:bb5fabac67ab 86 int b = 0;
RobMeades 0:bb5fabac67ab 87
RobMeades 0:bb5fabac67ab 88 // Note: not calling _at->recv() from here as we're
RobMeades 0:bb5fabac67ab 89 // already in an _at->recv()
RobMeades 0:bb5fabac67ab 90 // +CCWA: <status>[, <class>]
RobMeades 0:bb5fabac67ab 91 numChars = read_at_to_char(buf, sizeof (buf), '\n');
RobMeades 0:bb5fabac67ab 92 if (numChars > 0) {
rob.meades@u-blox.com 5:b935404dcf7c 93 if (sscanf(buf, ": %d,%d", &a, &b) > 0) {
RobMeades 0:bb5fabac67ab 94 if (_ssUrcBuf == NULL) {
RobMeades 0:bb5fabac67ab 95 _ssUrcBuf = (char *) malloc(numChars + 5 + 1);
RobMeades 0:bb5fabac67ab 96 if (_ssUrcBuf != NULL) {
RobMeades 0:bb5fabac67ab 97 memcpy (_ssUrcBuf, "+CCWA", 5);
RobMeades 0:bb5fabac67ab 98 memcpy (_ssUrcBuf + 5, buf, numChars);
RobMeades 0:bb5fabac67ab 99 *(_ssUrcBuf + numChars + 5) = 0;
RobMeades 0:bb5fabac67ab 100 if (a > 0) {
RobMeades 0:bb5fabac67ab 101 debug_if(_debug_trace_on, "Calling Waiting is active");
RobMeades 0:bb5fabac67ab 102 } else {
RobMeades 0:bb5fabac67ab 103 debug_if(_debug_trace_on, "Calling Waiting is not active");
RobMeades 0:bb5fabac67ab 104 }
RobMeades 0:bb5fabac67ab 105 if (b > 0) {
RobMeades 0:bb5fabac67ab 106 if (b & 0x01) {
RobMeades 0:bb5fabac67ab 107 debug_if(_debug_trace_on, " for voice\n");
RobMeades 0:bb5fabac67ab 108 }
RobMeades 0:bb5fabac67ab 109 if (b & 0x02) {
RobMeades 0:bb5fabac67ab 110 debug_if(_debug_trace_on, " for data\n");
RobMeades 0:bb5fabac67ab 111 }
RobMeades 0:bb5fabac67ab 112 if (b & 0x04) {
RobMeades 0:bb5fabac67ab 113 debug_if(_debug_trace_on, " for fax\n");
RobMeades 0:bb5fabac67ab 114 }
RobMeades 0:bb5fabac67ab 115 if (b & 0x08) {
RobMeades 0:bb5fabac67ab 116 debug_if(_debug_trace_on, " for SMS\n");
RobMeades 0:bb5fabac67ab 117 }
RobMeades 0:bb5fabac67ab 118 if (b & 0x10) {
RobMeades 0:bb5fabac67ab 119 debug_if(_debug_trace_on, " for data circuit sync\n");
RobMeades 0:bb5fabac67ab 120 }
RobMeades 0:bb5fabac67ab 121 if (b & 0x20) {
RobMeades 0:bb5fabac67ab 122 debug_if(_debug_trace_on, " for data circuit async\n");
RobMeades 0:bb5fabac67ab 123 }
RobMeades 0:bb5fabac67ab 124 if (b & 0x40) {
RobMeades 0:bb5fabac67ab 125 debug_if(_debug_trace_on, " for dedicated packet access\n");
RobMeades 0:bb5fabac67ab 126 }
RobMeades 0:bb5fabac67ab 127 if (b & 0x80) {
RobMeades 0:bb5fabac67ab 128 debug_if(_debug_trace_on, " for dedicated PAD access\n");
RobMeades 0:bb5fabac67ab 129 }
RobMeades 0:bb5fabac67ab 130 }
RobMeades 0:bb5fabac67ab 131 }
RobMeades 0:bb5fabac67ab 132 }
RobMeades 0:bb5fabac67ab 133 }
RobMeades 0:bb5fabac67ab 134 }
RobMeades 0:bb5fabac67ab 135 }
RobMeades 0:bb5fabac67ab 136
RobMeades 0:bb5fabac67ab 137 // URC for call forwarding.
RobMeades 0:bb5fabac67ab 138 void UbloxCellularDriverGen::CCFC_URC()
RobMeades 0:bb5fabac67ab 139 {
RobMeades 0:bb5fabac67ab 140 char buf[32];
RobMeades 0:bb5fabac67ab 141 int numChars;
RobMeades 0:bb5fabac67ab 142 char num[32];
RobMeades 0:bb5fabac67ab 143 int a, b;
RobMeades 0:bb5fabac67ab 144 int numValues;
RobMeades 0:bb5fabac67ab 145
RobMeades 0:bb5fabac67ab 146 // Note: not calling _at->recv() from here as we're
RobMeades 0:bb5fabac67ab 147 // already in an _at->recv()
RobMeades 0:bb5fabac67ab 148 // +CCFC: <status>[, <class>]
RobMeades 0:bb5fabac67ab 149 numChars = read_at_to_char(buf, sizeof (buf), '\n');
RobMeades 0:bb5fabac67ab 150 if (numChars > 0) {
RobMeades 0:bb5fabac67ab 151 memset (num, 0, sizeof (num));
RobMeades 0:bb5fabac67ab 152 numValues = sscanf(buf, ": %d,%d,\"%32[^\"][\"]", &a, &b, num);
RobMeades 0:bb5fabac67ab 153 if (numValues > 0) {
RobMeades 0:bb5fabac67ab 154 if (_ssUrcBuf == NULL) {
RobMeades 0:bb5fabac67ab 155 _ssUrcBuf = (char *) malloc(numChars + 5 + 1);
RobMeades 0:bb5fabac67ab 156 if (_ssUrcBuf != NULL) {
RobMeades 0:bb5fabac67ab 157 memcpy (_ssUrcBuf, "+CCFC", 5);
RobMeades 0:bb5fabac67ab 158 memcpy (_ssUrcBuf + 5, buf, numChars);
RobMeades 0:bb5fabac67ab 159 *(_ssUrcBuf + numChars + 5) = 0;
RobMeades 0:bb5fabac67ab 160 if (a > 0) {
RobMeades 0:bb5fabac67ab 161 debug_if(_debug_trace_on, "Calling Forwarding is active ");
RobMeades 0:bb5fabac67ab 162 } else {
RobMeades 0:bb5fabac67ab 163 debug_if(_debug_trace_on, "Calling Forwarding is not active ");
RobMeades 0:bb5fabac67ab 164 }
RobMeades 0:bb5fabac67ab 165 if (numValues > 1) {
RobMeades 0:bb5fabac67ab 166 if (b > 0) {
RobMeades 0:bb5fabac67ab 167 if (b & 0x01) {
RobMeades 0:bb5fabac67ab 168 debug_if(_debug_trace_on, " for voice");
RobMeades 0:bb5fabac67ab 169 }
RobMeades 0:bb5fabac67ab 170 if (b & 0x02) {
RobMeades 0:bb5fabac67ab 171 debug_if(_debug_trace_on, " for data");
RobMeades 0:bb5fabac67ab 172 }
RobMeades 0:bb5fabac67ab 173 if (b & 0x04) {
RobMeades 0:bb5fabac67ab 174 debug_if(_debug_trace_on, " for fax");
RobMeades 0:bb5fabac67ab 175 }
RobMeades 0:bb5fabac67ab 176 if (b & 0x08) {
RobMeades 0:bb5fabac67ab 177 debug_if(_debug_trace_on, " for SMS");
RobMeades 0:bb5fabac67ab 178 }
RobMeades 0:bb5fabac67ab 179 if (b & 0x10) {
RobMeades 0:bb5fabac67ab 180 debug_if(_debug_trace_on, " for data circuit sync");
RobMeades 0:bb5fabac67ab 181 }
RobMeades 0:bb5fabac67ab 182 if (b & 0x20) {
RobMeades 0:bb5fabac67ab 183 debug_if(_debug_trace_on, " for data circuit async");
RobMeades 0:bb5fabac67ab 184 }
RobMeades 0:bb5fabac67ab 185 if (b & 0x40) {
RobMeades 0:bb5fabac67ab 186 debug_if(_debug_trace_on, " for dedicated packet access");
RobMeades 0:bb5fabac67ab 187 }
RobMeades 0:bb5fabac67ab 188 if (b & 0x80) {
RobMeades 0:bb5fabac67ab 189 debug_if(_debug_trace_on, " for dedicated PAD access");
RobMeades 0:bb5fabac67ab 190 }
RobMeades 0:bb5fabac67ab 191 }
RobMeades 0:bb5fabac67ab 192 }
RobMeades 0:bb5fabac67ab 193 if (numValues > 2) {
RobMeades 0:bb5fabac67ab 194 debug_if(_debug_trace_on, " for %s\n", num);
RobMeades 0:bb5fabac67ab 195 } else {
RobMeades 0:bb5fabac67ab 196 debug_if(_debug_trace_on, "\n");
RobMeades 0:bb5fabac67ab 197 }
RobMeades 0:bb5fabac67ab 198 }
RobMeades 0:bb5fabac67ab 199 }
RobMeades 0:bb5fabac67ab 200 }
RobMeades 0:bb5fabac67ab 201 }
RobMeades 0:bb5fabac67ab 202 }
RobMeades 0:bb5fabac67ab 203
RobMeades 0:bb5fabac67ab 204
RobMeades 0:bb5fabac67ab 205 // URC for calling line ID restriction.
RobMeades 0:bb5fabac67ab 206 void UbloxCellularDriverGen::CLIR_URC()
RobMeades 0:bb5fabac67ab 207 {
RobMeades 0:bb5fabac67ab 208 char buf[32];
RobMeades 0:bb5fabac67ab 209 int numChars;
RobMeades 0:bb5fabac67ab 210 int a, b;
RobMeades 0:bb5fabac67ab 211 int numValues;
RobMeades 0:bb5fabac67ab 212
RobMeades 0:bb5fabac67ab 213 // Note: not calling _at->recv() from here as we're
RobMeades 0:bb5fabac67ab 214 // already in an _at->recv()
RobMeades 0:bb5fabac67ab 215 // +CLIR: <n>[, <m>]
RobMeades 0:bb5fabac67ab 216 numChars = read_at_to_char(buf, sizeof (buf), '\n');
RobMeades 0:bb5fabac67ab 217 if (numChars > 0) {
RobMeades 0:bb5fabac67ab 218 numValues = sscanf(buf, ": %d,%d", &a, &b);
RobMeades 0:bb5fabac67ab 219 if (numValues > 0) {
RobMeades 0:bb5fabac67ab 220 if (_ssUrcBuf == NULL) {
RobMeades 0:bb5fabac67ab 221 _ssUrcBuf = (char *) malloc(numChars + 5 + 1);
RobMeades 0:bb5fabac67ab 222 if (_ssUrcBuf != NULL) {
RobMeades 0:bb5fabac67ab 223 memcpy (_ssUrcBuf, "+CLIR", 5);
RobMeades 0:bb5fabac67ab 224 memcpy (_ssUrcBuf + 5, buf, numChars);
RobMeades 0:bb5fabac67ab 225 *(_ssUrcBuf + numChars + 5) = 0;
RobMeades 0:bb5fabac67ab 226 switch (a) {
RobMeades 0:bb5fabac67ab 227 case 0:
RobMeades 0:bb5fabac67ab 228 debug_if(_debug_trace_on, "Calling Line ID restriction is as subscribed\n");
RobMeades 0:bb5fabac67ab 229 break;
RobMeades 0:bb5fabac67ab 230 case 1:
RobMeades 0:bb5fabac67ab 231 debug_if(_debug_trace_on, "Calling Line ID invocation ");
RobMeades 0:bb5fabac67ab 232 break;
RobMeades 0:bb5fabac67ab 233 case 2:
RobMeades 0:bb5fabac67ab 234 debug_if(_debug_trace_on, "Calling Line ID suppression ");
RobMeades 0:bb5fabac67ab 235 break;
RobMeades 0:bb5fabac67ab 236 }
RobMeades 0:bb5fabac67ab 237 if (numValues > 2) {
RobMeades 0:bb5fabac67ab 238 switch (b) {
RobMeades 0:bb5fabac67ab 239 case 0:
RobMeades 0:bb5fabac67ab 240 debug_if(_debug_trace_on, " is not provisioned\n");
RobMeades 0:bb5fabac67ab 241 break;
RobMeades 0:bb5fabac67ab 242 case 1:
RobMeades 0:bb5fabac67ab 243 debug_if(_debug_trace_on, " is provisioned permanently\n");
RobMeades 0:bb5fabac67ab 244 break;
RobMeades 0:bb5fabac67ab 245 case 2:
RobMeades 0:bb5fabac67ab 246 debug_if(_debug_trace_on, " is unknown\n");
RobMeades 0:bb5fabac67ab 247 break;
RobMeades 0:bb5fabac67ab 248 case 3:
RobMeades 0:bb5fabac67ab 249 debug_if(_debug_trace_on, " is in temporary mode, presentation restricted\n");
RobMeades 0:bb5fabac67ab 250 break;
RobMeades 0:bb5fabac67ab 251 case 4:
RobMeades 0:bb5fabac67ab 252 debug_if(_debug_trace_on, " is in temporary mode, presentation allowed\n");
RobMeades 0:bb5fabac67ab 253 break;
RobMeades 0:bb5fabac67ab 254 }
RobMeades 0:bb5fabac67ab 255 }
RobMeades 0:bb5fabac67ab 256 }
RobMeades 0:bb5fabac67ab 257 }
RobMeades 0:bb5fabac67ab 258 }
RobMeades 0:bb5fabac67ab 259 }
RobMeades 0:bb5fabac67ab 260 }
RobMeades 0:bb5fabac67ab 261
RobMeades 0:bb5fabac67ab 262 // URC for calling line ID presentation.
RobMeades 0:bb5fabac67ab 263 void UbloxCellularDriverGen::CLIP_URC()
RobMeades 0:bb5fabac67ab 264 {
RobMeades 0:bb5fabac67ab 265 char buf[32];
RobMeades 0:bb5fabac67ab 266 int numChars;
RobMeades 0:bb5fabac67ab 267 int a, b;
RobMeades 0:bb5fabac67ab 268 int numValues;
RobMeades 0:bb5fabac67ab 269
RobMeades 0:bb5fabac67ab 270 // Note: not calling _at->recv() from here as we're
RobMeades 0:bb5fabac67ab 271 // already in an _at->recv()
RobMeades 0:bb5fabac67ab 272 // +CLIP: <n>[, <m>]
RobMeades 0:bb5fabac67ab 273 numChars = read_at_to_char(buf, sizeof (buf), '\n');
RobMeades 0:bb5fabac67ab 274 if (numChars > 0) {
RobMeades 0:bb5fabac67ab 275 numValues = sscanf(buf, ": %d,%d", &a, &b);
RobMeades 0:bb5fabac67ab 276 if (numValues > 0) {
RobMeades 0:bb5fabac67ab 277 if (_ssUrcBuf == NULL) {
RobMeades 0:bb5fabac67ab 278 _ssUrcBuf = (char *) malloc(numChars + 5 + 1);
RobMeades 0:bb5fabac67ab 279 if (_ssUrcBuf != NULL) {
RobMeades 0:bb5fabac67ab 280 memcpy (_ssUrcBuf, "+CLIP", 5);
RobMeades 0:bb5fabac67ab 281 memcpy (_ssUrcBuf + 5, buf, numChars);
RobMeades 0:bb5fabac67ab 282 *(_ssUrcBuf + numChars + 5) = 0;
RobMeades 0:bb5fabac67ab 283 switch (a) {
RobMeades 0:bb5fabac67ab 284 case 0:
RobMeades 0:bb5fabac67ab 285 debug_if(_debug_trace_on, "Calling Line ID disable ");
RobMeades 0:bb5fabac67ab 286 break;
RobMeades 0:bb5fabac67ab 287 case 1:
RobMeades 0:bb5fabac67ab 288 debug_if(_debug_trace_on, "Calling Line ID enable ");
RobMeades 0:bb5fabac67ab 289 break;
RobMeades 0:bb5fabac67ab 290 }
RobMeades 0:bb5fabac67ab 291 if (numValues > 1) {
RobMeades 0:bb5fabac67ab 292 switch (b) {
RobMeades 0:bb5fabac67ab 293 case 0:
RobMeades 0:bb5fabac67ab 294 debug_if(_debug_trace_on, " is not provisioned\n");
RobMeades 0:bb5fabac67ab 295 break;
RobMeades 0:bb5fabac67ab 296 case 1:
RobMeades 0:bb5fabac67ab 297 debug_if(_debug_trace_on, " is provisioned\n");
RobMeades 0:bb5fabac67ab 298 break;
RobMeades 0:bb5fabac67ab 299 case 2:
RobMeades 0:bb5fabac67ab 300 debug_if(_debug_trace_on, " is unknown\n");
RobMeades 0:bb5fabac67ab 301 break;
RobMeades 0:bb5fabac67ab 302 }
RobMeades 0:bb5fabac67ab 303 }
RobMeades 0:bb5fabac67ab 304 }
RobMeades 0:bb5fabac67ab 305 }
RobMeades 0:bb5fabac67ab 306 }
RobMeades 0:bb5fabac67ab 307 }
RobMeades 0:bb5fabac67ab 308 }
RobMeades 0:bb5fabac67ab 309
RobMeades 0:bb5fabac67ab 310 // URC for connected line ID presentation.
RobMeades 0:bb5fabac67ab 311 void UbloxCellularDriverGen::COLP_URC()
RobMeades 0:bb5fabac67ab 312 {
RobMeades 0:bb5fabac67ab 313 char buf[32];
RobMeades 0:bb5fabac67ab 314 int numChars;
RobMeades 0:bb5fabac67ab 315 int a, b;
RobMeades 0:bb5fabac67ab 316 int numValues;
RobMeades 0:bb5fabac67ab 317
RobMeades 0:bb5fabac67ab 318 // Note: not calling _at->recv() from here as we're
RobMeades 0:bb5fabac67ab 319 // already in an _at->recv()
RobMeades 0:bb5fabac67ab 320 // +COLP: <n>[, <m>]
RobMeades 0:bb5fabac67ab 321 numChars = read_at_to_char(buf, sizeof (buf), '\n');
RobMeades 0:bb5fabac67ab 322 if (numChars > 0) {
RobMeades 0:bb5fabac67ab 323 numValues = sscanf(buf, ": %d,%d", &a, &b);
RobMeades 0:bb5fabac67ab 324 if (numValues > 0) {
RobMeades 0:bb5fabac67ab 325 if (_ssUrcBuf == NULL) {
RobMeades 0:bb5fabac67ab 326 _ssUrcBuf = (char *) malloc(numChars + 5 + 1);
RobMeades 0:bb5fabac67ab 327 if (_ssUrcBuf != NULL) {
RobMeades 0:bb5fabac67ab 328 memcpy (_ssUrcBuf, "+COLP", 5);
RobMeades 0:bb5fabac67ab 329 memcpy (_ssUrcBuf + 5, buf, numChars);
RobMeades 0:bb5fabac67ab 330 *(_ssUrcBuf + numChars + 5) = 0;
RobMeades 0:bb5fabac67ab 331 switch (a) {
RobMeades 0:bb5fabac67ab 332 case 0:
RobMeades 0:bb5fabac67ab 333 debug_if(_debug_trace_on, "Connected Line ID disable ");
RobMeades 0:bb5fabac67ab 334 break;
RobMeades 0:bb5fabac67ab 335 case 1:
RobMeades 0:bb5fabac67ab 336 debug_if(_debug_trace_on, "Connected Line ID enable ");
RobMeades 0:bb5fabac67ab 337 break;
RobMeades 0:bb5fabac67ab 338 }
RobMeades 0:bb5fabac67ab 339 if (numValues > 1) {
RobMeades 0:bb5fabac67ab 340 switch (b) {
RobMeades 0:bb5fabac67ab 341 case 0:
RobMeades 0:bb5fabac67ab 342 debug_if(_debug_trace_on, " is not provisioned\n");
RobMeades 0:bb5fabac67ab 343 break;
RobMeades 0:bb5fabac67ab 344 case 1:
RobMeades 0:bb5fabac67ab 345 debug_if(_debug_trace_on, " is provisioned\n");
RobMeades 0:bb5fabac67ab 346 break;
RobMeades 0:bb5fabac67ab 347 case 2:
RobMeades 0:bb5fabac67ab 348 debug_if(_debug_trace_on, " is unknown\n");
RobMeades 0:bb5fabac67ab 349 break;
RobMeades 0:bb5fabac67ab 350 }
RobMeades 0:bb5fabac67ab 351 }
RobMeades 0:bb5fabac67ab 352 }
RobMeades 0:bb5fabac67ab 353 }
RobMeades 0:bb5fabac67ab 354 }
RobMeades 0:bb5fabac67ab 355 }
RobMeades 0:bb5fabac67ab 356 }
RobMeades 0:bb5fabac67ab 357
RobMeades 0:bb5fabac67ab 358 // URC for connected line ID restriction.
RobMeades 0:bb5fabac67ab 359 void UbloxCellularDriverGen::COLR_URC()
RobMeades 0:bb5fabac67ab 360 {
RobMeades 0:bb5fabac67ab 361 char buf[32];
RobMeades 0:bb5fabac67ab 362 int numChars;
RobMeades 0:bb5fabac67ab 363 int a;
RobMeades 0:bb5fabac67ab 364
RobMeades 0:bb5fabac67ab 365 // Note: not calling _at->recv() from here as we're
RobMeades 0:bb5fabac67ab 366 // already in an _at->recv()
RobMeades 0:bb5fabac67ab 367 // +COLR: <status>
RobMeades 0:bb5fabac67ab 368 numChars = read_at_to_char(buf, sizeof (buf), '\n');
RobMeades 0:bb5fabac67ab 369 if (numChars > 0) {
RobMeades 0:bb5fabac67ab 370 if (sscanf(buf, ": %d", &a) > 0) {
RobMeades 0:bb5fabac67ab 371 if (_ssUrcBuf == NULL) {
RobMeades 0:bb5fabac67ab 372 _ssUrcBuf = (char *) malloc(numChars + 5 + 1);
RobMeades 0:bb5fabac67ab 373 if (_ssUrcBuf != NULL) {
RobMeades 0:bb5fabac67ab 374 memcpy (_ssUrcBuf, "+COLR", 5);
RobMeades 0:bb5fabac67ab 375 memcpy (_ssUrcBuf + 5, buf, numChars);
RobMeades 0:bb5fabac67ab 376 *(_ssUrcBuf + numChars + 5) = 0;
RobMeades 0:bb5fabac67ab 377 switch (a) {
RobMeades 0:bb5fabac67ab 378 case 0:
RobMeades 0:bb5fabac67ab 379 debug_if(_debug_trace_on, "Connected Line ID restriction is not provisioned\n");
RobMeades 0:bb5fabac67ab 380 break;
RobMeades 0:bb5fabac67ab 381 case 1:
RobMeades 0:bb5fabac67ab 382 debug_if(_debug_trace_on, "Connected Line ID restriction is provisioned\n");
RobMeades 0:bb5fabac67ab 383 break;
RobMeades 0:bb5fabac67ab 384 case 2:
RobMeades 0:bb5fabac67ab 385 debug_if(_debug_trace_on, "Connected Line ID restriction is unknown\n");
RobMeades 0:bb5fabac67ab 386 break;
RobMeades 0:bb5fabac67ab 387 }
RobMeades 0:bb5fabac67ab 388 }
RobMeades 0:bb5fabac67ab 389 }
RobMeades 0:bb5fabac67ab 390 }
RobMeades 0:bb5fabac67ab 391 }
RobMeades 0:bb5fabac67ab 392 }
RobMeades 0:bb5fabac67ab 393
RobMeades 0:bb5fabac67ab 394 /**********************************************************************
RobMeades 0:bb5fabac67ab 395 * PUBLIC METHODS: Generic
RobMeades 0:bb5fabac67ab 396 **********************************************************************/
RobMeades 0:bb5fabac67ab 397
RobMeades 0:bb5fabac67ab 398 // Constructor.
RobMeades 0:bb5fabac67ab 399 UbloxCellularDriverGen::UbloxCellularDriverGen(PinName tx, PinName rx,
RobMeades 0:bb5fabac67ab 400 int baud, bool debug_on)
RobMeades 0:bb5fabac67ab 401 {
RobMeades 0:bb5fabac67ab 402 _userSmsIndex = NULL;
RobMeades 0:bb5fabac67ab 403 _userSmsNum = 0;
RobMeades 0:bb5fabac67ab 404 _smsCount = 0;
RobMeades 0:bb5fabac67ab 405 _ssUrcBuf = NULL;
RobMeades 0:bb5fabac67ab 406
RobMeades 0:bb5fabac67ab 407 // Initialise the base class, which starts the AT parser
RobMeades 0:bb5fabac67ab 408 baseClassInit(tx, rx, baud, debug_on);
RobMeades 0:bb5fabac67ab 409
RobMeades 0:bb5fabac67ab 410 // URCs related to SMS
RobMeades 0:bb5fabac67ab 411 _at->oob("+CMGL", callback(this, &UbloxCellularDriverGen::CMGL_URC));
RobMeades 0:bb5fabac67ab 412 // Include the colon with this one as otherwise it could be found
RobMeades 0:bb5fabac67ab 413 // by +CMT, should it ever occur
RobMeades 0:bb5fabac67ab 414 _at->oob("+CMTI:", callback(this, &UbloxCellularDriverGen::CMTI_URC));
RobMeades 0:bb5fabac67ab 415
rob.meades@u-blox.com 5:b935404dcf7c 416 // URCs related to supplementary services
RobMeades 0:bb5fabac67ab 417 _at->oob("+CCWA", callback(this, &UbloxCellularDriverGen::CCWA_URC));
RobMeades 0:bb5fabac67ab 418 _at->oob("+CCFC", callback(this, &UbloxCellularDriverGen::CCFC_URC));
RobMeades 0:bb5fabac67ab 419 _at->oob("+CLIR", callback(this, &UbloxCellularDriverGen::CLIR_URC));
RobMeades 0:bb5fabac67ab 420 _at->oob("+CLIP", callback(this, &UbloxCellularDriverGen::CLIP_URC));
RobMeades 0:bb5fabac67ab 421 _at->oob("+COLP", callback(this, &UbloxCellularDriverGen::COLP_URC));
RobMeades 0:bb5fabac67ab 422 _at->oob("+COLR", callback(this, &UbloxCellularDriverGen::COLR_URC));
RobMeades 0:bb5fabac67ab 423 }
RobMeades 0:bb5fabac67ab 424
RobMeades 0:bb5fabac67ab 425 // Destructor.
RobMeades 0:bb5fabac67ab 426 UbloxCellularDriverGen::~UbloxCellularDriverGen()
RobMeades 0:bb5fabac67ab 427 {
RobMeades 0:bb5fabac67ab 428 }
RobMeades 0:bb5fabac67ab 429
RobMeades 0:bb5fabac67ab 430 /**********************************************************************
RobMeades 0:bb5fabac67ab 431 * PUBLIC METHODS: Short Message Service
RobMeades 0:bb5fabac67ab 432 **********************************************************************/
RobMeades 0:bb5fabac67ab 433
RobMeades 0:bb5fabac67ab 434 // Count the number of messages on the module.
RobMeades 0:bb5fabac67ab 435 int UbloxCellularDriverGen::smsList(const char* stat, int* index, int num)
RobMeades 0:bb5fabac67ab 436 {
RobMeades 0:bb5fabac67ab 437 int numMessages = -1;
RobMeades 0:bb5fabac67ab 438 LOCK();
RobMeades 0:bb5fabac67ab 439
RobMeades 0:bb5fabac67ab 440 _userSmsIndex = index;
RobMeades 0:bb5fabac67ab 441 _userSmsNum = num;
RobMeades 0:bb5fabac67ab 442 _smsCount = 0;
RobMeades 0:bb5fabac67ab 443 // There is a callback to capture the result
RobMeades 0:bb5fabac67ab 444 // +CMGL: <ix>,...
RobMeades 0:bb5fabac67ab 445 _at->debug_on(false); // No time for AT interface debug
RobMeades 0:bb5fabac67ab 446 // as the list comes out in one long
RobMeades 0:bb5fabac67ab 447 // stream and we can lose characters if we
RobMeades 0:bb5fabac67ab 448 // pause to do printfs
RobMeades 0:bb5fabac67ab 449 if (_at->send("AT+CMGL=\"%s\"", stat) && _at->recv("OK\n")) {
RobMeades 0:bb5fabac67ab 450 numMessages = _smsCount;
RobMeades 0:bb5fabac67ab 451 }
RobMeades 0:bb5fabac67ab 452 _at->debug_on(_debug_trace_on);
RobMeades 0:bb5fabac67ab 453
RobMeades 0:bb5fabac67ab 454 // Set this back to null so that the URC won't trample
RobMeades 0:bb5fabac67ab 455 _userSmsIndex = NULL;
RobMeades 0:bb5fabac67ab 456
RobMeades 0:bb5fabac67ab 457 UNLOCK();
RobMeades 0:bb5fabac67ab 458 return numMessages;
RobMeades 0:bb5fabac67ab 459 }
RobMeades 0:bb5fabac67ab 460
RobMeades 0:bb5fabac67ab 461 // Send an SMS message.
RobMeades 0:bb5fabac67ab 462 bool UbloxCellularDriverGen::smsSend(const char* num, const char* buf)
RobMeades 0:bb5fabac67ab 463 {
RobMeades 0:bb5fabac67ab 464 bool success = false;
RobMeades 0:bb5fabac67ab 465 char typeOfAddress = TYPE_OF_ADDRESS_NATIONAL;
RobMeades 0:bb5fabac67ab 466 LOCK();
RobMeades 0:bb5fabac67ab 467
RobMeades 0:bb5fabac67ab 468 if ((strlen (num) > 0) && (*(num) == '+')) {
RobMeades 0:bb5fabac67ab 469 typeOfAddress = TYPE_OF_ADDRESS_INTERNATIONAL;
RobMeades 0:bb5fabac67ab 470 }
RobMeades 0:bb5fabac67ab 471 if (_at->send("AT+CMGS=\"%s\",%d", num, typeOfAddress) && _at->recv(">")) {
RobMeades 0:bb5fabac67ab 472 if ((_at->write(buf, (int) strlen(buf)) >= (int) strlen(buf)) &&
RobMeades 0:bb5fabac67ab 473 (_at->putc(0x1A) == 0) && // CTRL-Z
RobMeades 0:bb5fabac67ab 474 _at->recv("OK")) {
RobMeades 0:bb5fabac67ab 475 success = true;
RobMeades 0:bb5fabac67ab 476 }
RobMeades 0:bb5fabac67ab 477 }
RobMeades 0:bb5fabac67ab 478
RobMeades 0:bb5fabac67ab 479 UNLOCK();
RobMeades 0:bb5fabac67ab 480 return success;
RobMeades 0:bb5fabac67ab 481 }
RobMeades 0:bb5fabac67ab 482
RobMeades 0:bb5fabac67ab 483 bool UbloxCellularDriverGen::smsDelete(int index)
RobMeades 0:bb5fabac67ab 484 {
RobMeades 0:bb5fabac67ab 485 bool success;
RobMeades 0:bb5fabac67ab 486 LOCK();
RobMeades 0:bb5fabac67ab 487
RobMeades 0:bb5fabac67ab 488 success = _at->send("AT+CMGD=%d", index) && _at->recv("OK");
RobMeades 0:bb5fabac67ab 489
RobMeades 0:bb5fabac67ab 490 UNLOCK();
RobMeades 0:bb5fabac67ab 491 return success;
RobMeades 0:bb5fabac67ab 492 }
RobMeades 0:bb5fabac67ab 493
RobMeades 0:bb5fabac67ab 494 bool UbloxCellularDriverGen::smsRead(int index, char* num, char* buf, int len)
RobMeades 0:bb5fabac67ab 495 {
RobMeades 0:bb5fabac67ab 496 bool success = false;
RobMeades 0:bb5fabac67ab 497 char * endOfString;
RobMeades 0:bb5fabac67ab 498 int smsReadLength = 0;
RobMeades 0:bb5fabac67ab 499 LOCK();
RobMeades 0:bb5fabac67ab 500
RobMeades 0:bb5fabac67ab 501 if (len > 0) {
RobMeades 0:bb5fabac67ab 502 //+CMGR: "REC READ", "+393488535999",,"07/04/05,18:02:28+08",145,4,0,0,"+393492000466",145,93
RobMeades 0:bb5fabac67ab 503 // The text of the message.
RobMeades 0:bb5fabac67ab 504 // OK
RobMeades 0:bb5fabac67ab 505 memset (_smsBuf, 0, sizeof (SMS_BUFFER_SIZE)); // Ensure terminator
RobMeades 0:bb5fabac67ab 506 if (_at->send("AT+CMGR=%d", index) &&
RobMeades 0:bb5fabac67ab 507 _at->recv("+CMGR: \"%*[^\"]\",\"%15[^\"]\"%*[^\n]\n", num) &&
RobMeades 0:bb5fabac67ab 508 _at->recv("%" stringify(SMS_BUFFER_SIZE) "[^\n]\n", _smsBuf) &&
RobMeades 0:bb5fabac67ab 509 _at->recv("OK")) {
RobMeades 0:bb5fabac67ab 510 endOfString = strchr(_smsBuf, 0);
RobMeades 0:bb5fabac67ab 511 if (endOfString != NULL) {
RobMeades 0:bb5fabac67ab 512 smsReadLength = endOfString - _smsBuf;
RobMeades 0:bb5fabac67ab 513 if (smsReadLength + 1 > len) { // +1 for terminator
RobMeades 0:bb5fabac67ab 514 smsReadLength = len - 1;
RobMeades 0:bb5fabac67ab 515 }
RobMeades 0:bb5fabac67ab 516 memcpy(buf, _smsBuf, smsReadLength);
RobMeades 0:bb5fabac67ab 517 *(buf + smsReadLength) = 0; // Add terminator
RobMeades 0:bb5fabac67ab 518 success = true;
RobMeades 0:bb5fabac67ab 519 }
RobMeades 0:bb5fabac67ab 520 }
RobMeades 0:bb5fabac67ab 521 }
RobMeades 0:bb5fabac67ab 522
RobMeades 0:bb5fabac67ab 523 UNLOCK();
RobMeades 0:bb5fabac67ab 524 return success;
RobMeades 0:bb5fabac67ab 525 }
RobMeades 0:bb5fabac67ab 526
RobMeades 0:bb5fabac67ab 527 /**********************************************************************
RobMeades 0:bb5fabac67ab 528 * PUBLIC METHODS: Unstructured Supplementary Service Data
RobMeades 0:bb5fabac67ab 529 **********************************************************************/
RobMeades 0:bb5fabac67ab 530
RobMeades 0:bb5fabac67ab 531 // Perform a USSD command.
RobMeades 0:bb5fabac67ab 532 bool UbloxCellularDriverGen::ussdCommand(const char* cmd, char* buf, int len)
RobMeades 0:bb5fabac67ab 533 {
RobMeades 0:bb5fabac67ab 534 bool success = false;
RobMeades 0:bb5fabac67ab 535 char * tmpBuf;
RobMeades 0:bb5fabac67ab 536 int atTimeout;
RobMeades 0:bb5fabac67ab 537 int x;
RobMeades 0:bb5fabac67ab 538 Timer timer;
RobMeades 0:bb5fabac67ab 539 LOCK();
RobMeades 0:bb5fabac67ab 540 atTimeout = _at_timeout; // Has to be inside LOCK()s
RobMeades 0:bb5fabac67ab 541
RobMeades 0:bb5fabac67ab 542 if (len > 0) {
RobMeades 0:bb5fabac67ab 543 *buf = 0;
RobMeades 0:bb5fabac67ab 544 if (len > USSD_STRING_LENGTH + 1) {
RobMeades 0:bb5fabac67ab 545 len = USSD_STRING_LENGTH + 1;
RobMeades 0:bb5fabac67ab 546 }
RobMeades 0:bb5fabac67ab 547
RobMeades 0:bb5fabac67ab 548 tmpBuf = (char *) malloc(USSD_STRING_LENGTH + 1);
RobMeades 0:bb5fabac67ab 549
RobMeades 0:bb5fabac67ab 550 if (tmpBuf != NULL) {
RobMeades 0:bb5fabac67ab 551 memset (tmpBuf, 0, USSD_STRING_LENGTH + 1);
RobMeades 0:bb5fabac67ab 552 // +CUSD: \"%*d, \"%128[^\"]\",%*d"
RobMeades 0:bb5fabac67ab 553 if (_at->send("AT+CUSD=1,\"%s\"", cmd)) {
RobMeades 0:bb5fabac67ab 554 // Wait for either +CUSD to come back or
RobMeades 0:bb5fabac67ab 555 // one of the other SS related URCs to trigger
RobMeades 0:bb5fabac67ab 556 if (_ssUrcBuf != NULL) {
rob.meades@u-blox.com 5:b935404dcf7c 557 free(_ssUrcBuf);
RobMeades 0:bb5fabac67ab 558 _ssUrcBuf = NULL;
RobMeades 0:bb5fabac67ab 559 }
RobMeades 0:bb5fabac67ab 560 timer.start();
RobMeades 0:bb5fabac67ab 561 _at->set_timeout(1000);
rob.meades@u-blox.com 5:b935404dcf7c 562 while (!success && (timer.read_ms() < 30000)) {
RobMeades 0:bb5fabac67ab 563 if (_at->recv("+CUSD: %*d,\"")) {
RobMeades 0:bb5fabac67ab 564 // Note: don't wait for "OK" here as the +CUSD response may come
RobMeades 0:bb5fabac67ab 565 // before or after the OK
RobMeades 0:bb5fabac67ab 566 // Also, the return string may include newlines so can't just use
RobMeades 0:bb5fabac67ab 567 // recv() to capture it as recv() will stop capturing at a newline.
RobMeades 0:bb5fabac67ab 568 if (read_at_to_char(tmpBuf, USSD_STRING_LENGTH, '\"') > 0) {
RobMeades 0:bb5fabac67ab 569 success = true;
RobMeades 0:bb5fabac67ab 570 memcpy (buf, tmpBuf, len);
RobMeades 0:bb5fabac67ab 571 *(buf + len - 1) = 0;
RobMeades 0:bb5fabac67ab 572 }
RobMeades 0:bb5fabac67ab 573 } else {
RobMeades 0:bb5fabac67ab 574 // Some of the return values do not appear as +CUSD but
RobMeades 0:bb5fabac67ab 575 // instead as the relevant URC for call waiting, call forwarding,
RobMeades 0:bb5fabac67ab 576 // etc. Test those here.
RobMeades 0:bb5fabac67ab 577 if (_ssUrcBuf != NULL) {
RobMeades 0:bb5fabac67ab 578 success = true;
RobMeades 0:bb5fabac67ab 579 x = strlen (_ssUrcBuf);
RobMeades 0:bb5fabac67ab 580 if (x > len - 1 ) {
RobMeades 0:bb5fabac67ab 581 x = len - 1;
RobMeades 0:bb5fabac67ab 582 }
RobMeades 0:bb5fabac67ab 583 memcpy (buf, _ssUrcBuf, x);
RobMeades 0:bb5fabac67ab 584 *(buf + x) = 0;
RobMeades 0:bb5fabac67ab 585 free (_ssUrcBuf);
RobMeades 0:bb5fabac67ab 586 _ssUrcBuf = NULL;
RobMeades 0:bb5fabac67ab 587 }
RobMeades 0:bb5fabac67ab 588 }
RobMeades 0:bb5fabac67ab 589 }
RobMeades 0:bb5fabac67ab 590 at_set_timeout(atTimeout);
RobMeades 0:bb5fabac67ab 591 timer.stop();
RobMeades 0:bb5fabac67ab 592 }
RobMeades 0:bb5fabac67ab 593 }
RobMeades 0:bb5fabac67ab 594 }
RobMeades 0:bb5fabac67ab 595
RobMeades 0:bb5fabac67ab 596 UNLOCK();
RobMeades 0:bb5fabac67ab 597 return success;
RobMeades 0:bb5fabac67ab 598 }
RobMeades 0:bb5fabac67ab 599
RobMeades 0:bb5fabac67ab 600 /**********************************************************************
RobMeades 0:bb5fabac67ab 601 * PUBLIC: Module File System
RobMeades 0:bb5fabac67ab 602 **********************************************************************/
RobMeades 0:bb5fabac67ab 603
RobMeades 0:bb5fabac67ab 604 // Delete a file from the module's file system.
RobMeades 0:bb5fabac67ab 605 bool UbloxCellularDriverGen::delFile(const char* filename)
RobMeades 0:bb5fabac67ab 606 {
RobMeades 0:bb5fabac67ab 607 bool success;
RobMeades 0:bb5fabac67ab 608 LOCK();
RobMeades 0:bb5fabac67ab 609
RobMeades 0:bb5fabac67ab 610 success = _at->send("AT+UDELFILE=\"%s\"", filename) && _at->recv("OK");
RobMeades 0:bb5fabac67ab 611
RobMeades 0:bb5fabac67ab 612 UNLOCK();
RobMeades 0:bb5fabac67ab 613 return success;
RobMeades 0:bb5fabac67ab 614 }
RobMeades 0:bb5fabac67ab 615
RobMeades 0:bb5fabac67ab 616 // Write a buffer of data to a file in the module's file system.
RobMeades 0:bb5fabac67ab 617 int UbloxCellularDriverGen::writeFile(const char* filename, const char* buf, int len)
RobMeades 0:bb5fabac67ab 618 {
RobMeades 0:bb5fabac67ab 619 int bytesWritten = -1;
RobMeades 0:bb5fabac67ab 620 LOCK();
RobMeades 0:bb5fabac67ab 621
RobMeades 0:bb5fabac67ab 622 if (_at->send("AT+UDWNFILE=\"%s\",%d", filename, len) && _at->recv(">")) {
RobMeades 0:bb5fabac67ab 623 if ((_at->write(buf, len) >= len) && _at->recv("OK")) {
RobMeades 0:bb5fabac67ab 624 bytesWritten = len;
RobMeades 0:bb5fabac67ab 625 }
RobMeades 0:bb5fabac67ab 626 }
RobMeades 0:bb5fabac67ab 627
RobMeades 0:bb5fabac67ab 628 UNLOCK();
RobMeades 0:bb5fabac67ab 629 return bytesWritten;
RobMeades 0:bb5fabac67ab 630 }
RobMeades 0:bb5fabac67ab 631
RobMeades 0:bb5fabac67ab 632 // Read a file from the module's file system
RobMeades 0:bb5fabac67ab 633 // Note: this is implemented with block reads since UARTSerial
RobMeades 0:bb5fabac67ab 634 // does not currently allow flow control and there is a danger
RobMeades 0:bb5fabac67ab 635 // of character loss with large whole-file reads
RobMeades 0:bb5fabac67ab 636 int UbloxCellularDriverGen::readFile(const char* filename, char* buf, int len)
RobMeades 0:bb5fabac67ab 637 {
RobMeades 0:bb5fabac67ab 638 int countBytes = -1; // Counter for file reading (default value)
RobMeades 0:bb5fabac67ab 639 int bytesToRead = fileSize(filename); // Retrieve the size of the file
RobMeades 0:bb5fabac67ab 640 int offset = 0;
RobMeades 0:bb5fabac67ab 641 int blockSize = FILE_BUFFER_SIZE;
RobMeades 0:bb5fabac67ab 642 char respFilename[48 + 1];
RobMeades 0:bb5fabac67ab 643 int sz, sz_read;
RobMeades 0:bb5fabac67ab 644 bool success = true;
RobMeades 0:bb5fabac67ab 645 int ch = 0;
RobMeades 0:bb5fabac67ab 646 int timeLimit;
RobMeades 0:bb5fabac67ab 647 Timer timer;
RobMeades 0:bb5fabac67ab 648
RobMeades 0:bb5fabac67ab 649 debug_if(_debug_trace_on, "readFile: filename is %s; size is %d\n", filename, bytesToRead);
RobMeades 0:bb5fabac67ab 650
RobMeades 0:bb5fabac67ab 651 memset(respFilename, 0, sizeof (respFilename)); // Ensure terminator
RobMeades 0:bb5fabac67ab 652 if (bytesToRead > 0)
RobMeades 0:bb5fabac67ab 653 {
RobMeades 0:bb5fabac67ab 654 if (bytesToRead > len) {
RobMeades 0:bb5fabac67ab 655 bytesToRead = len;
RobMeades 0:bb5fabac67ab 656 }
RobMeades 0:bb5fabac67ab 657
RobMeades 0:bb5fabac67ab 658 while (success && (bytesToRead > 0)) {
RobMeades 0:bb5fabac67ab 659
RobMeades 0:bb5fabac67ab 660 if (bytesToRead < blockSize) {
RobMeades 0:bb5fabac67ab 661 blockSize = bytesToRead;
RobMeades 0:bb5fabac67ab 662 }
RobMeades 0:bb5fabac67ab 663 LOCK();
RobMeades 0:bb5fabac67ab 664
RobMeades 0:bb5fabac67ab 665 if (blockSize > 0) {
RobMeades 0:bb5fabac67ab 666 if (_at->send("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize) &&
rob.meades@u-blox.com 7:a9eea2dbdd68 667 _at->recv("+URDBLOCK:%48[^,],%d,\"", respFilename, &sz)) {
rob.meades@u-blox.com 7:a9eea2dbdd68 668 // Note: not checking respFilename as some modules (e.g. Sara-G350 00S-00)
rob.meades@u-blox.com 7:a9eea2dbdd68 669 // doesn't always include it.
rob.meades@u-blox.com 7:a9eea2dbdd68 670 // Would use _at->read() here, but if it runs ahead of the
rob.meades@u-blox.com 7:a9eea2dbdd68 671 // serial stream it returns -1 instead of the number of characters
rob.meades@u-blox.com 7:a9eea2dbdd68 672 // read so far, which is not very helpful so instead use _at->getc() and
rob.meades@u-blox.com 7:a9eea2dbdd68 673 // a time limit. The time limit is four times the amount of time it
rob.meades@u-blox.com 7:a9eea2dbdd68 674 // should take to read the block at the working baud rate with a minimum
rob.meades@u-blox.com 7:a9eea2dbdd68 675 // of 100 ms (for short files)
rob.meades@u-blox.com 7:a9eea2dbdd68 676 timer.reset();
rob.meades@u-blox.com 7:a9eea2dbdd68 677 timer.start();
rob.meades@u-blox.com 7:a9eea2dbdd68 678 timeLimit = blockSize * 4 / ((MBED_CONF_UBLOX_CELL_BAUD_RATE / 8) / 1000);
rob.meades@u-blox.com 7:a9eea2dbdd68 679 if (timeLimit < 100) {
rob.meades@u-blox.com 7:a9eea2dbdd68 680 timeLimit = 100;
rob.meades@u-blox.com 5:b935404dcf7c 681 }
rob.meades@u-blox.com 7:a9eea2dbdd68 682 sz_read = 0;
rob.meades@u-blox.com 7:a9eea2dbdd68 683 while ((sz_read < blockSize) && (timer.read_ms() < timeLimit)) {
rob.meades@u-blox.com 7:a9eea2dbdd68 684 ch = _at->getc();
rob.meades@u-blox.com 7:a9eea2dbdd68 685 if (ch >= 0) {
rob.meades@u-blox.com 7:a9eea2dbdd68 686 *buf = ch;
rob.meades@u-blox.com 7:a9eea2dbdd68 687 buf++;
rob.meades@u-blox.com 7:a9eea2dbdd68 688 sz_read++;
rob.meades@u-blox.com 5:b935404dcf7c 689 }
rob.meades@u-blox.com 7:a9eea2dbdd68 690 }
rob.meades@u-blox.com 7:a9eea2dbdd68 691 timer.stop();
RobMeades 0:bb5fabac67ab 692
rob.meades@u-blox.com 7:a9eea2dbdd68 693 if (sz_read == blockSize) {
rob.meades@u-blox.com 7:a9eea2dbdd68 694 bytesToRead -= sz_read;
rob.meades@u-blox.com 7:a9eea2dbdd68 695 offset += sz_read;
rob.meades@u-blox.com 7:a9eea2dbdd68 696 _at->recv("OK");
RobMeades 0:bb5fabac67ab 697 } else {
rob.meades@u-blox.com 7:a9eea2dbdd68 698 debug_if(_debug_trace_on, "blockSize %d but only received %d bytes\n", blockSize, sz_read);
RobMeades 0:bb5fabac67ab 699 success = false;
RobMeades 0:bb5fabac67ab 700 }
RobMeades 0:bb5fabac67ab 701 } else {
RobMeades 0:bb5fabac67ab 702 success = false;
RobMeades 0:bb5fabac67ab 703 }
RobMeades 0:bb5fabac67ab 704 }
RobMeades 0:bb5fabac67ab 705
RobMeades 0:bb5fabac67ab 706 UNLOCK();
RobMeades 0:bb5fabac67ab 707 }
RobMeades 0:bb5fabac67ab 708
RobMeades 0:bb5fabac67ab 709 if (success) {
RobMeades 0:bb5fabac67ab 710 countBytes = offset;
RobMeades 0:bb5fabac67ab 711 }
RobMeades 0:bb5fabac67ab 712 }
RobMeades 0:bb5fabac67ab 713
RobMeades 0:bb5fabac67ab 714 return countBytes;
RobMeades 0:bb5fabac67ab 715 }
RobMeades 0:bb5fabac67ab 716
RobMeades 0:bb5fabac67ab 717 // Return the size of a file.
RobMeades 0:bb5fabac67ab 718 int UbloxCellularDriverGen::fileSize(const char* filename)
RobMeades 0:bb5fabac67ab 719 {
RobMeades 0:bb5fabac67ab 720 int returnValue = -1;
RobMeades 0:bb5fabac67ab 721 int fileSize;
RobMeades 0:bb5fabac67ab 722 LOCK();
RobMeades 0:bb5fabac67ab 723
RobMeades 0:bb5fabac67ab 724 if (_at->send("AT+ULSTFILE=2,\"%s\"", filename) &&
RobMeades 0:bb5fabac67ab 725 _at->recv("+ULSTFILE: %d\n", &fileSize) &&
RobMeades 0:bb5fabac67ab 726 _at->recv("OK")) {
RobMeades 0:bb5fabac67ab 727 returnValue = fileSize;
RobMeades 0:bb5fabac67ab 728 }
RobMeades 0:bb5fabac67ab 729
RobMeades 0:bb5fabac67ab 730 UNLOCK();
RobMeades 0:bb5fabac67ab 731 return returnValue;
RobMeades 0:bb5fabac67ab 732 }
RobMeades 0:bb5fabac67ab 733
RobMeades 0:bb5fabac67ab 734 // End of file
RobMeades 0:bb5fabac67ab 735