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:
Thu Jun 15 01:14:18 2017 +0100
Revision:
5:b935404dcf7c
Parent:
4:4f2c12992e17
Child:
7:a9eea2dbdd68
Tests now pass on C027: cope with filenames being returned without quotation marks, reduce file size to write since some modules can't keep up when there's no HW flow control, increase USSD timeout, simplify JSON template and run test without debug.

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;
rob.meades@u-blox.com 5:b935404dcf7c 644 char * endQuote;
RobMeades 0:bb5fabac67ab 645 bool success = true;
RobMeades 0:bb5fabac67ab 646 int ch = 0;
RobMeades 0:bb5fabac67ab 647 int timeLimit;
RobMeades 0:bb5fabac67ab 648 Timer timer;
RobMeades 0:bb5fabac67ab 649
RobMeades 0:bb5fabac67ab 650 debug_if(_debug_trace_on, "readFile: filename is %s; size is %d\n", filename, bytesToRead);
RobMeades 0:bb5fabac67ab 651
RobMeades 0:bb5fabac67ab 652 memset(respFilename, 0, sizeof (respFilename)); // Ensure terminator
RobMeades 0:bb5fabac67ab 653 if (bytesToRead > 0)
RobMeades 0:bb5fabac67ab 654 {
RobMeades 0:bb5fabac67ab 655 if (bytesToRead > len) {
RobMeades 0:bb5fabac67ab 656 bytesToRead = len;
RobMeades 0:bb5fabac67ab 657 }
RobMeades 0:bb5fabac67ab 658
RobMeades 0:bb5fabac67ab 659 while (success && (bytesToRead > 0)) {
RobMeades 0:bb5fabac67ab 660
RobMeades 0:bb5fabac67ab 661 if (bytesToRead < blockSize) {
RobMeades 0:bb5fabac67ab 662 blockSize = bytesToRead;
RobMeades 0:bb5fabac67ab 663 }
RobMeades 0:bb5fabac67ab 664 LOCK();
RobMeades 0:bb5fabac67ab 665
RobMeades 0:bb5fabac67ab 666 if (blockSize > 0) {
RobMeades 0:bb5fabac67ab 667 if (_at->send("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize) &&
rob.meades@u-blox.com 5:b935404dcf7c 668 _at->recv("+URDBLOCK: %48[^,],%d,\"", respFilename, &sz)) {
rob.meades@u-blox.com 5:b935404dcf7c 669 // On some modules the response filename is not in quotes,
rob.meades@u-blox.com 5:b935404dcf7c 670 // on others it is, so strip them here
rob.meades@u-blox.com 5:b935404dcf7c 671 if ((*respFilename == '"') && ((endQuote = strchr(respFilename + 1, '"')) != NULL)) {
rob.meades@u-blox.com 5:b935404dcf7c 672 memcpy (respFilename, respFilename + 1, endQuote - respFilename - 1);
rob.meades@u-blox.com 5:b935404dcf7c 673 *(endQuote - 1) = 0;
rob.meades@u-blox.com 5:b935404dcf7c 674 }
rob.meades@u-blox.com 5:b935404dcf7c 675 if (strcmp(filename, respFilename) == 0) {
rob.meades@u-blox.com 5:b935404dcf7c 676 // Would use _at->read() here, but if it runs ahead of the
rob.meades@u-blox.com 5:b935404dcf7c 677 // serial stream it returns -1 instead of the number of characters
rob.meades@u-blox.com 5:b935404dcf7c 678 // read so far, which is not very helpful so instead use _at->getc() and
rob.meades@u-blox.com 5:b935404dcf7c 679 // a time limit. The time limit is three times the amount of time it
rob.meades@u-blox.com 5:b935404dcf7c 680 // should take to read the block at the working baud rate with a minimum
rob.meades@u-blox.com 5:b935404dcf7c 681 // of 10 ms (for short files)
rob.meades@u-blox.com 5:b935404dcf7c 682 timer.reset();
rob.meades@u-blox.com 5:b935404dcf7c 683 timer.start();
rob.meades@u-blox.com 5:b935404dcf7c 684 timeLimit = blockSize * 3 / ((MBED_CONF_UBLOX_CELL_BAUD_RATE / 8) / 1000);
rob.meades@u-blox.com 5:b935404dcf7c 685 if (timeLimit < 10) {
rob.meades@u-blox.com 5:b935404dcf7c 686 timeLimit = 10;
rob.meades@u-blox.com 5:b935404dcf7c 687 }
rob.meades@u-blox.com 5:b935404dcf7c 688 sz_read = 0;
rob.meades@u-blox.com 5:b935404dcf7c 689 while ((sz_read < blockSize) && (timer.read_ms() < timeLimit)) {
rob.meades@u-blox.com 5:b935404dcf7c 690 ch = _at->getc();
rob.meades@u-blox.com 5:b935404dcf7c 691 if (ch >= 0) {
rob.meades@u-blox.com 5:b935404dcf7c 692 *buf = ch;
rob.meades@u-blox.com 5:b935404dcf7c 693 buf++;
rob.meades@u-blox.com 5:b935404dcf7c 694 sz_read++;
rob.meades@u-blox.com 5:b935404dcf7c 695 }
rob.meades@u-blox.com 5:b935404dcf7c 696 }
rob.meades@u-blox.com 5:b935404dcf7c 697 timer.stop();
RobMeades 0:bb5fabac67ab 698
rob.meades@u-blox.com 5:b935404dcf7c 699 if (sz_read == blockSize) {
rob.meades@u-blox.com 5:b935404dcf7c 700 bytesToRead -= sz_read;
rob.meades@u-blox.com 5:b935404dcf7c 701 offset += sz_read;
rob.meades@u-blox.com 5:b935404dcf7c 702 _at->recv("OK");
rob.meades@u-blox.com 5:b935404dcf7c 703 } else {
rob.meades@u-blox.com 5:b935404dcf7c 704 debug_if(_debug_trace_on, "blockSize %d but only received %d bytes\n", blockSize, sz_read);
rob.meades@u-blox.com 5:b935404dcf7c 705 success = false;
RobMeades 0:bb5fabac67ab 706 }
RobMeades 0:bb5fabac67ab 707 } else {
RobMeades 0:bb5fabac67ab 708 success = false;
RobMeades 0:bb5fabac67ab 709 }
RobMeades 0:bb5fabac67ab 710 } else {
RobMeades 0:bb5fabac67ab 711 success = false;
RobMeades 0:bb5fabac67ab 712 }
RobMeades 0:bb5fabac67ab 713 }
RobMeades 0:bb5fabac67ab 714
RobMeades 0:bb5fabac67ab 715 UNLOCK();
RobMeades 0:bb5fabac67ab 716 }
RobMeades 0:bb5fabac67ab 717
RobMeades 0:bb5fabac67ab 718 if (success) {
RobMeades 0:bb5fabac67ab 719 countBytes = offset;
RobMeades 0:bb5fabac67ab 720 }
RobMeades 0:bb5fabac67ab 721 }
RobMeades 0:bb5fabac67ab 722
RobMeades 0:bb5fabac67ab 723 return countBytes;
RobMeades 0:bb5fabac67ab 724 }
RobMeades 0:bb5fabac67ab 725
RobMeades 0:bb5fabac67ab 726 // Return the size of a file.
RobMeades 0:bb5fabac67ab 727 int UbloxCellularDriverGen::fileSize(const char* filename)
RobMeades 0:bb5fabac67ab 728 {
RobMeades 0:bb5fabac67ab 729 int returnValue = -1;
RobMeades 0:bb5fabac67ab 730 int fileSize;
RobMeades 0:bb5fabac67ab 731 LOCK();
RobMeades 0:bb5fabac67ab 732
RobMeades 0:bb5fabac67ab 733 if (_at->send("AT+ULSTFILE=2,\"%s\"", filename) &&
RobMeades 0:bb5fabac67ab 734 _at->recv("+ULSTFILE: %d\n", &fileSize) &&
RobMeades 0:bb5fabac67ab 735 _at->recv("OK")) {
RobMeades 0:bb5fabac67ab 736 returnValue = fileSize;
RobMeades 0:bb5fabac67ab 737 }
RobMeades 0:bb5fabac67ab 738
RobMeades 0:bb5fabac67ab 739 UNLOCK();
RobMeades 0:bb5fabac67ab 740 return returnValue;
RobMeades 0:bb5fabac67ab 741 }
RobMeades 0:bb5fabac67ab 742
RobMeades 0:bb5fabac67ab 743 // End of file
RobMeades 0:bb5fabac67ab 744