ublox-cellular-driver-gen Fork
Fork of ublox-cellular-driver-gen by
UbloxCellularDriverGen.cpp@5:b935404dcf7c, 2017-06-15 (annotated)
- 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?
User | Revision | Line number | New 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 |