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