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

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

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

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

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

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

Committer:
mazgch
Date:
Fri May 16 14:13:00 2014 +0000
Revision:
75:ce6e12067d0c
Parent:
74:208e3e32d263
Child:
76:f7c3dd568dae
minor tweaks

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