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