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 07:39:29 2014 +0000
Revision:
52:8071747a7cb3
Parent:
50:d76aece8038f
Child:
53:cb0d94b9de3a
Child:
54:7ba8e4c218e2
rename some constants to avoid issues with OK define in HttpClient

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