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 06:14:13 2014 +0000
Revision:
58:e38a2e942fbb
Parent:
57:869bd35f44cc
Child:
59:382695f1ce85
fix some timeouts

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