support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets.

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

This library is intended to be used with u-blox products such as the C027 or a shield with u-blox cellular and GPS modules like the cellular and positioning shield from Embedded Artist.

For 2G/GSM and 3G/UMTS you need to:

  • have a SIM card and know its PIN number
  • need to know you network operators APN setting These setting should be passed to the connect or init and join functions. You can also extend the APN database in MDMAPN.h.

For CDMA products you need to make sure that you have provisioned and activated the modem with either Sprint or Verizon.

Committer:
mazgch
Date:
Mon May 12 13:58:47 2014 +0000
Revision:
57:869bd35f44cc
Parent:
56:3115ef44c771
Child:
58:e38a2e942fbb
simple connect api

Who changed what in which revision?

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