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:54:27 2014 +0000
Revision:
59:382695f1ce85
Parent:
58:e38a2e942fbb
Child:
61:eafa56058398
Child:
63:42cb563a25bc
some more LISA-C fixes

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 59:382695f1ce85 550 #if 0
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 59:382695f1ce85 555 #else
mazgch 59:382695f1ce85 556 return 0x01010101; // a fake IP
mazgch 59:382695f1ce85 557 #endif
mazgch 21:c4d64830bf02 558 } else {
mazgch 21:c4d64830bf02 559 // check gprs attach status
mazgch 21:c4d64830bf02 560 sendFormated("AT+CGATT?\r\n");
mazgch 52:8071747a7cb3 561 if (RESP_OK != waitFinalResp())
mazgch 31:a0bed6c1e05d 562 return NOIP;
mazgch 31:a0bed6c1e05d 563
mazgch 31:a0bed6c1e05d 564 // Check the profile
mazgch 31:a0bed6c1e05d 565 int a = 0;
mazgch 31:a0bed6c1e05d 566 sendFormated("AT+UPSND=" PROFILE ",8\r\n");
mazgch 52:8071747a7cb3 567 if (RESP_OK != waitFinalResp(_cbUPSND, &a))
mazgch 31:a0bed6c1e05d 568 return NOIP;
mazgch 31:a0bed6c1e05d 569 if (a == 1) {
mazgch 31:a0bed6c1e05d 570 // disconnect the profile already if it is connected
mazgch 31:a0bed6c1e05d 571 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 58:e38a2e942fbb 572 if (RESP_OK != waitFinalResp(NULL,NULL,40*1000))
mazgch 31:a0bed6c1e05d 573 return NOIP;;
mazgch 31:a0bed6c1e05d 574 }
mazgch 31:a0bed6c1e05d 575 // Set up the APN
mazgch 21:c4d64830bf02 576 if (apn) {
mazgch 21:c4d64830bf02 577 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
mazgch 52:8071747a7cb3 578 if (RESP_OK != waitFinalResp())
mazgch 31:a0bed6c1e05d 579 return NOIP;
mazgch 21:c4d64830bf02 580 }
mazgch 57:869bd35f44cc 581 if (username) {
mazgch 57:869bd35f44cc 582 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
mazgch 52:8071747a7cb3 583 if (RESP_OK != waitFinalResp())
mazgch 31:a0bed6c1e05d 584 return NOIP;
mazgch 21:c4d64830bf02 585 }
mazgch 21:c4d64830bf02 586 if (password) {
mazgch 21:c4d64830bf02 587 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
mazgch 52:8071747a7cb3 588 if (RESP_OK != waitFinalResp())
mazgch 31:a0bed6c1e05d 589 return NOIP;
mazgch 21:c4d64830bf02 590 }
mazgch 21:c4d64830bf02 591 // Set up the dynamic IP address assignment.
mazgch 21:c4d64830bf02 592 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
mazgch 52:8071747a7cb3 593 if (RESP_OK != waitFinalResp())
mazgch 31:a0bed6c1e05d 594 return NOIP;
mazgch 21:c4d64830bf02 595 // Activate the profile and make connection
mazgch 21:c4d64830bf02 596 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 58:e38a2e942fbb 597 if (RESP_OK != waitFinalResp(NULL,NULL,150*1000))
mazgch 31:a0bed6c1e05d 598 return NOIP;
mazgch 21:c4d64830bf02 599 //Get local IP address
mazgch 21:c4d64830bf02 600 sendFormated("AT+UPSND=" PROFILE ",0\r\n");
mazgch 52:8071747a7cb3 601 if (RESP_OK != waitFinalResp(_cbUPSND, &_ip))
mazgch 31:a0bed6c1e05d 602 return NOIP;
mazgch 31:a0bed6c1e05d 603 }
mazgch 32:8f12ac182bbb 604 return _ip;
mazgch 31:a0bed6c1e05d 605 }
mazgch 31:a0bed6c1e05d 606
mazgch 32:8f12ac182bbb 607 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip)
mazgch 32:8f12ac182bbb 608 {
mazgch 32:8f12ac182bbb 609 if ((type == TYPE_PLUS) && ip) {
mazgch 32:8f12ac182bbb 610 int a,b,c,d;
mazgch 32:8f12ac182bbb 611 if (sscanf(buf, "\r\n+CMIP: " IPSTR, &a,&b,&c,&d) == 4)
mazgch 32:8f12ac182bbb 612 *ip = IPADR(a,b,c,d);
mazgch 32:8f12ac182bbb 613 }
mazgch 32:8f12ac182bbb 614 return WAIT;
mazgch 32:8f12ac182bbb 615 }
mazgch 32:8f12ac182bbb 616
mazgch 31:a0bed6c1e05d 617 int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act)
mazgch 31:a0bed6c1e05d 618 {
mazgch 31:a0bed6c1e05d 619 if ((type == TYPE_PLUS) && act) {
mazgch 31:a0bed6c1e05d 620 if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1)
mazgch 31:a0bed6c1e05d 621 /*nothing*/;
mazgch 21:c4d64830bf02 622 }
mazgch 31:a0bed6c1e05d 623 return WAIT;
mazgch 31:a0bed6c1e05d 624 }
mazgch 31:a0bed6c1e05d 625
mazgch 31:a0bed6c1e05d 626 int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 627 {
mazgch 31:a0bed6c1e05d 628 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 629 int a,b,c,d;
mazgch 31:a0bed6c1e05d 630 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
mazgch 31:a0bed6c1e05d 631 if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 632 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 633 }
mazgch 31:a0bed6c1e05d 634 return WAIT;
mazgch 31:a0bed6c1e05d 635 }
mazgch 31:a0bed6c1e05d 636
mazgch 31:a0bed6c1e05d 637 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 638 {
mazgch 31:a0bed6c1e05d 639 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 640 int a,b,c,d;
mazgch 31:a0bed6c1e05d 641 if (sscanf(buf, "\r\n+UDNSRN: \""IPSTR"\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 642 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 643 }
mazgch 31:a0bed6c1e05d 644 return WAIT;
mazgch 21:c4d64830bf02 645 }
mazgch 21:c4d64830bf02 646
mazgch 21:c4d64830bf02 647 bool MDMParser::disconnect(void)
mazgch 21:c4d64830bf02 648 {
mazgch 31:a0bed6c1e05d 649 if (_ip == NOIP)
mazgch 21:c4d64830bf02 650 return true;
mazgch 32:8f12ac182bbb 651 if (_dev.dev == DEV_LISA_C200) {
mazgch 32:8f12ac182bbb 652 // TODO: is there something to do here?
mazgch 21:c4d64830bf02 653 } else {
mazgch 21:c4d64830bf02 654 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 52:8071747a7cb3 655 if (RESP_OK != waitFinalResp())
mazgch 32:8f12ac182bbb 656 return false;
mazgch 21:c4d64830bf02 657 }
mazgch 31:a0bed6c1e05d 658 _ip = NOIP;
mazgch 21:c4d64830bf02 659 return true;
mazgch 21:c4d64830bf02 660 }
mazgch 21:c4d64830bf02 661
mazgch 31:a0bed6c1e05d 662 MDMParser::IP MDMParser::gethostbyname(const char* host)
mazgch 21:c4d64830bf02 663 {
mazgch 31:a0bed6c1e05d 664 IP ip = NOIP;
mazgch 31:a0bed6c1e05d 665 int a,b,c,d;
mazgch 31:a0bed6c1e05d 666 if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 667 ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 668 else {
mazgch 31:a0bed6c1e05d 669 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host);
mazgch 52:8071747a7cb3 670 if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip))
mazgch 31:a0bed6c1e05d 671 return false;
mazgch 21:c4d64830bf02 672 }
mazgch 31:a0bed6c1e05d 673 return ip;
mazgch 21:c4d64830bf02 674 }
mazgch 21:c4d64830bf02 675
mazgch 21:c4d64830bf02 676 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 677 // sockets
mazgch 21:c4d64830bf02 678
mazgch 21:c4d64830bf02 679 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* socket)
mazgch 21:c4d64830bf02 680 {
mazgch 21:c4d64830bf02 681 if ((type == TYPE_PLUS) && socket) {
mazgch 21:c4d64830bf02 682 const char* p = strstr(buf,"+USOCR: ");
mazgch 21:c4d64830bf02 683 if (p)
mazgch 21:c4d64830bf02 684 *socket = atoi(p+8);
mazgch 21:c4d64830bf02 685 }
mazgch 21:c4d64830bf02 686 return WAIT;
mazgch 21:c4d64830bf02 687 }
mazgch 21:c4d64830bf02 688
mazgch 21:c4d64830bf02 689 int MDMParser::socketSocket(IpProtocol ipproto)
mazgch 21:c4d64830bf02 690 {
mazgch 47:9a89e5195721 691 TRACE("socketSocket(%d)\r\n", ipproto);
mazgch 21:c4d64830bf02 692 const char* cmd;
mazgch 21:c4d64830bf02 693 if(ipproto == IPPROTO_TCP) {
mazgch 21:c4d64830bf02 694 cmd = "AT+USOCR=6\r\n";
mazgch 21:c4d64830bf02 695 } else if(ipproto == IPPROTO_UDP) {
mazgch 21:c4d64830bf02 696 cmd = "AT+USOCR=17\r\n";
mazgch 21:c4d64830bf02 697 } else { // other types not supported
mazgch 21:c4d64830bf02 698 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 699 }
mazgch 21:c4d64830bf02 700 sendFormated(cmd);
mazgch 21:c4d64830bf02 701 int socket = -1;
mazgch 52:8071747a7cb3 702 if (RESP_OK != waitFinalResp(_cbUSOCR, &socket))
mazgch 21:c4d64830bf02 703 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 704 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_FREE))
mazgch 21:c4d64830bf02 705 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 706 // successfull
mazgch 21:c4d64830bf02 707 _sockets[socket].state = SOCK_CREATED;
mazgch 21:c4d64830bf02 708 _sockets[socket].pending = 0;
mazgch 44:9d12223b78ff 709 _sockets[socket].timeout_ms = 0; // non blocking
mazgch 21:c4d64830bf02 710 return socket;
mazgch 21:c4d64830bf02 711 }
mazgch 21:c4d64830bf02 712
mazgch 21:c4d64830bf02 713 bool MDMParser::socketConnect(int socket, const char * host, int port)
mazgch 21:c4d64830bf02 714 {
mazgch 47:9a89e5195721 715 TRACE("socketConnect(%d,%s,%d)\r\n", socket, host,port);
mazgch 31:a0bed6c1e05d 716 IP ip = gethostbyname(host);
mazgch 31:a0bed6c1e05d 717 if (ip == NOIP)
mazgch 21:c4d64830bf02 718 return false;
mazgch 21:c4d64830bf02 719 // connect to socket
mazgch 21:c4d64830bf02 720 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED))
mazgch 21:c4d64830bf02 721 return false;
mazgch 21:c4d64830bf02 722 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", socket, IPNUM(ip), port);
mazgch 52:8071747a7cb3 723 if (RESP_OK != waitFinalResp())
mazgch 21:c4d64830bf02 724 return false;
mazgch 21:c4d64830bf02 725 _sockets[socket].state = SOCK_CONNECTED;
mazgch 21:c4d64830bf02 726 return true;
mazgch 21:c4d64830bf02 727 }
mazgch 21:c4d64830bf02 728
mazgch 44:9d12223b78ff 729 bool MDMParser::socketIsConnected(int socket)
mazgch 44:9d12223b78ff 730 {
mazgch 47:9a89e5195721 731 TRACE("socketIsConnected(%d)\r\n", socket);
mazgch 47:9a89e5195721 732 if (!ISSOCKET(socket))
mazgch 47:9a89e5195721 733 return false;
mazgch 47:9a89e5195721 734 TRACE(" ... %d\r\n", _sockets[socket].state);
mazgch 47:9a89e5195721 735 return _sockets[socket].state == SOCK_CONNECTED;
mazgch 44:9d12223b78ff 736 }
mazgch 44:9d12223b78ff 737
mazgch 44:9d12223b78ff 738 bool MDMParser::socketSetBlocking(int socket, unsigned int timeout_ms)
mazgch 44:9d12223b78ff 739 {
mazgch 47:9a89e5195721 740 TRACE("socketSetBlocking(%d,%d)\r\n", socket, timeout_ms);
mazgch 44:9d12223b78ff 741 if (!ISSOCKET(socket))
mazgch 44:9d12223b78ff 742 return false;
mazgch 44:9d12223b78ff 743 _sockets[socket].timeout_ms = timeout_ms;
mazgch 44:9d12223b78ff 744 return true;
mazgch 44:9d12223b78ff 745 }
mazgch 44:9d12223b78ff 746
mazgch 21:c4d64830bf02 747 bool MDMParser::socketClose(int socket)
mazgch 21:c4d64830bf02 748 {
mazgch 47:9a89e5195721 749 TRACE("socketClose(%d)\r\n", socket);
mazgch 21:c4d64830bf02 750 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED))
mazgch 21:c4d64830bf02 751 return false;
mazgch 21:c4d64830bf02 752 sendFormated("AT+USOCL=%d\r\n", socket);
mazgch 52:8071747a7cb3 753 if (RESP_OK != waitFinalResp())
mazgch 21:c4d64830bf02 754 return false;
mazgch 44:9d12223b78ff 755 _sockets[socket].state = SOCK_CREATED;
mazgch 21:c4d64830bf02 756 return true;
mazgch 21:c4d64830bf02 757 }
mazgch 21:c4d64830bf02 758
mazgch 21:c4d64830bf02 759 bool MDMParser::socketFree(int socket)
mazgch 21:c4d64830bf02 760 {
mazgch 47:9a89e5195721 761 TRACE("socketFree(%d)\r\n", socket);
mazgch 21:c4d64830bf02 762 socketClose(socket);
mazgch 21:c4d64830bf02 763 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED))
mazgch 21:c4d64830bf02 764 return false;
mazgch 21:c4d64830bf02 765 _sockets[socket].state = SOCK_FREE;
mazgch 21:c4d64830bf02 766 return true;
mazgch 21:c4d64830bf02 767 }
mazgch 21:c4d64830bf02 768
mazgch 21:c4d64830bf02 769 int MDMParser::socketSend(int socket, const char * buf, int len)
mazgch 21:c4d64830bf02 770 {
mazgch 47:9a89e5195721 771 TRACE("socketSend(%d,,%d)\r\n", socket,len);
mazgch 21:c4d64830bf02 772 if(len > 0) {
mazgch 21:c4d64830bf02 773 sendFormated("AT+USOWR=%d,%d\r\n",socket,len);
mazgch 52:8071747a7cb3 774 if (RESP_PROMPT != waitFinalResp())
mazgch 21:c4d64830bf02 775 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 776 wait_ms(50);
mazgch 21:c4d64830bf02 777 send(buf, len);
mazgch 52:8071747a7cb3 778 if (RESP_OK != waitFinalResp())
mazgch 21:c4d64830bf02 779 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 780 }
mazgch 21:c4d64830bf02 781 return len;
mazgch 21:c4d64830bf02 782 }
mazgch 21:c4d64830bf02 783
mazgch 21:c4d64830bf02 784 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len)
mazgch 21:c4d64830bf02 785 {
mazgch 47:9a89e5195721 786 TRACE("socketSendTo(%d," IPSTR "%d,,%d)\r\n", socket, IPNUM(ip),port,len);
mazgch 21:c4d64830bf02 787 if(len > 0) {
mazgch 21:c4d64830bf02 788 sendFormated("AT+USOWR=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,len);
mazgch 52:8071747a7cb3 789 if (RESP_PROMPT != waitFinalResp())
mazgch 21:c4d64830bf02 790 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 791 wait_ms(50);
mazgch 21:c4d64830bf02 792 send(buf, len);
mazgch 52:8071747a7cb3 793 if (RESP_OK != waitFinalResp())
mazgch 21:c4d64830bf02 794 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 795 }
mazgch 21:c4d64830bf02 796 return len;
mazgch 21:c4d64830bf02 797 }
mazgch 21:c4d64830bf02 798
mazgch 21:c4d64830bf02 799 int MDMParser::socketReadable(int socket)
mazgch 21:c4d64830bf02 800 {
mazgch 47:9a89e5195721 801 TRACE("socketReadable(%d)\r\n", socket);
mazgch 21:c4d64830bf02 802 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED))
mazgch 21:c4d64830bf02 803 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 804 // allow to receive unsolicited commands
mazgch 21:c4d64830bf02 805 waitFinalResp(NULL, NULL, 0);
mazgch 21:c4d64830bf02 806 if (_sockets[socket].state != SOCK_CONNECTED)
mazgch 21:c4d64830bf02 807 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 808 return _sockets[socket].pending;
mazgch 21:c4d64830bf02 809 }
mazgch 21:c4d64830bf02 810
mazgch 21:c4d64830bf02 811 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out)
mazgch 21:c4d64830bf02 812 {
mazgch 21:c4d64830bf02 813 if ((type == TYPE_PLUS) && out) {
mazgch 21:c4d64830bf02 814 int sz, sk;
mazgch 21:c4d64830bf02 815 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) &&
mazgch 21:c4d64830bf02 816 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 817 memcpy(out, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 818 }
mazgch 21:c4d64830bf02 819 }
mazgch 21:c4d64830bf02 820 return WAIT;
mazgch 21:c4d64830bf02 821 }
mazgch 21:c4d64830bf02 822
mazgch 21:c4d64830bf02 823 int MDMParser::socketRecv(int socket, char* buf, int len)
mazgch 21:c4d64830bf02 824 {
mazgch 21:c4d64830bf02 825 int cnt = 0;
mazgch 47:9a89e5195721 826 TRACE("socketRecv(%d,,%d)\r\n", socket, len);
mazgch 21:c4d64830bf02 827 if (!ISSOCKET(socket))
mazgch 21:c4d64830bf02 828 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 829 memset(buf, '\0', len);
mazgch 44:9d12223b78ff 830 Timer timer;
mazgch 44:9d12223b78ff 831 timer.start();
mazgch 21:c4d64830bf02 832 while (len) {
mazgch 21:c4d64830bf02 833 int blk = MAX_SIZE - 64; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 834 if (_sockets[socket].pending < blk)
mazgch 21:c4d64830bf02 835 blk = _sockets[socket].pending;
mazgch 21:c4d64830bf02 836 if (len < blk) blk = len;
mazgch 21:c4d64830bf02 837 if (blk) {
mazgch 44:9d12223b78ff 838 sendFormated("AT+USORD=%d,%d\r\n",socket, blk);
mazgch 52:8071747a7cb3 839 if (RESP_OK != waitFinalResp(_cbUSORD, buf)) {
mazgch 44:9d12223b78ff 840 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 841 }
mazgch 21:c4d64830bf02 842 len -= blk;
mazgch 21:c4d64830bf02 843 cnt += blk;
mazgch 21:c4d64830bf02 844 buf += blk;
mazgch 21:c4d64830bf02 845 _sockets[socket].pending -= blk;
mazgch 44:9d12223b78ff 846 } else if ((_sockets[socket].state == SOCK_CONNECTED) && (
mazgch 44:9d12223b78ff 847 (_sockets[socket].timeout_ms == (unsigned int)-1 /* blocking */) ||
mazgch 44:9d12223b78ff 848 (timer.read_ms() < _sockets[socket].timeout_ms))){
mazgch 21:c4d64830bf02 849 // allow to receive unsolicited commands
mazgch 21:c4d64830bf02 850 waitFinalResp(NULL, NULL, 10);
mazgch 44:9d12223b78ff 851 } else {
mazgch 44:9d12223b78ff 852 len = 0; // no more data and socket closed or timed-out
mazgch 21:c4d64830bf02 853 }
mazgch 21:c4d64830bf02 854 }
mazgch 58:e38a2e942fbb 855
mazgch 44:9d12223b78ff 856 timer.stop();
mazgch 44:9d12223b78ff 857 timer.reset();
mazgch 21:c4d64830bf02 858 return cnt;
mazgch 21:c4d64830bf02 859 }
mazgch 21:c4d64830bf02 860
mazgch 21:c4d64830bf02 861 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param)
mazgch 21:c4d64830bf02 862 {
mazgch 21:c4d64830bf02 863 if ((type == TYPE_PLUS) && param) {
mazgch 21:c4d64830bf02 864 int sz, sk, p, a,b,c,d;
mazgch 21:c4d64830bf02 865 if ((sscanf(buf, "\r\n+USORF: %d,\""IPSTR"\",%d,%d,",
mazgch 21:c4d64830bf02 866 &sk,&a,&b,&c,&d,&p,&sz) == 7) &&
mazgch 21:c4d64830bf02 867 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 868 memcpy(param->buf, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 869 param->ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 870 param->port = p;
mazgch 21:c4d64830bf02 871 }
mazgch 21:c4d64830bf02 872 }
mazgch 21:c4d64830bf02 873 return WAIT;
mazgch 21:c4d64830bf02 874 }
mazgch 21:c4d64830bf02 875
mazgch 21:c4d64830bf02 876 int MDMParser::socketRecvFrom(int socket, char* buf, int len, IP* ip)
mazgch 21:c4d64830bf02 877 {
mazgch 21:c4d64830bf02 878 int cnt = 0;
mazgch 47:9a89e5195721 879 TRACE("socketRecvFrom(%d,,%d" IPSTR ")\r\n", socket, len, IPNUM(*ip));
mazgch 21:c4d64830bf02 880 if (!ISSOCKET(socket))
mazgch 21:c4d64830bf02 881 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 882 memset(buf, '\0', len);
mazgch 44:9d12223b78ff 883 Timer timer;
mazgch 44:9d12223b78ff 884 timer.start();
mazgch 21:c4d64830bf02 885 while (len) {
mazgch 21:c4d64830bf02 886 int blk = MAX_SIZE - 64; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 887 if (_sockets[socket].pending < blk)
mazgch 21:c4d64830bf02 888 blk = _sockets[socket].pending;
mazgch 21:c4d64830bf02 889 if (len < blk) blk = len;
mazgch 21:c4d64830bf02 890 if (blk) {
mazgch 21:c4d64830bf02 891 sendFormated("AT+USORF=%d,%d\r\n",socket, blk);
mazgch 21:c4d64830bf02 892 USORFparam param;
mazgch 21:c4d64830bf02 893 param.buf = buf;
mazgch 52:8071747a7cb3 894 if (RESP_OK != waitFinalResp(_cbUSORF, &param)) {
mazgch 44:9d12223b78ff 895 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 896 }
mazgch 21:c4d64830bf02 897 *ip = param.ip;
mazgch 21:c4d64830bf02 898 //*port = param.port;
mazgch 21:c4d64830bf02 899 len -= blk;
mazgch 21:c4d64830bf02 900 cnt += blk;
mazgch 21:c4d64830bf02 901 buf += blk;
mazgch 21:c4d64830bf02 902 _sockets[socket].pending -= blk;
mazgch 44:9d12223b78ff 903 } else if ((_sockets[socket].state == SOCK_CONNECTED) && (
mazgch 44:9d12223b78ff 904 (_sockets[socket].timeout_ms == (unsigned int)-1 /* blocking */) ||
mazgch 44:9d12223b78ff 905 (timer.read_ms() < _sockets[socket].timeout_ms))){
mazgch 21:c4d64830bf02 906 // allow to receive unsolicited commands
mazgch 21:c4d64830bf02 907 waitFinalResp(NULL, NULL, 10);
mazgch 44:9d12223b78ff 908 } else {
mazgch 44:9d12223b78ff 909 len = 0; // no more data and socket closed or timed-out
mazgch 21:c4d64830bf02 910 }
mazgch 21:c4d64830bf02 911 }
mazgch 44:9d12223b78ff 912 timer.stop();
mazgch 44:9d12223b78ff 913 timer.reset();
mazgch 21:c4d64830bf02 914 return cnt;
mazgch 21:c4d64830bf02 915 }
mazgch 21:c4d64830bf02 916
mazgch 21:c4d64830bf02 917 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 918
mazgch 31:a0bed6c1e05d 919 int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param)
mazgch 21:c4d64830bf02 920 {
mazgch 31:a0bed6c1e05d 921 if ((type == TYPE_PLUS) && param && param->num) {
mazgch 31:a0bed6c1e05d 922 // +CMGL: <ix>,...
mazgch 31:a0bed6c1e05d 923 int ix;
mazgch 31:a0bed6c1e05d 924 if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1)
mazgch 31:a0bed6c1e05d 925 {
mazgch 31:a0bed6c1e05d 926 *param->ix++ = ix;
mazgch 31:a0bed6c1e05d 927 param->num--;
mazgch 31:a0bed6c1e05d 928 }
mazgch 29:53d346010624 929 }
mazgch 29:53d346010624 930 return WAIT;
mazgch 21:c4d64830bf02 931 }
mazgch 21:c4d64830bf02 932
mazgch 31:a0bed6c1e05d 933 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) {
mazgch 31:a0bed6c1e05d 934 sendFormated("AT+CMGL=\"%s\"\r\n", stat);
mazgch 31:a0bed6c1e05d 935 CMGLparam param;
mazgch 31:a0bed6c1e05d 936 param.ix = ix;
mazgch 31:a0bed6c1e05d 937 param.num = num;
mazgch 52:8071747a7cb3 938 if (RESP_OK != waitFinalResp(_cbCMGL, &param))
mazgch 31:a0bed6c1e05d 939 return -1;
mazgch 31:a0bed6c1e05d 940 return num - param.num;
mazgch 21:c4d64830bf02 941 }
mazgch 21:c4d64830bf02 942
mazgch 21:c4d64830bf02 943 bool MDMParser::smsSend(const char* num, const char* buf)
mazgch 21:c4d64830bf02 944 {
mazgch 21:c4d64830bf02 945 sendFormated("AT+CMGS=\"%s\"\r",num);
mazgch 58:e38a2e942fbb 946 if (RESP_PROMPT != waitFinalResp(NULL,NULL,150*1000)) {
mazgch 21:c4d64830bf02 947 return false;
mazgch 21:c4d64830bf02 948 }
mazgch 21:c4d64830bf02 949 send(buf, strlen(buf));
mazgch 21:c4d64830bf02 950 const char ctrlZ = 0x1A;
mazgch 21:c4d64830bf02 951 send(&ctrlZ, sizeof(ctrlZ));
mazgch 52:8071747a7cb3 952 if (RESP_OK != waitFinalResp()) {
mazgch 21:c4d64830bf02 953 return false;
mazgch 21:c4d64830bf02 954 }
mazgch 21:c4d64830bf02 955 return true;
mazgch 21:c4d64830bf02 956 }
mazgch 21:c4d64830bf02 957
mazgch 21:c4d64830bf02 958 bool MDMParser::smsDelete(int ix)
mazgch 21:c4d64830bf02 959 {
mazgch 21:c4d64830bf02 960 sendFormated("AT+CMGD=%d\r\n",ix);
mazgch 52:8071747a7cb3 961 if (RESP_OK != waitFinalResp()) {
mazgch 21:c4d64830bf02 962 return false;
mazgch 21:c4d64830bf02 963 }
mazgch 21:c4d64830bf02 964 return true;
mazgch 21:c4d64830bf02 965 }
mazgch 21:c4d64830bf02 966
mazgch 21:c4d64830bf02 967 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param)
mazgch 21:c4d64830bf02 968 {
mazgch 21:c4d64830bf02 969 if (param) {
mazgch 21:c4d64830bf02 970 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 971 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) {
mazgch 21:c4d64830bf02 972 }
mazgch 37:cc3433329d66 973 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) {
mazgch 21:c4d64830bf02 974 memcpy(param->buf, buf, len-2);
mazgch 21:c4d64830bf02 975 param->buf[len-2] = '\0';
mazgch 21:c4d64830bf02 976 }
mazgch 21:c4d64830bf02 977 }
mazgch 21:c4d64830bf02 978 return WAIT;
mazgch 21:c4d64830bf02 979 }
mazgch 21:c4d64830bf02 980
mazgch 21:c4d64830bf02 981 bool MDMParser::smsRead(int ix, char* num, char* buf, int len)
mazgch 21:c4d64830bf02 982 {
mazgch 21:c4d64830bf02 983 CMGRparam param;
mazgch 21:c4d64830bf02 984 param.num = num;
mazgch 21:c4d64830bf02 985 param.buf = buf;
mazgch 21:c4d64830bf02 986 sendFormated("AT+CMGR=%d\r\n",ix);
mazgch 52:8071747a7cb3 987 if (RESP_OK != waitFinalResp(_cbCMGR, &param)) {
mazgch 21:c4d64830bf02 988 return false;
mazgch 21:c4d64830bf02 989 }
mazgch 21:c4d64830bf02 990 return true;
mazgch 21:c4d64830bf02 991 }
mazgch 54:7ba8e4c218e2 992
mazgch 54:7ba8e4c218e2 993 // ----------------------------------------------------------------
mazgch 54:7ba8e4c218e2 994
mazgch 54:7ba8e4c218e2 995 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status)
mazgch 54:7ba8e4c218e2 996 {
mazgch 57:869bd35f44cc 997 printf("Modem Device Status:\r\n");
mazgch 54:7ba8e4c218e2 998 const char* txtDev[] = { "Unknown", "SARA-G350", "LISA-U200", "LISA-C200" };
mazgch 54:7ba8e4c218e2 999 if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != MDMParser::DEV_UNKNOWN))
mazgch 54:7ba8e4c218e2 1000 printf(" Device: %s\r\n", txtDev[status->dev]);
mazgch 54:7ba8e4c218e2 1001 const char* txtLpm[] = { "Disabled", "Enabled", "Active" };
mazgch 54:7ba8e4c218e2 1002 if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm))
mazgch 54:7ba8e4c218e2 1003 printf(" Power Save: %s\r\n", txtLpm[status->lpm]);
mazgch 54:7ba8e4c218e2 1004 const char* txtSim[] = { "Unknown", "Pin", "Ready" };
mazgch 54:7ba8e4c218e2 1005 if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != MDMParser::SIM_UNKNOWN))
mazgch 54:7ba8e4c218e2 1006 printf(" SIM: %s\r\n", txtSim[status->sim]);
mazgch 54:7ba8e4c218e2 1007 if (*status->ccid)
mazgch 54:7ba8e4c218e2 1008 printf(" CCID: %s\r\n", status->ccid);
mazgch 54:7ba8e4c218e2 1009 if (*status->imei)
mazgch 54:7ba8e4c218e2 1010 printf(" IMEI: %s\r\n", status->imei);
mazgch 54:7ba8e4c218e2 1011 if (*status->imsi)
mazgch 54:7ba8e4c218e2 1012 printf(" IMSI: %s\r\n", status->imsi);
mazgch 54:7ba8e4c218e2 1013 if (*status->meid)
mazgch 54:7ba8e4c218e2 1014 printf(" MEID: %s\r\n", status->meid); // LISA-C
mazgch 54:7ba8e4c218e2 1015 if (*status->manu)
mazgch 54:7ba8e4c218e2 1016 printf(" Manufacturer: %s\r\n", status->manu);
mazgch 54:7ba8e4c218e2 1017 if (*status->model)
mazgch 54:7ba8e4c218e2 1018 printf(" Model: %s\r\n", status->model);
mazgch 54:7ba8e4c218e2 1019 if (*status->ver)
mazgch 54:7ba8e4c218e2 1020 printf(" Version: %s\r\n", status->ver);
mazgch 54:7ba8e4c218e2 1021 }
mazgch 54:7ba8e4c218e2 1022
mazgch 54:7ba8e4c218e2 1023 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status)
mazgch 54:7ba8e4c218e2 1024 {
mazgch 57:869bd35f44cc 1025 printf("Modem Network Status:\r\n");
mazgch 54:7ba8e4c218e2 1026 const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" };
mazgch 54:7ba8e4c218e2 1027 if (status->reg < sizeof(txtReg)/sizeof(*txtReg) && (status->reg != MDMParser::REG_UNKNOWN))
mazgch 54:7ba8e4c218e2 1028 printf(" Registration: %s\r\n", txtReg[status->reg]);
mazgch 54:7ba8e4c218e2 1029 const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA" };
mazgch 54:7ba8e4c218e2 1030 if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != MDMParser::ACT_UNKNOWN))
mazgch 54:7ba8e4c218e2 1031 printf(" Access Technology: %s\r\n", txtAct[status->act]);
mazgch 54:7ba8e4c218e2 1032 if (status->rssi)
mazgch 54:7ba8e4c218e2 1033 printf(" Signal Strength: %d dBm\r\n", status->rssi);
mazgch 54:7ba8e4c218e2 1034 if (status->ber)
mazgch 54:7ba8e4c218e2 1035 printf(" Bit Error Rate: %d\r\n", status->ber);
mazgch 54:7ba8e4c218e2 1036 if (*status->opr)
mazgch 54:7ba8e4c218e2 1037 printf(" Operator: %s\r\n", status->opr);
mazgch 54:7ba8e4c218e2 1038 if (status->lac != 0xFFFF)
mazgch 54:7ba8e4c218e2 1039 printf(" Location Area Code: %04X\r\n", status->lac);
mazgch 54:7ba8e4c218e2 1040 if (status->ci != 0xFFFFFFFF)
mazgch 54:7ba8e4c218e2 1041 printf(" Cell ID: %08X\r\n", status->ci);
mazgch 54:7ba8e4c218e2 1042 if (*status->num)
mazgch 54:7ba8e4c218e2 1043 printf(" Phone Number: %s\r\n", status->num);
mazgch 54:7ba8e4c218e2 1044 }
mazgch 54:7ba8e4c218e2 1045
mazgch 54:7ba8e4c218e2 1046 void MDMParser::dumpIp(MDMParser::IP ip)
mazgch 54:7ba8e4c218e2 1047 {
mazgch 57:869bd35f44cc 1048 if (ip != NOIP)
mazgch 57:869bd35f44cc 1049 printf("Modem IP Address: " IPSTR "\r\n", IPNUM(ip));
mazgch 54:7ba8e4c218e2 1050 }
mazgch 54:7ba8e4c218e2 1051
mazgch 21:c4d64830bf02 1052 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 1053
mazgch 21:c4d64830bf02 1054 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp)
mazgch 21:c4d64830bf02 1055 {
mazgch 21:c4d64830bf02 1056 if ((type == TYPE_PLUS) && resp) {
mazgch 21:c4d64830bf02 1057 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..);
mazgch 21:c4d64830bf02 1058 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) {
mazgch 21:c4d64830bf02 1059 /*nothing*/
mazgch 21:c4d64830bf02 1060 }
mazgch 21:c4d64830bf02 1061 }
mazgch 21:c4d64830bf02 1062 return WAIT;
mazgch 21:c4d64830bf02 1063 }
mazgch 31:a0bed6c1e05d 1064
mazgch 31:a0bed6c1e05d 1065 bool MDMParser::ussdCommand(const char* cmd, char* buf)
mazgch 21:c4d64830bf02 1066 {
mazgch 21:c4d64830bf02 1067 *buf = '\0';
mazgch 21:c4d64830bf02 1068 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
mazgch 52:8071747a7cb3 1069 if (RESP_OK != waitFinalResp(_cbCUSD, buf)) {
mazgch 31:a0bed6c1e05d 1070 return false;
mazgch 21:c4d64830bf02 1071 }
mazgch 31:a0bed6c1e05d 1072 return true;
mazgch 21:c4d64830bf02 1073 }
mazgch 26:07be5faf8925 1074
mazgch 21:c4d64830bf02 1075 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 1076 int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end)
mazgch 18:e5697801df29 1077 {
mazgch 18:e5697801df29 1078 int o = 0;
mazgch 21:c4d64830bf02 1079 if (sta) {
mazgch 21:c4d64830bf02 1080 while (*sta) {
mazgch 21:c4d64830bf02 1081 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1082 char ch = pipe->next();
mazgch 21:c4d64830bf02 1083 if (*sta++ != ch) return NOT_FOUND;
mazgch 21:c4d64830bf02 1084 }
mazgch 21:c4d64830bf02 1085 }
mazgch 21:c4d64830bf02 1086 if (!end) return o; // no termination
mazgch 35:9275215a3a5b 1087 // at least any char
mazgch 35:9275215a3a5b 1088 if (++o > len) return WAIT;
mazgch 35:9275215a3a5b 1089 pipe->next();
mazgch 35:9275215a3a5b 1090 // check the end
mazgch 21:c4d64830bf02 1091 int x = 0;
mazgch 21:c4d64830bf02 1092 while (end[x]) {
mazgch 21:c4d64830bf02 1093 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1094 char ch = pipe->next();
mazgch 21:c4d64830bf02 1095 x = (end[x] == ch) ? x + 1 :
mazgch 21:c4d64830bf02 1096 (end[0] == ch) ? 1 :
mazgch 21:c4d64830bf02 1097 0;
mazgch 21:c4d64830bf02 1098 }
mazgch 21:c4d64830bf02 1099 return o;
mazgch 21:c4d64830bf02 1100 }
mazgch 21:c4d64830bf02 1101
mazgch 21:c4d64830bf02 1102 int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt)
mazgch 21:c4d64830bf02 1103 {
mazgch 21:c4d64830bf02 1104 int o = 0;
mazgch 21:c4d64830bf02 1105 int num = 0;
mazgch 21:c4d64830bf02 1106 if (fmt) {
mazgch 21:c4d64830bf02 1107 while (*fmt) {
mazgch 21:c4d64830bf02 1108 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1109 char ch = pipe->next();
mazgch 21:c4d64830bf02 1110 if (*fmt == '%') {
mazgch 21:c4d64830bf02 1111 fmt++;
mazgch 21:c4d64830bf02 1112 if (*fmt == 'd') { // numeric
mazgch 21:c4d64830bf02 1113 fmt ++;
mazgch 21:c4d64830bf02 1114 num = 0;
mazgch 21:c4d64830bf02 1115 while (ch >= '0' && ch <= '9') {
mazgch 21:c4d64830bf02 1116 num = num * 10 + (ch - '0');
mazgch 21:c4d64830bf02 1117 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1118 ch = pipe->next();
mazgch 21:c4d64830bf02 1119 }
mazgch 21:c4d64830bf02 1120 }
mazgch 21:c4d64830bf02 1121 else if (*fmt == 'c') { // char buffer (takes last numeric as length)
mazgch 21:c4d64830bf02 1122 fmt ++;
mazgch 21:c4d64830bf02 1123 while (num --) {
mazgch 21:c4d64830bf02 1124 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1125 ch = pipe->next();
mazgch 21:c4d64830bf02 1126 }
mazgch 21:c4d64830bf02 1127 }
mazgch 21:c4d64830bf02 1128 }
mazgch 21:c4d64830bf02 1129 if (*fmt++ != ch) return NOT_FOUND;
mazgch 18:e5697801df29 1130 }
mazgch 18:e5697801df29 1131 }
mazgch 21:c4d64830bf02 1132 return o;
mazgch 21:c4d64830bf02 1133 }
mazgch 21:c4d64830bf02 1134
mazgch 21:c4d64830bf02 1135
mazgch 21:c4d64830bf02 1136 int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len)
mazgch 21:c4d64830bf02 1137 {
mazgch 21:c4d64830bf02 1138 int unkn = 0;
mazgch 21:c4d64830bf02 1139 int sz = pipe->size();
mazgch 21:c4d64830bf02 1140 int fr = pipe->free();
mazgch 21:c4d64830bf02 1141 if (len > sz)
mazgch 21:c4d64830bf02 1142 len = sz;
mazgch 21:c4d64830bf02 1143 while (len > 0)
mazgch 21:c4d64830bf02 1144 {
mazgch 21:c4d64830bf02 1145 static struct {
mazgch 21:c4d64830bf02 1146 const char* fmt; int type;
mazgch 21:c4d64830bf02 1147 } lutF[] = {
mazgch 21:c4d64830bf02 1148 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS },
mazgch 21:c4d64830bf02 1149 { "\r\n+USORF: %d,\""IPSTR"\",%d,%d,\"%c\"", TYPE_PLUS },
mazgch 21:c4d64830bf02 1150 };
mazgch 21:c4d64830bf02 1151 static struct {
mazgch 21:c4d64830bf02 1152 const char* sta; const char* end; int type;
mazgch 21:c4d64830bf02 1153 } lut[] = {
mazgch 21:c4d64830bf02 1154 { "\r\nOK\r\n", NULL, TYPE_OK },
mazgch 21:c4d64830bf02 1155 { "\r\nERROR\r\n", NULL, TYPE_ERROR },
mazgch 31:a0bed6c1e05d 1156 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 1157 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 1158 { "\r\nRING\r\n", NULL, TYPE_RING },
mazgch 21:c4d64830bf02 1159 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT },
mazgch 21:c4d64830bf02 1160 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER },
mazgch 21:c4d64830bf02 1161 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE },
mazgch 21:c4d64830bf02 1162 { "\r\nBUSY\r\n", NULL, TYPE_BUSY },
mazgch 21:c4d64830bf02 1163 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER },
mazgch 21:c4d64830bf02 1164 { "\r\n+", "\r\n", TYPE_PLUS },
mazgch 21:c4d64830bf02 1165 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets
mazgch 21:c4d64830bf02 1166 { "\r\n>", NULL, TYPE_PROMPT }, // SMS
mazgch 21:c4d64830bf02 1167 };
mazgch 21:c4d64830bf02 1168 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) {
mazgch 21:c4d64830bf02 1169 pipe->set(unkn);
mazgch 21:c4d64830bf02 1170 int ln = _parseFormated(pipe, len, lutF[i].fmt);
mazgch 21:c4d64830bf02 1171 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 1172 return WAIT;
mazgch 21:c4d64830bf02 1173 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 1174 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 1175 if (ln > 0)
mazgch 21:c4d64830bf02 1176 return lutF[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 1177 }
mazgch 21:c4d64830bf02 1178 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) {
mazgch 21:c4d64830bf02 1179 pipe->set(unkn);
mazgch 21:c4d64830bf02 1180 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end);
mazgch 21:c4d64830bf02 1181 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 1182 return WAIT;
mazgch 21:c4d64830bf02 1183 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 1184 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 1185 if (ln > 0)
mazgch 21:c4d64830bf02 1186 return lut[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 1187 }
mazgch 21:c4d64830bf02 1188 // UNKNOWN
mazgch 21:c4d64830bf02 1189 unkn ++;
mazgch 21:c4d64830bf02 1190 len--;
mazgch 21:c4d64830bf02 1191 }
mazgch 18:e5697801df29 1192 return WAIT;
mazgch 18:e5697801df29 1193 }
mazgch 18:e5697801df29 1194
mazgch 18:e5697801df29 1195 // ----------------------------------------------------------------
mazgch 18:e5697801df29 1196 // Serial Implementation
mazgch 18:e5697801df29 1197 // ----------------------------------------------------------------
mazgch 18:e5697801df29 1198
mazgch 19:2b5d097ca15d 1199 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/,
mazgch 19:2b5d097ca15d 1200 int baudrate /*= MDMBAUD*/,
mazgch 43:a89a7a505991 1201 #if DEVICE_SERIAL_FC
mazgch 19:2b5d097ca15d 1202 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/,
mazgch 43:a89a7a505991 1203 #endif
mazgch 18:e5697801df29 1204 int rxSize /*= 256*/, int txSize /*= 128*/) :
mazgch 35:9275215a3a5b 1205 SerialPipe(tx, rx, rxSize, txSize)
mazgch 18:e5697801df29 1206 {
mazgch 18:e5697801df29 1207 baud(baudrate);
mazgch 35:9275215a3a5b 1208 #if DEVICE_SERIAL_FC
mazgch 35:9275215a3a5b 1209 if ((rts != NC) || (cts != NC))
mazgch 35:9275215a3a5b 1210 {
mazgch 35:9275215a3a5b 1211 Flow flow = (cts == NC) ? RTS :
mazgch 35:9275215a3a5b 1212 (rts == NC) ? CTS : RTSCTS ;
mazgch 35:9275215a3a5b 1213 set_flow_control(flow, rts, cts);
mazgch 35:9275215a3a5b 1214 if (cts != NC) _dev.lpm = LPM_ENABLED;
mazgch 35:9275215a3a5b 1215 }
mazgch 35:9275215a3a5b 1216 #endif
mazgch 18:e5697801df29 1217 }
mazgch 18:e5697801df29 1218
mazgch 18:e5697801df29 1219 int MDMSerial::_send(const void* buf, int len)
mazgch 18:e5697801df29 1220 {
mazgch 35:9275215a3a5b 1221 return put((const char*)buf, len, true/*=blocking*/);
mazgch 18:e5697801df29 1222 }
mazgch 18:e5697801df29 1223
mazgch 18:e5697801df29 1224 int MDMSerial::getLine(char* buffer, int length)
mazgch 18:e5697801df29 1225 {
mazgch 18:e5697801df29 1226 return _getLine(&_pipeRx, buffer, length);
mazgch 18:e5697801df29 1227 }
mazgch 18:e5697801df29 1228
mazgch 18:e5697801df29 1229 // ----------------------------------------------------------------
mazgch 18:e5697801df29 1230 // USB Implementation
mazgch 18:e5697801df29 1231 // ----------------------------------------------------------------
mazgch 18:e5697801df29 1232
mazgch 18:e5697801df29 1233 #ifdef HAVE_MDMUSB
mazgch 18:e5697801df29 1234 // TODO properly implement with USB
mazgch 18:e5697801df29 1235 MDMUsb::MDMUsb(void) { }
mazgch 18:e5697801df29 1236 int MDMUsb::_send(const void* buf, int len) { return len; }
mazgch 18:e5697801df29 1237 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; }
mazgch 35:9275215a3a5b 1238 #endif