Support for LISA-N101

Fork of C027_Support by u-blox

This is a variant of the C027 driver code for the C027N version, i.e. the one with the Neul/Huawei/u-blox Cellular Internet of Things module on board. The AT command interface for this module is entirely different to the AT interface for the other u-blox modules, hence this fork of the driver. Work is underway to rearchitect the original C027 driver so that a merge can be done.

Committer:
RobMeades
Date:
Tue Mar 10 16:25:18 2015 +0000
Revision:
118:f3fd6c30dc19
Parent:
117:74e4e0109a9e
Child:
119:d62a42409280
Initial version of support for Lisa-N101.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mazgch 18:e5697801df29 1 #include "mbed.h"
mazgch 18:e5697801df29 2 #include "MDM.h"
mazgch 74:208e3e32d263 3 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 4 #include "C027_api.h"
mazgch 74:208e3e32d263 5 #endif
mazgch 85:dd8f4f0d0ca9 6 #include "MDMAPN.h"
mazgch 84:a05edb010176 7
mazgch 74:208e3e32d263 8 #define PROFILE "0" //!< this is the psd profile used
mazgch 74:208e3e32d263 9 #define MAX_SIZE 128 //!< max expected messages
mazgch 103:197fa7920ad8 10 // num sockets
mazgch 104:c64ba749a422 11 #define NUMSOCKETS (sizeof(_sockets)/sizeof(*_sockets))
mazgch 104:c64ba749a422 12 //! test if it is a socket is ok to use
mazgch 104:c64ba749a422 13 #define ISSOCKET(s) (((s) >= 0) && ((s) < NUMSOCKETS) && (_sockets[s].handle != SOCKET_ERROR))
mazgch 75:ce6e12067d0c 14 //! check for timeout
mazgch 75:ce6e12067d0c 15 #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms()))
mazgch 80:34985b4d821e 16 //! registration ok check helper
mazgch 79:291df065e345 17 #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING))
mazgch 80:34985b4d821e 18 //! registration done check helper (no need to poll further)
mazgch 79:291df065e345 19 #define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED))
mazgch 95:8282dbbe1492 20 //! helper to make sure that lock unlock pair is always balaced
mazgch 95:8282dbbe1492 21 #define LOCK() { lock()
mazgch 95:8282dbbe1492 22 //! helper to make sure that lock unlock pair is always balaced
mazgch 95:8282dbbe1492 23 #define UNLOCK() } unlock()
mazgch 79:291df065e345 24
mazgch 74:208e3e32d263 25 #ifdef MDM_DEBUG
mazgch 95:8282dbbe1492 26 #if 1 // colored terminal output using ANSI escape sequences
mazgch 95:8282dbbe1492 27 #define COL(c) "\033[" c
mazgch 95:8282dbbe1492 28 #else
mazgch 95:8282dbbe1492 29 #define COL(c)
mazgch 95:8282dbbe1492 30 #endif
mazgch 95:8282dbbe1492 31 #define DEF COL("39m")
mazgch 95:8282dbbe1492 32 #define BLA COL("30m")
mazgch 95:8282dbbe1492 33 #define RED COL("31m")
mazgch 95:8282dbbe1492 34 #define GRE COL("32m")
mazgch 95:8282dbbe1492 35 #define YEL COL("33m")
mazgch 95:8282dbbe1492 36 #define BLU COL("34m")
mazgch 95:8282dbbe1492 37 #define MAG COL("35m")
mazgch 95:8282dbbe1492 38 #define CYA COL("36m")
mazgch 95:8282dbbe1492 39 #define WHY COL("37m")
mazgch 95:8282dbbe1492 40
mazgch 74:208e3e32d263 41 void dumpAtCmd(const char* buf, int len)
mazgch 21:c4d64830bf02 42 {
mazgch 75:ce6e12067d0c 43 ::printf(" %3d \"", len);
mazgch 21:c4d64830bf02 44 while (len --) {
mazgch 21:c4d64830bf02 45 char ch = *buf++;
mazgch 75:ce6e12067d0c 46 if ((ch > 0x1F) && (ch != 0x7F)) { // is printable
mazgch 75:ce6e12067d0c 47 if (ch == '%') ::printf("%%");
mazgch 75:ce6e12067d0c 48 else if (ch == '"') ::printf("\\\"");
mazgch 75:ce6e12067d0c 49 else if (ch == '\\') ::printf("\\\\");
mazgch 75:ce6e12067d0c 50 else putchar(ch);
mazgch 75:ce6e12067d0c 51 } else {
mazgch 75:ce6e12067d0c 52 if (ch == '\a') ::printf("\\a"); // BEL (0x07)
mazgch 75:ce6e12067d0c 53 else if (ch == '\b') ::printf("\\b"); // Backspace (0x08)
mazgch 75:ce6e12067d0c 54 else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09)
mazgch 75:ce6e12067d0c 55 else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A)
mazgch 75:ce6e12067d0c 56 else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B)
mazgch 75:ce6e12067d0c 57 else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C)
mazgch 75:ce6e12067d0c 58 else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D)
mazgch 76:f7c3dd568dae 59 else ::printf("\\x%02x", (unsigned char)ch);
mazgch 75:ce6e12067d0c 60 }
mazgch 21:c4d64830bf02 61 }
mazgch 75:ce6e12067d0c 62 ::printf("\"\r\n");
mazgch 21:c4d64830bf02 63 }
mazgch 74:208e3e32d263 64
mazgch 117:74e4e0109a9e 65 void MDMParser::_debugPrint(int level, const char* color, const char* format, ...)
mazgch 117:74e4e0109a9e 66 {
mazgch 117:74e4e0109a9e 67 if (_debugLevel >= level)
mazgch 117:74e4e0109a9e 68 {
mazgch 117:74e4e0109a9e 69 ::printf("_debugPrint %d %d\r\n", _debugLevel, level);
mazgch 117:74e4e0109a9e 70 va_list args;
mazgch 117:74e4e0109a9e 71 va_start (args, format);
mazgch 117:74e4e0109a9e 72 if (color) ::printf(color);
mazgch 117:74e4e0109a9e 73 ::vprintf(format, args);
mazgch 117:74e4e0109a9e 74 if (color) ::printf(DEF);
mazgch 117:74e4e0109a9e 75 va_end (args);
mazgch 117:74e4e0109a9e 76 }
mazgch 117:74e4e0109a9e 77 }
mazgch 117:74e4e0109a9e 78
mazgch 117:74e4e0109a9e 79 #define ERROR(...) _debugPrint(0, RED, __VA_ARGS__)
mazgch 117:74e4e0109a9e 80 #define INFO(...) _debugPrint(1, GRE, __VA_ARGS__)
mazgch 117:74e4e0109a9e 81 #define TRACE(...) _debugPrint(2, DEF, __VA_ARGS__)
mazgch 117:74e4e0109a9e 82 #define TEST(...) _debugPrint(3, CYA, __VA_ARGS__)
mazgch 74:208e3e32d263 83
mazgch 74:208e3e32d263 84 #else
mazgch 74:208e3e32d263 85
mazgch 75:ce6e12067d0c 86 #define ERROR(...) (void)0 // no tracing
mazgch 95:8282dbbe1492 87 #define TEST(...) (void)0 // no tracing
mazgch 74:208e3e32d263 88 #define INFO(...) (void)0 // no tracing
mazgch 74:208e3e32d263 89 #define TRACE(...) (void)0 // no tracing
mazgch 74:208e3e32d263 90
mazgch 31:a0bed6c1e05d 91 #endif
mazgch 21:c4d64830bf02 92
mazgch 44:9d12223b78ff 93 MDMParser* MDMParser::inst;
mazgch 44:9d12223b78ff 94
mazgch 21:c4d64830bf02 95 MDMParser::MDMParser(void)
mazgch 21:c4d64830bf02 96 {
mazgch 44:9d12223b78ff 97 inst = this;
mazgch 31:a0bed6c1e05d 98 memset(&_dev, 0, sizeof(_dev));
mazgch 31:a0bed6c1e05d 99 memset(&_net, 0, sizeof(_net));
mazgch 54:7ba8e4c218e2 100 _net.lac = 0xFFFF;
mazgch 54:7ba8e4c218e2 101 _net.ci = 0xFFFFFFFF;
mazgch 35:9275215a3a5b 102 _ip = NOIP;
mazgch 76:f7c3dd568dae 103 _init = false;
mazgch 31:a0bed6c1e05d 104 memset(_sockets, 0, sizeof(_sockets));
mazgch 104:c64ba749a422 105 for (int socket = 0; socket < NUMSOCKETS; socket ++)
mazgch 103:197fa7920ad8 106 _sockets[socket].handle = SOCKET_ERROR;
RobMeades 118:f3fd6c30dc19 107 _outstandingNMI = 0;
mazgch 74:208e3e32d263 108 #ifdef MDM_DEBUG
mazgch 76:f7c3dd568dae 109 _debugLevel = 1;
mazgch 74:208e3e32d263 110 _debugTime.start();
mazgch 74:208e3e32d263 111 #endif
mazgch 74:208e3e32d263 112 }
mazgch 74:208e3e32d263 113
mazgch 18:e5697801df29 114 int MDMParser::send(const char* buf, int len)
mazgch 18:e5697801df29 115 {
mazgch 74:208e3e32d263 116 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 117 if (_debugLevel >= 3) {
mazgch 75:ce6e12067d0c 118 ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001);
mazgch 74:208e3e32d263 119 dumpAtCmd(buf,len);
mazgch 74:208e3e32d263 120 }
mazgch 21:c4d64830bf02 121 #endif
mazgch 18:e5697801df29 122 return _send(buf, len);
mazgch 18:e5697801df29 123 }
mazgch 18:e5697801df29 124
mazgch 21:c4d64830bf02 125 int MDMParser::sendFormated(const char* format, ...) {
mazgch 21:c4d64830bf02 126 char buf[MAX_SIZE];
mazgch 21:c4d64830bf02 127 va_list args;
mazgch 21:c4d64830bf02 128 va_start(args, format);
mazgch 21:c4d64830bf02 129 int len = vsnprintf(buf,sizeof(buf), format, args);
mazgch 21:c4d64830bf02 130 va_end(args);
mazgch 21:c4d64830bf02 131 return send(buf, len);
mazgch 21:c4d64830bf02 132 }
mazgch 21:c4d64830bf02 133
mazgch 26:07be5faf8925 134 int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/,
mazgch 26:07be5faf8925 135 void* param /* = NULL*/,
mazgch 26:07be5faf8925 136 int timeout_ms /*= 5000*/)
mazgch 26:07be5faf8925 137 {
mazgch 69:4d6fa520dfca 138 char buf[MAX_SIZE + 64 /* add some more space for framing */];
mazgch 21:c4d64830bf02 139 Timer timer;
mazgch 21:c4d64830bf02 140 timer.start();
mazgch 21:c4d64830bf02 141 do {
mazgch 21:c4d64830bf02 142 int ret = getLine(buf, sizeof(buf));
mazgch 74:208e3e32d263 143 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 144 if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND))
mazgch 21:c4d64830bf02 145 {
mazgch 31:a0bed6c1e05d 146 int len = LENGTH(ret);
mazgch 31:a0bed6c1e05d 147 int type = TYPE(ret);
mazgch 95:8282dbbe1492 148 const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF :
mazgch 95:8282dbbe1492 149 (type == TYPE_TEXT) ? MAG "TXT" DEF :
mazgch 95:8282dbbe1492 150 (type == TYPE_OK ) ? GRE "OK " DEF :
mazgch 95:8282dbbe1492 151 (type == TYPE_ERROR) ? RED "ERR" DEF :
mazgch 95:8282dbbe1492 152 (type == TYPE_PLUS) ? CYA " + " DEF :
mazgch 95:8282dbbe1492 153 (type == TYPE_PROMPT) ? BLU " > " DEF :
mazgch 95:8282dbbe1492 154 "..." ;
mazgch 75:ce6e12067d0c 155 ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
mazgch 74:208e3e32d263 156 dumpAtCmd(buf, len);
mazgch 21:c4d64830bf02 157 }
mazgch 21:c4d64830bf02 158 #endif
mazgch 21:c4d64830bf02 159 if ((ret != WAIT) && (ret != NOT_FOUND))
mazgch 18:e5697801df29 160 {
mazgch 21:c4d64830bf02 161 int type = TYPE(ret);
mazgch 21:c4d64830bf02 162 // handle unsolicited commands here
mazgch 21:c4d64830bf02 163 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 164 const char* cmd = buf+3;
mazgch 54:7ba8e4c218e2 165 int a, b, c, d, r;
mazgch 23:05a1aeeb5fd9 166 char s[32];
mazgch 21:c4d64830bf02 167
mazgch 31:a0bed6c1e05d 168 // SMS Command ---------------------------------
mazgch 31:a0bed6c1e05d 169 // +CNMI: <mem>,<index>
mazgch 31:a0bed6c1e05d 170 if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) {
mazgch 31:a0bed6c1e05d 171 TRACE("New SMS at index %d\r\n", a);
mazgch 21:c4d64830bf02 172 // Socket Specific Command ---------------------------------
mazgch 21:c4d64830bf02 173 // +UUSORD: <socket>,<length>
mazgch 103:197fa7920ad8 174 } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2)) {
mazgch 103:197fa7920ad8 175 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 176 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
mazgch 103:197fa7920ad8 177 if (socket != SOCKET_ERROR)
mazgch 103:197fa7920ad8 178 _sockets[socket].pending = b;
mazgch 69:4d6fa520dfca 179 // +UUSORF: <socket>,<length>
mazgch 103:197fa7920ad8 180 } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2)) {
mazgch 103:197fa7920ad8 181 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 182 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
mazgch 103:197fa7920ad8 183 if (socket != SOCKET_ERROR)
mazgch 103:197fa7920ad8 184 _sockets[socket].pending = b;
mazgch 21:c4d64830bf02 185 // +UUSOCL: <socket>
mazgch 103:197fa7920ad8 186 } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1)) {
mazgch 103:197fa7920ad8 187 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 188 TRACE("Socket %d: handle %d closed by remote host\r\n", socket, a);
mazgch 103:197fa7920ad8 189 if ((socket != SOCKET_ERROR) && _sockets[socket].connected)
mazgch 103:197fa7920ad8 190 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 191 }
mazgch 32:8f12ac182bbb 192 if (_dev.dev == DEV_LISA_C200) {
mazgch 21:c4d64830bf02 193 // CDMA Specific -------------------------------------------
mazgch 21:c4d64830bf02 194 // +CREG: <n><SID>,<NID>,<stat>
mazgch 54:7ba8e4c218e2 195 if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) {
mazgch 54:7ba8e4c218e2 196 // _net.sid = a;
mazgch 54:7ba8e4c218e2 197 // _net.nid = b;
mazgch 79:291df065e345 198 if (c == 0) _net.csd = REG_NONE; // not registered, home network
mazgch 79:291df065e345 199 else if (c == 1) _net.csd = REG_HOME; // registered, home network
mazgch 79:291df065e345 200 else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to
mazgch 79:291df065e345 201 else if (c == 3) _net.csd = REG_DENIED; // registration denied
mazgch 79:291df065e345 202 else if (c == 5) _net.csd = REG_ROAMING; // registered, roaming
mazgch 79:291df065e345 203 _net.psd = _net.csd; // fake PSD registration (CDMA is always registered)
mazgch 31:a0bed6c1e05d 204 _net.act = ACT_CDMA;
mazgch 84:a05edb010176 205 // +CSS: <mode>[,<format>,<oper>[,<AcT>]]
mazgch 21:c4d64830bf02 206 } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) {
mazgch 31:a0bed6c1e05d 207 //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME;
mazgch 21:c4d64830bf02 208 }
RobMeades 118:f3fd6c30dc19 209 } else if (_dev.dev == DEV_LISA_N101) {
RobMeades 118:f3fd6c30dc19 210 // Neul unsolicited responses ----------------------------
RobMeades 118:f3fd6c30dc19 211 // New Message Indication
RobMeades 118:f3fd6c30dc19 212 // +NMI:<length>,<data>
RobMeades 118:f3fd6c30dc19 213 if (sscanf(buf, "\r\n+NMI:%d,%s", &a, s) == 2) {
RobMeades 118:f3fd6c30dc19 214 _outstandingNMI++;
RobMeades 118:f3fd6c30dc19 215 TRACE("New Message Indication, length: %d\r\n", a);
RobMeades 118:f3fd6c30dc19 216 }
RobMeades 118:f3fd6c30dc19 217 // Send Message Indication
RobMeades 118:f3fd6c30dc19 218 // +SMI:<status>
RobMeades 118:f3fd6c30dc19 219 if (sscanf(cmd, "SMI:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 220 TRACE("Send message status: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 221 }
RobMeades 118:f3fd6c30dc19 222 // +GSN:<UUID>
RobMeades 118:f3fd6c30dc19 223 if (sscanf(cmd, "GSN:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 224 TRACE("Serial number is: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 225 }
RobMeades 118:f3fd6c30dc19 226 // +MGS:<status>
RobMeades 118:f3fd6c30dc19 227 if (sscanf(cmd, "MGS:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 228 TRACE("Message Send returned: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 229 }
RobMeades 118:f3fd6c30dc19 230 // +MGR:<length>,<data>
RobMeades 118:f3fd6c30dc19 231 if (sscanf(cmd, "MGR:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 232 TRACE("Message Receive returned: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 233 }
RobMeades 118:f3fd6c30dc19 234 // +RAS:<status>
RobMeades 118:f3fd6c30dc19 235 if (sscanf(cmd, "RAS:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 236 TRACE("Radio Activity Status returned: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 237 }
RobMeades 118:f3fd6c30dc19 238 // +QMGR:<status>
RobMeades 118:f3fd6c30dc19 239 if (sscanf(cmd, "QMGR:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 240 TRACE("Query Messages Received returned: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 241 }
RobMeades 118:f3fd6c30dc19 242 // +QMGS:<status>
RobMeades 118:f3fd6c30dc19 243 if (sscanf(cmd, "QMGS:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 244 TRACE("Query Messages Sent returned: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 245 }
RobMeades 118:f3fd6c30dc19 246 // +RB:<status>
RobMeades 118:f3fd6c30dc19 247 if (sscanf(cmd, "RB:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 248 TRACE("Rebooting returned: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 249 }
RobMeades 118:f3fd6c30dc19 250 // +CSQ: <0-255>
RobMeades 118:f3fd6c30dc19 251 if (sscanf(cmd, "CSQ: %d", &a) == 1) {
RobMeades 118:f3fd6c30dc19 252 TRACE("Signal strength is: %d\r\n", a);
RobMeades 118:f3fd6c30dc19 253 }
RobMeades 118:f3fd6c30dc19 254 // +LAC:<commandname>
RobMeades 118:f3fd6c30dc19 255 if (sscanf(cmd, "LAC:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 256 TRACE("An available command is: %s\r\n", s);
RobMeades 118:f3fd6c30dc19 257 }
RobMeades 118:f3fd6c30dc19 258 // +DI:<string>
RobMeades 118:f3fd6c30dc19 259 if (sscanf(cmd, "DI:%s", s) == 1) {
RobMeades 118:f3fd6c30dc19 260 // Do nothing, this will be spat out when debug is on anyway
RobMeades 118:f3fd6c30dc19 261 }
mazgch 21:c4d64830bf02 262 } else {
mazgch 21:c4d64830bf02 263 // GSM/UMTS Specific -------------------------------------------
mazgch 79:291df065e345 264 // +UUPSDD: <profile_id>
mazgch 79:291df065e345 265 if (sscanf(cmd, "UUPSDD: %d",&a) == 1) {
mazgch 79:291df065e345 266 if (*PROFILE == a) _ip = NOIP;
mazgch 79:291df065e345 267 } else {
mazgch 79:291df065e345 268 // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG
mazgch 79:291df065e345 269 // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC
mazgch 79:291df065e345 270 b = 0xFFFF; c = 0xFFFFFFFF; d = -1;
mazgch 79:291df065e345 271 r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
mazgch 79:291df065e345 272 if (r <= 1)
mazgch 79:291df065e345 273 r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
mazgch 79:291df065e345 274 if (r >= 2) {
mazgch 79:291df065e345 275 Reg *reg = !strcmp(s, "CREG:") ? &_net.csd :
mazgch 79:291df065e345 276 !strcmp(s, "CGREG:") ? &_net.psd : NULL;
mazgch 79:291df065e345 277 if (reg) {
mazgch 79:291df065e345 278 // network status
mazgch 79:291df065e345 279 if (a == 0) *reg = REG_NONE; // 0: not registered, home network
mazgch 79:291df065e345 280 else if (a == 1) *reg = REG_HOME; // 1: registered, home network
mazgch 79:291df065e345 281 else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to
mazgch 79:291df065e345 282 else if (a == 3) *reg = REG_DENIED; // 3: registration denied
mazgch 79:291df065e345 283 else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown
mazgch 79:291df065e345 284 else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming
mazgch 79:291df065e345 285 if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code
mazgch 79:291df065e345 286 if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID
mazgch 79:291df065e345 287 // access technology
mazgch 79:291df065e345 288 if (r >= 5) {
mazgch 79:291df065e345 289 if (d == 0) _net.act = ACT_GSM; // 0: GSM
mazgch 79:291df065e345 290 else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT
mazgch 79:291df065e345 291 else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN
mazgch 79:291df065e345 292 else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability
mazgch 79:291df065e345 293 else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability
mazgch 79:291df065e345 294 else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability
mazgch 79:291df065e345 295 else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability
mazgch 79:291df065e345 296 }
mazgch 79:291df065e345 297 }
mazgch 54:7ba8e4c218e2 298 }
mazgch 21:c4d64830bf02 299 }
mazgch 21:c4d64830bf02 300 }
mazgch 21:c4d64830bf02 301 }
mazgch 21:c4d64830bf02 302 if (cb) {
mazgch 21:c4d64830bf02 303 int len = LENGTH(ret);
mazgch 21:c4d64830bf02 304 int ret = cb(type, buf, len, param);
mazgch 21:c4d64830bf02 305 if (WAIT != ret)
mazgch 21:c4d64830bf02 306 return ret;
mazgch 21:c4d64830bf02 307 }
mazgch 95:8282dbbe1492 308 if (type == TYPE_OK)
mazgch 95:8282dbbe1492 309 return RESP_OK;
mazgch 95:8282dbbe1492 310 if (type == TYPE_ERROR)
mazgch 95:8282dbbe1492 311 return RESP_ERROR;
mazgch 95:8282dbbe1492 312 if (type == TYPE_PROMPT)
mazgch 95:8282dbbe1492 313 return RESP_PROMPT;
mazgch 21:c4d64830bf02 314 }
mazgch 21:c4d64830bf02 315 // relax a bit
mazgch 95:8282dbbe1492 316 wait_ms(10);
mazgch 21:c4d64830bf02 317 }
mazgch 75:ce6e12067d0c 318 while (!TIMEOUT(timer, timeout_ms));
mazgch 21:c4d64830bf02 319 return WAIT;
mazgch 21:c4d64830bf02 320 }
mazgch 21:c4d64830bf02 321
mazgch 31:a0bed6c1e05d 322 int MDMParser::_cbString(int type, const char* buf, int len, char* str)
mazgch 21:c4d64830bf02 323 {
mazgch 37:cc3433329d66 324 if (str && (type == TYPE_UNKNOWN)) {
mazgch 31:a0bed6c1e05d 325 if (sscanf(buf, "\r\n%s\r\n", str) == 1)
mazgch 31:a0bed6c1e05d 326 /*nothing*/;
mazgch 21:c4d64830bf02 327 }
mazgch 21:c4d64830bf02 328 return WAIT;
mazgch 21:c4d64830bf02 329 }
mazgch 21:c4d64830bf02 330
mazgch 31:a0bed6c1e05d 331 int MDMParser::_cbInt(int type, const char* buf, int len, int* val)
mazgch 31:a0bed6c1e05d 332 {
mazgch 37:cc3433329d66 333 if (val && (type == TYPE_UNKNOWN)) {
mazgch 31:a0bed6c1e05d 334 if (sscanf(buf, "\r\n%d\r\n", val) == 1)
mazgch 31:a0bed6c1e05d 335 /*nothing*/;
mazgch 31:a0bed6c1e05d 336 }
mazgch 31:a0bed6c1e05d 337 return WAIT;
mazgch 31:a0bed6c1e05d 338 }
mazgch 31:a0bed6c1e05d 339
RobMeades 118:f3fd6c30dc19 340 // Neul modem flavour of manufacturer ID string
RobMeades 118:f3fd6c30dc19 341 int MDMParser::_cbGmiString(int type, const char* buf, int len, char* str)
RobMeades 118:f3fd6c30dc19 342 {
RobMeades 118:f3fd6c30dc19 343 if (str && (type == TYPE_PLUS)) {
RobMeades 118:f3fd6c30dc19 344 if (sscanf(buf, "\r\n+GMI:%s\r\n", str) == 1)
RobMeades 118:f3fd6c30dc19 345 /*nothing*/;
RobMeades 118:f3fd6c30dc19 346 }
RobMeades 118:f3fd6c30dc19 347 return WAIT;
RobMeades 118:f3fd6c30dc19 348 }
RobMeades 118:f3fd6c30dc19 349
RobMeades 118:f3fd6c30dc19 350 // Neul modem flavour of manufacturer model string
RobMeades 118:f3fd6c30dc19 351 int MDMParser::_cbGmmString(int type, const char* buf, int len, char* str)
RobMeades 118:f3fd6c30dc19 352 {
RobMeades 118:f3fd6c30dc19 353 if (str && (type == TYPE_PLUS)) {
RobMeades 118:f3fd6c30dc19 354 if (sscanf(buf, "\r\n+GMM:%s\r\n", str) == 1)
RobMeades 118:f3fd6c30dc19 355 /*nothing*/;
RobMeades 118:f3fd6c30dc19 356 }
RobMeades 118:f3fd6c30dc19 357 return WAIT;
RobMeades 118:f3fd6c30dc19 358 }
RobMeades 118:f3fd6c30dc19 359
RobMeades 118:f3fd6c30dc19 360 // Neul modem flavour of manufacturer revision string
RobMeades 118:f3fd6c30dc19 361 int MDMParser::_cbGmrString(int type, const char* buf, int len, char* str)
RobMeades 118:f3fd6c30dc19 362 {
RobMeades 118:f3fd6c30dc19 363 if (str && (type == TYPE_PLUS)) {
RobMeades 118:f3fd6c30dc19 364 if (sscanf(buf, "\r\n+GMR:%s\r\n", str) == 1)
RobMeades 118:f3fd6c30dc19 365 /*nothing*/;
RobMeades 118:f3fd6c30dc19 366 }
RobMeades 118:f3fd6c30dc19 367 return WAIT;
RobMeades 118:f3fd6c30dc19 368 }
RobMeades 118:f3fd6c30dc19 369
mazgch 31:a0bed6c1e05d 370 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 371
mazgch 57:869bd35f44cc 372 bool MDMParser::connect(
mazgch 57:869bd35f44cc 373 const char* simpin,
mazgch 80:34985b4d821e 374 const char* apn, const char* username,
mazgch 80:34985b4d821e 375 const char* password, Auth auth,
mazgch 74:208e3e32d263 376 PinName pn)
mazgch 57:869bd35f44cc 377 {
mazgch 75:ce6e12067d0c 378 bool ok = init(simpin, NULL, pn);
mazgch 74:208e3e32d263 379 #ifdef MDM_DEBUG
mazgch 75:ce6e12067d0c 380 if (_debugLevel >= 1) dumpDevStatus(&_dev);
mazgch 74:208e3e32d263 381 #endif
mazgch 75:ce6e12067d0c 382 if (!ok)
mazgch 57:869bd35f44cc 383 return false;
mazgch 75:ce6e12067d0c 384 ok = registerNet();
mazgch 74:208e3e32d263 385 #ifdef MDM_DEBUG
mazgch 75:ce6e12067d0c 386 if (_debugLevel >= 1) dumpNetStatus(&_net);
mazgch 74:208e3e32d263 387 #endif
mazgch 75:ce6e12067d0c 388 if (!ok)
mazgch 57:869bd35f44cc 389 return false;
mazgch 80:34985b4d821e 390 IP ip = join(apn,username,password,auth);
mazgch 74:208e3e32d263 391 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 392 if (_debugLevel >= 1) dumpIp(ip);
mazgch 74:208e3e32d263 393 #endif
mazgch 57:869bd35f44cc 394 if (ip == NOIP)
mazgch 57:869bd35f44cc 395 return false;
mazgch 57:869bd35f44cc 396 return true;
mazgch 57:869bd35f44cc 397 }
mazgch 57:869bd35f44cc 398
mazgch 74:208e3e32d263 399 bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn)
mazgch 21:c4d64830bf02 400 {
mazgch 74:208e3e32d263 401 int i = 10;
mazgch 95:8282dbbe1492 402 LOCK();
mazgch 76:f7c3dd568dae 403 memset(&_dev, 0, sizeof(_dev));
mazgch 74:208e3e32d263 404 if (pn != NC) {
mazgch 74:208e3e32d263 405 INFO("Modem::wakeup\r\n");
mazgch 74:208e3e32d263 406 DigitalOut pin(pn, 1);
mazgch 74:208e3e32d263 407 while (i--) {
RobMeades 118:f3fd6c30dc19 408 if (_dev.dev != DEV_LISA_N101) {
RobMeades 118:f3fd6c30dc19 409 // SARA-U2/LISA-U2 50..80us
RobMeades 118:f3fd6c30dc19 410 pin = 0; ::wait_us(50);
RobMeades 118:f3fd6c30dc19 411 pin = 1; ::wait_ms(10);
mazgch 79:291df065e345 412
RobMeades 118:f3fd6c30dc19 413 // SARA-G35 >5ms, LISA-C2 > 150ms, LEON-G2 >5ms
RobMeades 118:f3fd6c30dc19 414 pin = 0; ::wait_ms(150);
RobMeades 118:f3fd6c30dc19 415 pin = 1; ::wait_ms(100);
RobMeades 118:f3fd6c30dc19 416 }
mazgch 79:291df065e345 417 // purge any messages
mazgch 101:edfeb8af206e 418 purge();
mazgch 95:8282dbbe1492 419
mazgch 101:edfeb8af206e 420 // check interface
mazgch 74:208e3e32d263 421 sendFormated("AT\r\n");
mazgch 101:edfeb8af206e 422 int r = waitFinalResp(NULL,NULL,1000);
mazgch 95:8282dbbe1492 423 if(RESP_OK == r) break;
RobMeades 118:f3fd6c30dc19 424 if(RESP_ERROR == r) break; // Neul modem responds with ERROR when sent AT with no following parameters
mazgch 74:208e3e32d263 425 }
mazgch 75:ce6e12067d0c 426 if (i < 0) {
mazgch 95:8282dbbe1492 427 ERROR("No Reply from Modem\r\n");
mazgch 95:8282dbbe1492 428 goto failure;
mazgch 75:ce6e12067d0c 429 }
mazgch 21:c4d64830bf02 430 }
mazgch 76:f7c3dd568dae 431 _init = true;
mazgch 75:ce6e12067d0c 432
mazgch 74:208e3e32d263 433 INFO("Modem::init\r\n");
RobMeades 118:f3fd6c30dc19 434 // Attempt to get the manufacturer model string
RobMeades 118:f3fd6c30dc19 435 sendFormated("AT+GMM\r\n");
RobMeades 118:f3fd6c30dc19 436 if (RESP_OK == waitFinalResp(_cbGmmString, _dev.model)) {
RobMeades 118:f3fd6c30dc19 437 // If successful it's probably the Neul modem, do a specific check though
RobMeades 118:f3fd6c30dc19 438 if (strstr (_dev.model, "Neul") == _dev.model) {
RobMeades 118:f3fd6c30dc19 439 _dev.dev = DEV_LISA_N101;
RobMeades 118:f3fd6c30dc19 440 // Neul modem specific init
RobMeades 118:f3fd6c30dc19 441 printf ("Neul AT parser revision 0.1 (for interface NT1001).\n");
RobMeades 118:f3fd6c30dc19 442 // get the manufacturer ID string
RobMeades 118:f3fd6c30dc19 443 sendFormated("AT+GMI\r\n");
RobMeades 118:f3fd6c30dc19 444 if (RESP_OK != waitFinalResp(_cbGmiString, _dev.manu))
RobMeades 118:f3fd6c30dc19 445 goto failure;
RobMeades 118:f3fd6c30dc19 446 #ifndef DISABLE_NEUL_TEST_COMMANDS
RobMeades 118:f3fd6c30dc19 447 // GSM Channel 183 (DL: 880.1MHz, UL: 835.1MHz), CRNTI 123456, DCI MCS = 4, CELL ID = 22
RobMeades 118:f3fd6c30dc19 448 // sendFormated ("AT+MACTEST=24,02000000a0427534609dc631160000004523010001040100\r\n");
RobMeades 118:f3fd6c30dc19 449 // GSM Channel 183 (DL: 880.1MHz, UL: 835.1MHz), CRNTI 123456, DCI MCS = 2, CELL ID = 22
RobMeades 118:f3fd6c30dc19 450 sendFormated ("AT+MACTEST=24,02000000a0427534609dc631160000004523010001020100\r\n");
mazgch 52:8071747a7cb3 451 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 452 goto failure;
RobMeades 118:f3fd6c30dc19 453 sendFormated ("AT+DI=0\r\n");
mazgch 52:8071747a7cb3 454 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 455 goto failure;
RobMeades 118:f3fd6c30dc19 456 //sendFormated ("AT+LQMI=0\r\n");
RobMeades 118:f3fd6c30dc19 457 //if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 458 // goto failure;
RobMeades 118:f3fd6c30dc19 459 #endif
RobMeades 118:f3fd6c30dc19 460 // get the sw version
RobMeades 118:f3fd6c30dc19 461 sendFormated("AT+GMR\r\n");
RobMeades 118:f3fd6c30dc19 462 if (RESP_OK != waitFinalResp(_cbGmrString, _dev.ver))
RobMeades 118:f3fd6c30dc19 463 goto failure;
RobMeades 118:f3fd6c30dc19 464 // Don't set an error if this fails as it's not set on some modules
RobMeades 118:f3fd6c30dc19 465 sendFormated("AT+GSN\r\n");
RobMeades 118:f3fd6c30dc19 466 waitFinalResp(NULL, NULL, 1000);
RobMeades 118:f3fd6c30dc19 467 #ifdef C027N_USE_NMI
RobMeades 118:f3fd6c30dc19 468 // Switch on new message indications
RobMeades 118:f3fd6c30dc19 469 sendFormated("AT+NMI=1\r\n");
RobMeades 118:f3fd6c30dc19 470 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 471 goto failure;
RobMeades 118:f3fd6c30dc19 472 #else
RobMeades 118:f3fd6c30dc19 473 sendFormated("AT+NMI=0\r\n");
RobMeades 118:f3fd6c30dc19 474 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 475 goto failure;
RobMeades 118:f3fd6c30dc19 476 #endif
RobMeades 118:f3fd6c30dc19 477 // Switch on send message indications
RobMeades 118:f3fd6c30dc19 478 sendFormated("AT+SMI=1\r\n");
mazgch 52:8071747a7cb3 479 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 480 goto failure;
mazgch 21:c4d64830bf02 481 }
RobMeades 118:f3fd6c30dc19 482 } else {
RobMeades 118:f3fd6c30dc19 483 // 3GPP/CDMA modem init
RobMeades 118:f3fd6c30dc19 484 // echo off
RobMeades 118:f3fd6c30dc19 485 sendFormated("AT E0\r\n");
RobMeades 118:f3fd6c30dc19 486 if(RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 487 goto failure;
RobMeades 118:f3fd6c30dc19 488 // enable verbose error messages
RobMeades 118:f3fd6c30dc19 489 sendFormated("AT+CMEE=2\r\n");
RobMeades 118:f3fd6c30dc19 490 if(RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 491 goto failure;
RobMeades 118:f3fd6c30dc19 492 // set baud rate
RobMeades 118:f3fd6c30dc19 493 sendFormated("AT+IPR=115200\r\n");
mazgch 79:291df065e345 494 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 495 goto failure;
RobMeades 118:f3fd6c30dc19 496 // wait some time until baudrate is applied
RobMeades 118:f3fd6c30dc19 497 wait_ms(200); // SARA-G > 40ms
RobMeades 118:f3fd6c30dc19 498 // identify the module
RobMeades 118:f3fd6c30dc19 499 sendFormated("ATI\r\n");
RobMeades 118:f3fd6c30dc19 500 if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev))
RobMeades 118:f3fd6c30dc19 501 goto failure;
RobMeades 118:f3fd6c30dc19 502 if (_dev.dev == DEV_UNKNOWN)
RobMeades 118:f3fd6c30dc19 503 goto failure;
RobMeades 118:f3fd6c30dc19 504 // 3GPP/CDMA device specific init
RobMeades 118:f3fd6c30dc19 505 if (_dev.dev == DEV_LISA_C200) {
RobMeades 118:f3fd6c30dc19 506 // get the manufacturer
RobMeades 118:f3fd6c30dc19 507 sendFormated("AT+GMI\r\n");
RobMeades 118:f3fd6c30dc19 508 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
RobMeades 118:f3fd6c30dc19 509 goto failure;
RobMeades 118:f3fd6c30dc19 510 // get the model identification
RobMeades 118:f3fd6c30dc19 511 sendFormated("AT+GMM\r\n");
RobMeades 118:f3fd6c30dc19 512 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
RobMeades 118:f3fd6c30dc19 513 goto failure;
RobMeades 118:f3fd6c30dc19 514 // get the sw version
RobMeades 118:f3fd6c30dc19 515 sendFormated("AT+GMR\r\n");
RobMeades 118:f3fd6c30dc19 516 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
RobMeades 118:f3fd6c30dc19 517 goto failure;
RobMeades 118:f3fd6c30dc19 518 // get the pseudo ESN or MEID
RobMeades 118:f3fd6c30dc19 519 sendFormated("AT+GSN\r\n");
RobMeades 118:f3fd6c30dc19 520 if (RESP_OK != waitFinalResp(_cbString, _dev.meid))
RobMeades 118:f3fd6c30dc19 521 goto failure;
RobMeades 118:f3fd6c30dc19 522 #if 0
RobMeades 118:f3fd6c30dc19 523 // enable power saving
RobMeades 118:f3fd6c30dc19 524 if (_dev.lpm != LPM_DISABLED) {
RobMeades 118:f3fd6c30dc19 525 // enable power saving (requires flow control, cts at least)
RobMeades 118:f3fd6c30dc19 526 sendFormated("AT+UPSV=1,1280\r\n");
RobMeades 118:f3fd6c30dc19 527 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 528 goto failure;
RobMeades 118:f3fd6c30dc19 529 _dev.lpm = LPM_ACTIVE;
RobMeades 118:f3fd6c30dc19 530 }
RobMeades 118:f3fd6c30dc19 531 #endif
RobMeades 118:f3fd6c30dc19 532 } else {
RobMeades 118:f3fd6c30dc19 533 if ((_dev.dev == DEV_LISA_U200) || (_dev.dev == DEV_LEON_G200)) {
RobMeades 118:f3fd6c30dc19 534 // enable the network identification feature
RobMeades 118:f3fd6c30dc19 535 sendFormated("AT+UGPIOC=20,2\r\n");
RobMeades 118:f3fd6c30dc19 536 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 537 goto failure;
RobMeades 118:f3fd6c30dc19 538 } else if ((_dev.dev == DEV_SARA_U260) || (_dev.dev == DEV_SARA_U270) ||
RobMeades 118:f3fd6c30dc19 539 (_dev.dev == DEV_SARA_G350)) {
RobMeades 118:f3fd6c30dc19 540 // enable the network identification feature
RobMeades 118:f3fd6c30dc19 541 sendFormated("AT+UGPIOC=16,2\r\n");
RobMeades 118:f3fd6c30dc19 542 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 543 goto failure;
RobMeades 118:f3fd6c30dc19 544 }
RobMeades 118:f3fd6c30dc19 545 // check the sim card
RobMeades 118:f3fd6c30dc19 546 for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) {
RobMeades 118:f3fd6c30dc19 547 sendFormated("AT+CPIN?\r\n");
RobMeades 118:f3fd6c30dc19 548 int ret = waitFinalResp(_cbCPIN, &_dev.sim);
RobMeades 118:f3fd6c30dc19 549 // having an error here is ok (sim may still be initializing)
RobMeades 118:f3fd6c30dc19 550 if ((RESP_OK != ret) && (RESP_ERROR != ret))
RobMeades 118:f3fd6c30dc19 551 goto failure;
RobMeades 118:f3fd6c30dc19 552 // Enter PIN if needed
RobMeades 118:f3fd6c30dc19 553 if (_dev.sim == SIM_PIN) {
RobMeades 118:f3fd6c30dc19 554 if (!simpin) {
RobMeades 118:f3fd6c30dc19 555 ERROR("SIM PIN not available\r\n");
RobMeades 118:f3fd6c30dc19 556 goto failure;
RobMeades 118:f3fd6c30dc19 557 }
RobMeades 118:f3fd6c30dc19 558 sendFormated("AT+CPIN=%s\r\n", simpin);
RobMeades 118:f3fd6c30dc19 559 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim))
RobMeades 118:f3fd6c30dc19 560 goto failure;
RobMeades 118:f3fd6c30dc19 561 } else if (_dev.sim != SIM_READY) {
RobMeades 118:f3fd6c30dc19 562 wait_ms(1000);
RobMeades 118:f3fd6c30dc19 563 }
RobMeades 118:f3fd6c30dc19 564 }
RobMeades 118:f3fd6c30dc19 565 if (_dev.sim != SIM_READY) {
RobMeades 118:f3fd6c30dc19 566 if (_dev.sim == SIM_MISSING)
RobMeades 118:f3fd6c30dc19 567 ERROR("SIM not inserted\r\n");
RobMeades 118:f3fd6c30dc19 568 goto failure;
RobMeades 118:f3fd6c30dc19 569 }
RobMeades 118:f3fd6c30dc19 570 // get the manufacturer
RobMeades 118:f3fd6c30dc19 571 sendFormated("AT+CGMI\r\n");
RobMeades 118:f3fd6c30dc19 572 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
RobMeades 118:f3fd6c30dc19 573 goto failure;
RobMeades 118:f3fd6c30dc19 574 // get the model identification
RobMeades 118:f3fd6c30dc19 575 sendFormated("AT+CGMM\r\n");
RobMeades 118:f3fd6c30dc19 576 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
RobMeades 118:f3fd6c30dc19 577 goto failure;
RobMeades 118:f3fd6c30dc19 578 // get the
RobMeades 118:f3fd6c30dc19 579 sendFormated("AT+CGMR\r\n");
RobMeades 118:f3fd6c30dc19 580 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
RobMeades 118:f3fd6c30dc19 581 goto failure;
RobMeades 118:f3fd6c30dc19 582 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
RobMeades 118:f3fd6c30dc19 583 // ICCID is a serial number identifying the SIM.
RobMeades 118:f3fd6c30dc19 584 sendFormated("AT+CCID\r\n");
RobMeades 118:f3fd6c30dc19 585 if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid))
RobMeades 118:f3fd6c30dc19 586 goto failure;
RobMeades 118:f3fd6c30dc19 587 // Returns the product serial number, IMEI (International Mobile Equipment Identity)
RobMeades 118:f3fd6c30dc19 588 sendFormated("AT+CGSN\r\n");
RobMeades 118:f3fd6c30dc19 589 if (RESP_OK != waitFinalResp(_cbString, _dev.imei))
RobMeades 118:f3fd6c30dc19 590 goto failure;
RobMeades 118:f3fd6c30dc19 591 // enable power saving
RobMeades 118:f3fd6c30dc19 592 if (_dev.lpm != LPM_DISABLED) {
RobMeades 118:f3fd6c30dc19 593 // enable power saving (requires flow control, cts at least)
RobMeades 118:f3fd6c30dc19 594 sendFormated("AT+UPSV=1\r\n");
RobMeades 118:f3fd6c30dc19 595 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 596 goto failure;
RobMeades 118:f3fd6c30dc19 597 _dev.lpm = LPM_ACTIVE;
RobMeades 118:f3fd6c30dc19 598 }
RobMeades 118:f3fd6c30dc19 599 // enable the psd registration unsolicited result code
RobMeades 118:f3fd6c30dc19 600 sendFormated("AT+CGREG=2\r\n");
RobMeades 118:f3fd6c30dc19 601 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 602 goto failure;
RobMeades 118:f3fd6c30dc19 603 }
RobMeades 118:f3fd6c30dc19 604 // enable the network registration unsolicited result code
RobMeades 118:f3fd6c30dc19 605 sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C200) ? 1 : 2);
RobMeades 118:f3fd6c30dc19 606 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 607 goto failure;
RobMeades 118:f3fd6c30dc19 608 // Setup SMS in text mode
RobMeades 118:f3fd6c30dc19 609 sendFormated("AT+CMGF=1\r\n");
RobMeades 118:f3fd6c30dc19 610 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 611 goto failure;
RobMeades 118:f3fd6c30dc19 612 // setup new message indication
RobMeades 118:f3fd6c30dc19 613 sendFormated("AT+CNMI=2,1\r\n");
RobMeades 118:f3fd6c30dc19 614 if (RESP_OK != waitFinalResp())
RobMeades 118:f3fd6c30dc19 615 goto failure;
RobMeades 118:f3fd6c30dc19 616 // Request IMSI (International Mobile Subscriber Identification)
RobMeades 118:f3fd6c30dc19 617 sendFormated("AT+CIMI\r\n");
RobMeades 118:f3fd6c30dc19 618 if (RESP_OK != waitFinalResp(_cbString, _dev.imsi))
RobMeades 118:f3fd6c30dc19 619 goto failure;
RobMeades 118:f3fd6c30dc19 620 if (status)
RobMeades 118:f3fd6c30dc19 621 memcpy(status, &_dev, sizeof(DevStatus));
RobMeades 118:f3fd6c30dc19 622 UNLOCK();
RobMeades 118:f3fd6c30dc19 623 }
mazgch 31:a0bed6c1e05d 624 return true;
mazgch 95:8282dbbe1492 625 failure:
mazgch 95:8282dbbe1492 626 unlock();
mazgch 95:8282dbbe1492 627 return false;
mazgch 31:a0bed6c1e05d 628 }
mazgch 31:a0bed6c1e05d 629
mazgch 74:208e3e32d263 630 bool MDMParser::powerOff(void)
mazgch 74:208e3e32d263 631 {
mazgch 95:8282dbbe1492 632 bool ok = false;
mazgch 76:f7c3dd568dae 633 if (_init) {
mazgch 95:8282dbbe1492 634 LOCK();
mazgch 76:f7c3dd568dae 635 INFO("Modem::powerOff\r\n");
mazgch 76:f7c3dd568dae 636 sendFormated("AT+CPWROFF\r\n");
mazgch 95:8282dbbe1492 637 if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) {
mazgch 95:8282dbbe1492 638 _init = false;
mazgch 95:8282dbbe1492 639 ok = true;
mazgch 95:8282dbbe1492 640 }
mazgch 95:8282dbbe1492 641 UNLOCK();
mazgch 76:f7c3dd568dae 642 }
mazgch 95:8282dbbe1492 643 return ok;
mazgch 74:208e3e32d263 644 }
mazgch 74:208e3e32d263 645
mazgch 32:8f12ac182bbb 646 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev)
mazgch 31:a0bed6c1e05d 647 {
mazgch 37:cc3433329d66 648 if ((type == TYPE_UNKNOWN) && dev) {
mazgch 98:c786461edd40 649 if (strstr(buf, "SARA-G350")) *dev = DEV_SARA_G350;
mazgch 98:c786461edd40 650 else if (strstr(buf, "LISA-U200")) *dev = DEV_LISA_U200;
mazgch 98:c786461edd40 651 else if (strstr(buf, "LISA-C200")) *dev = DEV_LISA_C200;
mazgch 98:c786461edd40 652 else if (strstr(buf, "SARA-U260")) *dev = DEV_SARA_U260;
mazgch 98:c786461edd40 653 else if (strstr(buf, "SARA-U270")) *dev = DEV_SARA_U270;
mazgch 98:c786461edd40 654 else if (strstr(buf, "LEON-G200")) *dev = DEV_LEON_G200;
mazgch 28:4d9509e3b1cf 655 }
mazgch 31:a0bed6c1e05d 656 return WAIT;
mazgch 31:a0bed6c1e05d 657 }
mazgch 31:a0bed6c1e05d 658
mazgch 31:a0bed6c1e05d 659 int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim)
mazgch 31:a0bed6c1e05d 660 {
mazgch 75:ce6e12067d0c 661 if (sim) {
mazgch 75:ce6e12067d0c 662 if (type == TYPE_PLUS){
mazgch 75:ce6e12067d0c 663 char s[16];
mazgch 75:ce6e12067d0c 664 if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1)
mazgch 75:ce6e12067d0c 665 *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN;
mazgch 75:ce6e12067d0c 666 } else if (type == TYPE_ERROR) {
mazgch 75:ce6e12067d0c 667 if (strstr(buf, "+CME ERROR: SIM not inserted"))
mazgch 75:ce6e12067d0c 668 *sim = SIM_MISSING;
mazgch 31:a0bed6c1e05d 669 }
mazgch 31:a0bed6c1e05d 670 }
mazgch 31:a0bed6c1e05d 671 return WAIT;
mazgch 21:c4d64830bf02 672 }
mazgch 21:c4d64830bf02 673
mazgch 26:07be5faf8925 674 int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid)
mazgch 26:07be5faf8925 675 {
mazgch 26:07be5faf8925 676 if ((type == TYPE_PLUS) && ccid){
mazgch 26:07be5faf8925 677 if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1)
mazgch 31:a0bed6c1e05d 678 /*TRACE("Got CCID: %s\r\n", ccid)*/;
mazgch 26:07be5faf8925 679 }
mazgch 26:07be5faf8925 680 return WAIT;
mazgch 26:07be5faf8925 681 }
mazgch 26:07be5faf8925 682
mazgch 75:ce6e12067d0c 683 bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/)
mazgch 75:ce6e12067d0c 684 {
mazgch 75:ce6e12067d0c 685 Timer timer;
mazgch 75:ce6e12067d0c 686 timer.start();
mazgch 75:ce6e12067d0c 687 INFO("Modem::register\r\n");
mazgch 75:ce6e12067d0c 688 while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms))
mazgch 95:8282dbbe1492 689 wait_ms(1000);
mazgch 79:291df065e345 690 if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n");
mazgch 79:291df065e345 691 if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n");
mazgch 79:291df065e345 692 return REG_OK(_net.csd) || REG_OK(_net.psd);
mazgch 75:ce6e12067d0c 693 }
mazgch 75:ce6e12067d0c 694
mazgch 28:4d9509e3b1cf 695 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
mazgch 21:c4d64830bf02 696 {
mazgch 95:8282dbbe1492 697 bool ok = false;
mazgch 95:8282dbbe1492 698 LOCK();
mazgch 75:ce6e12067d0c 699 memset(&_net, 0, sizeof(_net));
mazgch 75:ce6e12067d0c 700 _net.lac = 0xFFFF;
mazgch 75:ce6e12067d0c 701 _net.ci = 0xFFFFFFFF;
mazgch 21:c4d64830bf02 702 // check registration
RobMeades 118:f3fd6c30dc19 703 if (_dev.dev == DEV_LISA_N101) {
RobMeades 118:f3fd6c30dc19 704 // Neul modem --------------------------
RobMeades 118:f3fd6c30dc19 705 sendFormated("AT+RAS\r\n");
RobMeades 118:f3fd6c30dc19 706 if (RESP_OK != waitFinalResp(_cbRAS, &ok))
RobMeades 118:f3fd6c30dc19 707 goto failure;
RobMeades 118:f3fd6c30dc19 708 _net.psd = REG_HOME;
RobMeades 118:f3fd6c30dc19 709 sendFormated("AT+CSQ\r\n");
RobMeades 118:f3fd6c30dc19 710 if (RESP_OK != waitFinalResp(_cbCSQN, &(_net.rssi)))
RobMeades 118:f3fd6c30dc19 711 goto failure;
RobMeades 118:f3fd6c30dc19 712 } else {
RobMeades 118:f3fd6c30dc19 713 sendFormated("AT+CREG?\r\n");
RobMeades 118:f3fd6c30dc19 714 waitFinalResp(); // don't fail as service could be not subscribed
RobMeades 118:f3fd6c30dc19 715 if (_dev.dev != DEV_LISA_C200) {
RobMeades 118:f3fd6c30dc19 716 // check PSD registration
RobMeades 118:f3fd6c30dc19 717 sendFormated("AT+CGREG?\r\n");
RobMeades 118:f3fd6c30dc19 718 waitFinalResp(); // don't fail as service could be not subscribed
RobMeades 118:f3fd6c30dc19 719 }
RobMeades 118:f3fd6c30dc19 720 if (REG_OK(_net.csd) || REG_OK(_net.psd))
RobMeades 118:f3fd6c30dc19 721 {
RobMeades 118:f3fd6c30dc19 722 // check modem specific status messages
RobMeades 118:f3fd6c30dc19 723 if (_dev.dev == DEV_LISA_C200) {
RobMeades 118:f3fd6c30dc19 724 sendFormated("AT+CSS?\r\n");
RobMeades 118:f3fd6c30dc19 725 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 726 goto failure;
RobMeades 118:f3fd6c30dc19 727 while (1) {
RobMeades 118:f3fd6c30dc19 728 // get the Telephone number
RobMeades 118:f3fd6c30dc19 729 sendFormated("AT$MDN?\r\n");
RobMeades 118:f3fd6c30dc19 730 if (RESP_OK != waitFinalResp(_cbString, _net.num))
mazgch 95:8282dbbe1492 731 goto failure;
RobMeades 118:f3fd6c30dc19 732 // check if we have a Mobile Directory Number
RobMeades 118:f3fd6c30dc19 733 if (*_net.num && (memcmp(_net.num, "000000", 6) != 0))
RobMeades 118:f3fd6c30dc19 734 break;
RobMeades 118:f3fd6c30dc19 735
RobMeades 118:f3fd6c30dc19 736 INFO("Device not yet activated\r\n");
RobMeades 118:f3fd6c30dc19 737 INFO("Make sure you have a valid contract with the network operator for this device.\r\n");
RobMeades 118:f3fd6c30dc19 738 // Check if the the version contains a V for Verizon
RobMeades 118:f3fd6c30dc19 739 // Verizon: E0.V.xx.00.xxR,
RobMeades 118:f3fd6c30dc19 740 // Sprint E0.S.xx.00.xxR
RobMeades 118:f3fd6c30dc19 741 if (_dev.ver[3] == 'V') {
RobMeades 118:f3fd6c30dc19 742 int i;
RobMeades 118:f3fd6c30dc19 743 INFO("Start device over-the-air activation (this can take a few minutes)\r\n");
RobMeades 118:f3fd6c30dc19 744 sendFormated("AT+CDV=*22899\r\n");
RobMeades 118:f3fd6c30dc19 745 i = 1;
RobMeades 118:f3fd6c30dc19 746 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
RobMeades 118:f3fd6c30dc19 747 ERROR("Device over-the-air activation failed\r\n");
RobMeades 118:f3fd6c30dc19 748 goto failure;
RobMeades 118:f3fd6c30dc19 749 }
RobMeades 118:f3fd6c30dc19 750 INFO("Device over-the-air activation successful\r\n");
RobMeades 118:f3fd6c30dc19 751
RobMeades 118:f3fd6c30dc19 752 INFO("Start PRL over-the-air update (this can take a few minutes)\r\n");
RobMeades 118:f3fd6c30dc19 753 sendFormated("AT+CDV=*22891\r\n");
RobMeades 118:f3fd6c30dc19 754 i = 1;
RobMeades 118:f3fd6c30dc19 755 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
RobMeades 118:f3fd6c30dc19 756 ERROR("PRL over-the-air update failed\r\n");
RobMeades 118:f3fd6c30dc19 757 goto failure;
RobMeades 118:f3fd6c30dc19 758 }
RobMeades 118:f3fd6c30dc19 759 INFO("PRL over-the-air update successful\r\n");
RobMeades 118:f3fd6c30dc19 760
RobMeades 118:f3fd6c30dc19 761 } else {
RobMeades 118:f3fd6c30dc19 762 // Sprint or Aeris
RobMeades 118:f3fd6c30dc19 763 INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n");
RobMeades 118:f3fd6c30dc19 764 wait_ms(120*1000);
mazgch 81:3966a5c17037 765 }
mazgch 81:3966a5c17037 766 }
RobMeades 118:f3fd6c30dc19 767 // get the the Network access identifier string
RobMeades 118:f3fd6c30dc19 768 char nai[64];
RobMeades 118:f3fd6c30dc19 769 sendFormated("AT$QCMIPNAI?\r\n");
RobMeades 118:f3fd6c30dc19 770 if (RESP_OK != waitFinalResp(_cbString, nai))
RobMeades 118:f3fd6c30dc19 771 goto failure;
RobMeades 118:f3fd6c30dc19 772 } else {
RobMeades 118:f3fd6c30dc19 773 sendFormated("AT+COPS?\r\n");
RobMeades 118:f3fd6c30dc19 774 if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
RobMeades 118:f3fd6c30dc19 775 goto failure;
RobMeades 118:f3fd6c30dc19 776 // get the MSISDNs related to this subscriber
RobMeades 118:f3fd6c30dc19 777 sendFormated("AT+CNUM\r\n");
RobMeades 118:f3fd6c30dc19 778 if (RESP_OK != waitFinalResp(_cbCNUM, _net.num))
RobMeades 118:f3fd6c30dc19 779 goto failure;
RobMeades 118:f3fd6c30dc19 780 }
RobMeades 118:f3fd6c30dc19 781 // get the signal strength indication
RobMeades 118:f3fd6c30dc19 782 sendFormated("AT+CSQ\r\n");
RobMeades 118:f3fd6c30dc19 783 if (RESP_OK != waitFinalResp(_cbCSQ, &_net))
mazgch 95:8282dbbe1492 784 goto failure;
RobMeades 118:f3fd6c30dc19 785 }
mazgch 75:ce6e12067d0c 786 }
mazgch 28:4d9509e3b1cf 787 if (status) {
mazgch 31:a0bed6c1e05d 788 memcpy(status, &_net, sizeof(NetStatus));
mazgch 25:4045d02e44f1 789 }
RobMeades 118:f3fd6c30dc19 790 if (_dev.dev == DEV_LISA_N101) {
RobMeades 118:f3fd6c30dc19 791 ok = REG_DONE(_net.psd); // No CSD for the Neul modem
RobMeades 118:f3fd6c30dc19 792 } else {
RobMeades 118:f3fd6c30dc19 793 ok = REG_DONE(_net.csd) && REG_DONE(_net.psd);
RobMeades 118:f3fd6c30dc19 794 }
mazgch 95:8282dbbe1492 795 UNLOCK();
mazgch 95:8282dbbe1492 796 return ok;
mazgch 95:8282dbbe1492 797 failure:
mazgch 95:8282dbbe1492 798 unlock();
mazgch 95:8282dbbe1492 799 return false;
mazgch 31:a0bed6c1e05d 800 }
mazgch 31:a0bed6c1e05d 801
mazgch 31:a0bed6c1e05d 802 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status)
mazgch 31:a0bed6c1e05d 803 {
mazgch 31:a0bed6c1e05d 804 if ((type == TYPE_PLUS) && status){
mazgch 31:a0bed6c1e05d 805 int act = 99;
mazgch 31:a0bed6c1e05d 806 // +COPS: <mode>[,<format>,<oper>[,<AcT>]]
mazgch 31:a0bed6c1e05d 807 if (sscanf(buf, "\r\n+COPS: %*d,%*d,\"%[^\"]\",%d",status->opr,&act) >= 1) {
mazgch 31:a0bed6c1e05d 808 if (act == 0) status->act = ACT_GSM; // 0: GSM,
mazgch 31:a0bed6c1e05d 809 else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN
mazgch 31:a0bed6c1e05d 810 }
mazgch 31:a0bed6c1e05d 811 }
mazgch 31:a0bed6c1e05d 812 return WAIT;
mazgch 31:a0bed6c1e05d 813 }
mazgch 31:a0bed6c1e05d 814
mazgch 31:a0bed6c1e05d 815 int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num)
mazgch 31:a0bed6c1e05d 816 {
mazgch 31:a0bed6c1e05d 817 if ((type == TYPE_PLUS) && num){
mazgch 31:a0bed6c1e05d 818 int a;
mazgch 31:a0bed6c1e05d 819 if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) &&
mazgch 31:a0bed6c1e05d 820 ((a == 129) || (a == 145))) {
mazgch 31:a0bed6c1e05d 821 }
mazgch 31:a0bed6c1e05d 822 }
mazgch 31:a0bed6c1e05d 823 return WAIT;
mazgch 31:a0bed6c1e05d 824 }
mazgch 31:a0bed6c1e05d 825
mazgch 54:7ba8e4c218e2 826 int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status)
mazgch 31:a0bed6c1e05d 827 {
mazgch 54:7ba8e4c218e2 828 if ((type == TYPE_PLUS) && status){
mazgch 54:7ba8e4c218e2 829 int a,b;
mazgch 54:7ba8e4c218e2 830 char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4
mazgch 31:a0bed6c1e05d 831 // +CSQ: <rssi>,<qual>
mazgch 54:7ba8e4c218e2 832 if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) {
mazgch 54:7ba8e4c218e2 833 if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps
mazgch 54:7ba8e4c218e2 834 if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; //
mazgch 31:a0bed6c1e05d 835 }
mazgch 31:a0bed6c1e05d 836 }
mazgch 31:a0bed6c1e05d 837 return WAIT;
mazgch 31:a0bed6c1e05d 838 }
mazgch 21:c4d64830bf02 839
mazgch 81:3966a5c17037 840 int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i)
mazgch 81:3966a5c17037 841 {
mazgch 81:3966a5c17037 842 if ((type == TYPE_PLUS) && i){
mazgch 82:055dcfcf9dcc 843 int a;
mazgch 82:055dcfcf9dcc 844 if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) {
mazgch 82:055dcfcf9dcc 845 *i = a;
mazgch 81:3966a5c17037 846 }
mazgch 81:3966a5c17037 847 }
mazgch 81:3966a5c17037 848 return WAIT;
mazgch 81:3966a5c17037 849 }
mazgch 81:3966a5c17037 850
RobMeades 118:f3fd6c30dc19 851 // Neul radio activity status
RobMeades 118:f3fd6c30dc19 852 int MDMParser::_cbRAS(int type, const char* buf, int len, bool* connected)
RobMeades 118:f3fd6c30dc19 853 {
RobMeades 118:f3fd6c30dc19 854 *connected = false;
RobMeades 118:f3fd6c30dc19 855 char status[32];
RobMeades 118:f3fd6c30dc19 856 if ((type == TYPE_PLUS) && connected) {
RobMeades 118:f3fd6c30dc19 857 // +RAS: <status>
RobMeades 118:f3fd6c30dc19 858 if (sscanf(buf, "\r\n+RAS:%s", status) == 1) {
RobMeades 118:f3fd6c30dc19 859 if (strcmp ("CONNECTED\r\n", status) == 0) {
RobMeades 118:f3fd6c30dc19 860 *connected = true;
RobMeades 118:f3fd6c30dc19 861 }
RobMeades 118:f3fd6c30dc19 862 return RESP_OK;
RobMeades 118:f3fd6c30dc19 863 }
RobMeades 118:f3fd6c30dc19 864 }
RobMeades 118:f3fd6c30dc19 865 return WAIT;
RobMeades 118:f3fd6c30dc19 866 }
RobMeades 118:f3fd6c30dc19 867
mazgch 21:c4d64830bf02 868 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 869 // internet connection
mazgch 21:c4d64830bf02 870
mazgch 79:291df065e345 871 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/,
mazgch 79:291df065e345 872 const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/)
mazgch 21:c4d64830bf02 873 {
mazgch 95:8282dbbe1492 874 LOCK();
mazgch 78:caf0014375cb 875 INFO("Modem::join\r\n");
mazgch 32:8f12ac182bbb 876 _ip = NOIP;
mazgch 32:8f12ac182bbb 877 if (_dev.dev == DEV_LISA_C200) {
mazgch 76:f7c3dd568dae 878 // make a dumy dns lookup (which will fail, so ignore the result)
mazgch 76:f7c3dd568dae 879 sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n");
mazgch 76:f7c3dd568dae 880 waitFinalResp();
mazgch 76:f7c3dd568dae 881 // This fake lookup will enable the IP connection and we
mazgch 76:f7c3dd568dae 882 // should have an IP after this, so we check it
mazgch 76:f7c3dd568dae 883
mazgch 21:c4d64830bf02 884 //Get local IP address
mazgch 21:c4d64830bf02 885 sendFormated("AT+CMIP?\r\n");
mazgch 52:8071747a7cb3 886 if (RESP_OK != waitFinalResp(_cbCMIP, &_ip))
mazgch 95:8282dbbe1492 887 goto failure;
mazgch 21:c4d64830bf02 888 } else {
mazgch 21:c4d64830bf02 889 // check gprs attach status
mazgch 72:d1e943ad6558 890 sendFormated("AT+CGATT=1\r\n");
mazgch 74:208e3e32d263 891 if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000))
mazgch 95:8282dbbe1492 892 goto failure;
mazgch 31:a0bed6c1e05d 893
mazgch 31:a0bed6c1e05d 894 // Check the profile
mazgch 31:a0bed6c1e05d 895 int a = 0;
mazgch 79:291df065e345 896 bool force = true;
mazgch 31:a0bed6c1e05d 897 sendFormated("AT+UPSND=" PROFILE ",8\r\n");
mazgch 52:8071747a7cb3 898 if (RESP_OK != waitFinalResp(_cbUPSND, &a))
mazgch 95:8282dbbe1492 899 goto failure;
mazgch 79:291df065e345 900 if (a == 1 && force) {
mazgch 31:a0bed6c1e05d 901 // disconnect the profile already if it is connected
mazgch 31:a0bed6c1e05d 902 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 58:e38a2e942fbb 903 if (RESP_OK != waitFinalResp(NULL,NULL,40*1000))
mazgch 95:8282dbbe1492 904 goto failure;
mazgch 79:291df065e345 905 a = 0;
mazgch 31:a0bed6c1e05d 906 }
mazgch 79:291df065e345 907 if (a == 0) {
mazgch 84:a05edb010176 908 bool ok = false;
mazgch 84:a05edb010176 909 // try to lookup the apn settings from our local database by mccmnc
mazgch 84:a05edb010176 910 const char* config = NULL;
mazgch 88:135fb4bb7aac 911 if (!apn && !username && !password)
mazgch 88:135fb4bb7aac 912 config = apnconfig(_dev.imsi);
mazgch 84:a05edb010176 913
mazgch 79:291df065e345 914 // Set up the dynamic IP address assignment.
mazgch 79:291df065e345 915 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
mazgch 52:8071747a7cb3 916 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 917 goto failure;
mazgch 84:a05edb010176 918
mazgch 84:a05edb010176 919 do {
mazgch 84:a05edb010176 920 if (config) {
mazgch 85:dd8f4f0d0ca9 921 apn = _APN_GET(config);
mazgch 85:dd8f4f0d0ca9 922 username = _APN_GET(config);
mazgch 85:dd8f4f0d0ca9 923 password = _APN_GET(config);
mazgch 84:a05edb010176 924 TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\")\r\n", apn, username, password);
mazgch 79:291df065e345 925 }
mazgch 84:a05edb010176 926 // Set up the APN
mazgch 90:3915192f6d7e 927 if (apn && *apn) {
mazgch 90:3915192f6d7e 928 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
mazgch 90:3915192f6d7e 929 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 930 goto failure;
mazgch 90:3915192f6d7e 931 }
mazgch 90:3915192f6d7e 932 if (username && *username) {
mazgch 90:3915192f6d7e 933 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
mazgch 90:3915192f6d7e 934 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 935 goto failure;
mazgch 90:3915192f6d7e 936 }
mazgch 90:3915192f6d7e 937 if (password && *password) {
mazgch 90:3915192f6d7e 938 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
mazgch 90:3915192f6d7e 939 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 940 goto failure;
mazgch 90:3915192f6d7e 941 }
mazgch 84:a05edb010176 942 // try different Authentication Protocols
mazgch 84:a05edb010176 943 // 0 = none
mazgch 84:a05edb010176 944 // 1 = PAP (Password Authentication Protocol)
mazgch 84:a05edb010176 945 // 2 = CHAP (Challenge Handshake Authentication Protocol)
mazgch 84:a05edb010176 946 for (int i = AUTH_NONE; i <= AUTH_CHAP && !ok; i ++) {
mazgch 84:a05edb010176 947 if ((auth == AUTH_DETECT) || (auth == i)) {
mazgch 84:a05edb010176 948 // Set up the Authentication Protocol
mazgch 84:a05edb010176 949 sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n", i);
mazgch 84:a05edb010176 950 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 951 goto failure;
mazgch 84:a05edb010176 952 // Activate the profile and make connection
mazgch 84:a05edb010176 953 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 84:a05edb010176 954 if (RESP_OK == waitFinalResp(NULL,NULL,150*1000))
mazgch 84:a05edb010176 955 ok = true;
mazgch 84:a05edb010176 956 }
mazgch 84:a05edb010176 957 }
mazgch 99:3116d3e900ed 958 } while (!ok && config && *config); // maybe use next setting ?
mazgch 84:a05edb010176 959 if (!ok) {
mazgch 79:291df065e345 960 ERROR("Your modem APN/password/username may be wrong\r\n");
mazgch 95:8282dbbe1492 961 goto failure;
mazgch 79:291df065e345 962 }
mazgch 74:208e3e32d263 963 }
mazgch 21:c4d64830bf02 964 //Get local IP address
mazgch 21:c4d64830bf02 965 sendFormated("AT+UPSND=" PROFILE ",0\r\n");
mazgch 52:8071747a7cb3 966 if (RESP_OK != waitFinalResp(_cbUPSND, &_ip))
mazgch 95:8282dbbe1492 967 goto failure;
mazgch 31:a0bed6c1e05d 968 }
mazgch 95:8282dbbe1492 969 UNLOCK();
mazgch 32:8f12ac182bbb 970 return _ip;
mazgch 95:8282dbbe1492 971 failure:
mazgch 95:8282dbbe1492 972 unlock();
mazgch 95:8282dbbe1492 973 return NOIP;
mazgch 31:a0bed6c1e05d 974 }
mazgch 31:a0bed6c1e05d 975
mazgch 84:a05edb010176 976 int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc)
mazgch 84:a05edb010176 977 {
mazgch 84:a05edb010176 978 if ((type == TYPE_PLUS) && mccmnc) {
mazgch 84:a05edb010176 979 if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1)
mazgch 84:a05edb010176 980 ;
mazgch 84:a05edb010176 981 }
mazgch 84:a05edb010176 982 return WAIT;
mazgch 84:a05edb010176 983 }
mazgch 84:a05edb010176 984
mazgch 32:8f12ac182bbb 985 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip)
mazgch 32:8f12ac182bbb 986 {
mazgch 102:fb982ff9da82 987 if ((type == TYPE_UNKNOWN) && ip) {
mazgch 32:8f12ac182bbb 988 int a,b,c,d;
mazgch 102:fb982ff9da82 989 if (sscanf(buf, "\r\n" IPSTR, &a,&b,&c,&d) == 4)
mazgch 32:8f12ac182bbb 990 *ip = IPADR(a,b,c,d);
mazgch 32:8f12ac182bbb 991 }
mazgch 32:8f12ac182bbb 992 return WAIT;
mazgch 32:8f12ac182bbb 993 }
mazgch 32:8f12ac182bbb 994
mazgch 31:a0bed6c1e05d 995 int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act)
mazgch 31:a0bed6c1e05d 996 {
mazgch 31:a0bed6c1e05d 997 if ((type == TYPE_PLUS) && act) {
mazgch 31:a0bed6c1e05d 998 if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1)
mazgch 31:a0bed6c1e05d 999 /*nothing*/;
mazgch 21:c4d64830bf02 1000 }
mazgch 31:a0bed6c1e05d 1001 return WAIT;
mazgch 31:a0bed6c1e05d 1002 }
mazgch 31:a0bed6c1e05d 1003
mazgch 31:a0bed6c1e05d 1004 int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 1005 {
mazgch 31:a0bed6c1e05d 1006 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 1007 int a,b,c,d;
mazgch 31:a0bed6c1e05d 1008 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
mazgch 31:a0bed6c1e05d 1009 if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 1010 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 1011 }
mazgch 31:a0bed6c1e05d 1012 return WAIT;
mazgch 31:a0bed6c1e05d 1013 }
mazgch 31:a0bed6c1e05d 1014
mazgch 31:a0bed6c1e05d 1015 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 1016 {
mazgch 31:a0bed6c1e05d 1017 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 1018 int a,b,c,d;
mazgch 95:8282dbbe1492 1019 if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 1020 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 1021 }
mazgch 31:a0bed6c1e05d 1022 return WAIT;
mazgch 21:c4d64830bf02 1023 }
mazgch 21:c4d64830bf02 1024
mazgch 21:c4d64830bf02 1025 bool MDMParser::disconnect(void)
mazgch 21:c4d64830bf02 1026 {
mazgch 95:8282dbbe1492 1027 bool ok = false;
mazgch 95:8282dbbe1492 1028 LOCK();
mazgch 74:208e3e32d263 1029 INFO("Modem::disconnect\r\n");
mazgch 95:8282dbbe1492 1030 if (_ip != NOIP) {
mazgch 95:8282dbbe1492 1031 if (_dev.dev == DEV_LISA_C200) {
mazgch 95:8282dbbe1492 1032 // There something to do here
mazgch 95:8282dbbe1492 1033 _ip = NOIP;
mazgch 95:8282dbbe1492 1034 ok = true;
mazgch 95:8282dbbe1492 1035 } else {
mazgch 95:8282dbbe1492 1036 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 95:8282dbbe1492 1037 if (RESP_OK != waitFinalResp()) {
mazgch 95:8282dbbe1492 1038 _ip = NOIP;
mazgch 95:8282dbbe1492 1039 ok = true;
mazgch 95:8282dbbe1492 1040 }
mazgch 95:8282dbbe1492 1041 }
mazgch 21:c4d64830bf02 1042 }
mazgch 95:8282dbbe1492 1043 UNLOCK();
mazgch 95:8282dbbe1492 1044 return ok;
mazgch 21:c4d64830bf02 1045 }
mazgch 21:c4d64830bf02 1046
mazgch 31:a0bed6c1e05d 1047 MDMParser::IP MDMParser::gethostbyname(const char* host)
mazgch 21:c4d64830bf02 1048 {
mazgch 31:a0bed6c1e05d 1049 IP ip = NOIP;
mazgch 31:a0bed6c1e05d 1050 int a,b,c,d;
mazgch 31:a0bed6c1e05d 1051 if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 1052 ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 1053 else {
mazgch 95:8282dbbe1492 1054 LOCK();
mazgch 31:a0bed6c1e05d 1055 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host);
mazgch 52:8071747a7cb3 1056 if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip))
mazgch 95:8282dbbe1492 1057 ip = NOIP;
mazgch 95:8282dbbe1492 1058 UNLOCK();
mazgch 21:c4d64830bf02 1059 }
mazgch 31:a0bed6c1e05d 1060 return ip;
mazgch 21:c4d64830bf02 1061 }
mazgch 21:c4d64830bf02 1062
mazgch 21:c4d64830bf02 1063 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 1064 // sockets
mazgch 21:c4d64830bf02 1065
mazgch 103:197fa7920ad8 1066 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* handle)
mazgch 21:c4d64830bf02 1067 {
mazgch 103:197fa7920ad8 1068 if ((type == TYPE_PLUS) && handle) {
mazgch 108:254bf037f83f 1069 // +USOCR: socket
mazgch 108:254bf037f83f 1070 if (sscanf(buf, "\r\n+USOCR: %d", handle) == 1)
mazgch 108:254bf037f83f 1071 /*nothing*/;
mazgch 21:c4d64830bf02 1072 }
mazgch 21:c4d64830bf02 1073 return WAIT;
mazgch 21:c4d64830bf02 1074 }
mazgch 21:c4d64830bf02 1075
mazgch 63:42cb563a25bc 1076 int MDMParser::socketSocket(IpProtocol ipproto, int port)
mazgch 21:c4d64830bf02 1077 {
mazgch 103:197fa7920ad8 1078 int socket;
mazgch 95:8282dbbe1492 1079 LOCK();
mazgch 103:197fa7920ad8 1080 // find an free socket
mazgch 103:197fa7920ad8 1081 socket = _findSocket();
mazgch 47:9a89e5195721 1082 TRACE("socketSocket(%d)\r\n", ipproto);
mazgch 95:8282dbbe1492 1083 if (socket != SOCKET_ERROR) {
mazgch 106:18aeacdae391 1084 if (ipproto == IPPROTO_UDP) {
mazgch 106:18aeacdae391 1085 // sending port can only be set on 2G/3G modules
mazgch 106:18aeacdae391 1086 if ((port != -1) && (_dev.dev != DEV_LISA_C200)) {
mazgch 106:18aeacdae391 1087 sendFormated("AT+USOCR=17,%d\r\n", port);
mazgch 106:18aeacdae391 1088 } else {
mazgch 106:18aeacdae391 1089 sendFormated("AT+USOCR=17\r\n");
mazgch 106:18aeacdae391 1090 }
mazgch 103:197fa7920ad8 1091 } else /*(ipproto == IPPROTO_TCP)*/ {
mazgch 103:197fa7920ad8 1092 sendFormated("AT+USOCR=6\r\n");
mazgch 103:197fa7920ad8 1093 }
mazgch 103:197fa7920ad8 1094 int handle = SOCKET_ERROR;
mazgch 103:197fa7920ad8 1095 if ((RESP_OK == waitFinalResp(_cbUSOCR, &handle)) &&
mazgch 103:197fa7920ad8 1096 (handle != SOCKET_ERROR)) {
mazgch 103:197fa7920ad8 1097 TRACE("Socket %d: handle %d was created\r\n", socket, handle);
mazgch 103:197fa7920ad8 1098 _sockets[socket].handle = handle;
mazgch 103:197fa7920ad8 1099 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
mazgch 103:197fa7920ad8 1100 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 1101 _sockets[socket].pending = 0;
mazgch 103:197fa7920ad8 1102 }
mazgch 103:197fa7920ad8 1103 else
mazgch 103:197fa7920ad8 1104 socket = SOCKET_ERROR;
mazgch 95:8282dbbe1492 1105 }
mazgch 95:8282dbbe1492 1106 UNLOCK();
mazgch 21:c4d64830bf02 1107 return socket;
mazgch 21:c4d64830bf02 1108 }
mazgch 21:c4d64830bf02 1109
mazgch 21:c4d64830bf02 1110 bool MDMParser::socketConnect(int socket, const char * host, int port)
mazgch 21:c4d64830bf02 1111 {
mazgch 31:a0bed6c1e05d 1112 IP ip = gethostbyname(host);
mazgch 31:a0bed6c1e05d 1113 if (ip == NOIP)
mazgch 21:c4d64830bf02 1114 return false;
mazgch 21:c4d64830bf02 1115 // connect to socket
mazgch 95:8282dbbe1492 1116 bool ok = false;
mazgch 95:8282dbbe1492 1117 LOCK();
mazgch 103:197fa7920ad8 1118 if (ISSOCKET(socket) && (!_sockets[socket].connected)) {
mazgch 95:8282dbbe1492 1119 TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port);
mazgch 103:197fa7920ad8 1120 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", _sockets[socket].handle, IPNUM(ip), port);
mazgch 95:8282dbbe1492 1121 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1122 ok = _sockets[socket].connected = true;
mazgch 95:8282dbbe1492 1123 }
mazgch 95:8282dbbe1492 1124 UNLOCK();
mazgch 95:8282dbbe1492 1125 return ok;
mazgch 21:c4d64830bf02 1126 }
mazgch 21:c4d64830bf02 1127
mazgch 44:9d12223b78ff 1128 bool MDMParser::socketIsConnected(int socket)
mazgch 44:9d12223b78ff 1129 {
mazgch 95:8282dbbe1492 1130 bool ok = false;
mazgch 95:8282dbbe1492 1131 LOCK();
mazgch 103:197fa7920ad8 1132 ok = ISSOCKET(socket) && _sockets[socket].connected;
mazgch 107:436ee320efd6 1133 TRACE("socketIsConnected(%d) %s\r\n", socket, ok?"yes":"no");
mazgch 95:8282dbbe1492 1134 UNLOCK();
mazgch 95:8282dbbe1492 1135 return ok;
mazgch 44:9d12223b78ff 1136 }
mazgch 44:9d12223b78ff 1137
mazgch 66:69072b3c5bca 1138 bool MDMParser::socketSetBlocking(int socket, int timeout_ms)
mazgch 44:9d12223b78ff 1139 {
mazgch 95:8282dbbe1492 1140 bool ok = false;
mazgch 95:8282dbbe1492 1141 LOCK();
mazgch 103:197fa7920ad8 1142 TRACE("socketSetBlocking(%d,%d)\r\n", socket,timeout_ms);
mazgch 95:8282dbbe1492 1143 if (ISSOCKET(socket)) {
mazgch 95:8282dbbe1492 1144 _sockets[socket].timeout_ms = timeout_ms;
mazgch 95:8282dbbe1492 1145 ok = true;
mazgch 95:8282dbbe1492 1146 }
mazgch 95:8282dbbe1492 1147 UNLOCK();
mazgch 95:8282dbbe1492 1148 return ok;
mazgch 44:9d12223b78ff 1149 }
mazgch 44:9d12223b78ff 1150
mazgch 21:c4d64830bf02 1151 bool MDMParser::socketClose(int socket)
mazgch 21:c4d64830bf02 1152 {
mazgch 95:8282dbbe1492 1153 bool ok = false;
mazgch 95:8282dbbe1492 1154 LOCK();
mazgch 103:197fa7920ad8 1155 if (ISSOCKET(socket) && _sockets[socket].connected) {
mazgch 95:8282dbbe1492 1156 TRACE("socketClose(%d)\r\n", socket);
mazgch 103:197fa7920ad8 1157 sendFormated("AT+USOCL=%d\r\n", _sockets[socket].handle);
mazgch 95:8282dbbe1492 1158 if (RESP_OK == waitFinalResp()) {
mazgch 103:197fa7920ad8 1159 _sockets[socket].connected = false;
mazgch 95:8282dbbe1492 1160 ok = true;
mazgch 95:8282dbbe1492 1161 }
mazgch 95:8282dbbe1492 1162 }
mazgch 95:8282dbbe1492 1163 UNLOCK();
mazgch 95:8282dbbe1492 1164 return ok;
mazgch 21:c4d64830bf02 1165 }
mazgch 21:c4d64830bf02 1166
mazgch 21:c4d64830bf02 1167 bool MDMParser::socketFree(int socket)
mazgch 21:c4d64830bf02 1168 {
mazgch 95:8282dbbe1492 1169 // make sure it is closed
mazgch 21:c4d64830bf02 1170 socketClose(socket);
mazgch 95:8282dbbe1492 1171 bool ok = true;
mazgch 95:8282dbbe1492 1172 LOCK();
mazgch 103:197fa7920ad8 1173 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1174 TRACE("socketFree(%d)\r\n", socket);
mazgch 103:197fa7920ad8 1175 _sockets[socket].handle = SOCKET_ERROR;
mazgch 103:197fa7920ad8 1176 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
mazgch 103:197fa7920ad8 1177 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 1178 _sockets[socket].pending = 0;
mazgch 95:8282dbbe1492 1179 ok = true;
mazgch 95:8282dbbe1492 1180 }
mazgch 95:8282dbbe1492 1181 UNLOCK();
mazgch 95:8282dbbe1492 1182 return ok;
mazgch 21:c4d64830bf02 1183 }
mazgch 21:c4d64830bf02 1184
mazgch 69:4d6fa520dfca 1185 #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket
mazgch 69:4d6fa520dfca 1186
mazgch 21:c4d64830bf02 1187 int MDMParser::socketSend(int socket, const char * buf, int len)
mazgch 21:c4d64830bf02 1188 {
mazgch 47:9a89e5195721 1189 TRACE("socketSend(%d,,%d)\r\n", socket,len);
mazgch 68:33a96cf64986 1190 int cnt = len;
mazgch 68:33a96cf64986 1191 while (cnt > 0) {
mazgch 69:4d6fa520dfca 1192 int blk = USO_MAX_WRITE;
mazgch 68:33a96cf64986 1193 if (cnt < blk)
mazgch 68:33a96cf64986 1194 blk = cnt;
mazgch 95:8282dbbe1492 1195 bool ok = false;
mazgch 95:8282dbbe1492 1196 LOCK();
mazgch 103:197fa7920ad8 1197 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1198 sendFormated("AT+USOWR=%d,%d\r\n",_sockets[socket].handle,blk);
mazgch 103:197fa7920ad8 1199 if (RESP_PROMPT == waitFinalResp()) {
mazgch 103:197fa7920ad8 1200 wait_ms(50);
mazgch 103:197fa7920ad8 1201 send(buf, blk);
mazgch 103:197fa7920ad8 1202 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1203 ok = true;
mazgch 103:197fa7920ad8 1204 }
mazgch 95:8282dbbe1492 1205 }
mazgch 95:8282dbbe1492 1206 UNLOCK();
mazgch 95:8282dbbe1492 1207 if (!ok)
mazgch 21:c4d64830bf02 1208 return SOCKET_ERROR;
mazgch 68:33a96cf64986 1209 buf += blk;
mazgch 68:33a96cf64986 1210 cnt -= blk;
mazgch 21:c4d64830bf02 1211 }
mazgch 68:33a96cf64986 1212 return (len - cnt);
mazgch 21:c4d64830bf02 1213 }
mazgch 21:c4d64830bf02 1214
mazgch 21:c4d64830bf02 1215 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len)
mazgch 21:c4d64830bf02 1216 {
mazgch 103:197fa7920ad8 1217 TRACE("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket,IPNUM(ip),port,len);
mazgch 68:33a96cf64986 1218 int cnt = len;
mazgch 68:33a96cf64986 1219 while (cnt > 0) {
mazgch 69:4d6fa520dfca 1220 int blk = USO_MAX_WRITE;
mazgch 68:33a96cf64986 1221 if (cnt < blk)
mazgch 68:33a96cf64986 1222 blk = cnt;
mazgch 95:8282dbbe1492 1223 bool ok = false;
mazgch 95:8282dbbe1492 1224 LOCK();
mazgch 103:197fa7920ad8 1225 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1226 sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",_sockets[socket].handle,IPNUM(ip),port,blk);
mazgch 103:197fa7920ad8 1227 if (RESP_PROMPT == waitFinalResp()) {
mazgch 103:197fa7920ad8 1228 wait_ms(50);
mazgch 103:197fa7920ad8 1229 send(buf, blk);
mazgch 103:197fa7920ad8 1230 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1231 ok = true;
mazgch 103:197fa7920ad8 1232 }
mazgch 95:8282dbbe1492 1233 }
mazgch 95:8282dbbe1492 1234 UNLOCK();
mazgch 95:8282dbbe1492 1235 if (!ok)
mazgch 21:c4d64830bf02 1236 return SOCKET_ERROR;
mazgch 68:33a96cf64986 1237 buf += blk;
mazgch 68:33a96cf64986 1238 cnt -= blk;
mazgch 21:c4d64830bf02 1239 }
mazgch 68:33a96cf64986 1240 return (len - cnt);
mazgch 21:c4d64830bf02 1241 }
mazgch 21:c4d64830bf02 1242
mazgch 21:c4d64830bf02 1243 int MDMParser::socketReadable(int socket)
mazgch 21:c4d64830bf02 1244 {
mazgch 95:8282dbbe1492 1245 int pending = SOCKET_ERROR;
mazgch 95:8282dbbe1492 1246 LOCK();
mazgch 103:197fa7920ad8 1247 if (ISSOCKET(socket) && _sockets[socket].connected) {
mazgch 95:8282dbbe1492 1248 TRACE("socketReadable(%d)\r\n", socket);
mazgch 95:8282dbbe1492 1249 // allow to receive unsolicited commands
mazgch 95:8282dbbe1492 1250 waitFinalResp(NULL, NULL, 0);
mazgch 103:197fa7920ad8 1251 if (_sockets[socket].connected)
mazgch 95:8282dbbe1492 1252 pending = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1253 }
mazgch 95:8282dbbe1492 1254 UNLOCK();
mazgch 95:8282dbbe1492 1255 return pending;
mazgch 21:c4d64830bf02 1256 }
mazgch 21:c4d64830bf02 1257
mazgch 21:c4d64830bf02 1258 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out)
mazgch 21:c4d64830bf02 1259 {
mazgch 21:c4d64830bf02 1260 if ((type == TYPE_PLUS) && out) {
mazgch 21:c4d64830bf02 1261 int sz, sk;
mazgch 21:c4d64830bf02 1262 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) &&
mazgch 21:c4d64830bf02 1263 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 1264 memcpy(out, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 1265 }
mazgch 21:c4d64830bf02 1266 }
mazgch 21:c4d64830bf02 1267 return WAIT;
mazgch 21:c4d64830bf02 1268 }
mazgch 21:c4d64830bf02 1269
mazgch 21:c4d64830bf02 1270 int MDMParser::socketRecv(int socket, char* buf, int len)
mazgch 21:c4d64830bf02 1271 {
mazgch 21:c4d64830bf02 1272 int cnt = 0;
mazgch 47:9a89e5195721 1273 TRACE("socketRecv(%d,,%d)\r\n", socket, len);
mazgch 95:8282dbbe1492 1274 #ifdef MDM_DEBUG
mazgch 21:c4d64830bf02 1275 memset(buf, '\0', len);
mazgch 95:8282dbbe1492 1276 #endif
mazgch 44:9d12223b78ff 1277 Timer timer;
mazgch 44:9d12223b78ff 1278 timer.start();
mazgch 21:c4d64830bf02 1279 while (len) {
mazgch 69:4d6fa520dfca 1280 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 1281 if (len < blk) blk = len;
mazgch 95:8282dbbe1492 1282 bool ok = false;
mazgch 95:8282dbbe1492 1283 LOCK();
mazgch 95:8282dbbe1492 1284 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1285 if (_sockets[socket].connected) {
mazgch 95:8282dbbe1492 1286 if (_sockets[socket].pending < blk)
mazgch 95:8282dbbe1492 1287 blk = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1288 if (blk > 0) {
mazgch 103:197fa7920ad8 1289 sendFormated("AT+USORD=%d,%d\r\n",_sockets[socket].handle, blk);
mazgch 95:8282dbbe1492 1290 if (RESP_OK == waitFinalResp(_cbUSORD, buf)) {
mazgch 95:8282dbbe1492 1291 _sockets[socket].pending -= blk;
mazgch 95:8282dbbe1492 1292 len -= blk;
mazgch 95:8282dbbe1492 1293 cnt += blk;
mazgch 95:8282dbbe1492 1294 buf += blk;
mazgch 95:8282dbbe1492 1295 ok = true;
mazgch 95:8282dbbe1492 1296 }
mazgch 95:8282dbbe1492 1297 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
mazgch 95:8282dbbe1492 1298 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
mazgch 95:8282dbbe1492 1299 } else {
mazgch 95:8282dbbe1492 1300 len = 0;
mazgch 95:8282dbbe1492 1301 ok = true;
mazgch 95:8282dbbe1492 1302 }
mazgch 103:197fa7920ad8 1303 } else {
mazgch 95:8282dbbe1492 1304 len = 0;
mazgch 95:8282dbbe1492 1305 ok = true;
mazgch 21:c4d64830bf02 1306 }
mazgch 21:c4d64830bf02 1307 }
mazgch 95:8282dbbe1492 1308 UNLOCK();
mazgch 107:436ee320efd6 1309 if (!ok) {
mazgch 107:436ee320efd6 1310 TRACE("socketRecv: ERROR\r\n");
mazgch 95:8282dbbe1492 1311 return SOCKET_ERROR;
mazgch 107:436ee320efd6 1312 }
mazgch 21:c4d64830bf02 1313 }
mazgch 107:436ee320efd6 1314 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt);
mazgch 21:c4d64830bf02 1315 return cnt;
mazgch 21:c4d64830bf02 1316 }
mazgch 21:c4d64830bf02 1317
mazgch 21:c4d64830bf02 1318 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param)
mazgch 21:c4d64830bf02 1319 {
mazgch 21:c4d64830bf02 1320 if ((type == TYPE_PLUS) && param) {
mazgch 21:c4d64830bf02 1321 int sz, sk, p, a,b,c,d;
mazgch 95:8282dbbe1492 1322 int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,",
mazgch 95:8282dbbe1492 1323 &sk,&a,&b,&c,&d,&p,&sz);
mazgch 95:8282dbbe1492 1324 if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 1325 memcpy(param->buf, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 1326 param->ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 1327 param->port = p;
mazgch 21:c4d64830bf02 1328 }
mazgch 21:c4d64830bf02 1329 }
mazgch 21:c4d64830bf02 1330 return WAIT;
mazgch 21:c4d64830bf02 1331 }
mazgch 21:c4d64830bf02 1332
mazgch 63:42cb563a25bc 1333 int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len)
mazgch 21:c4d64830bf02 1334 {
mazgch 21:c4d64830bf02 1335 int cnt = 0;
mazgch 63:42cb563a25bc 1336 TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len);
mazgch 95:8282dbbe1492 1337 #ifdef MDM_DEBUG
mazgch 21:c4d64830bf02 1338 memset(buf, '\0', len);
mazgch 95:8282dbbe1492 1339 #endif
mazgch 44:9d12223b78ff 1340 Timer timer;
mazgch 44:9d12223b78ff 1341 timer.start();
mazgch 21:c4d64830bf02 1342 while (len) {
mazgch 69:4d6fa520dfca 1343 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 1344 if (len < blk) blk = len;
mazgch 95:8282dbbe1492 1345 bool ok = false;
mazgch 95:8282dbbe1492 1346 LOCK();
mazgch 95:8282dbbe1492 1347 if (ISSOCKET(socket)) {
mazgch 95:8282dbbe1492 1348 if (_sockets[socket].pending < blk)
mazgch 95:8282dbbe1492 1349 blk = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1350 if (blk > 0) {
mazgch 103:197fa7920ad8 1351 sendFormated("AT+USORF=%d,%d\r\n",_sockets[socket].handle, blk);
mazgch 95:8282dbbe1492 1352 USORFparam param;
mazgch 95:8282dbbe1492 1353 param.buf = buf;
mazgch 95:8282dbbe1492 1354 if (RESP_OK == waitFinalResp(_cbUSORF, &param)) {
mazgch 95:8282dbbe1492 1355 _sockets[socket].pending -= blk;
mazgch 95:8282dbbe1492 1356 *ip = param.ip;
mazgch 95:8282dbbe1492 1357 *port = param.port;
mazgch 95:8282dbbe1492 1358 len -= blk;
mazgch 95:8282dbbe1492 1359 cnt += blk;
mazgch 95:8282dbbe1492 1360 buf += blk;
mazgch 95:8282dbbe1492 1361 len = 0; // done
mazgch 95:8282dbbe1492 1362 ok = true;
mazgch 95:8282dbbe1492 1363 }
mazgch 95:8282dbbe1492 1364 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
mazgch 95:8282dbbe1492 1365 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
mazgch 95:8282dbbe1492 1366 } else {
mazgch 95:8282dbbe1492 1367 len = 0; // no more data and socket closed or timed-out
mazgch 95:8282dbbe1492 1368 ok = true;
mazgch 21:c4d64830bf02 1369 }
mazgch 95:8282dbbe1492 1370 }
mazgch 95:8282dbbe1492 1371 UNLOCK();
mazgch 107:436ee320efd6 1372 if (!ok) {
mazgch 107:436ee320efd6 1373 TRACE("socketRecv: ERROR\r\n");
mazgch 95:8282dbbe1492 1374 return SOCKET_ERROR;
mazgch 107:436ee320efd6 1375 }
mazgch 21:c4d64830bf02 1376 }
mazgch 44:9d12223b78ff 1377 timer.stop();
mazgch 44:9d12223b78ff 1378 timer.reset();
mazgch 107:436ee320efd6 1379 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt);
mazgch 21:c4d64830bf02 1380 return cnt;
mazgch 21:c4d64830bf02 1381 }
mazgch 21:c4d64830bf02 1382
mazgch 103:197fa7920ad8 1383 int MDMParser::_findSocket(int handle) {
mazgch 104:c64ba749a422 1384 for (int socket = 0; socket < NUMSOCKETS; socket ++) {
mazgch 103:197fa7920ad8 1385 if (_sockets[socket].handle == handle)
mazgch 103:197fa7920ad8 1386 return socket;
mazgch 103:197fa7920ad8 1387 }
mazgch 103:197fa7920ad8 1388 return SOCKET_ERROR;
mazgch 103:197fa7920ad8 1389 }
mazgch 103:197fa7920ad8 1390
mazgch 21:c4d64830bf02 1391 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 1392
mazgch 31:a0bed6c1e05d 1393 int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param)
mazgch 21:c4d64830bf02 1394 {
mazgch 31:a0bed6c1e05d 1395 if ((type == TYPE_PLUS) && param && param->num) {
mazgch 31:a0bed6c1e05d 1396 // +CMGL: <ix>,...
mazgch 31:a0bed6c1e05d 1397 int ix;
mazgch 31:a0bed6c1e05d 1398 if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1)
mazgch 31:a0bed6c1e05d 1399 {
mazgch 31:a0bed6c1e05d 1400 *param->ix++ = ix;
mazgch 31:a0bed6c1e05d 1401 param->num--;
mazgch 31:a0bed6c1e05d 1402 }
mazgch 29:53d346010624 1403 }
mazgch 29:53d346010624 1404 return WAIT;
mazgch 21:c4d64830bf02 1405 }
mazgch 21:c4d64830bf02 1406
mazgch 31:a0bed6c1e05d 1407 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) {
mazgch 95:8282dbbe1492 1408 int ret = -1;
mazgch 95:8282dbbe1492 1409 LOCK();
mazgch 31:a0bed6c1e05d 1410 sendFormated("AT+CMGL=\"%s\"\r\n", stat);
mazgch 31:a0bed6c1e05d 1411 CMGLparam param;
mazgch 31:a0bed6c1e05d 1412 param.ix = ix;
mazgch 31:a0bed6c1e05d 1413 param.num = num;
mazgch 95:8282dbbe1492 1414 if (RESP_OK == waitFinalResp(_cbCMGL, &param))
mazgch 95:8282dbbe1492 1415 ret = num - param.num;
mazgch 95:8282dbbe1492 1416 UNLOCK();
mazgch 95:8282dbbe1492 1417 return ret;
mazgch 21:c4d64830bf02 1418 }
mazgch 21:c4d64830bf02 1419
mazgch 21:c4d64830bf02 1420 bool MDMParser::smsSend(const char* num, const char* buf)
mazgch 21:c4d64830bf02 1421 {
mazgch 95:8282dbbe1492 1422 bool ok = false;
mazgch 95:8282dbbe1492 1423 LOCK();
mazgch 80:34985b4d821e 1424 sendFormated("AT+CMGS=\"%s\"\r\n",num);
mazgch 95:8282dbbe1492 1425 if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) {
mazgch 95:8282dbbe1492 1426 send(buf, strlen(buf));
mazgch 95:8282dbbe1492 1427 const char ctrlZ = 0x1A;
mazgch 95:8282dbbe1492 1428 send(&ctrlZ, sizeof(ctrlZ));
mazgch 95:8282dbbe1492 1429 ok = (RESP_OK == waitFinalResp());
mazgch 21:c4d64830bf02 1430 }
mazgch 95:8282dbbe1492 1431 UNLOCK();
mazgch 95:8282dbbe1492 1432 return ok;
mazgch 21:c4d64830bf02 1433 }
mazgch 21:c4d64830bf02 1434
mazgch 21:c4d64830bf02 1435 bool MDMParser::smsDelete(int ix)
mazgch 21:c4d64830bf02 1436 {
mazgch 95:8282dbbe1492 1437 bool ok = false;
mazgch 95:8282dbbe1492 1438 LOCK();
mazgch 21:c4d64830bf02 1439 sendFormated("AT+CMGD=%d\r\n",ix);
mazgch 95:8282dbbe1492 1440 ok = (RESP_OK == waitFinalResp());
mazgch 95:8282dbbe1492 1441 UNLOCK();
mazgch 95:8282dbbe1492 1442 return ok;
mazgch 21:c4d64830bf02 1443 }
mazgch 21:c4d64830bf02 1444
mazgch 21:c4d64830bf02 1445 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param)
mazgch 21:c4d64830bf02 1446 {
mazgch 21:c4d64830bf02 1447 if (param) {
mazgch 21:c4d64830bf02 1448 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 1449 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) {
mazgch 21:c4d64830bf02 1450 }
mazgch 37:cc3433329d66 1451 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) {
mazgch 21:c4d64830bf02 1452 memcpy(param->buf, buf, len-2);
mazgch 21:c4d64830bf02 1453 param->buf[len-2] = '\0';
mazgch 21:c4d64830bf02 1454 }
mazgch 21:c4d64830bf02 1455 }
mazgch 21:c4d64830bf02 1456 return WAIT;
mazgch 21:c4d64830bf02 1457 }
mazgch 21:c4d64830bf02 1458
mazgch 21:c4d64830bf02 1459 bool MDMParser::smsRead(int ix, char* num, char* buf, int len)
mazgch 21:c4d64830bf02 1460 {
mazgch 95:8282dbbe1492 1461 bool ok = false;
mazgch 95:8282dbbe1492 1462 LOCK();
mazgch 21:c4d64830bf02 1463 CMGRparam param;
mazgch 21:c4d64830bf02 1464 param.num = num;
mazgch 21:c4d64830bf02 1465 param.buf = buf;
mazgch 21:c4d64830bf02 1466 sendFormated("AT+CMGR=%d\r\n",ix);
mazgch 95:8282dbbe1492 1467 ok = (RESP_OK == waitFinalResp(_cbCMGR, &param));
mazgch 95:8282dbbe1492 1468 UNLOCK();
mazgch 95:8282dbbe1492 1469 return ok;
mazgch 21:c4d64830bf02 1470 }
mazgch 54:7ba8e4c218e2 1471
mazgch 54:7ba8e4c218e2 1472 // ----------------------------------------------------------------
mazgch 70:0a87d256cd24 1473
mazgch 70:0a87d256cd24 1474 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp)
mazgch 70:0a87d256cd24 1475 {
mazgch 70:0a87d256cd24 1476 if ((type == TYPE_PLUS) && resp) {
mazgch 70:0a87d256cd24 1477 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..);
mazgch 70:0a87d256cd24 1478 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) {
mazgch 70:0a87d256cd24 1479 /*nothing*/
mazgch 70:0a87d256cd24 1480 }
mazgch 70:0a87d256cd24 1481 }
mazgch 70:0a87d256cd24 1482 return WAIT;
mazgch 70:0a87d256cd24 1483 }
mazgch 70:0a87d256cd24 1484
mazgch 70:0a87d256cd24 1485 bool MDMParser::ussdCommand(const char* cmd, char* buf)
mazgch 70:0a87d256cd24 1486 {
mazgch 95:8282dbbe1492 1487 bool ok = false;
mazgch 95:8282dbbe1492 1488 LOCK();
mazgch 70:0a87d256cd24 1489 *buf = '\0';
mazgch 95:8282dbbe1492 1490 if (_dev.dev != DEV_LISA_C200) {
mazgch 95:8282dbbe1492 1491 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
mazgch 95:8282dbbe1492 1492 ok = (RESP_OK == waitFinalResp(_cbCUSD, buf));
mazgch 70:0a87d256cd24 1493 }
mazgch 95:8282dbbe1492 1494 UNLOCK();
mazgch 95:8282dbbe1492 1495 return ok;
mazgch 70:0a87d256cd24 1496 }
mazgch 80:34985b4d821e 1497
mazgch 80:34985b4d821e 1498 // ----------------------------------------------------------------
RobMeades 118:f3fd6c30dc19 1499 // Neul AT command handling functions
RobMeades 118:f3fd6c30dc19 1500 int MDMParser::_cbMGS (int type, const char* buf, int len, bool* ok)
RobMeades 118:f3fd6c30dc19 1501 {
RobMeades 118:f3fd6c30dc19 1502 *ok = false;
RobMeades 118:f3fd6c30dc19 1503 if (type == TYPE_PLUS) {
RobMeades 118:f3fd6c30dc19 1504 if (strstr(buf, "\r\n+MGS:OK") == buf) {
RobMeades 118:f3fd6c30dc19 1505 *ok = true;
RobMeades 118:f3fd6c30dc19 1506 return RESP_OK;
RobMeades 118:f3fd6c30dc19 1507 }
RobMeades 118:f3fd6c30dc19 1508 }
RobMeades 118:f3fd6c30dc19 1509 return WAIT;
RobMeades 118:f3fd6c30dc19 1510 }
RobMeades 118:f3fd6c30dc19 1511
RobMeades 118:f3fd6c30dc19 1512 int MDMParser::_cbSMI (int type, const char* buf, int len, bool* sent)
RobMeades 118:f3fd6c30dc19 1513 {
RobMeades 118:f3fd6c30dc19 1514 *sent = false;
RobMeades 118:f3fd6c30dc19 1515 if (type == TYPE_PLUS) {
RobMeades 118:f3fd6c30dc19 1516 if (strstr(buf, "\r\n+SMI:SENT") == buf) {
RobMeades 118:f3fd6c30dc19 1517 *sent = true;
RobMeades 118:f3fd6c30dc19 1518 return RESP_OK;
RobMeades 118:f3fd6c30dc19 1519 }
RobMeades 118:f3fd6c30dc19 1520 }
RobMeades 118:f3fd6c30dc19 1521 return WAIT;
RobMeades 118:f3fd6c30dc19 1522 }
RobMeades 118:f3fd6c30dc19 1523
RobMeades 118:f3fd6c30dc19 1524 bool MDMParser::datagramSend(int size, const char* buf)
RobMeades 118:f3fd6c30dc19 1525 {
RobMeades 118:f3fd6c30dc19 1526 bool ok = false;
RobMeades 118:f3fd6c30dc19 1527
RobMeades 118:f3fd6c30dc19 1528 LOCK();
RobMeades 118:f3fd6c30dc19 1529 sendFormated ("AT+MGS=%d,%.*s\r\n", size / 2, size, buf);
RobMeades 118:f3fd6c30dc19 1530 ok = (RESP_OK == waitFinalResp(_cbMGS, &ok)) && ok;
RobMeades 118:f3fd6c30dc19 1531 if (ok) {
RobMeades 118:f3fd6c30dc19 1532 ok = (RESP_OK == waitFinalResp(NULL));
RobMeades 118:f3fd6c30dc19 1533 if (ok) {
RobMeades 118:f3fd6c30dc19 1534 ok = (RESP_OK == waitFinalResp(_cbSMI, &ok, 30000)) && ok;
RobMeades 118:f3fd6c30dc19 1535 }
RobMeades 118:f3fd6c30dc19 1536 }
RobMeades 118:f3fd6c30dc19 1537 UNLOCK();
RobMeades 118:f3fd6c30dc19 1538
RobMeades 118:f3fd6c30dc19 1539 return ok;
RobMeades 118:f3fd6c30dc19 1540 }
RobMeades 118:f3fd6c30dc19 1541
RobMeades 118:f3fd6c30dc19 1542 int MDMParser::_cbMGR (int type, const char* buf, int len, MGRparam* param)
RobMeades 118:f3fd6c30dc19 1543 {
RobMeades 118:f3fd6c30dc19 1544 int a = 0;
RobMeades 118:f3fd6c30dc19 1545 if (param) {
RobMeades 118:f3fd6c30dc19 1546 if (type == TYPE_PLUS) {
RobMeades 118:f3fd6c30dc19 1547 if ((sscanf(buf, "\r\n+MGR:%d", &a) == 1) && (a * 2 < param->maxlen)) {
RobMeades 118:f3fd6c30dc19 1548 if (sscanf(buf, "\r\n+MGR:%d,%s", &(param->outlen), param->buf) == 2) {
RobMeades 118:f3fd6c30dc19 1549 param->outlen *=2; // length in bytes rather than hex-char representation
RobMeades 118:f3fd6c30dc19 1550 return RESP_OK;
RobMeades 118:f3fd6c30dc19 1551 }
RobMeades 118:f3fd6c30dc19 1552 }
RobMeades 118:f3fd6c30dc19 1553 }
RobMeades 118:f3fd6c30dc19 1554 }
RobMeades 118:f3fd6c30dc19 1555
RobMeades 118:f3fd6c30dc19 1556 return WAIT;
RobMeades 118:f3fd6c30dc19 1557 }
RobMeades 118:f3fd6c30dc19 1558
RobMeades 118:f3fd6c30dc19 1559 bool MDMParser::doMGR (int* size, char* buf, MGRparam *param)
RobMeades 118:f3fd6c30dc19 1560 {
RobMeades 118:f3fd6c30dc19 1561 bool ok;
RobMeades 118:f3fd6c30dc19 1562
RobMeades 118:f3fd6c30dc19 1563 sendFormated ("AT+MGR\r\n");
RobMeades 118:f3fd6c30dc19 1564 ok = (RESP_OK == waitFinalResp(_cbMGR, param, 1000));
RobMeades 118:f3fd6c30dc19 1565 if (ok) {
RobMeades 118:f3fd6c30dc19 1566 if (ok && (param->outlen > 0)) {
RobMeades 118:f3fd6c30dc19 1567 ok = (RESP_OK == waitFinalResp(NULL));
RobMeades 118:f3fd6c30dc19 1568 *size = param->maxlen;
RobMeades 118:f3fd6c30dc19 1569 hexStringToBytes (param->buf, param->outlen, buf, size);
RobMeades 118:f3fd6c30dc19 1570 }
RobMeades 118:f3fd6c30dc19 1571 }
RobMeades 118:f3fd6c30dc19 1572
RobMeades 118:f3fd6c30dc19 1573 return ok;
RobMeades 118:f3fd6c30dc19 1574 }
RobMeades 118:f3fd6c30dc19 1575
RobMeades 118:f3fd6c30dc19 1576 #ifdef C027N_USE_NMI
RobMeades 118:f3fd6c30dc19 1577
RobMeades 118:f3fd6c30dc19 1578 bool MDMParser::datagramRecv(int* size, char* buf, int timeoutMs /* 10000 */)
RobMeades 118:f3fd6c30dc19 1579 {
RobMeades 118:f3fd6c30dc19 1580 bool gotDatagram = false;
RobMeades 118:f3fd6c30dc19 1581 MGRparam param;
RobMeades 118:f3fd6c30dc19 1582 param.buf = buf;
RobMeades 118:f3fd6c30dc19 1583 param.maxlen = *size;
RobMeades 118:f3fd6c30dc19 1584 param.outlen = 0;
RobMeades 118:f3fd6c30dc19 1585
RobMeades 118:f3fd6c30dc19 1586 LOCK();
RobMeades 118:f3fd6c30dc19 1587 if (_outstandingNMI == 0)
RobMeades 118:f3fd6c30dc19 1588 {
RobMeades 118:f3fd6c30dc19 1589 waitFinalResp(NULL, NULL, timeoutMs);
RobMeades 118:f3fd6c30dc19 1590 }
RobMeades 118:f3fd6c30dc19 1591 if (_outstandingNMI > 0)
RobMeades 118:f3fd6c30dc19 1592 {
RobMeades 118:f3fd6c30dc19 1593 gotDatagram = doMGR (size, buf, &param);
RobMeades 118:f3fd6c30dc19 1594 if (gotDatagram) {
RobMeades 118:f3fd6c30dc19 1595 _outstandingNMI--;
RobMeades 118:f3fd6c30dc19 1596 if (param.outlen > 0) {
RobMeades 118:f3fd6c30dc19 1597 gotDatagram = true;
RobMeades 118:f3fd6c30dc19 1598 }
RobMeades 118:f3fd6c30dc19 1599 } else {
RobMeades 118:f3fd6c30dc19 1600 *size = 0;
RobMeades 118:f3fd6c30dc19 1601 }
RobMeades 118:f3fd6c30dc19 1602 }
RobMeades 118:f3fd6c30dc19 1603 UNLOCK();
RobMeades 118:f3fd6c30dc19 1604
RobMeades 118:f3fd6c30dc19 1605 return gotDatagram;
RobMeades 118:f3fd6c30dc19 1606 }
RobMeades 118:f3fd6c30dc19 1607
RobMeades 118:f3fd6c30dc19 1608 #else
RobMeades 118:f3fd6c30dc19 1609
RobMeades 118:f3fd6c30dc19 1610 bool MDMParser::datagramRecv(int* size, char* buf, int timeoutMs /* 10000 */)
RobMeades 118:f3fd6c30dc19 1611 {
RobMeades 118:f3fd6c30dc19 1612 bool ok = false;
RobMeades 118:f3fd6c30dc19 1613 MGRparam param;
RobMeades 118:f3fd6c30dc19 1614 Timer timer;
RobMeades 118:f3fd6c30dc19 1615 param.buf = buf;
RobMeades 118:f3fd6c30dc19 1616 param.maxlen = *size;
RobMeades 118:f3fd6c30dc19 1617 param.outlen = 0;
RobMeades 118:f3fd6c30dc19 1618
RobMeades 118:f3fd6c30dc19 1619 // The correct way to do this would be to switch on NMI and wait, however
RobMeades 118:f3fd6c30dc19 1620 // the NMI carries all the data with it, it's not just a flag, and so
RobMeades 118:f3fd6c30dc19 1621 // the parser here would have to handle queues of data, which it can't.
RobMeades 118:f3fd6c30dc19 1622 // So instead, just poll with AT+MGR until a mode of NMI comes along
RobMeades 118:f3fd6c30dc19 1623 // which leaves the data in the buffer.
RobMeades 118:f3fd6c30dc19 1624
RobMeades 118:f3fd6c30dc19 1625 LOCK();
RobMeades 118:f3fd6c30dc19 1626 timer.start();
RobMeades 118:f3fd6c30dc19 1627 ok = true;
RobMeades 118:f3fd6c30dc19 1628 while (ok && (param.outlen == 0) && (timer.read_ms() < timeoutMs)) {
RobMeades 118:f3fd6c30dc19 1629 ok = doMGR (size, buf, &param);
RobMeades 118:f3fd6c30dc19 1630 if (ok && param.outlen == 0) {
RobMeades 118:f3fd6c30dc19 1631 wait_ms (500);
RobMeades 118:f3fd6c30dc19 1632 }
RobMeades 118:f3fd6c30dc19 1633 }
RobMeades 118:f3fd6c30dc19 1634 if (param.outlen == 0) {
RobMeades 118:f3fd6c30dc19 1635 ok = false;
RobMeades 118:f3fd6c30dc19 1636 *size = 0;
RobMeades 118:f3fd6c30dc19 1637 }
RobMeades 118:f3fd6c30dc19 1638 UNLOCK();
RobMeades 118:f3fd6c30dc19 1639
RobMeades 118:f3fd6c30dc19 1640 return ok;
RobMeades 118:f3fd6c30dc19 1641 }
RobMeades 118:f3fd6c30dc19 1642
RobMeades 118:f3fd6c30dc19 1643 #endif
RobMeades 118:f3fd6c30dc19 1644
RobMeades 118:f3fd6c30dc19 1645 int MDMParser::_cbCSQN(int type, const char* buf, int len, int* rssi)
RobMeades 118:f3fd6c30dc19 1646 {
RobMeades 118:f3fd6c30dc19 1647 if ((type == TYPE_PLUS) && rssi) {
RobMeades 118:f3fd6c30dc19 1648 // +CSQ: <rssi>
RobMeades 118:f3fd6c30dc19 1649 if (sscanf(buf, "\r\n+CSQ: %d", rssi) == 1) {
RobMeades 118:f3fd6c30dc19 1650 return RESP_OK;
RobMeades 118:f3fd6c30dc19 1651 }
RobMeades 118:f3fd6c30dc19 1652 }
RobMeades 118:f3fd6c30dc19 1653
RobMeades 118:f3fd6c30dc19 1654 return WAIT;
RobMeades 118:f3fd6c30dc19 1655 }
RobMeades 118:f3fd6c30dc19 1656
RobMeades 118:f3fd6c30dc19 1657 bool MDMParser::getRssi(int *rssi)
RobMeades 118:f3fd6c30dc19 1658 {
RobMeades 118:f3fd6c30dc19 1659 bool ok = false;
RobMeades 118:f3fd6c30dc19 1660 if (rssi) {
RobMeades 118:f3fd6c30dc19 1661 LOCK();
RobMeades 118:f3fd6c30dc19 1662 sendFormated ("AT+CSQ\r\n");
RobMeades 118:f3fd6c30dc19 1663 ok = (RESP_OK == waitFinalResp(_cbCSQN, rssi));
RobMeades 118:f3fd6c30dc19 1664 if (ok) {
RobMeades 118:f3fd6c30dc19 1665 ok = (RESP_OK == waitFinalResp(NULL));
RobMeades 118:f3fd6c30dc19 1666 }
RobMeades 118:f3fd6c30dc19 1667 UNLOCK();
RobMeades 118:f3fd6c30dc19 1668 }
RobMeades 118:f3fd6c30dc19 1669 return ok;
RobMeades 118:f3fd6c30dc19 1670 }
RobMeades 118:f3fd6c30dc19 1671
RobMeades 118:f3fd6c30dc19 1672 int MDMParser::_cbRB (int type, const char* buf, int len, bool* ok)
RobMeades 118:f3fd6c30dc19 1673 {
RobMeades 118:f3fd6c30dc19 1674 *ok = false;
RobMeades 118:f3fd6c30dc19 1675 if (type == TYPE_PLUS) {
RobMeades 118:f3fd6c30dc19 1676 if (strstr(buf, "\r\n+RB:REBOOTING") == buf) {
RobMeades 118:f3fd6c30dc19 1677 *ok = true;
RobMeades 118:f3fd6c30dc19 1678 return RESP_OK;
RobMeades 118:f3fd6c30dc19 1679 }
RobMeades 118:f3fd6c30dc19 1680 }
RobMeades 118:f3fd6c30dc19 1681 return WAIT;
RobMeades 118:f3fd6c30dc19 1682 }
RobMeades 118:f3fd6c30dc19 1683
RobMeades 118:f3fd6c30dc19 1684 bool MDMParser::neulReboot()
RobMeades 118:f3fd6c30dc19 1685 {
RobMeades 118:f3fd6c30dc19 1686 bool ok = false;
RobMeades 118:f3fd6c30dc19 1687 LOCK();
RobMeades 118:f3fd6c30dc19 1688 sendFormated ("AT+RB\r\n");
RobMeades 118:f3fd6c30dc19 1689 ok = (RESP_OK == waitFinalResp(_cbRB, &ok)) && ok;
RobMeades 118:f3fd6c30dc19 1690 if (ok) {
RobMeades 118:f3fd6c30dc19 1691 ok = (RESP_OK == waitFinalResp(NULL));
RobMeades 118:f3fd6c30dc19 1692 }
RobMeades 118:f3fd6c30dc19 1693 UNLOCK();
RobMeades 118:f3fd6c30dc19 1694
RobMeades 118:f3fd6c30dc19 1695 return ok;
RobMeades 118:f3fd6c30dc19 1696 }
RobMeades 118:f3fd6c30dc19 1697
RobMeades 118:f3fd6c30dc19 1698 void MDMParser::hexStringToBytes (const char *inBuf, int lenInBuf, char * outBuf, int* lenOutBuf)
RobMeades 118:f3fd6c30dc19 1699 {
RobMeades 118:f3fd6c30dc19 1700 int x;
RobMeades 118:f3fd6c30dc19 1701 int y = 0;
RobMeades 118:f3fd6c30dc19 1702 int z;
RobMeades 118:f3fd6c30dc19 1703
RobMeades 118:f3fd6c30dc19 1704 for (x = 0; (x < lenInBuf) && (y < *lenOutBuf); x++)
RobMeades 118:f3fd6c30dc19 1705 {
RobMeades 118:f3fd6c30dc19 1706 z = *(inBuf + x);
RobMeades 118:f3fd6c30dc19 1707 if ((z >= '0') && (z <= '9'))
RobMeades 118:f3fd6c30dc19 1708 {
RobMeades 118:f3fd6c30dc19 1709 z = z - '0';
RobMeades 118:f3fd6c30dc19 1710 }
RobMeades 118:f3fd6c30dc19 1711 else
RobMeades 118:f3fd6c30dc19 1712 {
RobMeades 118:f3fd6c30dc19 1713 z &= ~0x20;
RobMeades 118:f3fd6c30dc19 1714 if ((z >= 'A') && (z <= 'F'))
RobMeades 118:f3fd6c30dc19 1715 {
RobMeades 118:f3fd6c30dc19 1716 z = z - 'A' + 10;
RobMeades 118:f3fd6c30dc19 1717 }
RobMeades 118:f3fd6c30dc19 1718 }
RobMeades 118:f3fd6c30dc19 1719
RobMeades 118:f3fd6c30dc19 1720 if (x % 2 == 0)
RobMeades 118:f3fd6c30dc19 1721 {
RobMeades 118:f3fd6c30dc19 1722 *(outBuf + y) = (z << 4) & 0xF0;
RobMeades 118:f3fd6c30dc19 1723 }
RobMeades 118:f3fd6c30dc19 1724 else
RobMeades 118:f3fd6c30dc19 1725 {
RobMeades 118:f3fd6c30dc19 1726 *(outBuf + y) += z;
RobMeades 118:f3fd6c30dc19 1727 y++;
RobMeades 118:f3fd6c30dc19 1728 }
RobMeades 118:f3fd6c30dc19 1729 }
RobMeades 118:f3fd6c30dc19 1730
RobMeades 118:f3fd6c30dc19 1731 *lenOutBuf = y;
RobMeades 118:f3fd6c30dc19 1732 }
RobMeades 118:f3fd6c30dc19 1733
RobMeades 118:f3fd6c30dc19 1734 // ----------------------------------------------------------------
mazgch 70:0a87d256cd24 1735
mazgch 115:d8d94b73c725 1736 int MDMParser::_cbUDELFILE(int type, const char* buf, int len, void*)
mazgch 115:d8d94b73c725 1737 {
mazgch 115:d8d94b73c725 1738 if ((type == TYPE_ERROR) && strstr(buf, "+CME ERROR: FILE NOT FOUND"))
mazgch 115:d8d94b73c725 1739 return RESP_OK; // file does not exist, so all ok...
mazgch 115:d8d94b73c725 1740 return WAIT;
mazgch 115:d8d94b73c725 1741 }
mazgch 115:d8d94b73c725 1742
mazgch 80:34985b4d821e 1743 bool MDMParser::delFile(const char* filename)
mazgch 80:34985b4d821e 1744 {
mazgch 95:8282dbbe1492 1745 bool ok = false;
mazgch 95:8282dbbe1492 1746 LOCK();
mazgch 80:34985b4d821e 1747 sendFormated("AT+UDELFILE=\"%s\"\r\n", filename);
mazgch 115:d8d94b73c725 1748 ok = (RESP_OK == waitFinalResp(_cbUDELFILE));
mazgch 95:8282dbbe1492 1749 UNLOCK();
mazgch 95:8282dbbe1492 1750 return ok;
mazgch 80:34985b4d821e 1751 }
mazgch 80:34985b4d821e 1752
mazgch 80:34985b4d821e 1753 int MDMParser::writeFile(const char* filename, const char* buf, int len)
mazgch 80:34985b4d821e 1754 {
mazgch 95:8282dbbe1492 1755 bool ok = false;
mazgch 95:8282dbbe1492 1756 LOCK();
mazgch 80:34985b4d821e 1757 sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len);
mazgch 95:8282dbbe1492 1758 if (RESP_PROMPT == waitFinalResp()) {
mazgch 95:8282dbbe1492 1759 send(buf, len);
mazgch 95:8282dbbe1492 1760 ok = (RESP_OK == waitFinalResp());
mazgch 95:8282dbbe1492 1761 }
mazgch 95:8282dbbe1492 1762 UNLOCK();
mazgch 95:8282dbbe1492 1763 return ok ? len : -1;
mazgch 80:34985b4d821e 1764 }
mazgch 80:34985b4d821e 1765
mazgch 80:34985b4d821e 1766 int MDMParser::readFile(const char* filename, char* buf, int len)
mazgch 80:34985b4d821e 1767 {
mazgch 80:34985b4d821e 1768 URDFILEparam param;
mazgch 80:34985b4d821e 1769 param.filename = filename;
mazgch 80:34985b4d821e 1770 param.buf = buf;
mazgch 80:34985b4d821e 1771 param.sz = len;
mazgch 80:34985b4d821e 1772 param.len = 0;
mazgch 95:8282dbbe1492 1773 LOCK();
mazgch 95:8282dbbe1492 1774 sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len);
mazgch 105:f6bb2a20de70 1775 if (RESP_OK != waitFinalResp(_cbURDFILE, &param))
mazgch 95:8282dbbe1492 1776 param.len = -1;
mazgch 95:8282dbbe1492 1777 UNLOCK();
mazgch 80:34985b4d821e 1778 return param.len;
mazgch 80:34985b4d821e 1779 }
mazgch 80:34985b4d821e 1780
mazgch 80:34985b4d821e 1781 int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param)
mazgch 80:34985b4d821e 1782 {
mazgch 80:34985b4d821e 1783 if ((type == TYPE_PLUS) && param && param->filename && param->buf) {
mazgch 80:34985b4d821e 1784 char filename[48];
mazgch 80:34985b4d821e 1785 int sz;
mazgch 80:34985b4d821e 1786 if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) &&
mazgch 80:34985b4d821e 1787 (0 == strcmp(param->filename, filename)) &&
mazgch 80:34985b4d821e 1788 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 80:34985b4d821e 1789 param->len = (sz < param->sz) ? sz : param->sz;
mazgch 80:34985b4d821e 1790 memcpy(param->buf, &buf[len-1-sz], param->len);
mazgch 80:34985b4d821e 1791 }
mazgch 80:34985b4d821e 1792 }
mazgch 80:34985b4d821e 1793 return WAIT;
mazgch 80:34985b4d821e 1794 }
mazgch 80:34985b4d821e 1795
mazgch 70:0a87d256cd24 1796 // ----------------------------------------------------------------
mazgch 74:208e3e32d263 1797 bool MDMParser::setDebug(int level)
mazgch 74:208e3e32d263 1798 {
mazgch 74:208e3e32d263 1799 #ifdef MDM_DEBUG
mazgch 117:74e4e0109a9e 1800 if ((_debugLevel >= -1) && (level >= -1) &&
mazgch 117:74e4e0109a9e 1801 (_debugLevel <= 3) && (level <= 3)) {
mazgch 74:208e3e32d263 1802 _debugLevel = level;
mazgch 74:208e3e32d263 1803 return true;
mazgch 74:208e3e32d263 1804 }
mazgch 74:208e3e32d263 1805 #endif
mazgch 74:208e3e32d263 1806 return false;
mazgch 74:208e3e32d263 1807 }
mazgch 74:208e3e32d263 1808
mazgch 73:2b32e0a21df2 1809 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status,
mazgch 73:2b32e0a21df2 1810 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 1811 {
mazgch 75:ce6e12067d0c 1812 dprint(param, "Modem::devStatus\r\n");
mazgch 98:c786461edd40 1813 const char* txtDev[] = { "Unknown", "SARA-G350", "LISA-U200", "LISA-C200", "SARA-U260", "SARA-U270", "LEON-G200" };
mazgch 98:c786461edd40 1814 if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != DEV_UNKNOWN))
mazgch 73:2b32e0a21df2 1815 dprint(param, " Device: %s\r\n", txtDev[status->dev]);
mazgch 54:7ba8e4c218e2 1816 const char* txtLpm[] = { "Disabled", "Enabled", "Active" };
mazgch 54:7ba8e4c218e2 1817 if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm))
mazgch 73:2b32e0a21df2 1818 dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]);
mazgch 75:ce6e12067d0c 1819 const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" };
mazgch 98:c786461edd40 1820 if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != SIM_UNKNOWN))
mazgch 73:2b32e0a21df2 1821 dprint(param, " SIM: %s\r\n", txtSim[status->sim]);
mazgch 54:7ba8e4c218e2 1822 if (*status->ccid)
mazgch 73:2b32e0a21df2 1823 dprint(param, " CCID: %s\r\n", status->ccid);
mazgch 54:7ba8e4c218e2 1824 if (*status->imei)
mazgch 73:2b32e0a21df2 1825 dprint(param, " IMEI: %s\r\n", status->imei);
mazgch 54:7ba8e4c218e2 1826 if (*status->imsi)
mazgch 73:2b32e0a21df2 1827 dprint(param, " IMSI: %s\r\n", status->imsi);
mazgch 54:7ba8e4c218e2 1828 if (*status->meid)
mazgch 73:2b32e0a21df2 1829 dprint(param, " MEID: %s\r\n", status->meid); // LISA-C
mazgch 54:7ba8e4c218e2 1830 if (*status->manu)
mazgch 73:2b32e0a21df2 1831 dprint(param, " Manufacturer: %s\r\n", status->manu);
mazgch 54:7ba8e4c218e2 1832 if (*status->model)
mazgch 73:2b32e0a21df2 1833 dprint(param, " Model: %s\r\n", status->model);
mazgch 54:7ba8e4c218e2 1834 if (*status->ver)
mazgch 73:2b32e0a21df2 1835 dprint(param, " Version: %s\r\n", status->ver);
mazgch 54:7ba8e4c218e2 1836 }
mazgch 54:7ba8e4c218e2 1837
mazgch 73:2b32e0a21df2 1838 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status,
mazgch 73:2b32e0a21df2 1839 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 1840 {
mazgch 75:ce6e12067d0c 1841 dprint(param, "Modem::netStatus\r\n");
mazgch 54:7ba8e4c218e2 1842 const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" };
mazgch 98:c786461edd40 1843 if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != REG_UNKNOWN))
mazgch 79:291df065e345 1844 dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]);
mazgch 98:c786461edd40 1845 if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != REG_UNKNOWN))
mazgch 79:291df065e345 1846 dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]);
mazgch 54:7ba8e4c218e2 1847 const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA" };
mazgch 98:c786461edd40 1848 if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != ACT_UNKNOWN))
mazgch 73:2b32e0a21df2 1849 dprint(param, " Access Technology: %s\r\n", txtAct[status->act]);
mazgch 54:7ba8e4c218e2 1850 if (status->rssi)
mazgch 73:2b32e0a21df2 1851 dprint(param, " Signal Strength: %d dBm\r\n", status->rssi);
mazgch 54:7ba8e4c218e2 1852 if (status->ber)
mazgch 73:2b32e0a21df2 1853 dprint(param, " Bit Error Rate: %d\r\n", status->ber);
mazgch 54:7ba8e4c218e2 1854 if (*status->opr)
mazgch 73:2b32e0a21df2 1855 dprint(param, " Operator: %s\r\n", status->opr);
mazgch 54:7ba8e4c218e2 1856 if (status->lac != 0xFFFF)
mazgch 73:2b32e0a21df2 1857 dprint(param, " Location Area Code: %04X\r\n", status->lac);
mazgch 54:7ba8e4c218e2 1858 if (status->ci != 0xFFFFFFFF)
mazgch 73:2b32e0a21df2 1859 dprint(param, " Cell ID: %08X\r\n", status->ci);
mazgch 54:7ba8e4c218e2 1860 if (*status->num)
mazgch 73:2b32e0a21df2 1861 dprint(param, " Phone Number: %s\r\n", status->num);
mazgch 54:7ba8e4c218e2 1862 }
mazgch 54:7ba8e4c218e2 1863
mazgch 73:2b32e0a21df2 1864 void MDMParser::dumpIp(MDMParser::IP ip,
mazgch 73:2b32e0a21df2 1865 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 1866 {
mazgch 57:869bd35f44cc 1867 if (ip != NOIP)
mazgch 75:ce6e12067d0c 1868 dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip));
mazgch 54:7ba8e4c218e2 1869 }
mazgch 70:0a87d256cd24 1870
mazgch 21:c4d64830bf02 1871 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 1872 int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end)
mazgch 18:e5697801df29 1873 {
mazgch 18:e5697801df29 1874 int o = 0;
mazgch 21:c4d64830bf02 1875 if (sta) {
mazgch 21:c4d64830bf02 1876 while (*sta) {
mazgch 21:c4d64830bf02 1877 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1878 char ch = pipe->next();
mazgch 21:c4d64830bf02 1879 if (*sta++ != ch) return NOT_FOUND;
mazgch 21:c4d64830bf02 1880 }
mazgch 21:c4d64830bf02 1881 }
mazgch 21:c4d64830bf02 1882 if (!end) return o; // no termination
mazgch 35:9275215a3a5b 1883 // at least any char
mazgch 35:9275215a3a5b 1884 if (++o > len) return WAIT;
mazgch 35:9275215a3a5b 1885 pipe->next();
mazgch 35:9275215a3a5b 1886 // check the end
mazgch 21:c4d64830bf02 1887 int x = 0;
mazgch 21:c4d64830bf02 1888 while (end[x]) {
mazgch 21:c4d64830bf02 1889 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1890 char ch = pipe->next();
mazgch 21:c4d64830bf02 1891 x = (end[x] == ch) ? x + 1 :
mazgch 21:c4d64830bf02 1892 (end[0] == ch) ? 1 :
mazgch 21:c4d64830bf02 1893 0;
mazgch 21:c4d64830bf02 1894 }
mazgch 21:c4d64830bf02 1895 return o;
mazgch 21:c4d64830bf02 1896 }
mazgch 21:c4d64830bf02 1897
mazgch 21:c4d64830bf02 1898 int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt)
mazgch 21:c4d64830bf02 1899 {
mazgch 21:c4d64830bf02 1900 int o = 0;
mazgch 21:c4d64830bf02 1901 int num = 0;
mazgch 21:c4d64830bf02 1902 if (fmt) {
mazgch 21:c4d64830bf02 1903 while (*fmt) {
mazgch 21:c4d64830bf02 1904 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1905 char ch = pipe->next();
mazgch 21:c4d64830bf02 1906 if (*fmt == '%') {
mazgch 21:c4d64830bf02 1907 fmt++;
mazgch 21:c4d64830bf02 1908 if (*fmt == 'd') { // numeric
mazgch 21:c4d64830bf02 1909 fmt ++;
mazgch 21:c4d64830bf02 1910 num = 0;
mazgch 21:c4d64830bf02 1911 while (ch >= '0' && ch <= '9') {
mazgch 21:c4d64830bf02 1912 num = num * 10 + (ch - '0');
mazgch 21:c4d64830bf02 1913 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1914 ch = pipe->next();
mazgch 21:c4d64830bf02 1915 }
mazgch 21:c4d64830bf02 1916 }
mazgch 21:c4d64830bf02 1917 else if (*fmt == 'c') { // char buffer (takes last numeric as length)
mazgch 21:c4d64830bf02 1918 fmt ++;
mazgch 21:c4d64830bf02 1919 while (num --) {
mazgch 21:c4d64830bf02 1920 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1921 ch = pipe->next();
mazgch 21:c4d64830bf02 1922 }
mazgch 21:c4d64830bf02 1923 }
mazgch 80:34985b4d821e 1924 else if (*fmt == 's') {
mazgch 80:34985b4d821e 1925 fmt ++;
mazgch 80:34985b4d821e 1926 if (ch != '\"') return NOT_FOUND;
mazgch 80:34985b4d821e 1927 do {
mazgch 80:34985b4d821e 1928 if (++o > len) return WAIT;
mazgch 80:34985b4d821e 1929 ch = pipe->next();
mazgch 80:34985b4d821e 1930 } while (ch != '\"');
mazgch 80:34985b4d821e 1931 if (++o > len) return WAIT;
mazgch 80:34985b4d821e 1932 ch = pipe->next();
mazgch 80:34985b4d821e 1933 }
mazgch 21:c4d64830bf02 1934 }
mazgch 21:c4d64830bf02 1935 if (*fmt++ != ch) return NOT_FOUND;
mazgch 18:e5697801df29 1936 }
mazgch 18:e5697801df29 1937 }
mazgch 21:c4d64830bf02 1938 return o;
mazgch 21:c4d64830bf02 1939 }
mazgch 21:c4d64830bf02 1940
mazgch 21:c4d64830bf02 1941 int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len)
mazgch 21:c4d64830bf02 1942 {
mazgch 21:c4d64830bf02 1943 int unkn = 0;
mazgch 21:c4d64830bf02 1944 int sz = pipe->size();
mazgch 21:c4d64830bf02 1945 int fr = pipe->free();
mazgch 21:c4d64830bf02 1946 if (len > sz)
mazgch 21:c4d64830bf02 1947 len = sz;
mazgch 21:c4d64830bf02 1948 while (len > 0)
mazgch 21:c4d64830bf02 1949 {
mazgch 21:c4d64830bf02 1950 static struct {
mazgch 21:c4d64830bf02 1951 const char* fmt; int type;
mazgch 21:c4d64830bf02 1952 } lutF[] = {
mazgch 21:c4d64830bf02 1953 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS },
mazgch 95:8282dbbe1492 1954 { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS },
mazgch 80:34985b4d821e 1955 { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS },
mazgch 21:c4d64830bf02 1956 };
mazgch 21:c4d64830bf02 1957 static struct {
mazgch 21:c4d64830bf02 1958 const char* sta; const char* end; int type;
mazgch 21:c4d64830bf02 1959 } lut[] = {
mazgch 21:c4d64830bf02 1960 { "\r\nOK\r\n", NULL, TYPE_OK },
mazgch 21:c4d64830bf02 1961 { "\r\nERROR\r\n", NULL, TYPE_ERROR },
mazgch 31:a0bed6c1e05d 1962 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 1963 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 1964 { "\r\nRING\r\n", NULL, TYPE_RING },
mazgch 21:c4d64830bf02 1965 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT },
mazgch 21:c4d64830bf02 1966 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER },
mazgch 21:c4d64830bf02 1967 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE },
mazgch 21:c4d64830bf02 1968 { "\r\nBUSY\r\n", NULL, TYPE_BUSY },
mazgch 21:c4d64830bf02 1969 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER },
mazgch 21:c4d64830bf02 1970 { "\r\n+", "\r\n", TYPE_PLUS },
mazgch 21:c4d64830bf02 1971 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets
mazgch 21:c4d64830bf02 1972 { "\r\n>", NULL, TYPE_PROMPT }, // SMS
mazgch 80:34985b4d821e 1973 { "\n>", NULL, TYPE_PROMPT }, // File
mazgch 21:c4d64830bf02 1974 };
mazgch 21:c4d64830bf02 1975 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) {
mazgch 21:c4d64830bf02 1976 pipe->set(unkn);
mazgch 21:c4d64830bf02 1977 int ln = _parseFormated(pipe, len, lutF[i].fmt);
mazgch 21:c4d64830bf02 1978 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 1979 return WAIT;
mazgch 21:c4d64830bf02 1980 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 1981 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 1982 if (ln > 0)
mazgch 21:c4d64830bf02 1983 return lutF[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 1984 }
mazgch 21:c4d64830bf02 1985 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) {
mazgch 21:c4d64830bf02 1986 pipe->set(unkn);
mazgch 21:c4d64830bf02 1987 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end);
mazgch 21:c4d64830bf02 1988 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 1989 return WAIT;
mazgch 21:c4d64830bf02 1990 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 1991 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 1992 if (ln > 0)
mazgch 21:c4d64830bf02 1993 return lut[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 1994 }
mazgch 21:c4d64830bf02 1995 // UNKNOWN
mazgch 21:c4d64830bf02 1996 unkn ++;
mazgch 21:c4d64830bf02 1997 len--;
mazgch 21:c4d64830bf02 1998 }
mazgch 18:e5697801df29 1999 return WAIT;
mazgch 18:e5697801df29 2000 }
mazgch 18:e5697801df29 2001
mazgch 18:e5697801df29 2002 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2003 // Serial Implementation
mazgch 18:e5697801df29 2004 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2005
mazgch 76:f7c3dd568dae 2006 /*! Helper Dev Null Device
mazgch 76:f7c3dd568dae 2007 Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout
mazgch 76:f7c3dd568dae 2008 is shared with the serial port of the modem. Having printfs inbetween the
mazgch 76:f7c3dd568dae 2009 AT commands you cause a failure of the modem.
mazgch 76:f7c3dd568dae 2010 */
mazgch 76:f7c3dd568dae 2011 class DevNull : public Stream {
mazgch 76:f7c3dd568dae 2012 public:
mazgch 76:f7c3dd568dae 2013 DevNull() : Stream(_name+1) { } //!< Constructor
mazgch 76:f7c3dd568dae 2014 void claim(const char* mode, FILE* file)
mazgch 76:f7c3dd568dae 2015 { freopen(_name, mode, file); } //!< claim a stream
mazgch 76:f7c3dd568dae 2016 protected:
mazgch 76:f7c3dd568dae 2017 virtual int _getc() { return EOF; } //!< Nothing
mazgch 76:f7c3dd568dae 2018 virtual int _putc(int c) { return c; } //!< Discard
mazgch 76:f7c3dd568dae 2019 static const char* _name; //!< File name
mazgch 76:f7c3dd568dae 2020 };
mazgch 76:f7c3dd568dae 2021 const char* DevNull::_name = "/null"; //!< the null device name
mazgch 76:f7c3dd568dae 2022 static DevNull null; //!< the null device
mazgch 76:f7c3dd568dae 2023
mazgch 19:2b5d097ca15d 2024 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/,
mazgch 19:2b5d097ca15d 2025 int baudrate /*= MDMBAUD*/,
mazgch 43:a89a7a505991 2026 #if DEVICE_SERIAL_FC
mazgch 19:2b5d097ca15d 2027 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/,
mazgch 43:a89a7a505991 2028 #endif
mazgch 18:e5697801df29 2029 int rxSize /*= 256*/, int txSize /*= 128*/) :
mazgch 35:9275215a3a5b 2030 SerialPipe(tx, rx, rxSize, txSize)
mazgch 18:e5697801df29 2031 {
mazgch 76:f7c3dd568dae 2032 if (rx == USBRX)
mazgch 76:f7c3dd568dae 2033 null.claim("r", stdin);
mazgch 76:f7c3dd568dae 2034 if (tx == USBTX) {
mazgch 76:f7c3dd568dae 2035 null.claim("w", stdout);
mazgch 76:f7c3dd568dae 2036 null.claim("w", stderr);
mazgch 74:208e3e32d263 2037 #ifdef MDM_DEBUG
mazgch 76:f7c3dd568dae 2038 _debugLevel = -1;
mazgch 76:f7c3dd568dae 2039 #endif
mazgch 76:f7c3dd568dae 2040 }
mazgch 74:208e3e32d263 2041 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 2042 _onboard = (tx == MDMTXD) && (rx == MDMRXD);
mazgch 74:208e3e32d263 2043 if (_onboard)
mazgch 74:208e3e32d263 2044 c027_mdm_powerOn(false);
mazgch 74:208e3e32d263 2045 #endif
mazgch 18:e5697801df29 2046 baud(baudrate);
mazgch 35:9275215a3a5b 2047 #if DEVICE_SERIAL_FC
mazgch 35:9275215a3a5b 2048 if ((rts != NC) || (cts != NC))
mazgch 35:9275215a3a5b 2049 {
mazgch 35:9275215a3a5b 2050 Flow flow = (cts == NC) ? RTS :
mazgch 35:9275215a3a5b 2051 (rts == NC) ? CTS : RTSCTS ;
mazgch 35:9275215a3a5b 2052 set_flow_control(flow, rts, cts);
mazgch 35:9275215a3a5b 2053 if (cts != NC) _dev.lpm = LPM_ENABLED;
mazgch 35:9275215a3a5b 2054 }
mazgch 35:9275215a3a5b 2055 #endif
mazgch 18:e5697801df29 2056 }
mazgch 18:e5697801df29 2057
mazgch 76:f7c3dd568dae 2058 MDMSerial::~MDMSerial(void)
mazgch 76:f7c3dd568dae 2059 {
mazgch 76:f7c3dd568dae 2060 powerOff();
mazgch 76:f7c3dd568dae 2061 #ifdef TARGET_UBLOX_C027
mazgch 76:f7c3dd568dae 2062 if (_onboard)
mazgch 76:f7c3dd568dae 2063 c027_mdm_powerOff();
mazgch 76:f7c3dd568dae 2064 #endif
mazgch 76:f7c3dd568dae 2065 }
mazgch 76:f7c3dd568dae 2066
mazgch 18:e5697801df29 2067 int MDMSerial::_send(const void* buf, int len)
mazgch 18:e5697801df29 2068 {
mazgch 35:9275215a3a5b 2069 return put((const char*)buf, len, true/*=blocking*/);
mazgch 18:e5697801df29 2070 }
mazgch 18:e5697801df29 2071
mazgch 18:e5697801df29 2072 int MDMSerial::getLine(char* buffer, int length)
mazgch 18:e5697801df29 2073 {
mazgch 18:e5697801df29 2074 return _getLine(&_pipeRx, buffer, length);
mazgch 18:e5697801df29 2075 }
mazgch 18:e5697801df29 2076
mazgch 18:e5697801df29 2077 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2078 // USB Implementation
mazgch 18:e5697801df29 2079 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2080
mazgch 18:e5697801df29 2081 #ifdef HAVE_MDMUSB
mazgch 76:f7c3dd568dae 2082 MDMUsb::MDMUsb(void)
mazgch 74:208e3e32d263 2083 {
mazgch 74:208e3e32d263 2084 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 2085 _debugLevel = 1;
mazgch 74:208e3e32d263 2086 #endif
mazgch 74:208e3e32d263 2087 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 2088 _onboard = true;
mazgch 74:208e3e32d263 2089 c027_mdm_powerOn(true);
mazgch 74:208e3e32d263 2090 #endif
mazgch 74:208e3e32d263 2091 }
mazgch 76:f7c3dd568dae 2092
mazgch 76:f7c3dd568dae 2093 MDMUsb::~MDMUsb(void)
mazgch 76:f7c3dd568dae 2094 {
mazgch 76:f7c3dd568dae 2095 powerOff();
mazgch 76:f7c3dd568dae 2096 #ifdef TARGET_UBLOX_C027
mazgch 76:f7c3dd568dae 2097 if (_onboard)
mazgch 76:f7c3dd568dae 2098 c027_mdm_powerOff();
mazgch 76:f7c3dd568dae 2099 #endif
mazgch 76:f7c3dd568dae 2100 }
mazgch 76:f7c3dd568dae 2101
mazgch 76:f7c3dd568dae 2102 int MDMUsb::_send(const void* buf, int len) { return 0; }
mazgch 76:f7c3dd568dae 2103
mazgch 18:e5697801df29 2104 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; }
mazgch 76:f7c3dd568dae 2105
mazgch 35:9275215a3a5b 2106 #endif