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.

Committer:
mazgch
Date:
Tue May 20 11:40:07 2014 +0000
Revision:
78:caf0014375cb
Parent:
77:55788e619858
Child:
79:291df065e345
remove some headers, parse CREG URC

Who changed what in which revision?

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