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

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

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

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

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

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

Committer:
mazgch
Date:
Tue May 13 12:31:33 2014 +0000
Revision:
63:42cb563a25bc
Parent:
59:382695f1ce85
Child:
64:ba4ea655a451
some progress on UDP

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