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:
Mon May 12 13:05:27 2014 +0000
Revision:
56:3115ef44c771
Parent:
55:e6cfbedfae8c
Child:
57:869bd35f44cc
disable debug

Who changed what in which revision?

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