ublox-cellular-driver-gen Fork
Fork of ublox-cellular-driver-gen by
UbloxCellularDriverGen.cpp@7:a9eea2dbdd68, 2017-06-16 (annotated)
- Committer:
- rob.meades@u-blox.com
- Date:
- Fri Jun 16 00:49:52 2017 +0100
- Revision:
- 7:a9eea2dbdd68
- Parent:
- 5:b935404dcf7c
C027 compatibility: don't check the response filename when doing a block read as teh Sara-G350 module doesn't always return it. Increase the minimum wait time for a read response and the maximum wait time as well, again 'cos Sara-G350 is not as responsive as Sara-U201.
Who changed what in which revision?
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; |
RobMeades | 0:bb5fabac67ab | 644 | bool success = true; |
RobMeades | 0:bb5fabac67ab | 645 | int ch = 0; |
RobMeades | 0:bb5fabac67ab | 646 | int timeLimit; |
RobMeades | 0:bb5fabac67ab | 647 | Timer timer; |
RobMeades | 0:bb5fabac67ab | 648 | |
RobMeades | 0:bb5fabac67ab | 649 | debug_if(_debug_trace_on, "readFile: filename is %s; size is %d\n", filename, bytesToRead); |
RobMeades | 0:bb5fabac67ab | 650 | |
RobMeades | 0:bb5fabac67ab | 651 | memset(respFilename, 0, sizeof (respFilename)); // Ensure terminator |
RobMeades | 0:bb5fabac67ab | 652 | if (bytesToRead > 0) |
RobMeades | 0:bb5fabac67ab | 653 | { |
RobMeades | 0:bb5fabac67ab | 654 | if (bytesToRead > len) { |
RobMeades | 0:bb5fabac67ab | 655 | bytesToRead = len; |
RobMeades | 0:bb5fabac67ab | 656 | } |
RobMeades | 0:bb5fabac67ab | 657 | |
RobMeades | 0:bb5fabac67ab | 658 | while (success && (bytesToRead > 0)) { |
RobMeades | 0:bb5fabac67ab | 659 | |
RobMeades | 0:bb5fabac67ab | 660 | if (bytesToRead < blockSize) { |
RobMeades | 0:bb5fabac67ab | 661 | blockSize = bytesToRead; |
RobMeades | 0:bb5fabac67ab | 662 | } |
RobMeades | 0:bb5fabac67ab | 663 | LOCK(); |
RobMeades | 0:bb5fabac67ab | 664 | |
RobMeades | 0:bb5fabac67ab | 665 | if (blockSize > 0) { |
RobMeades | 0:bb5fabac67ab | 666 | if (_at->send("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize) && |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 667 | _at->recv("+URDBLOCK:%48[^,],%d,\"", respFilename, &sz)) { |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 668 | // Note: not checking respFilename as some modules (e.g. Sara-G350 00S-00) |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 669 | // doesn't always include it. |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 670 | // Would use _at->read() here, but if it runs ahead of the |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 671 | // serial stream it returns -1 instead of the number of characters |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 672 | // read so far, which is not very helpful so instead use _at->getc() and |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 673 | // a time limit. The time limit is four times the amount of time it |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 674 | // should take to read the block at the working baud rate with a minimum |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 675 | // of 100 ms (for short files) |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 676 | timer.reset(); |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 677 | timer.start(); |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 678 | timeLimit = blockSize * 4 / ((MBED_CONF_UBLOX_CELL_BAUD_RATE / 8) / 1000); |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 679 | if (timeLimit < 100) { |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 680 | timeLimit = 100; |
rob.meades@u-blox.com | 5:b935404dcf7c | 681 | } |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 682 | sz_read = 0; |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 683 | while ((sz_read < blockSize) && (timer.read_ms() < timeLimit)) { |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 684 | ch = _at->getc(); |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 685 | if (ch >= 0) { |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 686 | *buf = ch; |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 687 | buf++; |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 688 | sz_read++; |
rob.meades@u-blox.com | 5:b935404dcf7c | 689 | } |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 690 | } |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 691 | timer.stop(); |
RobMeades | 0:bb5fabac67ab | 692 | |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 693 | if (sz_read == blockSize) { |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 694 | bytesToRead -= sz_read; |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 695 | offset += sz_read; |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 696 | _at->recv("OK"); |
RobMeades | 0:bb5fabac67ab | 697 | } else { |
rob.meades@u-blox.com | 7:a9eea2dbdd68 | 698 | debug_if(_debug_trace_on, "blockSize %d but only received %d bytes\n", blockSize, sz_read); |
RobMeades | 0:bb5fabac67ab | 699 | success = false; |
RobMeades | 0:bb5fabac67ab | 700 | } |
RobMeades | 0:bb5fabac67ab | 701 | } else { |
RobMeades | 0:bb5fabac67ab | 702 | success = false; |
RobMeades | 0:bb5fabac67ab | 703 | } |
RobMeades | 0:bb5fabac67ab | 704 | } |
RobMeades | 0:bb5fabac67ab | 705 | |
RobMeades | 0:bb5fabac67ab | 706 | UNLOCK(); |
RobMeades | 0:bb5fabac67ab | 707 | } |
RobMeades | 0:bb5fabac67ab | 708 | |
RobMeades | 0:bb5fabac67ab | 709 | if (success) { |
RobMeades | 0:bb5fabac67ab | 710 | countBytes = offset; |
RobMeades | 0:bb5fabac67ab | 711 | } |
RobMeades | 0:bb5fabac67ab | 712 | } |
RobMeades | 0:bb5fabac67ab | 713 | |
RobMeades | 0:bb5fabac67ab | 714 | return countBytes; |
RobMeades | 0:bb5fabac67ab | 715 | } |
RobMeades | 0:bb5fabac67ab | 716 | |
RobMeades | 0:bb5fabac67ab | 717 | // Return the size of a file. |
RobMeades | 0:bb5fabac67ab | 718 | int UbloxCellularDriverGen::fileSize(const char* filename) |
RobMeades | 0:bb5fabac67ab | 719 | { |
RobMeades | 0:bb5fabac67ab | 720 | int returnValue = -1; |
RobMeades | 0:bb5fabac67ab | 721 | int fileSize; |
RobMeades | 0:bb5fabac67ab | 722 | LOCK(); |
RobMeades | 0:bb5fabac67ab | 723 | |
RobMeades | 0:bb5fabac67ab | 724 | if (_at->send("AT+ULSTFILE=2,\"%s\"", filename) && |
RobMeades | 0:bb5fabac67ab | 725 | _at->recv("+ULSTFILE: %d\n", &fileSize) && |
RobMeades | 0:bb5fabac67ab | 726 | _at->recv("OK")) { |
RobMeades | 0:bb5fabac67ab | 727 | returnValue = fileSize; |
RobMeades | 0:bb5fabac67ab | 728 | } |
RobMeades | 0:bb5fabac67ab | 729 | |
RobMeades | 0:bb5fabac67ab | 730 | UNLOCK(); |
RobMeades | 0:bb5fabac67ab | 731 | return returnValue; |
RobMeades | 0:bb5fabac67ab | 732 | } |
RobMeades | 0:bb5fabac67ab | 733 | |
RobMeades | 0:bb5fabac67ab | 734 | // End of file |
RobMeades | 0:bb5fabac67ab | 735 |