support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets.
Dependents: HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more
This library is intended to be used with u-blox products such as the C027 or a shield with u-blox cellular and GPS modules like the cellular and positioning shield from Embedded Artist.
For 2G/GSM and 3G/UMTS you need to:
- have a SIM card and know its PIN number
- need to know you network operators APN setting These setting should be passed to the connect or init and join functions. You can also extend the APN database in MDMAPN.h.
For CDMA products you need to make sure that you have provisioned and activated the modem with either Sprint or Verizon.
MDM.cpp@88:135fb4bb7aac, 2014-06-06 (annotated)
- Committer:
- mazgch
- Date:
- Fri Jun 06 10:33:13 2014 +0000
- Revision:
- 88:135fb4bb7aac
- Parent:
- 85:dd8f4f0d0ca9
- Child:
- 90:3915192f6d7e
improve apn lookup
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mazgch | 18:e5697801df29 | 1 | #include "mbed.h" |
mazgch | 18:e5697801df29 | 2 | #include "MDM.h" |
mazgch | 74:208e3e32d263 | 3 | #include "Relax.h" |
mazgch | 74:208e3e32d263 | 4 | #ifdef TARGET_UBLOX_C027 |
mazgch | 74:208e3e32d263 | 5 | #include "C027_api.h" |
mazgch | 74:208e3e32d263 | 6 | #endif |
mazgch | 85:dd8f4f0d0ca9 | 7 | #include "MDMAPN.h" |
mazgch | 84:a05edb010176 | 8 | |
mazgch | 74:208e3e32d263 | 9 | #define PROFILE "0" //!< this is the psd profile used |
mazgch | 74:208e3e32d263 | 10 | #define MAX_SIZE 128 //!< max expected messages |
mazgch | 74:208e3e32d263 | 11 | //! test if it is a socket |
mazgch | 21:c4d64830bf02 | 12 | #define ISSOCKET(s) (((s) >= 0) && ((s) < (sizeof(_sockets)/sizeof(*_sockets)))) |
mazgch | 75:ce6e12067d0c | 13 | //! check for timeout |
mazgch | 75:ce6e12067d0c | 14 | #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms())) |
mazgch | 80:34985b4d821e | 15 | //! registration ok check helper |
mazgch | 79:291df065e345 | 16 | #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING)) |
mazgch | 80:34985b4d821e | 17 | //! registration done check helper (no need to poll further) |
mazgch | 79:291df065e345 | 18 | #define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED)) |
mazgch | 79:291df065e345 | 19 | |
mazgch | 74:208e3e32d263 | 20 | #ifdef MDM_DEBUG |
mazgch | 74:208e3e32d263 | 21 | void dumpAtCmd(const char* buf, int len) |
mazgch | 21:c4d64830bf02 | 22 | { |
mazgch | 75:ce6e12067d0c | 23 | ::printf(" %3d \"", len); |
mazgch | 21:c4d64830bf02 | 24 | while (len --) { |
mazgch | 21:c4d64830bf02 | 25 | char ch = *buf++; |
mazgch | 75:ce6e12067d0c | 26 | if ((ch > 0x1F) && (ch != 0x7F)) { // is printable |
mazgch | 75:ce6e12067d0c | 27 | if (ch == '%') ::printf("%%"); |
mazgch | 75:ce6e12067d0c | 28 | else if (ch == '"') ::printf("\\\""); |
mazgch | 75:ce6e12067d0c | 29 | else if (ch == '\\') ::printf("\\\\"); |
mazgch | 75:ce6e12067d0c | 30 | else putchar(ch); |
mazgch | 75:ce6e12067d0c | 31 | } else { |
mazgch | 75:ce6e12067d0c | 32 | if (ch == '\a') ::printf("\\a"); // BEL (0x07) |
mazgch | 75:ce6e12067d0c | 33 | else if (ch == '\b') ::printf("\\b"); // Backspace (0x08) |
mazgch | 75:ce6e12067d0c | 34 | else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09) |
mazgch | 75:ce6e12067d0c | 35 | else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A) |
mazgch | 75:ce6e12067d0c | 36 | else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B) |
mazgch | 75:ce6e12067d0c | 37 | else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C) |
mazgch | 75:ce6e12067d0c | 38 | else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D) |
mazgch | 76:f7c3dd568dae | 39 | else ::printf("\\x%02x", (unsigned char)ch); |
mazgch | 75:ce6e12067d0c | 40 | } |
mazgch | 21:c4d64830bf02 | 41 | } |
mazgch | 75:ce6e12067d0c | 42 | ::printf("\"\r\n"); |
mazgch | 21:c4d64830bf02 | 43 | } |
mazgch | 74:208e3e32d263 | 44 | |
mazgch | 75:ce6e12067d0c | 45 | #define ERROR(fmt) (_debugLevel < 0) ? : ::printf(RED(fmt)) |
mazgch | 75:ce6e12067d0c | 46 | #define INFO(fmt) (_debugLevel < 1) ? : ::printf(GRE(fmt)) |
mazgch | 75:ce6e12067d0c | 47 | #define TRACE(...) (_debugLevel < 2) ? : ::printf(__VA_ARGS__) |
mazgch | 74:208e3e32d263 | 48 | |
mazgch | 31:a0bed6c1e05d | 49 | #if 1 // colored terminal output using ANSI escape sequences |
mazgch | 75:ce6e12067d0c | 50 | #define COL(c,t) "\033[" c t "\033[" "39m" |
mazgch | 31:a0bed6c1e05d | 51 | #else |
mazgch | 31:a0bed6c1e05d | 52 | #define COL(c,t) t |
mazgch | 31:a0bed6c1e05d | 53 | #endif |
mazgch | 31:a0bed6c1e05d | 54 | #define BLA(t) COL("30m",t) |
mazgch | 31:a0bed6c1e05d | 55 | #define RED(t) COL("31m",t) |
mazgch | 31:a0bed6c1e05d | 56 | #define GRE(t) COL("32m",t) |
mazgch | 31:a0bed6c1e05d | 57 | #define YEL(t) COL("33m",t) |
mazgch | 31:a0bed6c1e05d | 58 | #define BLU(t) COL("34m",t) |
mazgch | 31:a0bed6c1e05d | 59 | #define MAG(t) COL("35m",t) |
mazgch | 31:a0bed6c1e05d | 60 | #define CYA(t) COL("36m",t) |
mazgch | 31:a0bed6c1e05d | 61 | #define WHY(t) COL("37m",t) |
mazgch | 74:208e3e32d263 | 62 | |
mazgch | 74:208e3e32d263 | 63 | #else |
mazgch | 74:208e3e32d263 | 64 | |
mazgch | 75:ce6e12067d0c | 65 | #define ERROR(...) (void)0 // no tracing |
mazgch | 74:208e3e32d263 | 66 | #define INFO(...) (void)0 // no tracing |
mazgch | 74:208e3e32d263 | 67 | #define TRACE(...) (void)0 // no tracing |
mazgch | 74:208e3e32d263 | 68 | |
mazgch | 31:a0bed6c1e05d | 69 | #endif |
mazgch | 21:c4d64830bf02 | 70 | |
mazgch | 44:9d12223b78ff | 71 | MDMParser* MDMParser::inst; |
mazgch | 44:9d12223b78ff | 72 | |
mazgch | 21:c4d64830bf02 | 73 | MDMParser::MDMParser(void) |
mazgch | 21:c4d64830bf02 | 74 | { |
mazgch | 44:9d12223b78ff | 75 | inst = this; |
mazgch | 31:a0bed6c1e05d | 76 | memset(&_dev, 0, sizeof(_dev)); |
mazgch | 31:a0bed6c1e05d | 77 | memset(&_net, 0, sizeof(_net)); |
mazgch | 54:7ba8e4c218e2 | 78 | _net.lac = 0xFFFF; |
mazgch | 54:7ba8e4c218e2 | 79 | _net.ci = 0xFFFFFFFF; |
mazgch | 35:9275215a3a5b | 80 | _ip = NOIP; |
mazgch | 76:f7c3dd568dae | 81 | _init = false; |
mazgch | 31:a0bed6c1e05d | 82 | memset(_sockets, 0, sizeof(_sockets)); |
mazgch | 74:208e3e32d263 | 83 | #ifdef MDM_DEBUG |
mazgch | 76:f7c3dd568dae | 84 | _debugLevel = 1; |
mazgch | 74:208e3e32d263 | 85 | _debugTime.start(); |
mazgch | 74:208e3e32d263 | 86 | #endif |
mazgch | 74:208e3e32d263 | 87 | } |
mazgch | 74:208e3e32d263 | 88 | |
mazgch | 18:e5697801df29 | 89 | int MDMParser::send(const char* buf, int len) |
mazgch | 18:e5697801df29 | 90 | { |
mazgch | 74:208e3e32d263 | 91 | #ifdef MDM_DEBUG |
mazgch | 74:208e3e32d263 | 92 | if (_debugLevel >= 3) { |
mazgch | 75:ce6e12067d0c | 93 | ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001); |
mazgch | 74:208e3e32d263 | 94 | dumpAtCmd(buf,len); |
mazgch | 74:208e3e32d263 | 95 | } |
mazgch | 21:c4d64830bf02 | 96 | #endif |
mazgch | 18:e5697801df29 | 97 | return _send(buf, len); |
mazgch | 18:e5697801df29 | 98 | } |
mazgch | 18:e5697801df29 | 99 | |
mazgch | 21:c4d64830bf02 | 100 | int MDMParser::sendFormated(const char* format, ...) { |
mazgch | 21:c4d64830bf02 | 101 | char buf[MAX_SIZE]; |
mazgch | 21:c4d64830bf02 | 102 | va_list args; |
mazgch | 21:c4d64830bf02 | 103 | va_start(args, format); |
mazgch | 21:c4d64830bf02 | 104 | int len = vsnprintf(buf,sizeof(buf), format, args); |
mazgch | 21:c4d64830bf02 | 105 | va_end(args); |
mazgch | 21:c4d64830bf02 | 106 | return send(buf, len); |
mazgch | 21:c4d64830bf02 | 107 | } |
mazgch | 21:c4d64830bf02 | 108 | |
mazgch | 26:07be5faf8925 | 109 | int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/, |
mazgch | 26:07be5faf8925 | 110 | void* param /* = NULL*/, |
mazgch | 26:07be5faf8925 | 111 | int timeout_ms /*= 5000*/) |
mazgch | 26:07be5faf8925 | 112 | { |
mazgch | 69:4d6fa520dfca | 113 | char buf[MAX_SIZE + 64 /* add some more space for framing */]; |
mazgch | 21:c4d64830bf02 | 114 | Timer timer; |
mazgch | 21:c4d64830bf02 | 115 | timer.start(); |
mazgch | 21:c4d64830bf02 | 116 | do { |
mazgch | 21:c4d64830bf02 | 117 | int ret = getLine(buf, sizeof(buf)); |
mazgch | 74:208e3e32d263 | 118 | #ifdef MDM_DEBUG |
mazgch | 74:208e3e32d263 | 119 | if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND)) |
mazgch | 21:c4d64830bf02 | 120 | { |
mazgch | 31:a0bed6c1e05d | 121 | int len = LENGTH(ret); |
mazgch | 31:a0bed6c1e05d | 122 | int type = TYPE(ret); |
mazgch | 31:a0bed6c1e05d | 123 | const char* s = (type == TYPE_UNKNOWN)? YEL("UNK") : |
mazgch | 35:9275215a3a5b | 124 | (type == TYPE_TEXT) ? MAG("TXT") : |
mazgch | 53:cb0d94b9de3a | 125 | (type == TYPE_OK ) ? GRE("OK ") : |
mazgch | 31:a0bed6c1e05d | 126 | (type == TYPE_ERROR) ? RED("ERR") : |
mazgch | 31:a0bed6c1e05d | 127 | (type == TYPE_PLUS) ? CYA(" + ") : |
mazgch | 31:a0bed6c1e05d | 128 | (type == TYPE_PROMPT) ? BLU(" > ") : |
mazgch | 31:a0bed6c1e05d | 129 | "..." ; |
mazgch | 75:ce6e12067d0c | 130 | ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s); |
mazgch | 74:208e3e32d263 | 131 | dumpAtCmd(buf, len); |
mazgch | 21:c4d64830bf02 | 132 | } |
mazgch | 21:c4d64830bf02 | 133 | #endif |
mazgch | 21:c4d64830bf02 | 134 | if ((ret != WAIT) && (ret != NOT_FOUND)) |
mazgch | 18:e5697801df29 | 135 | { |
mazgch | 21:c4d64830bf02 | 136 | int type = TYPE(ret); |
mazgch | 21:c4d64830bf02 | 137 | // handle unsolicited commands here |
mazgch | 21:c4d64830bf02 | 138 | if (type == TYPE_PLUS) { |
mazgch | 21:c4d64830bf02 | 139 | const char* cmd = buf+3; |
mazgch | 54:7ba8e4c218e2 | 140 | int a, b, c, d, r; |
mazgch | 23:05a1aeeb5fd9 | 141 | char s[32]; |
mazgch | 21:c4d64830bf02 | 142 | |
mazgch | 31:a0bed6c1e05d | 143 | // SMS Command --------------------------------- |
mazgch | 31:a0bed6c1e05d | 144 | // +CNMI: <mem>,<index> |
mazgch | 31:a0bed6c1e05d | 145 | if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) { |
mazgch | 31:a0bed6c1e05d | 146 | TRACE("New SMS at index %d\r\n", a); |
mazgch | 21:c4d64830bf02 | 147 | // Socket Specific Command --------------------------------- |
mazgch | 21:c4d64830bf02 | 148 | // +UUSORD: <socket>,<length> |
mazgch | 21:c4d64830bf02 | 149 | } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2) && |
mazgch | 63:42cb563a25bc | 150 | ISSOCKET(a) /*&& (_sockets[a].state == SOCK_CONNECTED)*/) { |
mazgch | 31:a0bed6c1e05d | 151 | TRACE("Socket %d: %d bytes pending\r\n", a, b); |
mazgch | 21:c4d64830bf02 | 152 | _sockets[a].pending = b; |
mazgch | 69:4d6fa520dfca | 153 | // +UUSORF: <socket>,<length> |
mazgch | 69:4d6fa520dfca | 154 | } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2) && |
mazgch | 69:4d6fa520dfca | 155 | ISSOCKET(a) /*&& (_sockets[a].state == SOCK_CONNECTED)*/) { |
mazgch | 69:4d6fa520dfca | 156 | TRACE("Socket %d: %d bytes pending\r\n", a, b); |
mazgch | 69:4d6fa520dfca | 157 | _sockets[a].pending = b; |
mazgch | 21:c4d64830bf02 | 158 | // +UUSOCL: <socket> |
mazgch | 21:c4d64830bf02 | 159 | } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1) && |
mazgch | 21:c4d64830bf02 | 160 | ISSOCKET(a) && (_sockets[a].state == SOCK_CONNECTED)) { |
mazgch | 31:a0bed6c1e05d | 161 | TRACE("Socket %d: closed by remote host\r\n", a); |
mazgch | 21:c4d64830bf02 | 162 | _sockets[a].state = SOCK_CREATED/*=CLOSED*/; |
mazgch | 21:c4d64830bf02 | 163 | } |
mazgch | 32:8f12ac182bbb | 164 | if (_dev.dev == DEV_LISA_C200) { |
mazgch | 21:c4d64830bf02 | 165 | // CDMA Specific ------------------------------------------- |
mazgch | 21:c4d64830bf02 | 166 | // +CREG: <n><SID>,<NID>,<stat> |
mazgch | 54:7ba8e4c218e2 | 167 | if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) { |
mazgch | 54:7ba8e4c218e2 | 168 | // _net.sid = a; |
mazgch | 54:7ba8e4c218e2 | 169 | // _net.nid = b; |
mazgch | 79:291df065e345 | 170 | if (c == 0) _net.csd = REG_NONE; // not registered, home network |
mazgch | 79:291df065e345 | 171 | else if (c == 1) _net.csd = REG_HOME; // registered, home network |
mazgch | 79:291df065e345 | 172 | else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to |
mazgch | 79:291df065e345 | 173 | else if (c == 3) _net.csd = REG_DENIED; // registration denied |
mazgch | 79:291df065e345 | 174 | else if (c == 5) _net.csd = REG_ROAMING; // registered, roaming |
mazgch | 79:291df065e345 | 175 | _net.psd = _net.csd; // fake PSD registration (CDMA is always registered) |
mazgch | 31:a0bed6c1e05d | 176 | _net.act = ACT_CDMA; |
mazgch | 84:a05edb010176 | 177 | // +CSS: <mode>[,<format>,<oper>[,<AcT>]] |
mazgch | 21:c4d64830bf02 | 178 | } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) { |
mazgch | 31:a0bed6c1e05d | 179 | //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME; |
mazgch | 21:c4d64830bf02 | 180 | } |
mazgch | 21:c4d64830bf02 | 181 | } else { |
mazgch | 21:c4d64830bf02 | 182 | // GSM/UMTS Specific ------------------------------------------- |
mazgch | 79:291df065e345 | 183 | // +UUPSDD: <profile_id> |
mazgch | 79:291df065e345 | 184 | if (sscanf(cmd, "UUPSDD: %d",&a) == 1) { |
mazgch | 79:291df065e345 | 185 | if (*PROFILE == a) _ip = NOIP; |
mazgch | 79:291df065e345 | 186 | } else { |
mazgch | 79:291df065e345 | 187 | // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG |
mazgch | 79:291df065e345 | 188 | // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC |
mazgch | 79:291df065e345 | 189 | b = 0xFFFF; c = 0xFFFFFFFF; d = -1; |
mazgch | 79:291df065e345 | 190 | r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d); |
mazgch | 79:291df065e345 | 191 | if (r <= 1) |
mazgch | 79:291df065e345 | 192 | r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d); |
mazgch | 79:291df065e345 | 193 | if (r >= 2) { |
mazgch | 79:291df065e345 | 194 | Reg *reg = !strcmp(s, "CREG:") ? &_net.csd : |
mazgch | 79:291df065e345 | 195 | !strcmp(s, "CGREG:") ? &_net.psd : NULL; |
mazgch | 79:291df065e345 | 196 | if (reg) { |
mazgch | 79:291df065e345 | 197 | // network status |
mazgch | 79:291df065e345 | 198 | if (a == 0) *reg = REG_NONE; // 0: not registered, home network |
mazgch | 79:291df065e345 | 199 | else if (a == 1) *reg = REG_HOME; // 1: registered, home network |
mazgch | 79:291df065e345 | 200 | else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to |
mazgch | 79:291df065e345 | 201 | else if (a == 3) *reg = REG_DENIED; // 3: registration denied |
mazgch | 79:291df065e345 | 202 | else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown |
mazgch | 79:291df065e345 | 203 | else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming |
mazgch | 79:291df065e345 | 204 | if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code |
mazgch | 79:291df065e345 | 205 | if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID |
mazgch | 79:291df065e345 | 206 | // access technology |
mazgch | 79:291df065e345 | 207 | if (r >= 5) { |
mazgch | 79:291df065e345 | 208 | if (d == 0) _net.act = ACT_GSM; // 0: GSM |
mazgch | 79:291df065e345 | 209 | else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT |
mazgch | 79:291df065e345 | 210 | else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN |
mazgch | 79:291df065e345 | 211 | else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability |
mazgch | 79:291df065e345 | 212 | else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability |
mazgch | 79:291df065e345 | 213 | else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability |
mazgch | 79:291df065e345 | 214 | else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability |
mazgch | 79:291df065e345 | 215 | } |
mazgch | 79:291df065e345 | 216 | } |
mazgch | 54:7ba8e4c218e2 | 217 | } |
mazgch | 21:c4d64830bf02 | 218 | } |
mazgch | 21:c4d64830bf02 | 219 | } |
mazgch | 21:c4d64830bf02 | 220 | } |
mazgch | 21:c4d64830bf02 | 221 | if (cb) { |
mazgch | 21:c4d64830bf02 | 222 | int len = LENGTH(ret); |
mazgch | 21:c4d64830bf02 | 223 | int ret = cb(type, buf, len, param); |
mazgch | 21:c4d64830bf02 | 224 | if (WAIT != ret) |
mazgch | 21:c4d64830bf02 | 225 | return ret; |
mazgch | 21:c4d64830bf02 | 226 | } |
mazgch | 75:ce6e12067d0c | 227 | if (type == TYPE_OK) return RESP_OK; |
mazgch | 75:ce6e12067d0c | 228 | if (type == TYPE_ERROR) return RESP_ERROR; |
mazgch | 75:ce6e12067d0c | 229 | if (type == TYPE_PROMPT) return RESP_PROMPT; |
mazgch | 21:c4d64830bf02 | 230 | } |
mazgch | 21:c4d64830bf02 | 231 | // relax a bit |
mazgch | 74:208e3e32d263 | 232 | RELAX_MS(10); |
mazgch | 21:c4d64830bf02 | 233 | } |
mazgch | 75:ce6e12067d0c | 234 | while (!TIMEOUT(timer, timeout_ms)); |
mazgch | 21:c4d64830bf02 | 235 | return WAIT; |
mazgch | 21:c4d64830bf02 | 236 | } |
mazgch | 21:c4d64830bf02 | 237 | |
mazgch | 31:a0bed6c1e05d | 238 | int MDMParser::_cbString(int type, const char* buf, int len, char* str) |
mazgch | 21:c4d64830bf02 | 239 | { |
mazgch | 37:cc3433329d66 | 240 | if (str && (type == TYPE_UNKNOWN)) { |
mazgch | 31:a0bed6c1e05d | 241 | if (sscanf(buf, "\r\n%s\r\n", str) == 1) |
mazgch | 31:a0bed6c1e05d | 242 | /*nothing*/; |
mazgch | 21:c4d64830bf02 | 243 | } |
mazgch | 21:c4d64830bf02 | 244 | return WAIT; |
mazgch | 21:c4d64830bf02 | 245 | } |
mazgch | 21:c4d64830bf02 | 246 | |
mazgch | 31:a0bed6c1e05d | 247 | int MDMParser::_cbInt(int type, const char* buf, int len, int* val) |
mazgch | 31:a0bed6c1e05d | 248 | { |
mazgch | 37:cc3433329d66 | 249 | if (val && (type == TYPE_UNKNOWN)) { |
mazgch | 31:a0bed6c1e05d | 250 | if (sscanf(buf, "\r\n%d\r\n", val) == 1) |
mazgch | 31:a0bed6c1e05d | 251 | /*nothing*/; |
mazgch | 31:a0bed6c1e05d | 252 | } |
mazgch | 31:a0bed6c1e05d | 253 | return WAIT; |
mazgch | 31:a0bed6c1e05d | 254 | } |
mazgch | 31:a0bed6c1e05d | 255 | |
mazgch | 31:a0bed6c1e05d | 256 | // ---------------------------------------------------------------- |
mazgch | 31:a0bed6c1e05d | 257 | |
mazgch | 57:869bd35f44cc | 258 | bool MDMParser::connect( |
mazgch | 57:869bd35f44cc | 259 | const char* simpin, |
mazgch | 80:34985b4d821e | 260 | const char* apn, const char* username, |
mazgch | 80:34985b4d821e | 261 | const char* password, Auth auth, |
mazgch | 74:208e3e32d263 | 262 | PinName pn) |
mazgch | 57:869bd35f44cc | 263 | { |
mazgch | 75:ce6e12067d0c | 264 | bool ok = init(simpin, NULL, pn); |
mazgch | 74:208e3e32d263 | 265 | #ifdef MDM_DEBUG |
mazgch | 75:ce6e12067d0c | 266 | if (_debugLevel >= 1) dumpDevStatus(&_dev); |
mazgch | 74:208e3e32d263 | 267 | #endif |
mazgch | 75:ce6e12067d0c | 268 | if (!ok) |
mazgch | 57:869bd35f44cc | 269 | return false; |
mazgch | 75:ce6e12067d0c | 270 | ok = registerNet(); |
mazgch | 74:208e3e32d263 | 271 | #ifdef MDM_DEBUG |
mazgch | 75:ce6e12067d0c | 272 | if (_debugLevel >= 1) dumpNetStatus(&_net); |
mazgch | 74:208e3e32d263 | 273 | #endif |
mazgch | 75:ce6e12067d0c | 274 | if (!ok) |
mazgch | 57:869bd35f44cc | 275 | return false; |
mazgch | 80:34985b4d821e | 276 | IP ip = join(apn,username,password,auth); |
mazgch | 74:208e3e32d263 | 277 | #ifdef MDM_DEBUG |
mazgch | 74:208e3e32d263 | 278 | if (_debugLevel >= 1) dumpIp(ip); |
mazgch | 74:208e3e32d263 | 279 | #endif |
mazgch | 57:869bd35f44cc | 280 | if (ip == NOIP) |
mazgch | 57:869bd35f44cc | 281 | return false; |
mazgch | 57:869bd35f44cc | 282 | return true; |
mazgch | 57:869bd35f44cc | 283 | } |
mazgch | 57:869bd35f44cc | 284 | |
mazgch | 74:208e3e32d263 | 285 | bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn) |
mazgch | 21:c4d64830bf02 | 286 | { |
mazgch | 74:208e3e32d263 | 287 | int i = 10; |
mazgch | 76:f7c3dd568dae | 288 | memset(&_dev, 0, sizeof(_dev)); |
mazgch | 74:208e3e32d263 | 289 | if (pn != NC) { |
mazgch | 74:208e3e32d263 | 290 | INFO("Modem::wakeup\r\n"); |
mazgch | 74:208e3e32d263 | 291 | DigitalOut pin(pn, 1); |
mazgch | 74:208e3e32d263 | 292 | while (i--) { |
mazgch | 79:291df065e345 | 293 | // SARA-U2/LISA-U2 50..80us |
mazgch | 79:291df065e345 | 294 | pin = 0; wait_us(50); |
mazgch | 79:291df065e345 | 295 | pin = 1; wait_ms(10); |
mazgch | 79:291df065e345 | 296 | |
mazgch | 79:291df065e345 | 297 | // SARA-G35 >5ms, LISA-C2 > 150ms |
mazgch | 79:291df065e345 | 298 | pin = 0; wait_ms(150); |
mazgch | 79:291df065e345 | 299 | pin = 1; wait_ms(100); |
mazgch | 79:291df065e345 | 300 | |
mazgch | 79:291df065e345 | 301 | // purge any messages |
mazgch | 79:291df065e345 | 302 | while (WAIT != waitFinalResp(NULL,NULL,0)) |
mazgch | 79:291df065e345 | 303 | /* nothing */; |
mazgch | 74:208e3e32d263 | 304 | // check interface and disable local echo |
mazgch | 74:208e3e32d263 | 305 | sendFormated("AT\r\n"); |
mazgch | 74:208e3e32d263 | 306 | if(RESP_OK == waitFinalResp(NULL,NULL,500)) |
mazgch | 74:208e3e32d263 | 307 | break; |
mazgch | 74:208e3e32d263 | 308 | } |
mazgch | 75:ce6e12067d0c | 309 | if (i < 0) { |
mazgch | 75:ce6e12067d0c | 310 | ERROR("No Reply from Modem"); |
mazgch | 74:208e3e32d263 | 311 | return false; |
mazgch | 75:ce6e12067d0c | 312 | } |
mazgch | 21:c4d64830bf02 | 313 | } |
mazgch | 76:f7c3dd568dae | 314 | _init = true; |
mazgch | 75:ce6e12067d0c | 315 | |
mazgch | 74:208e3e32d263 | 316 | INFO("Modem::init\r\n"); |
mazgch | 21:c4d64830bf02 | 317 | // echo off |
mazgch | 21:c4d64830bf02 | 318 | sendFormated("AT E0\r\n"); |
mazgch | 52:8071747a7cb3 | 319 | if(RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 320 | return false; |
mazgch | 21:c4d64830bf02 | 321 | // enable verbose error messages |
mazgch | 21:c4d64830bf02 | 322 | sendFormated("AT+CMEE=2\r\n"); |
mazgch | 52:8071747a7cb3 | 323 | if(RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 324 | return false; |
mazgch | 21:c4d64830bf02 | 325 | // set baud rate |
mazgch | 21:c4d64830bf02 | 326 | sendFormated("AT+IPR=115200\r\n"); |
mazgch | 52:8071747a7cb3 | 327 | if (RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 328 | return false; |
mazgch | 74:208e3e32d263 | 329 | RELAX_MS(40); |
mazgch | 21:c4d64830bf02 | 330 | // identify the module |
mazgch | 21:c4d64830bf02 | 331 | sendFormated("ATI\r\n"); |
mazgch | 52:8071747a7cb3 | 332 | if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev)) |
mazgch | 21:c4d64830bf02 | 333 | return false; |
mazgch | 32:8f12ac182bbb | 334 | if (_dev.dev == DEV_UNKNOWN) |
mazgch | 21:c4d64830bf02 | 335 | return false; |
mazgch | 32:8f12ac182bbb | 336 | // device specific init |
mazgch | 32:8f12ac182bbb | 337 | if (_dev.dev == DEV_LISA_C200) { |
mazgch | 32:8f12ac182bbb | 338 | // get the manufacturer |
mazgch | 32:8f12ac182bbb | 339 | sendFormated("AT+GMI\r\n"); |
mazgch | 52:8071747a7cb3 | 340 | if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) |
mazgch | 32:8f12ac182bbb | 341 | return false; |
mazgch | 32:8f12ac182bbb | 342 | // get the model identification |
mazgch | 32:8f12ac182bbb | 343 | sendFormated("AT+GMM\r\n"); |
mazgch | 52:8071747a7cb3 | 344 | if (RESP_OK != waitFinalResp(_cbString, _dev.model)) |
mazgch | 32:8f12ac182bbb | 345 | return false; |
mazgch | 32:8f12ac182bbb | 346 | // get the sw version |
mazgch | 32:8f12ac182bbb | 347 | sendFormated("AT+GMR\r\n"); |
mazgch | 52:8071747a7cb3 | 348 | if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) |
mazgch | 32:8f12ac182bbb | 349 | return false; |
mazgch | 21:c4d64830bf02 | 350 | // Return the pseudo ESN or MEID |
mazgch | 21:c4d64830bf02 | 351 | sendFormated("AT+GSN\r\n"); |
mazgch | 52:8071747a7cb3 | 352 | if (RESP_OK != waitFinalResp(_cbString, _dev.meid)) |
mazgch | 26:07be5faf8925 | 353 | return false; |
mazgch | 50:d76aece8038f | 354 | #if 0 |
mazgch | 50:d76aece8038f | 355 | // enable power saving |
mazgch | 50:d76aece8038f | 356 | if (_dev.lpm != LPM_DISABLED) { |
mazgch | 50:d76aece8038f | 357 | // enable power saving (requires flow control, cts at least) |
mazgch | 50:d76aece8038f | 358 | sendFormated("AT+UPSV=1,1280\r\n"); |
mazgch | 52:8071747a7cb3 | 359 | if (RESP_OK != waitFinalResp()) |
mazgch | 50:d76aece8038f | 360 | return false; |
mazgch | 50:d76aece8038f | 361 | _dev.lpm = LPM_ACTIVE; |
mazgch | 50:d76aece8038f | 362 | } |
mazgch | 50:d76aece8038f | 363 | #endif |
mazgch | 26:07be5faf8925 | 364 | } else { |
mazgch | 32:8f12ac182bbb | 365 | if (_dev.dev == DEV_LISA_U200) { |
mazgch | 35:9275215a3a5b | 366 | // enable the network identification feature |
mazgch | 21:c4d64830bf02 | 367 | sendFormated("AT+UGPIOC=20,2\r\n"); |
mazgch | 52:8071747a7cb3 | 368 | if (RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 369 | return false; |
mazgch | 21:c4d64830bf02 | 370 | } else { |
mazgch | 35:9275215a3a5b | 371 | // enable the network identification feature |
mazgch | 21:c4d64830bf02 | 372 | sendFormated("AT+UGPIOC=16,2\r\n"); |
mazgch | 52:8071747a7cb3 | 373 | if (RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 374 | return false; |
mazgch | 21:c4d64830bf02 | 375 | } |
mazgch | 21:c4d64830bf02 | 376 | // check the sim card |
mazgch | 31:a0bed6c1e05d | 377 | for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) { |
mazgch | 21:c4d64830bf02 | 378 | sendFormated("AT+CPIN?\r\n"); |
mazgch | 31:a0bed6c1e05d | 379 | int ret = waitFinalResp(_cbCPIN, &_dev.sim); |
mazgch | 62:a02f026bdd7c | 380 | // having an error here is ok (sim may still be initializing) |
mazgch | 52:8071747a7cb3 | 381 | if ((RESP_OK != ret) && (RESP_ERROR != ret)) |
mazgch | 21:c4d64830bf02 | 382 | return false; |
mazgch | 31:a0bed6c1e05d | 383 | // Enter PIN if needed |
mazgch | 77:55788e619858 | 384 | if (_dev.sim == SIM_PIN) { |
mazgch | 57:869bd35f44cc | 385 | if (!simpin) { |
mazgch | 75:ce6e12067d0c | 386 | ERROR("SIM PIN not available\r\n"); |
mazgch | 31:a0bed6c1e05d | 387 | return false; |
mazgch | 31:a0bed6c1e05d | 388 | } |
mazgch | 57:869bd35f44cc | 389 | sendFormated("AT+CPIN=%s\r\n", simpin); |
mazgch | 52:8071747a7cb3 | 390 | if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim)) |
mazgch | 31:a0bed6c1e05d | 391 | return false; |
mazgch | 62:a02f026bdd7c | 392 | } else if (_dev.sim != SIM_READY) { |
mazgch | 74:208e3e32d263 | 393 | RELAX_MS(1000); |
mazgch | 62:a02f026bdd7c | 394 | } |
mazgch | 21:c4d64830bf02 | 395 | } |
mazgch | 77:55788e619858 | 396 | if (_dev.sim != SIM_READY) { |
mazgch | 77:55788e619858 | 397 | if (_dev.sim == SIM_MISSING) |
mazgch | 77:55788e619858 | 398 | ERROR("SIM not inserted\r\n"); |
mazgch | 21:c4d64830bf02 | 399 | return false; |
mazgch | 77:55788e619858 | 400 | } |
mazgch | 32:8f12ac182bbb | 401 | // get the manufacturer |
mazgch | 32:8f12ac182bbb | 402 | sendFormated("AT+CGMI\r\n"); |
mazgch | 52:8071747a7cb3 | 403 | if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) |
mazgch | 32:8f12ac182bbb | 404 | return false; |
mazgch | 32:8f12ac182bbb | 405 | // get the model identification |
mazgch | 32:8f12ac182bbb | 406 | sendFormated("AT+CGMM\r\n"); |
mazgch | 52:8071747a7cb3 | 407 | if (RESP_OK != waitFinalResp(_cbString, _dev.model)) |
mazgch | 32:8f12ac182bbb | 408 | return false; |
mazgch | 32:8f12ac182bbb | 409 | // get the |
mazgch | 32:8f12ac182bbb | 410 | sendFormated("AT+CGMR\r\n"); |
mazgch | 52:8071747a7cb3 | 411 | if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) |
mazgch | 32:8f12ac182bbb | 412 | return false; |
mazgch | 21:c4d64830bf02 | 413 | // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card. |
mazgch | 21:c4d64830bf02 | 414 | // ICCID is a serial number identifying the SIM. |
mazgch | 21:c4d64830bf02 | 415 | sendFormated("AT+CCID\r\n"); |
mazgch | 52:8071747a7cb3 | 416 | if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid)) |
mazgch | 21:c4d64830bf02 | 417 | return false; |
mazgch | 21:c4d64830bf02 | 418 | // Returns the product serial number, IMEI (International Mobile Equipment Identity) |
mazgch | 21:c4d64830bf02 | 419 | sendFormated("AT+CGSN\r\n"); |
mazgch | 52:8071747a7cb3 | 420 | if (RESP_OK != waitFinalResp(_cbString, _dev.imei)) |
mazgch | 21:c4d64830bf02 | 421 | return false; |
mazgch | 50:d76aece8038f | 422 | // enable power saving |
mazgch | 50:d76aece8038f | 423 | if (_dev.lpm != LPM_DISABLED) { |
mazgch | 50:d76aece8038f | 424 | // enable power saving (requires flow control, cts at least) |
mazgch | 50:d76aece8038f | 425 | sendFormated("AT+UPSV=1\r\n"); |
mazgch | 52:8071747a7cb3 | 426 | if (RESP_OK != waitFinalResp()) |
mazgch | 50:d76aece8038f | 427 | return false; |
mazgch | 50:d76aece8038f | 428 | _dev.lpm = LPM_ACTIVE; |
mazgch | 50:d76aece8038f | 429 | } |
mazgch | 79:291df065e345 | 430 | // enable the psd registration unsolicited result code |
mazgch | 79:291df065e345 | 431 | sendFormated("AT+CGREG=2\r\n"); |
mazgch | 79:291df065e345 | 432 | if (RESP_OK != waitFinalResp()) |
mazgch | 79:291df065e345 | 433 | return false; |
mazgch | 84:a05edb010176 | 434 | // set operator selection |
mazgch | 84:a05edb010176 | 435 | sendFormated("AT+COPS=0,0\r\n"); |
mazgch | 84:a05edb010176 | 436 | if (RESP_OK != waitFinalResp(NULL,NULL,180*1000)) |
mazgch | 84:a05edb010176 | 437 | return false; |
mazgch | 21:c4d64830bf02 | 438 | } |
mazgch | 79:291df065e345 | 439 | // enable the network registration unsolicited result code |
mazgch | 79:291df065e345 | 440 | sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C200) ? 1 : 2); |
mazgch | 79:291df065e345 | 441 | if (RESP_OK != waitFinalResp()) |
mazgch | 79:291df065e345 | 442 | return false; |
mazgch | 31:a0bed6c1e05d | 443 | // Setup SMS in text mode |
mazgch | 31:a0bed6c1e05d | 444 | sendFormated("AT+CMGF=1\r\n"); |
mazgch | 52:8071747a7cb3 | 445 | if (RESP_OK != waitFinalResp()) |
mazgch | 31:a0bed6c1e05d | 446 | return false; |
mazgch | 31:a0bed6c1e05d | 447 | // setup new message indication |
mazgch | 75:ce6e12067d0c | 448 | sendFormated("AT+CNMI=2,1\r\n"); |
mazgch | 52:8071747a7cb3 | 449 | if (RESP_OK != waitFinalResp()) |
mazgch | 31:a0bed6c1e05d | 450 | return false; |
mazgch | 21:c4d64830bf02 | 451 | // Request IMSI (International Mobile Subscriber Identification) |
mazgch | 21:c4d64830bf02 | 452 | sendFormated("AT+CIMI\r\n"); |
mazgch | 52:8071747a7cb3 | 453 | if (RESP_OK != waitFinalResp(_cbString, _dev.imsi)) |
mazgch | 21:c4d64830bf02 | 454 | return false; |
mazgch | 28:4d9509e3b1cf | 455 | if (status) |
mazgch | 31:a0bed6c1e05d | 456 | memcpy(status, &_dev, sizeof(DevStatus)); |
mazgch | 31:a0bed6c1e05d | 457 | return true; |
mazgch | 31:a0bed6c1e05d | 458 | } |
mazgch | 31:a0bed6c1e05d | 459 | |
mazgch | 74:208e3e32d263 | 460 | bool MDMParser::powerOff(void) |
mazgch | 74:208e3e32d263 | 461 | { |
mazgch | 76:f7c3dd568dae | 462 | if (_init) { |
mazgch | 76:f7c3dd568dae | 463 | INFO("Modem::powerOff\r\n"); |
mazgch | 76:f7c3dd568dae | 464 | sendFormated("AT+CPWROFF\r\n"); |
mazgch | 76:f7c3dd568dae | 465 | if (RESP_OK != waitFinalResp(NULL,NULL,120*1000)) |
mazgch | 76:f7c3dd568dae | 466 | return false; |
mazgch | 76:f7c3dd568dae | 467 | _init = false; |
mazgch | 76:f7c3dd568dae | 468 | } |
mazgch | 74:208e3e32d263 | 469 | return true; |
mazgch | 74:208e3e32d263 | 470 | } |
mazgch | 74:208e3e32d263 | 471 | |
mazgch | 32:8f12ac182bbb | 472 | int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev) |
mazgch | 31:a0bed6c1e05d | 473 | { |
mazgch | 37:cc3433329d66 | 474 | if ((type == TYPE_UNKNOWN) && dev) { |
mazgch | 31:a0bed6c1e05d | 475 | if (strstr(buf, "SARA-G350")) { |
mazgch | 32:8f12ac182bbb | 476 | *dev = DEV_SARA_G350; |
mazgch | 32:8f12ac182bbb | 477 | /*TRACE("Identified Device: SARA-G350 2G\\n")*/; |
mazgch | 31:a0bed6c1e05d | 478 | } else if (strstr(buf, "LISA-U200")) { |
mazgch | 32:8f12ac182bbb | 479 | *dev = DEV_LISA_U200; |
mazgch | 32:8f12ac182bbb | 480 | /*TRACE("Identified Device: LISA-U200 2G/3G\r\n")*/; |
mazgch | 31:a0bed6c1e05d | 481 | } else if (strstr(buf, "LISA-C200")) { |
mazgch | 32:8f12ac182bbb | 482 | *dev= DEV_LISA_C200; |
mazgch | 32:8f12ac182bbb | 483 | /*TRACE("Identified Device: LISA-C200 CDMA\r\n")*/; |
mazgch | 31:a0bed6c1e05d | 484 | } |
mazgch | 28:4d9509e3b1cf | 485 | } |
mazgch | 31:a0bed6c1e05d | 486 | return WAIT; |
mazgch | 31:a0bed6c1e05d | 487 | } |
mazgch | 31:a0bed6c1e05d | 488 | |
mazgch | 31:a0bed6c1e05d | 489 | int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim) |
mazgch | 31:a0bed6c1e05d | 490 | { |
mazgch | 75:ce6e12067d0c | 491 | if (sim) { |
mazgch | 75:ce6e12067d0c | 492 | if (type == TYPE_PLUS){ |
mazgch | 75:ce6e12067d0c | 493 | char s[16]; |
mazgch | 75:ce6e12067d0c | 494 | if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1) |
mazgch | 75:ce6e12067d0c | 495 | *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN; |
mazgch | 75:ce6e12067d0c | 496 | } else if (type == TYPE_ERROR) { |
mazgch | 75:ce6e12067d0c | 497 | if (strstr(buf, "+CME ERROR: SIM not inserted")) |
mazgch | 75:ce6e12067d0c | 498 | *sim = SIM_MISSING; |
mazgch | 31:a0bed6c1e05d | 499 | } |
mazgch | 31:a0bed6c1e05d | 500 | } |
mazgch | 31:a0bed6c1e05d | 501 | return WAIT; |
mazgch | 21:c4d64830bf02 | 502 | } |
mazgch | 21:c4d64830bf02 | 503 | |
mazgch | 26:07be5faf8925 | 504 | int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid) |
mazgch | 26:07be5faf8925 | 505 | { |
mazgch | 26:07be5faf8925 | 506 | if ((type == TYPE_PLUS) && ccid){ |
mazgch | 26:07be5faf8925 | 507 | if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1) |
mazgch | 31:a0bed6c1e05d | 508 | /*TRACE("Got CCID: %s\r\n", ccid)*/; |
mazgch | 26:07be5faf8925 | 509 | } |
mazgch | 26:07be5faf8925 | 510 | return WAIT; |
mazgch | 26:07be5faf8925 | 511 | } |
mazgch | 26:07be5faf8925 | 512 | |
mazgch | 75:ce6e12067d0c | 513 | bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/) |
mazgch | 75:ce6e12067d0c | 514 | { |
mazgch | 75:ce6e12067d0c | 515 | Timer timer; |
mazgch | 75:ce6e12067d0c | 516 | timer.start(); |
mazgch | 75:ce6e12067d0c | 517 | INFO("Modem::register\r\n"); |
mazgch | 75:ce6e12067d0c | 518 | while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms)) |
mazgch | 75:ce6e12067d0c | 519 | RELAX_MS(1000); |
mazgch | 79:291df065e345 | 520 | if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n"); |
mazgch | 79:291df065e345 | 521 | if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n"); |
mazgch | 79:291df065e345 | 522 | return REG_OK(_net.csd) || REG_OK(_net.psd); |
mazgch | 75:ce6e12067d0c | 523 | } |
mazgch | 75:ce6e12067d0c | 524 | |
mazgch | 28:4d9509e3b1cf | 525 | bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/) |
mazgch | 21:c4d64830bf02 | 526 | { |
mazgch | 75:ce6e12067d0c | 527 | memset(&_net, 0, sizeof(_net)); |
mazgch | 75:ce6e12067d0c | 528 | _net.lac = 0xFFFF; |
mazgch | 75:ce6e12067d0c | 529 | _net.ci = 0xFFFFFFFF; |
mazgch | 21:c4d64830bf02 | 530 | // check registration |
mazgch | 21:c4d64830bf02 | 531 | sendFormated("AT+CREG?\r\n"); |
mazgch | 88:135fb4bb7aac | 532 | waitFinalResp(); // don't fail as service could be not subscribed |
mazgch | 79:291df065e345 | 533 | if (_dev.dev != DEV_LISA_C200) { |
mazgch | 79:291df065e345 | 534 | // check PSD registration |
mazgch | 79:291df065e345 | 535 | sendFormated("AT+CGREG?\r\n"); |
mazgch | 88:135fb4bb7aac | 536 | waitFinalResp(); // don't fail as service could be not subscribed |
mazgch | 79:291df065e345 | 537 | } |
mazgch | 79:291df065e345 | 538 | if (REG_OK(_net.csd) || REG_OK(_net.psd)) |
mazgch | 75:ce6e12067d0c | 539 | { |
mazgch | 75:ce6e12067d0c | 540 | // check modem specific status messages |
mazgch | 75:ce6e12067d0c | 541 | if (_dev.dev == DEV_LISA_C200) { |
mazgch | 75:ce6e12067d0c | 542 | sendFormated("AT+CSS?\r\n"); |
mazgch | 75:ce6e12067d0c | 543 | if (RESP_OK != waitFinalResp()) |
mazgch | 75:ce6e12067d0c | 544 | return false; |
mazgch | 81:3966a5c17037 | 545 | while (1) { |
mazgch | 81:3966a5c17037 | 546 | // get the Telephone number |
mazgch | 81:3966a5c17037 | 547 | sendFormated("AT$MDN?\r\n"); |
mazgch | 81:3966a5c17037 | 548 | if (RESP_OK != waitFinalResp(_cbString, _net.num)) |
mazgch | 81:3966a5c17037 | 549 | return false; |
mazgch | 81:3966a5c17037 | 550 | // check if we have a Mobile Directory Number |
mazgch | 81:3966a5c17037 | 551 | if (*_net.num && (memcmp(_net.num, "000000", 6) != 0)) |
mazgch | 81:3966a5c17037 | 552 | break; |
mazgch | 81:3966a5c17037 | 553 | |
mazgch | 81:3966a5c17037 | 554 | INFO("Device not yet activated\r\n"); |
mazgch | 81:3966a5c17037 | 555 | INFO("Make sure you have a valid contract with the network operator for this device.\r\n"); |
mazgch | 81:3966a5c17037 | 556 | // Check if the the version contains a V for Verizon |
mazgch | 81:3966a5c17037 | 557 | // Verizon: E0.V.xx.00.xxR, |
mazgch | 81:3966a5c17037 | 558 | // Sprint E0.S.xx.00.xxR |
mazgch | 81:3966a5c17037 | 559 | if (_dev.ver[3] == 'V') { |
mazgch | 81:3966a5c17037 | 560 | int i; |
mazgch | 81:3966a5c17037 | 561 | INFO("Start device over-the-air activation (this can take a few minutes)\r\n"); |
mazgch | 81:3966a5c17037 | 562 | sendFormated("AT+CDV=*22899\r\n"); |
mazgch | 81:3966a5c17037 | 563 | i = 1; |
mazgch | 82:055dcfcf9dcc | 564 | if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { |
mazgch | 81:3966a5c17037 | 565 | ERROR("Device over-the-air activation failed\r\n"); |
mazgch | 81:3966a5c17037 | 566 | return false; |
mazgch | 81:3966a5c17037 | 567 | } |
mazgch | 81:3966a5c17037 | 568 | INFO("Device over-the-air activation successful\r\n"); |
mazgch | 81:3966a5c17037 | 569 | |
mazgch | 81:3966a5c17037 | 570 | INFO("Start PRL over-the-air update (this can take a few minutes)\r\n"); |
mazgch | 81:3966a5c17037 | 571 | sendFormated("AT+CDV=*22891\r\n"); |
mazgch | 81:3966a5c17037 | 572 | i = 1; |
mazgch | 82:055dcfcf9dcc | 573 | if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { |
mazgch | 81:3966a5c17037 | 574 | ERROR("PRL over-the-air update failed\r\n"); |
mazgch | 81:3966a5c17037 | 575 | return false; |
mazgch | 81:3966a5c17037 | 576 | } |
mazgch | 81:3966a5c17037 | 577 | INFO("PRL over-the-air update successful\r\n"); |
mazgch | 81:3966a5c17037 | 578 | |
mazgch | 81:3966a5c17037 | 579 | } else { |
mazgch | 81:3966a5c17037 | 580 | // Sprint or Aeris |
mazgch | 81:3966a5c17037 | 581 | INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n"); |
mazgch | 81:3966a5c17037 | 582 | RELAX_MS(120*1000); |
mazgch | 81:3966a5c17037 | 583 | } |
mazgch | 81:3966a5c17037 | 584 | } |
mazgch | 75:ce6e12067d0c | 585 | // get the the Network access identifier string |
mazgch | 75:ce6e12067d0c | 586 | char nai[64]; |
mazgch | 75:ce6e12067d0c | 587 | sendFormated("AT$QCMIPNAI?\r\n"); |
mazgch | 75:ce6e12067d0c | 588 | if (RESP_OK != waitFinalResp(_cbString, nai)) |
mazgch | 75:ce6e12067d0c | 589 | return false; |
mazgch | 75:ce6e12067d0c | 590 | } else { |
mazgch | 75:ce6e12067d0c | 591 | sendFormated("AT+COPS?\r\n"); |
mazgch | 75:ce6e12067d0c | 592 | if (RESP_OK != waitFinalResp(_cbCOPS, &_net)) |
mazgch | 75:ce6e12067d0c | 593 | return false; |
mazgch | 75:ce6e12067d0c | 594 | // Returns the MSISDNs related to this subscriber |
mazgch | 75:ce6e12067d0c | 595 | sendFormated("AT+CNUM\r\n"); |
mazgch | 75:ce6e12067d0c | 596 | if (RESP_OK != waitFinalResp(_cbCNUM, _net.num)) |
mazgch | 75:ce6e12067d0c | 597 | return false; |
mazgch | 75:ce6e12067d0c | 598 | } |
mazgch | 75:ce6e12067d0c | 599 | // Returns the signal strength indication |
mazgch | 75:ce6e12067d0c | 600 | sendFormated("AT+CSQ\r\n"); |
mazgch | 75:ce6e12067d0c | 601 | if (RESP_OK != waitFinalResp(_cbCSQ, &_net)) |
mazgch | 32:8f12ac182bbb | 602 | return false; |
mazgch | 75:ce6e12067d0c | 603 | } |
mazgch | 28:4d9509e3b1cf | 604 | if (status) { |
mazgch | 31:a0bed6c1e05d | 605 | memcpy(status, &_net, sizeof(NetStatus)); |
mazgch | 25:4045d02e44f1 | 606 | } |
mazgch | 79:291df065e345 | 607 | return REG_DONE(_net.csd) && REG_DONE(_net.psd); |
mazgch | 31:a0bed6c1e05d | 608 | } |
mazgch | 31:a0bed6c1e05d | 609 | |
mazgch | 31:a0bed6c1e05d | 610 | int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status) |
mazgch | 31:a0bed6c1e05d | 611 | { |
mazgch | 31:a0bed6c1e05d | 612 | if ((type == TYPE_PLUS) && status){ |
mazgch | 31:a0bed6c1e05d | 613 | int act = 99; |
mazgch | 31:a0bed6c1e05d | 614 | // +COPS: <mode>[,<format>,<oper>[,<AcT>]] |
mazgch | 31:a0bed6c1e05d | 615 | if (sscanf(buf, "\r\n+COPS: %*d,%*d,\"%[^\"]\",%d",status->opr,&act) >= 1) { |
mazgch | 31:a0bed6c1e05d | 616 | if (act == 0) status->act = ACT_GSM; // 0: GSM, |
mazgch | 31:a0bed6c1e05d | 617 | else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN |
mazgch | 31:a0bed6c1e05d | 618 | } |
mazgch | 31:a0bed6c1e05d | 619 | } |
mazgch | 31:a0bed6c1e05d | 620 | return WAIT; |
mazgch | 31:a0bed6c1e05d | 621 | } |
mazgch | 31:a0bed6c1e05d | 622 | |
mazgch | 31:a0bed6c1e05d | 623 | int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num) |
mazgch | 31:a0bed6c1e05d | 624 | { |
mazgch | 31:a0bed6c1e05d | 625 | if ((type == TYPE_PLUS) && num){ |
mazgch | 31:a0bed6c1e05d | 626 | int a; |
mazgch | 31:a0bed6c1e05d | 627 | if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) && |
mazgch | 31:a0bed6c1e05d | 628 | ((a == 129) || (a == 145))) { |
mazgch | 31:a0bed6c1e05d | 629 | } |
mazgch | 31:a0bed6c1e05d | 630 | } |
mazgch | 31:a0bed6c1e05d | 631 | return WAIT; |
mazgch | 31:a0bed6c1e05d | 632 | } |
mazgch | 31:a0bed6c1e05d | 633 | |
mazgch | 54:7ba8e4c218e2 | 634 | int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status) |
mazgch | 31:a0bed6c1e05d | 635 | { |
mazgch | 54:7ba8e4c218e2 | 636 | if ((type == TYPE_PLUS) && status){ |
mazgch | 54:7ba8e4c218e2 | 637 | int a,b; |
mazgch | 54:7ba8e4c218e2 | 638 | char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4 |
mazgch | 31:a0bed6c1e05d | 639 | // +CSQ: <rssi>,<qual> |
mazgch | 54:7ba8e4c218e2 | 640 | if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) { |
mazgch | 54:7ba8e4c218e2 | 641 | if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps |
mazgch | 54:7ba8e4c218e2 | 642 | if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; // |
mazgch | 31:a0bed6c1e05d | 643 | } |
mazgch | 31:a0bed6c1e05d | 644 | } |
mazgch | 31:a0bed6c1e05d | 645 | return WAIT; |
mazgch | 31:a0bed6c1e05d | 646 | } |
mazgch | 21:c4d64830bf02 | 647 | |
mazgch | 81:3966a5c17037 | 648 | int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i) |
mazgch | 81:3966a5c17037 | 649 | { |
mazgch | 81:3966a5c17037 | 650 | if ((type == TYPE_PLUS) && i){ |
mazgch | 82:055dcfcf9dcc | 651 | int a; |
mazgch | 82:055dcfcf9dcc | 652 | if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) { |
mazgch | 82:055dcfcf9dcc | 653 | *i = a; |
mazgch | 81:3966a5c17037 | 654 | } |
mazgch | 81:3966a5c17037 | 655 | } |
mazgch | 81:3966a5c17037 | 656 | return WAIT; |
mazgch | 81:3966a5c17037 | 657 | } |
mazgch | 81:3966a5c17037 | 658 | |
mazgch | 21:c4d64830bf02 | 659 | // ---------------------------------------------------------------- |
mazgch | 21:c4d64830bf02 | 660 | // internet connection |
mazgch | 21:c4d64830bf02 | 661 | |
mazgch | 79:291df065e345 | 662 | MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, |
mazgch | 79:291df065e345 | 663 | const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/) |
mazgch | 21:c4d64830bf02 | 664 | { |
mazgch | 78:caf0014375cb | 665 | INFO("Modem::join\r\n"); |
mazgch | 32:8f12ac182bbb | 666 | _ip = NOIP; |
mazgch | 32:8f12ac182bbb | 667 | if (_dev.dev == DEV_LISA_C200) { |
mazgch | 76:f7c3dd568dae | 668 | // make a dumy dns lookup (which will fail, so ignore the result) |
mazgch | 76:f7c3dd568dae | 669 | sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n"); |
mazgch | 76:f7c3dd568dae | 670 | waitFinalResp(); |
mazgch | 76:f7c3dd568dae | 671 | // This fake lookup will enable the IP connection and we |
mazgch | 76:f7c3dd568dae | 672 | // should have an IP after this, so we check it |
mazgch | 76:f7c3dd568dae | 673 | |
mazgch | 21:c4d64830bf02 | 674 | //Get local IP address |
mazgch | 21:c4d64830bf02 | 675 | sendFormated("AT+CMIP?\r\n"); |
mazgch | 52:8071747a7cb3 | 676 | if (RESP_OK != waitFinalResp(_cbCMIP, &_ip)) |
mazgch | 31:a0bed6c1e05d | 677 | return NOIP; |
mazgch | 21:c4d64830bf02 | 678 | } else { |
mazgch | 21:c4d64830bf02 | 679 | // check gprs attach status |
mazgch | 72:d1e943ad6558 | 680 | sendFormated("AT+CGATT=1\r\n"); |
mazgch | 74:208e3e32d263 | 681 | if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000)) |
mazgch | 31:a0bed6c1e05d | 682 | return NOIP; |
mazgch | 31:a0bed6c1e05d | 683 | |
mazgch | 31:a0bed6c1e05d | 684 | // Check the profile |
mazgch | 31:a0bed6c1e05d | 685 | int a = 0; |
mazgch | 79:291df065e345 | 686 | bool force = true; |
mazgch | 31:a0bed6c1e05d | 687 | sendFormated("AT+UPSND=" PROFILE ",8\r\n"); |
mazgch | 52:8071747a7cb3 | 688 | if (RESP_OK != waitFinalResp(_cbUPSND, &a)) |
mazgch | 31:a0bed6c1e05d | 689 | return NOIP; |
mazgch | 79:291df065e345 | 690 | if (a == 1 && force) { |
mazgch | 31:a0bed6c1e05d | 691 | // disconnect the profile already if it is connected |
mazgch | 31:a0bed6c1e05d | 692 | sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); |
mazgch | 58:e38a2e942fbb | 693 | if (RESP_OK != waitFinalResp(NULL,NULL,40*1000)) |
mazgch | 84:a05edb010176 | 694 | return NOIP; |
mazgch | 79:291df065e345 | 695 | a = 0; |
mazgch | 31:a0bed6c1e05d | 696 | } |
mazgch | 79:291df065e345 | 697 | if (a == 0) { |
mazgch | 84:a05edb010176 | 698 | bool ok = false; |
mazgch | 84:a05edb010176 | 699 | // try to lookup the apn settings from our local database by mccmnc |
mazgch | 84:a05edb010176 | 700 | const char* config = NULL; |
mazgch | 88:135fb4bb7aac | 701 | if (!apn && !username && !password) |
mazgch | 88:135fb4bb7aac | 702 | config = apnconfig(_dev.imsi); |
mazgch | 84:a05edb010176 | 703 | |
mazgch | 79:291df065e345 | 704 | // Set up the dynamic IP address assignment. |
mazgch | 79:291df065e345 | 705 | sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n"); |
mazgch | 52:8071747a7cb3 | 706 | if (RESP_OK != waitFinalResp()) |
mazgch | 31:a0bed6c1e05d | 707 | return NOIP; |
mazgch | 84:a05edb010176 | 708 | |
mazgch | 84:a05edb010176 | 709 | do { |
mazgch | 84:a05edb010176 | 710 | if (config) { |
mazgch | 85:dd8f4f0d0ca9 | 711 | apn = _APN_GET(config); |
mazgch | 85:dd8f4f0d0ca9 | 712 | username = _APN_GET(config); |
mazgch | 85:dd8f4f0d0ca9 | 713 | password = _APN_GET(config); |
mazgch | 84:a05edb010176 | 714 | TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\")\r\n", apn, username, password); |
mazgch | 79:291df065e345 | 715 | } |
mazgch | 84:a05edb010176 | 716 | // Set up the APN |
mazgch | 84:a05edb010176 | 717 | sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn?apn:""); |
mazgch | 84:a05edb010176 | 718 | if (RESP_OK != waitFinalResp()) |
mazgch | 84:a05edb010176 | 719 | return NOIP; |
mazgch | 84:a05edb010176 | 720 | sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username?username:""); |
mazgch | 84:a05edb010176 | 721 | if (RESP_OK != waitFinalResp()) |
mazgch | 84:a05edb010176 | 722 | return NOIP; |
mazgch | 84:a05edb010176 | 723 | sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password?password:""); |
mazgch | 84:a05edb010176 | 724 | if (RESP_OK != waitFinalResp()) |
mazgch | 84:a05edb010176 | 725 | return NOIP; |
mazgch | 84:a05edb010176 | 726 | // try different Authentication Protocols |
mazgch | 84:a05edb010176 | 727 | // 0 = none |
mazgch | 84:a05edb010176 | 728 | // 1 = PAP (Password Authentication Protocol) |
mazgch | 84:a05edb010176 | 729 | // 2 = CHAP (Challenge Handshake Authentication Protocol) |
mazgch | 84:a05edb010176 | 730 | for (int i = AUTH_NONE; i <= AUTH_CHAP && !ok; i ++) { |
mazgch | 84:a05edb010176 | 731 | if ((auth == AUTH_DETECT) || (auth == i)) { |
mazgch | 84:a05edb010176 | 732 | // Set up the Authentication Protocol |
mazgch | 84:a05edb010176 | 733 | sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n", i); |
mazgch | 84:a05edb010176 | 734 | if (RESP_OK != waitFinalResp()) |
mazgch | 84:a05edb010176 | 735 | return NOIP; |
mazgch | 84:a05edb010176 | 736 | // Activate the profile and make connection |
mazgch | 84:a05edb010176 | 737 | sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); |
mazgch | 84:a05edb010176 | 738 | if (RESP_OK == waitFinalResp(NULL,NULL,150*1000)) |
mazgch | 84:a05edb010176 | 739 | ok = true; |
mazgch | 84:a05edb010176 | 740 | } |
mazgch | 84:a05edb010176 | 741 | } |
mazgch | 85:dd8f4f0d0ca9 | 742 | } while (config && *config); // maybe use next setting ? |
mazgch | 84:a05edb010176 | 743 | if (!ok) { |
mazgch | 79:291df065e345 | 744 | ERROR("Your modem APN/password/username may be wrong\r\n"); |
mazgch | 31:a0bed6c1e05d | 745 | return NOIP; |
mazgch | 79:291df065e345 | 746 | } |
mazgch | 74:208e3e32d263 | 747 | } |
mazgch | 21:c4d64830bf02 | 748 | //Get local IP address |
mazgch | 21:c4d64830bf02 | 749 | sendFormated("AT+UPSND=" PROFILE ",0\r\n"); |
mazgch | 52:8071747a7cb3 | 750 | if (RESP_OK != waitFinalResp(_cbUPSND, &_ip)) |
mazgch | 31:a0bed6c1e05d | 751 | return NOIP; |
mazgch | 31:a0bed6c1e05d | 752 | } |
mazgch | 32:8f12ac182bbb | 753 | return _ip; |
mazgch | 31:a0bed6c1e05d | 754 | } |
mazgch | 31:a0bed6c1e05d | 755 | |
mazgch | 84:a05edb010176 | 756 | int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc) |
mazgch | 84:a05edb010176 | 757 | { |
mazgch | 84:a05edb010176 | 758 | if ((type == TYPE_PLUS) && mccmnc) { |
mazgch | 84:a05edb010176 | 759 | if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1) |
mazgch | 84:a05edb010176 | 760 | ; |
mazgch | 84:a05edb010176 | 761 | } |
mazgch | 84:a05edb010176 | 762 | return WAIT; |
mazgch | 84:a05edb010176 | 763 | } |
mazgch | 84:a05edb010176 | 764 | |
mazgch | 32:8f12ac182bbb | 765 | int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip) |
mazgch | 32:8f12ac182bbb | 766 | { |
mazgch | 32:8f12ac182bbb | 767 | if ((type == TYPE_PLUS) && ip) { |
mazgch | 32:8f12ac182bbb | 768 | int a,b,c,d; |
mazgch | 32:8f12ac182bbb | 769 | if (sscanf(buf, "\r\n+CMIP: " IPSTR, &a,&b,&c,&d) == 4) |
mazgch | 32:8f12ac182bbb | 770 | *ip = IPADR(a,b,c,d); |
mazgch | 32:8f12ac182bbb | 771 | } |
mazgch | 32:8f12ac182bbb | 772 | return WAIT; |
mazgch | 32:8f12ac182bbb | 773 | } |
mazgch | 32:8f12ac182bbb | 774 | |
mazgch | 31:a0bed6c1e05d | 775 | int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act) |
mazgch | 31:a0bed6c1e05d | 776 | { |
mazgch | 31:a0bed6c1e05d | 777 | if ((type == TYPE_PLUS) && act) { |
mazgch | 31:a0bed6c1e05d | 778 | if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1) |
mazgch | 31:a0bed6c1e05d | 779 | /*nothing*/; |
mazgch | 21:c4d64830bf02 | 780 | } |
mazgch | 31:a0bed6c1e05d | 781 | return WAIT; |
mazgch | 31:a0bed6c1e05d | 782 | } |
mazgch | 31:a0bed6c1e05d | 783 | |
mazgch | 31:a0bed6c1e05d | 784 | int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip) |
mazgch | 31:a0bed6c1e05d | 785 | { |
mazgch | 31:a0bed6c1e05d | 786 | if ((type == TYPE_PLUS) && ip) { |
mazgch | 31:a0bed6c1e05d | 787 | int a,b,c,d; |
mazgch | 31:a0bed6c1e05d | 788 | // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>] |
mazgch | 31:a0bed6c1e05d | 789 | if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4) |
mazgch | 31:a0bed6c1e05d | 790 | *ip = IPADR(a,b,c,d); |
mazgch | 31:a0bed6c1e05d | 791 | } |
mazgch | 31:a0bed6c1e05d | 792 | return WAIT; |
mazgch | 31:a0bed6c1e05d | 793 | } |
mazgch | 31:a0bed6c1e05d | 794 | |
mazgch | 31:a0bed6c1e05d | 795 | int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip) |
mazgch | 31:a0bed6c1e05d | 796 | { |
mazgch | 31:a0bed6c1e05d | 797 | if ((type == TYPE_PLUS) && ip) { |
mazgch | 31:a0bed6c1e05d | 798 | int a,b,c,d; |
mazgch | 31:a0bed6c1e05d | 799 | if (sscanf(buf, "\r\n+UDNSRN: \""IPSTR"\"", &a,&b,&c,&d) == 4) |
mazgch | 31:a0bed6c1e05d | 800 | *ip = IPADR(a,b,c,d); |
mazgch | 31:a0bed6c1e05d | 801 | } |
mazgch | 31:a0bed6c1e05d | 802 | return WAIT; |
mazgch | 21:c4d64830bf02 | 803 | } |
mazgch | 21:c4d64830bf02 | 804 | |
mazgch | 21:c4d64830bf02 | 805 | bool MDMParser::disconnect(void) |
mazgch | 21:c4d64830bf02 | 806 | { |
mazgch | 31:a0bed6c1e05d | 807 | if (_ip == NOIP) |
mazgch | 21:c4d64830bf02 | 808 | return true; |
mazgch | 74:208e3e32d263 | 809 | INFO("Modem::disconnect\r\n"); |
mazgch | 32:8f12ac182bbb | 810 | if (_dev.dev == DEV_LISA_C200) { |
mazgch | 76:f7c3dd568dae | 811 | // There something to do here |
mazgch | 21:c4d64830bf02 | 812 | } else { |
mazgch | 21:c4d64830bf02 | 813 | sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); |
mazgch | 52:8071747a7cb3 | 814 | if (RESP_OK != waitFinalResp()) |
mazgch | 32:8f12ac182bbb | 815 | return false; |
mazgch | 21:c4d64830bf02 | 816 | } |
mazgch | 31:a0bed6c1e05d | 817 | _ip = NOIP; |
mazgch | 21:c4d64830bf02 | 818 | return true; |
mazgch | 21:c4d64830bf02 | 819 | } |
mazgch | 21:c4d64830bf02 | 820 | |
mazgch | 31:a0bed6c1e05d | 821 | MDMParser::IP MDMParser::gethostbyname(const char* host) |
mazgch | 21:c4d64830bf02 | 822 | { |
mazgch | 31:a0bed6c1e05d | 823 | IP ip = NOIP; |
mazgch | 31:a0bed6c1e05d | 824 | int a,b,c,d; |
mazgch | 31:a0bed6c1e05d | 825 | if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4) |
mazgch | 31:a0bed6c1e05d | 826 | ip = IPADR(a,b,c,d); |
mazgch | 31:a0bed6c1e05d | 827 | else { |
mazgch | 31:a0bed6c1e05d | 828 | sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host); |
mazgch | 52:8071747a7cb3 | 829 | if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip)) |
mazgch | 31:a0bed6c1e05d | 830 | return false; |
mazgch | 21:c4d64830bf02 | 831 | } |
mazgch | 31:a0bed6c1e05d | 832 | return ip; |
mazgch | 21:c4d64830bf02 | 833 | } |
mazgch | 21:c4d64830bf02 | 834 | |
mazgch | 21:c4d64830bf02 | 835 | // ---------------------------------------------------------------- |
mazgch | 21:c4d64830bf02 | 836 | // sockets |
mazgch | 21:c4d64830bf02 | 837 | |
mazgch | 21:c4d64830bf02 | 838 | int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* socket) |
mazgch | 21:c4d64830bf02 | 839 | { |
mazgch | 21:c4d64830bf02 | 840 | if ((type == TYPE_PLUS) && socket) { |
mazgch | 21:c4d64830bf02 | 841 | const char* p = strstr(buf,"+USOCR: "); |
mazgch | 21:c4d64830bf02 | 842 | if (p) |
mazgch | 21:c4d64830bf02 | 843 | *socket = atoi(p+8); |
mazgch | 21:c4d64830bf02 | 844 | } |
mazgch | 21:c4d64830bf02 | 845 | return WAIT; |
mazgch | 21:c4d64830bf02 | 846 | } |
mazgch | 21:c4d64830bf02 | 847 | |
mazgch | 63:42cb563a25bc | 848 | int MDMParser::socketSocket(IpProtocol ipproto, int port) |
mazgch | 21:c4d64830bf02 | 849 | { |
mazgch | 47:9a89e5195721 | 850 | TRACE("socketSocket(%d)\r\n", ipproto); |
mazgch | 21:c4d64830bf02 | 851 | if(ipproto == IPPROTO_TCP) { |
mazgch | 63:42cb563a25bc | 852 | sendFormated("AT+USOCR=6\r\n"); |
mazgch | 63:42cb563a25bc | 853 | } else if ((ipproto == IPPROTO_UDP) && (port == -1)){ |
mazgch | 63:42cb563a25bc | 854 | sendFormated("AT+USOCR=17\r\n"); |
mazgch | 63:42cb563a25bc | 855 | } else if (ipproto == IPPROTO_UDP){ |
mazgch | 63:42cb563a25bc | 856 | sendFormated("AT+USOCR=17,%d\r\n", port); |
mazgch | 21:c4d64830bf02 | 857 | } else { // other types not supported |
mazgch | 21:c4d64830bf02 | 858 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 859 | } |
mazgch | 21:c4d64830bf02 | 860 | int socket = -1; |
mazgch | 52:8071747a7cb3 | 861 | if (RESP_OK != waitFinalResp(_cbUSOCR, &socket)) |
mazgch | 21:c4d64830bf02 | 862 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 863 | if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_FREE)) |
mazgch | 21:c4d64830bf02 | 864 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 865 | // successfull |
mazgch | 21:c4d64830bf02 | 866 | _sockets[socket].state = SOCK_CREATED; |
mazgch | 21:c4d64830bf02 | 867 | _sockets[socket].pending = 0; |
mazgch | 66:69072b3c5bca | 868 | _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; |
mazgch | 21:c4d64830bf02 | 869 | return socket; |
mazgch | 21:c4d64830bf02 | 870 | } |
mazgch | 21:c4d64830bf02 | 871 | |
mazgch | 21:c4d64830bf02 | 872 | bool MDMParser::socketConnect(int socket, const char * host, int port) |
mazgch | 21:c4d64830bf02 | 873 | { |
mazgch | 47:9a89e5195721 | 874 | TRACE("socketConnect(%d,%s,%d)\r\n", socket, host,port); |
mazgch | 31:a0bed6c1e05d | 875 | IP ip = gethostbyname(host); |
mazgch | 31:a0bed6c1e05d | 876 | if (ip == NOIP) |
mazgch | 21:c4d64830bf02 | 877 | return false; |
mazgch | 21:c4d64830bf02 | 878 | // connect to socket |
mazgch | 21:c4d64830bf02 | 879 | if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED)) |
mazgch | 21:c4d64830bf02 | 880 | return false; |
mazgch | 21:c4d64830bf02 | 881 | sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", socket, IPNUM(ip), port); |
mazgch | 52:8071747a7cb3 | 882 | if (RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 883 | return false; |
mazgch | 21:c4d64830bf02 | 884 | _sockets[socket].state = SOCK_CONNECTED; |
mazgch | 21:c4d64830bf02 | 885 | return true; |
mazgch | 21:c4d64830bf02 | 886 | } |
mazgch | 21:c4d64830bf02 | 887 | |
mazgch | 44:9d12223b78ff | 888 | bool MDMParser::socketIsConnected(int socket) |
mazgch | 44:9d12223b78ff | 889 | { |
mazgch | 47:9a89e5195721 | 890 | TRACE("socketIsConnected(%d)\r\n", socket); |
mazgch | 47:9a89e5195721 | 891 | if (!ISSOCKET(socket)) |
mazgch | 47:9a89e5195721 | 892 | return false; |
mazgch | 47:9a89e5195721 | 893 | return _sockets[socket].state == SOCK_CONNECTED; |
mazgch | 44:9d12223b78ff | 894 | } |
mazgch | 44:9d12223b78ff | 895 | |
mazgch | 66:69072b3c5bca | 896 | bool MDMParser::socketSetBlocking(int socket, int timeout_ms) |
mazgch | 44:9d12223b78ff | 897 | { |
mazgch | 47:9a89e5195721 | 898 | TRACE("socketSetBlocking(%d,%d)\r\n", socket, timeout_ms); |
mazgch | 44:9d12223b78ff | 899 | if (!ISSOCKET(socket)) |
mazgch | 44:9d12223b78ff | 900 | return false; |
mazgch | 44:9d12223b78ff | 901 | _sockets[socket].timeout_ms = timeout_ms; |
mazgch | 44:9d12223b78ff | 902 | return true; |
mazgch | 44:9d12223b78ff | 903 | } |
mazgch | 44:9d12223b78ff | 904 | |
mazgch | 21:c4d64830bf02 | 905 | bool MDMParser::socketClose(int socket) |
mazgch | 21:c4d64830bf02 | 906 | { |
mazgch | 47:9a89e5195721 | 907 | TRACE("socketClose(%d)\r\n", socket); |
mazgch | 21:c4d64830bf02 | 908 | if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED)) |
mazgch | 21:c4d64830bf02 | 909 | return false; |
mazgch | 21:c4d64830bf02 | 910 | sendFormated("AT+USOCL=%d\r\n", socket); |
mazgch | 52:8071747a7cb3 | 911 | if (RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 912 | return false; |
mazgch | 44:9d12223b78ff | 913 | _sockets[socket].state = SOCK_CREATED; |
mazgch | 21:c4d64830bf02 | 914 | return true; |
mazgch | 21:c4d64830bf02 | 915 | } |
mazgch | 21:c4d64830bf02 | 916 | |
mazgch | 21:c4d64830bf02 | 917 | bool MDMParser::socketFree(int socket) |
mazgch | 21:c4d64830bf02 | 918 | { |
mazgch | 47:9a89e5195721 | 919 | TRACE("socketFree(%d)\r\n", socket); |
mazgch | 21:c4d64830bf02 | 920 | socketClose(socket); |
mazgch | 21:c4d64830bf02 | 921 | if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED)) |
mazgch | 21:c4d64830bf02 | 922 | return false; |
mazgch | 21:c4d64830bf02 | 923 | _sockets[socket].state = SOCK_FREE; |
mazgch | 21:c4d64830bf02 | 924 | return true; |
mazgch | 21:c4d64830bf02 | 925 | } |
mazgch | 21:c4d64830bf02 | 926 | |
mazgch | 69:4d6fa520dfca | 927 | #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket |
mazgch | 69:4d6fa520dfca | 928 | |
mazgch | 21:c4d64830bf02 | 929 | int MDMParser::socketSend(int socket, const char * buf, int len) |
mazgch | 21:c4d64830bf02 | 930 | { |
mazgch | 47:9a89e5195721 | 931 | TRACE("socketSend(%d,,%d)\r\n", socket,len); |
mazgch | 68:33a96cf64986 | 932 | int cnt = len; |
mazgch | 68:33a96cf64986 | 933 | while (cnt > 0) { |
mazgch | 69:4d6fa520dfca | 934 | int blk = USO_MAX_WRITE; |
mazgch | 68:33a96cf64986 | 935 | if (cnt < blk) |
mazgch | 68:33a96cf64986 | 936 | blk = cnt; |
mazgch | 68:33a96cf64986 | 937 | sendFormated("AT+USOWR=%d,%d\r\n",socket,blk); |
mazgch | 52:8071747a7cb3 | 938 | if (RESP_PROMPT != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 939 | return SOCKET_ERROR; |
mazgch | 74:208e3e32d263 | 940 | RELAX_MS(50); |
mazgch | 68:33a96cf64986 | 941 | send(buf, blk); |
mazgch | 52:8071747a7cb3 | 942 | if (RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 943 | return SOCKET_ERROR; |
mazgch | 68:33a96cf64986 | 944 | buf += blk; |
mazgch | 68:33a96cf64986 | 945 | cnt -= blk; |
mazgch | 21:c4d64830bf02 | 946 | } |
mazgch | 68:33a96cf64986 | 947 | return (len - cnt); |
mazgch | 21:c4d64830bf02 | 948 | } |
mazgch | 21:c4d64830bf02 | 949 | |
mazgch | 21:c4d64830bf02 | 950 | int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len) |
mazgch | 21:c4d64830bf02 | 951 | { |
mazgch | 65:dd94f920a762 | 952 | TRACE("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket, IPNUM(ip),port,len); |
mazgch | 68:33a96cf64986 | 953 | int cnt = len; |
mazgch | 68:33a96cf64986 | 954 | while (cnt > 0) { |
mazgch | 69:4d6fa520dfca | 955 | int blk = USO_MAX_WRITE; |
mazgch | 68:33a96cf64986 | 956 | if (cnt < blk) |
mazgch | 68:33a96cf64986 | 957 | blk = cnt; |
mazgch | 68:33a96cf64986 | 958 | sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,blk); |
mazgch | 52:8071747a7cb3 | 959 | if (RESP_PROMPT != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 960 | return SOCKET_ERROR; |
mazgch | 74:208e3e32d263 | 961 | RELAX_MS(50); |
mazgch | 68:33a96cf64986 | 962 | send(buf, blk); |
mazgch | 63:42cb563a25bc | 963 | if (RESP_OK != waitFinalResp()) |
mazgch | 21:c4d64830bf02 | 964 | return SOCKET_ERROR; |
mazgch | 68:33a96cf64986 | 965 | buf += blk; |
mazgch | 68:33a96cf64986 | 966 | cnt -= blk; |
mazgch | 21:c4d64830bf02 | 967 | } |
mazgch | 68:33a96cf64986 | 968 | return (len - cnt); |
mazgch | 21:c4d64830bf02 | 969 | } |
mazgch | 21:c4d64830bf02 | 970 | |
mazgch | 21:c4d64830bf02 | 971 | int MDMParser::socketReadable(int socket) |
mazgch | 21:c4d64830bf02 | 972 | { |
mazgch | 47:9a89e5195721 | 973 | TRACE("socketReadable(%d)\r\n", socket); |
mazgch | 21:c4d64830bf02 | 974 | if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED)) |
mazgch | 21:c4d64830bf02 | 975 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 976 | // allow to receive unsolicited commands |
mazgch | 21:c4d64830bf02 | 977 | waitFinalResp(NULL, NULL, 0); |
mazgch | 21:c4d64830bf02 | 978 | if (_sockets[socket].state != SOCK_CONNECTED) |
mazgch | 21:c4d64830bf02 | 979 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 980 | return _sockets[socket].pending; |
mazgch | 21:c4d64830bf02 | 981 | } |
mazgch | 21:c4d64830bf02 | 982 | |
mazgch | 21:c4d64830bf02 | 983 | int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out) |
mazgch | 21:c4d64830bf02 | 984 | { |
mazgch | 21:c4d64830bf02 | 985 | if ((type == TYPE_PLUS) && out) { |
mazgch | 21:c4d64830bf02 | 986 | int sz, sk; |
mazgch | 21:c4d64830bf02 | 987 | if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) && |
mazgch | 21:c4d64830bf02 | 988 | (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { |
mazgch | 21:c4d64830bf02 | 989 | memcpy(out, &buf[len-1-sz], sz); |
mazgch | 21:c4d64830bf02 | 990 | } |
mazgch | 21:c4d64830bf02 | 991 | } |
mazgch | 21:c4d64830bf02 | 992 | return WAIT; |
mazgch | 21:c4d64830bf02 | 993 | } |
mazgch | 21:c4d64830bf02 | 994 | |
mazgch | 21:c4d64830bf02 | 995 | int MDMParser::socketRecv(int socket, char* buf, int len) |
mazgch | 21:c4d64830bf02 | 996 | { |
mazgch | 21:c4d64830bf02 | 997 | int cnt = 0; |
mazgch | 47:9a89e5195721 | 998 | TRACE("socketRecv(%d,,%d)\r\n", socket, len); |
mazgch | 21:c4d64830bf02 | 999 | if (!ISSOCKET(socket)) |
mazgch | 21:c4d64830bf02 | 1000 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 1001 | memset(buf, '\0', len); |
mazgch | 44:9d12223b78ff | 1002 | Timer timer; |
mazgch | 44:9d12223b78ff | 1003 | timer.start(); |
mazgch | 21:c4d64830bf02 | 1004 | while (len) { |
mazgch | 69:4d6fa520dfca | 1005 | int blk = MAX_SIZE; // still need space for headers and unsolicited commands |
mazgch | 21:c4d64830bf02 | 1006 | if (_sockets[socket].pending < blk) |
mazgch | 21:c4d64830bf02 | 1007 | blk = _sockets[socket].pending; |
mazgch | 21:c4d64830bf02 | 1008 | if (len < blk) blk = len; |
mazgch | 21:c4d64830bf02 | 1009 | if (blk) { |
mazgch | 44:9d12223b78ff | 1010 | sendFormated("AT+USORD=%d,%d\r\n",socket, blk); |
mazgch | 52:8071747a7cb3 | 1011 | if (RESP_OK != waitFinalResp(_cbUSORD, buf)) { |
mazgch | 44:9d12223b78ff | 1012 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 1013 | } |
mazgch | 21:c4d64830bf02 | 1014 | len -= blk; |
mazgch | 21:c4d64830bf02 | 1015 | cnt += blk; |
mazgch | 21:c4d64830bf02 | 1016 | buf += blk; |
mazgch | 21:c4d64830bf02 | 1017 | _sockets[socket].pending -= blk; |
mazgch | 75:ce6e12067d0c | 1018 | } else if ((_sockets[socket].state == SOCK_CONNECTED) && |
mazgch | 75:ce6e12067d0c | 1019 | !TIMEOUT(timer, _sockets[socket].timeout_ms)) { |
mazgch | 21:c4d64830bf02 | 1020 | // allow to receive unsolicited commands |
mazgch | 21:c4d64830bf02 | 1021 | waitFinalResp(NULL, NULL, 10); |
mazgch | 44:9d12223b78ff | 1022 | } else { |
mazgch | 44:9d12223b78ff | 1023 | len = 0; // no more data and socket closed or timed-out |
mazgch | 21:c4d64830bf02 | 1024 | } |
mazgch | 21:c4d64830bf02 | 1025 | } |
mazgch | 21:c4d64830bf02 | 1026 | return cnt; |
mazgch | 21:c4d64830bf02 | 1027 | } |
mazgch | 21:c4d64830bf02 | 1028 | |
mazgch | 21:c4d64830bf02 | 1029 | int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param) |
mazgch | 21:c4d64830bf02 | 1030 | { |
mazgch | 21:c4d64830bf02 | 1031 | if ((type == TYPE_PLUS) && param) { |
mazgch | 21:c4d64830bf02 | 1032 | int sz, sk, p, a,b,c,d; |
mazgch | 21:c4d64830bf02 | 1033 | if ((sscanf(buf, "\r\n+USORF: %d,\""IPSTR"\",%d,%d,", |
mazgch | 21:c4d64830bf02 | 1034 | &sk,&a,&b,&c,&d,&p,&sz) == 7) && |
mazgch | 21:c4d64830bf02 | 1035 | (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { |
mazgch | 21:c4d64830bf02 | 1036 | memcpy(param->buf, &buf[len-1-sz], sz); |
mazgch | 21:c4d64830bf02 | 1037 | param->ip = IPADR(a,b,c,d); |
mazgch | 21:c4d64830bf02 | 1038 | param->port = p; |
mazgch | 21:c4d64830bf02 | 1039 | } |
mazgch | 21:c4d64830bf02 | 1040 | } |
mazgch | 21:c4d64830bf02 | 1041 | return WAIT; |
mazgch | 21:c4d64830bf02 | 1042 | } |
mazgch | 21:c4d64830bf02 | 1043 | |
mazgch | 63:42cb563a25bc | 1044 | int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len) |
mazgch | 21:c4d64830bf02 | 1045 | { |
mazgch | 21:c4d64830bf02 | 1046 | int cnt = 0; |
mazgch | 63:42cb563a25bc | 1047 | TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len); |
mazgch | 21:c4d64830bf02 | 1048 | if (!ISSOCKET(socket)) |
mazgch | 21:c4d64830bf02 | 1049 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 1050 | memset(buf, '\0', len); |
mazgch | 44:9d12223b78ff | 1051 | Timer timer; |
mazgch | 44:9d12223b78ff | 1052 | timer.start(); |
mazgch | 21:c4d64830bf02 | 1053 | while (len) { |
mazgch | 69:4d6fa520dfca | 1054 | int blk = MAX_SIZE; // still need space for headers and unsolicited commands |
mazgch | 21:c4d64830bf02 | 1055 | if (_sockets[socket].pending < blk) |
mazgch | 21:c4d64830bf02 | 1056 | blk = _sockets[socket].pending; |
mazgch | 21:c4d64830bf02 | 1057 | if (len < blk) blk = len; |
mazgch | 21:c4d64830bf02 | 1058 | if (blk) { |
mazgch | 21:c4d64830bf02 | 1059 | sendFormated("AT+USORF=%d,%d\r\n",socket, blk); |
mazgch | 21:c4d64830bf02 | 1060 | USORFparam param; |
mazgch | 21:c4d64830bf02 | 1061 | param.buf = buf; |
mazgch | 52:8071747a7cb3 | 1062 | if (RESP_OK != waitFinalResp(_cbUSORF, ¶m)) { |
mazgch | 44:9d12223b78ff | 1063 | return SOCKET_ERROR; |
mazgch | 21:c4d64830bf02 | 1064 | } |
mazgch | 21:c4d64830bf02 | 1065 | *ip = param.ip; |
mazgch | 63:42cb563a25bc | 1066 | *port = param.port; |
mazgch | 21:c4d64830bf02 | 1067 | len -= blk; |
mazgch | 21:c4d64830bf02 | 1068 | cnt += blk; |
mazgch | 21:c4d64830bf02 | 1069 | buf += blk; |
mazgch | 21:c4d64830bf02 | 1070 | _sockets[socket].pending -= blk; |
mazgch | 75:ce6e12067d0c | 1071 | } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) { |
mazgch | 21:c4d64830bf02 | 1072 | // allow to receive unsolicited commands |
mazgch | 21:c4d64830bf02 | 1073 | waitFinalResp(NULL, NULL, 10); |
mazgch | 75:ce6e12067d0c | 1074 | } else |
mazgch | 44:9d12223b78ff | 1075 | len = 0; // no more data and socket closed or timed-out |
mazgch | 21:c4d64830bf02 | 1076 | } |
mazgch | 44:9d12223b78ff | 1077 | timer.stop(); |
mazgch | 44:9d12223b78ff | 1078 | timer.reset(); |
mazgch | 21:c4d64830bf02 | 1079 | return cnt; |
mazgch | 21:c4d64830bf02 | 1080 | } |
mazgch | 21:c4d64830bf02 | 1081 | |
mazgch | 21:c4d64830bf02 | 1082 | // ---------------------------------------------------------------- |
mazgch | 31:a0bed6c1e05d | 1083 | |
mazgch | 31:a0bed6c1e05d | 1084 | int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param) |
mazgch | 21:c4d64830bf02 | 1085 | { |
mazgch | 31:a0bed6c1e05d | 1086 | if ((type == TYPE_PLUS) && param && param->num) { |
mazgch | 31:a0bed6c1e05d | 1087 | // +CMGL: <ix>,... |
mazgch | 31:a0bed6c1e05d | 1088 | int ix; |
mazgch | 31:a0bed6c1e05d | 1089 | if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1) |
mazgch | 31:a0bed6c1e05d | 1090 | { |
mazgch | 31:a0bed6c1e05d | 1091 | *param->ix++ = ix; |
mazgch | 31:a0bed6c1e05d | 1092 | param->num--; |
mazgch | 31:a0bed6c1e05d | 1093 | } |
mazgch | 29:53d346010624 | 1094 | } |
mazgch | 29:53d346010624 | 1095 | return WAIT; |
mazgch | 21:c4d64830bf02 | 1096 | } |
mazgch | 21:c4d64830bf02 | 1097 | |
mazgch | 31:a0bed6c1e05d | 1098 | int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) { |
mazgch | 31:a0bed6c1e05d | 1099 | sendFormated("AT+CMGL=\"%s\"\r\n", stat); |
mazgch | 31:a0bed6c1e05d | 1100 | CMGLparam param; |
mazgch | 31:a0bed6c1e05d | 1101 | param.ix = ix; |
mazgch | 31:a0bed6c1e05d | 1102 | param.num = num; |
mazgch | 52:8071747a7cb3 | 1103 | if (RESP_OK != waitFinalResp(_cbCMGL, ¶m)) |
mazgch | 31:a0bed6c1e05d | 1104 | return -1; |
mazgch | 31:a0bed6c1e05d | 1105 | return num - param.num; |
mazgch | 21:c4d64830bf02 | 1106 | } |
mazgch | 21:c4d64830bf02 | 1107 | |
mazgch | 21:c4d64830bf02 | 1108 | bool MDMParser::smsSend(const char* num, const char* buf) |
mazgch | 21:c4d64830bf02 | 1109 | { |
mazgch | 80:34985b4d821e | 1110 | sendFormated("AT+CMGS=\"%s\"\r\n",num); |
mazgch | 58:e38a2e942fbb | 1111 | if (RESP_PROMPT != waitFinalResp(NULL,NULL,150*1000)) { |
mazgch | 21:c4d64830bf02 | 1112 | return false; |
mazgch | 21:c4d64830bf02 | 1113 | } |
mazgch | 21:c4d64830bf02 | 1114 | send(buf, strlen(buf)); |
mazgch | 21:c4d64830bf02 | 1115 | const char ctrlZ = 0x1A; |
mazgch | 21:c4d64830bf02 | 1116 | send(&ctrlZ, sizeof(ctrlZ)); |
mazgch | 52:8071747a7cb3 | 1117 | if (RESP_OK != waitFinalResp()) { |
mazgch | 21:c4d64830bf02 | 1118 | return false; |
mazgch | 21:c4d64830bf02 | 1119 | } |
mazgch | 21:c4d64830bf02 | 1120 | return true; |
mazgch | 21:c4d64830bf02 | 1121 | } |
mazgch | 21:c4d64830bf02 | 1122 | |
mazgch | 21:c4d64830bf02 | 1123 | bool MDMParser::smsDelete(int ix) |
mazgch | 21:c4d64830bf02 | 1124 | { |
mazgch | 21:c4d64830bf02 | 1125 | sendFormated("AT+CMGD=%d\r\n",ix); |
mazgch | 52:8071747a7cb3 | 1126 | if (RESP_OK != waitFinalResp()) { |
mazgch | 21:c4d64830bf02 | 1127 | return false; |
mazgch | 21:c4d64830bf02 | 1128 | } |
mazgch | 21:c4d64830bf02 | 1129 | return true; |
mazgch | 21:c4d64830bf02 | 1130 | } |
mazgch | 21:c4d64830bf02 | 1131 | |
mazgch | 21:c4d64830bf02 | 1132 | int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param) |
mazgch | 21:c4d64830bf02 | 1133 | { |
mazgch | 21:c4d64830bf02 | 1134 | if (param) { |
mazgch | 21:c4d64830bf02 | 1135 | if (type == TYPE_PLUS) { |
mazgch | 21:c4d64830bf02 | 1136 | if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) { |
mazgch | 21:c4d64830bf02 | 1137 | } |
mazgch | 37:cc3433329d66 | 1138 | } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) { |
mazgch | 21:c4d64830bf02 | 1139 | memcpy(param->buf, buf, len-2); |
mazgch | 21:c4d64830bf02 | 1140 | param->buf[len-2] = '\0'; |
mazgch | 21:c4d64830bf02 | 1141 | } |
mazgch | 21:c4d64830bf02 | 1142 | } |
mazgch | 21:c4d64830bf02 | 1143 | return WAIT; |
mazgch | 21:c4d64830bf02 | 1144 | } |
mazgch | 21:c4d64830bf02 | 1145 | |
mazgch | 21:c4d64830bf02 | 1146 | bool MDMParser::smsRead(int ix, char* num, char* buf, int len) |
mazgch | 21:c4d64830bf02 | 1147 | { |
mazgch | 21:c4d64830bf02 | 1148 | CMGRparam param; |
mazgch | 21:c4d64830bf02 | 1149 | param.num = num; |
mazgch | 21:c4d64830bf02 | 1150 | param.buf = buf; |
mazgch | 21:c4d64830bf02 | 1151 | sendFormated("AT+CMGR=%d\r\n",ix); |
mazgch | 52:8071747a7cb3 | 1152 | if (RESP_OK != waitFinalResp(_cbCMGR, ¶m)) { |
mazgch | 21:c4d64830bf02 | 1153 | return false; |
mazgch | 21:c4d64830bf02 | 1154 | } |
mazgch | 21:c4d64830bf02 | 1155 | return true; |
mazgch | 21:c4d64830bf02 | 1156 | } |
mazgch | 54:7ba8e4c218e2 | 1157 | |
mazgch | 54:7ba8e4c218e2 | 1158 | // ---------------------------------------------------------------- |
mazgch | 70:0a87d256cd24 | 1159 | |
mazgch | 70:0a87d256cd24 | 1160 | int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp) |
mazgch | 70:0a87d256cd24 | 1161 | { |
mazgch | 70:0a87d256cd24 | 1162 | if ((type == TYPE_PLUS) && resp) { |
mazgch | 70:0a87d256cd24 | 1163 | // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..); |
mazgch | 70:0a87d256cd24 | 1164 | if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) { |
mazgch | 70:0a87d256cd24 | 1165 | /*nothing*/ |
mazgch | 70:0a87d256cd24 | 1166 | } |
mazgch | 70:0a87d256cd24 | 1167 | } |
mazgch | 70:0a87d256cd24 | 1168 | return WAIT; |
mazgch | 70:0a87d256cd24 | 1169 | } |
mazgch | 70:0a87d256cd24 | 1170 | |
mazgch | 70:0a87d256cd24 | 1171 | bool MDMParser::ussdCommand(const char* cmd, char* buf) |
mazgch | 70:0a87d256cd24 | 1172 | { |
mazgch | 80:34985b4d821e | 1173 | if (_dev.dev == DEV_LISA_C200) |
mazgch | 80:34985b4d821e | 1174 | return false; |
mazgch | 70:0a87d256cd24 | 1175 | *buf = '\0'; |
mazgch | 70:0a87d256cd24 | 1176 | sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd); |
mazgch | 70:0a87d256cd24 | 1177 | if (RESP_OK != waitFinalResp(_cbCUSD, buf)) { |
mazgch | 70:0a87d256cd24 | 1178 | return false; |
mazgch | 70:0a87d256cd24 | 1179 | } |
mazgch | 70:0a87d256cd24 | 1180 | return true; |
mazgch | 70:0a87d256cd24 | 1181 | } |
mazgch | 80:34985b4d821e | 1182 | |
mazgch | 80:34985b4d821e | 1183 | // ---------------------------------------------------------------- |
mazgch | 70:0a87d256cd24 | 1184 | |
mazgch | 80:34985b4d821e | 1185 | bool MDMParser::delFile(const char* filename) |
mazgch | 80:34985b4d821e | 1186 | { |
mazgch | 80:34985b4d821e | 1187 | sendFormated("AT+UDELFILE=\"%s\"\r\n", filename); |
mazgch | 80:34985b4d821e | 1188 | if (RESP_OK != waitFinalResp()) |
mazgch | 80:34985b4d821e | 1189 | return false; |
mazgch | 80:34985b4d821e | 1190 | return true; |
mazgch | 80:34985b4d821e | 1191 | } |
mazgch | 80:34985b4d821e | 1192 | |
mazgch | 80:34985b4d821e | 1193 | int MDMParser::writeFile(const char* filename, const char* buf, int len) |
mazgch | 80:34985b4d821e | 1194 | { |
mazgch | 80:34985b4d821e | 1195 | sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len); |
mazgch | 80:34985b4d821e | 1196 | if (RESP_PROMPT != waitFinalResp()) |
mazgch | 80:34985b4d821e | 1197 | return 0; |
mazgch | 80:34985b4d821e | 1198 | send(buf, len); |
mazgch | 80:34985b4d821e | 1199 | if (RESP_OK != waitFinalResp()) |
mazgch | 80:34985b4d821e | 1200 | return 0; |
mazgch | 80:34985b4d821e | 1201 | return len; |
mazgch | 80:34985b4d821e | 1202 | } |
mazgch | 80:34985b4d821e | 1203 | |
mazgch | 80:34985b4d821e | 1204 | int MDMParser::readFile(const char* filename, char* buf, int len) |
mazgch | 80:34985b4d821e | 1205 | { |
mazgch | 80:34985b4d821e | 1206 | sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len); |
mazgch | 80:34985b4d821e | 1207 | URDFILEparam param; |
mazgch | 80:34985b4d821e | 1208 | param.filename = filename; |
mazgch | 80:34985b4d821e | 1209 | param.buf = buf; |
mazgch | 80:34985b4d821e | 1210 | param.sz = len; |
mazgch | 80:34985b4d821e | 1211 | param.len = 0; |
mazgch | 80:34985b4d821e | 1212 | if (RESP_OK != waitFinalResp(_cbURDFILE, ¶m)) |
mazgch | 80:34985b4d821e | 1213 | return -1; |
mazgch | 80:34985b4d821e | 1214 | return param.len; |
mazgch | 80:34985b4d821e | 1215 | } |
mazgch | 80:34985b4d821e | 1216 | |
mazgch | 80:34985b4d821e | 1217 | int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param) |
mazgch | 80:34985b4d821e | 1218 | { |
mazgch | 80:34985b4d821e | 1219 | if ((type == TYPE_PLUS) && param && param->filename && param->buf) { |
mazgch | 80:34985b4d821e | 1220 | char filename[48]; |
mazgch | 80:34985b4d821e | 1221 | int sz; |
mazgch | 80:34985b4d821e | 1222 | if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) && |
mazgch | 80:34985b4d821e | 1223 | (0 == strcmp(param->filename, filename)) && |
mazgch | 80:34985b4d821e | 1224 | (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { |
mazgch | 80:34985b4d821e | 1225 | param->len = (sz < param->sz) ? sz : param->sz; |
mazgch | 80:34985b4d821e | 1226 | memcpy(param->buf, &buf[len-1-sz], param->len); |
mazgch | 80:34985b4d821e | 1227 | } |
mazgch | 80:34985b4d821e | 1228 | } |
mazgch | 80:34985b4d821e | 1229 | return WAIT; |
mazgch | 80:34985b4d821e | 1230 | } |
mazgch | 80:34985b4d821e | 1231 | |
mazgch | 70:0a87d256cd24 | 1232 | // ---------------------------------------------------------------- |
mazgch | 74:208e3e32d263 | 1233 | bool MDMParser::setDebug(int level) |
mazgch | 74:208e3e32d263 | 1234 | { |
mazgch | 74:208e3e32d263 | 1235 | #ifdef MDM_DEBUG |
mazgch | 74:208e3e32d263 | 1236 | if ((_debugLevel >= 0) && (level >= 0)) { |
mazgch | 74:208e3e32d263 | 1237 | _debugLevel = level; |
mazgch | 74:208e3e32d263 | 1238 | return true; |
mazgch | 74:208e3e32d263 | 1239 | } |
mazgch | 74:208e3e32d263 | 1240 | #endif |
mazgch | 74:208e3e32d263 | 1241 | return false; |
mazgch | 74:208e3e32d263 | 1242 | } |
mazgch | 74:208e3e32d263 | 1243 | |
mazgch | 73:2b32e0a21df2 | 1244 | void MDMParser::dumpDevStatus(MDMParser::DevStatus* status, |
mazgch | 73:2b32e0a21df2 | 1245 | _DPRINT dprint, void* param) |
mazgch | 54:7ba8e4c218e2 | 1246 | { |
mazgch | 75:ce6e12067d0c | 1247 | dprint(param, "Modem::devStatus\r\n"); |
mazgch | 54:7ba8e4c218e2 | 1248 | const char* txtDev[] = { "Unknown", "SARA-G350", "LISA-U200", "LISA-C200" }; |
mazgch | 54:7ba8e4c218e2 | 1249 | if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != MDMParser::DEV_UNKNOWN)) |
mazgch | 73:2b32e0a21df2 | 1250 | dprint(param, " Device: %s\r\n", txtDev[status->dev]); |
mazgch | 54:7ba8e4c218e2 | 1251 | const char* txtLpm[] = { "Disabled", "Enabled", "Active" }; |
mazgch | 54:7ba8e4c218e2 | 1252 | if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm)) |
mazgch | 73:2b32e0a21df2 | 1253 | dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]); |
mazgch | 75:ce6e12067d0c | 1254 | const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" }; |
mazgch | 54:7ba8e4c218e2 | 1255 | if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != MDMParser::SIM_UNKNOWN)) |
mazgch | 73:2b32e0a21df2 | 1256 | dprint(param, " SIM: %s\r\n", txtSim[status->sim]); |
mazgch | 54:7ba8e4c218e2 | 1257 | if (*status->ccid) |
mazgch | 73:2b32e0a21df2 | 1258 | dprint(param, " CCID: %s\r\n", status->ccid); |
mazgch | 54:7ba8e4c218e2 | 1259 | if (*status->imei) |
mazgch | 73:2b32e0a21df2 | 1260 | dprint(param, " IMEI: %s\r\n", status->imei); |
mazgch | 54:7ba8e4c218e2 | 1261 | if (*status->imsi) |
mazgch | 73:2b32e0a21df2 | 1262 | dprint(param, " IMSI: %s\r\n", status->imsi); |
mazgch | 54:7ba8e4c218e2 | 1263 | if (*status->meid) |
mazgch | 73:2b32e0a21df2 | 1264 | dprint(param, " MEID: %s\r\n", status->meid); // LISA-C |
mazgch | 54:7ba8e4c218e2 | 1265 | if (*status->manu) |
mazgch | 73:2b32e0a21df2 | 1266 | dprint(param, " Manufacturer: %s\r\n", status->manu); |
mazgch | 54:7ba8e4c218e2 | 1267 | if (*status->model) |
mazgch | 73:2b32e0a21df2 | 1268 | dprint(param, " Model: %s\r\n", status->model); |
mazgch | 54:7ba8e4c218e2 | 1269 | if (*status->ver) |
mazgch | 73:2b32e0a21df2 | 1270 | dprint(param, " Version: %s\r\n", status->ver); |
mazgch | 54:7ba8e4c218e2 | 1271 | } |
mazgch | 54:7ba8e4c218e2 | 1272 | |
mazgch | 73:2b32e0a21df2 | 1273 | void MDMParser::dumpNetStatus(MDMParser::NetStatus *status, |
mazgch | 73:2b32e0a21df2 | 1274 | _DPRINT dprint, void* param) |
mazgch | 54:7ba8e4c218e2 | 1275 | { |
mazgch | 75:ce6e12067d0c | 1276 | dprint(param, "Modem::netStatus\r\n"); |
mazgch | 54:7ba8e4c218e2 | 1277 | const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" }; |
mazgch | 79:291df065e345 | 1278 | if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != MDMParser::REG_UNKNOWN)) |
mazgch | 79:291df065e345 | 1279 | dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]); |
mazgch | 79:291df065e345 | 1280 | if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != MDMParser::REG_UNKNOWN)) |
mazgch | 79:291df065e345 | 1281 | dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]); |
mazgch | 54:7ba8e4c218e2 | 1282 | const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA" }; |
mazgch | 54:7ba8e4c218e2 | 1283 | if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != MDMParser::ACT_UNKNOWN)) |
mazgch | 73:2b32e0a21df2 | 1284 | dprint(param, " Access Technology: %s\r\n", txtAct[status->act]); |
mazgch | 54:7ba8e4c218e2 | 1285 | if (status->rssi) |
mazgch | 73:2b32e0a21df2 | 1286 | dprint(param, " Signal Strength: %d dBm\r\n", status->rssi); |
mazgch | 54:7ba8e4c218e2 | 1287 | if (status->ber) |
mazgch | 73:2b32e0a21df2 | 1288 | dprint(param, " Bit Error Rate: %d\r\n", status->ber); |
mazgch | 54:7ba8e4c218e2 | 1289 | if (*status->opr) |
mazgch | 73:2b32e0a21df2 | 1290 | dprint(param, " Operator: %s\r\n", status->opr); |
mazgch | 54:7ba8e4c218e2 | 1291 | if (status->lac != 0xFFFF) |
mazgch | 73:2b32e0a21df2 | 1292 | dprint(param, " Location Area Code: %04X\r\n", status->lac); |
mazgch | 54:7ba8e4c218e2 | 1293 | if (status->ci != 0xFFFFFFFF) |
mazgch | 73:2b32e0a21df2 | 1294 | dprint(param, " Cell ID: %08X\r\n", status->ci); |
mazgch | 54:7ba8e4c218e2 | 1295 | if (*status->num) |
mazgch | 73:2b32e0a21df2 | 1296 | dprint(param, " Phone Number: %s\r\n", status->num); |
mazgch | 54:7ba8e4c218e2 | 1297 | } |
mazgch | 54:7ba8e4c218e2 | 1298 | |
mazgch | 73:2b32e0a21df2 | 1299 | void MDMParser::dumpIp(MDMParser::IP ip, |
mazgch | 73:2b32e0a21df2 | 1300 | _DPRINT dprint, void* param) |
mazgch | 54:7ba8e4c218e2 | 1301 | { |
mazgch | 57:869bd35f44cc | 1302 | if (ip != NOIP) |
mazgch | 75:ce6e12067d0c | 1303 | dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip)); |
mazgch | 54:7ba8e4c218e2 | 1304 | } |
mazgch | 70:0a87d256cd24 | 1305 | |
mazgch | 21:c4d64830bf02 | 1306 | // ---------------------------------------------------------------- |
mazgch | 21:c4d64830bf02 | 1307 | int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end) |
mazgch | 18:e5697801df29 | 1308 | { |
mazgch | 18:e5697801df29 | 1309 | int o = 0; |
mazgch | 21:c4d64830bf02 | 1310 | if (sta) { |
mazgch | 21:c4d64830bf02 | 1311 | while (*sta) { |
mazgch | 21:c4d64830bf02 | 1312 | if (++o > len) return WAIT; |
mazgch | 21:c4d64830bf02 | 1313 | char ch = pipe->next(); |
mazgch | 21:c4d64830bf02 | 1314 | if (*sta++ != ch) return NOT_FOUND; |
mazgch | 21:c4d64830bf02 | 1315 | } |
mazgch | 21:c4d64830bf02 | 1316 | } |
mazgch | 21:c4d64830bf02 | 1317 | if (!end) return o; // no termination |
mazgch | 35:9275215a3a5b | 1318 | // at least any char |
mazgch | 35:9275215a3a5b | 1319 | if (++o > len) return WAIT; |
mazgch | 35:9275215a3a5b | 1320 | pipe->next(); |
mazgch | 35:9275215a3a5b | 1321 | // check the end |
mazgch | 21:c4d64830bf02 | 1322 | int x = 0; |
mazgch | 21:c4d64830bf02 | 1323 | while (end[x]) { |
mazgch | 21:c4d64830bf02 | 1324 | if (++o > len) return WAIT; |
mazgch | 21:c4d64830bf02 | 1325 | char ch = pipe->next(); |
mazgch | 21:c4d64830bf02 | 1326 | x = (end[x] == ch) ? x + 1 : |
mazgch | 21:c4d64830bf02 | 1327 | (end[0] == ch) ? 1 : |
mazgch | 21:c4d64830bf02 | 1328 | 0; |
mazgch | 21:c4d64830bf02 | 1329 | } |
mazgch | 21:c4d64830bf02 | 1330 | return o; |
mazgch | 21:c4d64830bf02 | 1331 | } |
mazgch | 21:c4d64830bf02 | 1332 | |
mazgch | 21:c4d64830bf02 | 1333 | int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt) |
mazgch | 21:c4d64830bf02 | 1334 | { |
mazgch | 21:c4d64830bf02 | 1335 | int o = 0; |
mazgch | 21:c4d64830bf02 | 1336 | int num = 0; |
mazgch | 21:c4d64830bf02 | 1337 | if (fmt) { |
mazgch | 21:c4d64830bf02 | 1338 | while (*fmt) { |
mazgch | 21:c4d64830bf02 | 1339 | if (++o > len) return WAIT; |
mazgch | 21:c4d64830bf02 | 1340 | char ch = pipe->next(); |
mazgch | 21:c4d64830bf02 | 1341 | if (*fmt == '%') { |
mazgch | 21:c4d64830bf02 | 1342 | fmt++; |
mazgch | 21:c4d64830bf02 | 1343 | if (*fmt == 'd') { // numeric |
mazgch | 21:c4d64830bf02 | 1344 | fmt ++; |
mazgch | 21:c4d64830bf02 | 1345 | num = 0; |
mazgch | 21:c4d64830bf02 | 1346 | while (ch >= '0' && ch <= '9') { |
mazgch | 21:c4d64830bf02 | 1347 | num = num * 10 + (ch - '0'); |
mazgch | 21:c4d64830bf02 | 1348 | if (++o > len) return WAIT; |
mazgch | 21:c4d64830bf02 | 1349 | ch = pipe->next(); |
mazgch | 21:c4d64830bf02 | 1350 | } |
mazgch | 21:c4d64830bf02 | 1351 | } |
mazgch | 21:c4d64830bf02 | 1352 | else if (*fmt == 'c') { // char buffer (takes last numeric as length) |
mazgch | 21:c4d64830bf02 | 1353 | fmt ++; |
mazgch | 21:c4d64830bf02 | 1354 | while (num --) { |
mazgch | 21:c4d64830bf02 | 1355 | if (++o > len) return WAIT; |
mazgch | 21:c4d64830bf02 | 1356 | ch = pipe->next(); |
mazgch | 21:c4d64830bf02 | 1357 | } |
mazgch | 21:c4d64830bf02 | 1358 | } |
mazgch | 80:34985b4d821e | 1359 | else if (*fmt == 's') { |
mazgch | 80:34985b4d821e | 1360 | fmt ++; |
mazgch | 80:34985b4d821e | 1361 | if (ch != '\"') return NOT_FOUND; |
mazgch | 80:34985b4d821e | 1362 | do { |
mazgch | 80:34985b4d821e | 1363 | if (++o > len) return WAIT; |
mazgch | 80:34985b4d821e | 1364 | ch = pipe->next(); |
mazgch | 80:34985b4d821e | 1365 | } while (ch != '\"'); |
mazgch | 80:34985b4d821e | 1366 | if (++o > len) return WAIT; |
mazgch | 80:34985b4d821e | 1367 | ch = pipe->next(); |
mazgch | 80:34985b4d821e | 1368 | } |
mazgch | 21:c4d64830bf02 | 1369 | } |
mazgch | 21:c4d64830bf02 | 1370 | if (*fmt++ != ch) return NOT_FOUND; |
mazgch | 18:e5697801df29 | 1371 | } |
mazgch | 18:e5697801df29 | 1372 | } |
mazgch | 21:c4d64830bf02 | 1373 | return o; |
mazgch | 21:c4d64830bf02 | 1374 | } |
mazgch | 21:c4d64830bf02 | 1375 | |
mazgch | 21:c4d64830bf02 | 1376 | int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len) |
mazgch | 21:c4d64830bf02 | 1377 | { |
mazgch | 21:c4d64830bf02 | 1378 | int unkn = 0; |
mazgch | 21:c4d64830bf02 | 1379 | int sz = pipe->size(); |
mazgch | 21:c4d64830bf02 | 1380 | int fr = pipe->free(); |
mazgch | 21:c4d64830bf02 | 1381 | if (len > sz) |
mazgch | 21:c4d64830bf02 | 1382 | len = sz; |
mazgch | 21:c4d64830bf02 | 1383 | while (len > 0) |
mazgch | 21:c4d64830bf02 | 1384 | { |
mazgch | 21:c4d64830bf02 | 1385 | static struct { |
mazgch | 21:c4d64830bf02 | 1386 | const char* fmt; int type; |
mazgch | 21:c4d64830bf02 | 1387 | } lutF[] = { |
mazgch | 21:c4d64830bf02 | 1388 | { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS }, |
mazgch | 21:c4d64830bf02 | 1389 | { "\r\n+USORF: %d,\""IPSTR"\",%d,%d,\"%c\"", TYPE_PLUS }, |
mazgch | 80:34985b4d821e | 1390 | { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS }, |
mazgch | 21:c4d64830bf02 | 1391 | }; |
mazgch | 21:c4d64830bf02 | 1392 | static struct { |
mazgch | 21:c4d64830bf02 | 1393 | const char* sta; const char* end; int type; |
mazgch | 21:c4d64830bf02 | 1394 | } lut[] = { |
mazgch | 21:c4d64830bf02 | 1395 | { "\r\nOK\r\n", NULL, TYPE_OK }, |
mazgch | 21:c4d64830bf02 | 1396 | { "\r\nERROR\r\n", NULL, TYPE_ERROR }, |
mazgch | 31:a0bed6c1e05d | 1397 | { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR }, |
mazgch | 21:c4d64830bf02 | 1398 | { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR }, |
mazgch | 21:c4d64830bf02 | 1399 | { "\r\nRING\r\n", NULL, TYPE_RING }, |
mazgch | 21:c4d64830bf02 | 1400 | { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT }, |
mazgch | 21:c4d64830bf02 | 1401 | { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER }, |
mazgch | 21:c4d64830bf02 | 1402 | { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE }, |
mazgch | 21:c4d64830bf02 | 1403 | { "\r\nBUSY\r\n", NULL, TYPE_BUSY }, |
mazgch | 21:c4d64830bf02 | 1404 | { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER }, |
mazgch | 21:c4d64830bf02 | 1405 | { "\r\n+", "\r\n", TYPE_PLUS }, |
mazgch | 21:c4d64830bf02 | 1406 | { "\r\n@", NULL, TYPE_PROMPT }, // Sockets |
mazgch | 21:c4d64830bf02 | 1407 | { "\r\n>", NULL, TYPE_PROMPT }, // SMS |
mazgch | 80:34985b4d821e | 1408 | { "\n>", NULL, TYPE_PROMPT }, // File |
mazgch | 21:c4d64830bf02 | 1409 | }; |
mazgch | 21:c4d64830bf02 | 1410 | for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) { |
mazgch | 21:c4d64830bf02 | 1411 | pipe->set(unkn); |
mazgch | 21:c4d64830bf02 | 1412 | int ln = _parseFormated(pipe, len, lutF[i].fmt); |
mazgch | 21:c4d64830bf02 | 1413 | if (ln == WAIT && fr) |
mazgch | 21:c4d64830bf02 | 1414 | return WAIT; |
mazgch | 21:c4d64830bf02 | 1415 | if ((ln != NOT_FOUND) && (unkn > 0)) |
mazgch | 31:a0bed6c1e05d | 1416 | return TYPE_UNKNOWN | pipe->get(buf, unkn); |
mazgch | 21:c4d64830bf02 | 1417 | if (ln > 0) |
mazgch | 21:c4d64830bf02 | 1418 | return lutF[i].type | pipe->get(buf, ln); |
mazgch | 21:c4d64830bf02 | 1419 | } |
mazgch | 21:c4d64830bf02 | 1420 | for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) { |
mazgch | 21:c4d64830bf02 | 1421 | pipe->set(unkn); |
mazgch | 21:c4d64830bf02 | 1422 | int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end); |
mazgch | 21:c4d64830bf02 | 1423 | if (ln == WAIT && fr) |
mazgch | 21:c4d64830bf02 | 1424 | return WAIT; |
mazgch | 21:c4d64830bf02 | 1425 | if ((ln != NOT_FOUND) && (unkn > 0)) |
mazgch | 31:a0bed6c1e05d | 1426 | return TYPE_UNKNOWN | pipe->get(buf, unkn); |
mazgch | 21:c4d64830bf02 | 1427 | if (ln > 0) |
mazgch | 21:c4d64830bf02 | 1428 | return lut[i].type | pipe->get(buf, ln); |
mazgch | 21:c4d64830bf02 | 1429 | } |
mazgch | 21:c4d64830bf02 | 1430 | // UNKNOWN |
mazgch | 21:c4d64830bf02 | 1431 | unkn ++; |
mazgch | 21:c4d64830bf02 | 1432 | len--; |
mazgch | 21:c4d64830bf02 | 1433 | } |
mazgch | 18:e5697801df29 | 1434 | return WAIT; |
mazgch | 18:e5697801df29 | 1435 | } |
mazgch | 18:e5697801df29 | 1436 | |
mazgch | 18:e5697801df29 | 1437 | // ---------------------------------------------------------------- |
mazgch | 18:e5697801df29 | 1438 | // Serial Implementation |
mazgch | 18:e5697801df29 | 1439 | // ---------------------------------------------------------------- |
mazgch | 18:e5697801df29 | 1440 | |
mazgch | 76:f7c3dd568dae | 1441 | /*! Helper Dev Null Device |
mazgch | 76:f7c3dd568dae | 1442 | Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout |
mazgch | 76:f7c3dd568dae | 1443 | is shared with the serial port of the modem. Having printfs inbetween the |
mazgch | 76:f7c3dd568dae | 1444 | AT commands you cause a failure of the modem. |
mazgch | 76:f7c3dd568dae | 1445 | */ |
mazgch | 76:f7c3dd568dae | 1446 | class DevNull : public Stream { |
mazgch | 76:f7c3dd568dae | 1447 | public: |
mazgch | 76:f7c3dd568dae | 1448 | DevNull() : Stream(_name+1) { } //!< Constructor |
mazgch | 76:f7c3dd568dae | 1449 | void claim(const char* mode, FILE* file) |
mazgch | 76:f7c3dd568dae | 1450 | { freopen(_name, mode, file); } //!< claim a stream |
mazgch | 76:f7c3dd568dae | 1451 | protected: |
mazgch | 76:f7c3dd568dae | 1452 | virtual int _getc() { return EOF; } //!< Nothing |
mazgch | 76:f7c3dd568dae | 1453 | virtual int _putc(int c) { return c; } //!< Discard |
mazgch | 76:f7c3dd568dae | 1454 | static const char* _name; //!< File name |
mazgch | 76:f7c3dd568dae | 1455 | }; |
mazgch | 76:f7c3dd568dae | 1456 | const char* DevNull::_name = "/null"; //!< the null device name |
mazgch | 76:f7c3dd568dae | 1457 | static DevNull null; //!< the null device |
mazgch | 76:f7c3dd568dae | 1458 | |
mazgch | 19:2b5d097ca15d | 1459 | MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/, |
mazgch | 19:2b5d097ca15d | 1460 | int baudrate /*= MDMBAUD*/, |
mazgch | 43:a89a7a505991 | 1461 | #if DEVICE_SERIAL_FC |
mazgch | 19:2b5d097ca15d | 1462 | PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/, |
mazgch | 43:a89a7a505991 | 1463 | #endif |
mazgch | 18:e5697801df29 | 1464 | int rxSize /*= 256*/, int txSize /*= 128*/) : |
mazgch | 35:9275215a3a5b | 1465 | SerialPipe(tx, rx, rxSize, txSize) |
mazgch | 18:e5697801df29 | 1466 | { |
mazgch | 76:f7c3dd568dae | 1467 | if (rx == USBRX) |
mazgch | 76:f7c3dd568dae | 1468 | null.claim("r", stdin); |
mazgch | 76:f7c3dd568dae | 1469 | if (tx == USBTX) { |
mazgch | 76:f7c3dd568dae | 1470 | null.claim("w", stdout); |
mazgch | 76:f7c3dd568dae | 1471 | null.claim("w", stderr); |
mazgch | 74:208e3e32d263 | 1472 | #ifdef MDM_DEBUG |
mazgch | 76:f7c3dd568dae | 1473 | _debugLevel = -1; |
mazgch | 76:f7c3dd568dae | 1474 | #endif |
mazgch | 76:f7c3dd568dae | 1475 | } |
mazgch | 74:208e3e32d263 | 1476 | #ifdef TARGET_UBLOX_C027 |
mazgch | 74:208e3e32d263 | 1477 | _onboard = (tx == MDMTXD) && (rx == MDMRXD); |
mazgch | 74:208e3e32d263 | 1478 | if (_onboard) |
mazgch | 74:208e3e32d263 | 1479 | c027_mdm_powerOn(false); |
mazgch | 74:208e3e32d263 | 1480 | #endif |
mazgch | 18:e5697801df29 | 1481 | baud(baudrate); |
mazgch | 35:9275215a3a5b | 1482 | #if DEVICE_SERIAL_FC |
mazgch | 35:9275215a3a5b | 1483 | if ((rts != NC) || (cts != NC)) |
mazgch | 35:9275215a3a5b | 1484 | { |
mazgch | 35:9275215a3a5b | 1485 | Flow flow = (cts == NC) ? RTS : |
mazgch | 35:9275215a3a5b | 1486 | (rts == NC) ? CTS : RTSCTS ; |
mazgch | 35:9275215a3a5b | 1487 | set_flow_control(flow, rts, cts); |
mazgch | 35:9275215a3a5b | 1488 | if (cts != NC) _dev.lpm = LPM_ENABLED; |
mazgch | 35:9275215a3a5b | 1489 | } |
mazgch | 35:9275215a3a5b | 1490 | #endif |
mazgch | 18:e5697801df29 | 1491 | } |
mazgch | 18:e5697801df29 | 1492 | |
mazgch | 76:f7c3dd568dae | 1493 | MDMSerial::~MDMSerial(void) |
mazgch | 76:f7c3dd568dae | 1494 | { |
mazgch | 76:f7c3dd568dae | 1495 | powerOff(); |
mazgch | 76:f7c3dd568dae | 1496 | #ifdef TARGET_UBLOX_C027 |
mazgch | 76:f7c3dd568dae | 1497 | if (_onboard) |
mazgch | 76:f7c3dd568dae | 1498 | c027_mdm_powerOff(); |
mazgch | 76:f7c3dd568dae | 1499 | #endif |
mazgch | 76:f7c3dd568dae | 1500 | } |
mazgch | 76:f7c3dd568dae | 1501 | |
mazgch | 18:e5697801df29 | 1502 | int MDMSerial::_send(const void* buf, int len) |
mazgch | 18:e5697801df29 | 1503 | { |
mazgch | 35:9275215a3a5b | 1504 | return put((const char*)buf, len, true/*=blocking*/); |
mazgch | 18:e5697801df29 | 1505 | } |
mazgch | 18:e5697801df29 | 1506 | |
mazgch | 18:e5697801df29 | 1507 | int MDMSerial::getLine(char* buffer, int length) |
mazgch | 18:e5697801df29 | 1508 | { |
mazgch | 18:e5697801df29 | 1509 | return _getLine(&_pipeRx, buffer, length); |
mazgch | 18:e5697801df29 | 1510 | } |
mazgch | 18:e5697801df29 | 1511 | |
mazgch | 18:e5697801df29 | 1512 | // ---------------------------------------------------------------- |
mazgch | 18:e5697801df29 | 1513 | // USB Implementation |
mazgch | 18:e5697801df29 | 1514 | // ---------------------------------------------------------------- |
mazgch | 18:e5697801df29 | 1515 | |
mazgch | 18:e5697801df29 | 1516 | #ifdef HAVE_MDMUSB |
mazgch | 76:f7c3dd568dae | 1517 | MDMUsb::MDMUsb(void) |
mazgch | 74:208e3e32d263 | 1518 | { |
mazgch | 74:208e3e32d263 | 1519 | #ifdef MDM_DEBUG |
mazgch | 74:208e3e32d263 | 1520 | _debugLevel = 1; |
mazgch | 74:208e3e32d263 | 1521 | #endif |
mazgch | 74:208e3e32d263 | 1522 | #ifdef TARGET_UBLOX_C027 |
mazgch | 74:208e3e32d263 | 1523 | _onboard = true; |
mazgch | 74:208e3e32d263 | 1524 | c027_mdm_powerOn(true); |
mazgch | 74:208e3e32d263 | 1525 | #endif |
mazgch | 74:208e3e32d263 | 1526 | } |
mazgch | 76:f7c3dd568dae | 1527 | |
mazgch | 76:f7c3dd568dae | 1528 | MDMUsb::~MDMUsb(void) |
mazgch | 76:f7c3dd568dae | 1529 | { |
mazgch | 76:f7c3dd568dae | 1530 | powerOff(); |
mazgch | 76:f7c3dd568dae | 1531 | #ifdef TARGET_UBLOX_C027 |
mazgch | 76:f7c3dd568dae | 1532 | if (_onboard) |
mazgch | 76:f7c3dd568dae | 1533 | c027_mdm_powerOff(); |
mazgch | 76:f7c3dd568dae | 1534 | #endif |
mazgch | 76:f7c3dd568dae | 1535 | } |
mazgch | 76:f7c3dd568dae | 1536 | |
mazgch | 76:f7c3dd568dae | 1537 | int MDMUsb::_send(const void* buf, int len) { return 0; } |
mazgch | 76:f7c3dd568dae | 1538 | |
mazgch | 18:e5697801df29 | 1539 | int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; } |
mazgch | 76:f7c3dd568dae | 1540 | |
mazgch | 35:9275215a3a5b | 1541 | #endif |