Axeda demo software for u-blox C027 (GSM)

Dependencies:   mbed

Committer:
AxedaCorp
Date:
Mon Aug 11 19:07:20 2014 +0000
Revision:
1:ff6d8adaf6b9
Parent:
0:a725e8eab383
Pointed to platform (prod)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AxedaCorp 0:a725e8eab383 1 #include "mbed.h"
AxedaCorp 0:a725e8eab383 2 #include "MDM.h"
AxedaCorp 0:a725e8eab383 3 #ifdef TARGET_UBLOX_C027
AxedaCorp 0:a725e8eab383 4 #include "C027_api.h"
AxedaCorp 0:a725e8eab383 5 #endif
AxedaCorp 0:a725e8eab383 6 #include "MDMAPN.h"
AxedaCorp 0:a725e8eab383 7
AxedaCorp 0:a725e8eab383 8 #define PROFILE "0" //!< this is the psd profile used
AxedaCorp 0:a725e8eab383 9 #define MAX_SIZE 128 //!< max expected messages
AxedaCorp 0:a725e8eab383 10 // num sockets
AxedaCorp 0:a725e8eab383 11 #define NUMSOCKETS (sizeof(_sockets)/sizeof(*_sockets))
AxedaCorp 0:a725e8eab383 12 //! test if it is a socket is ok to use
AxedaCorp 0:a725e8eab383 13 #define ISSOCKET(s) (((s) >= 0) && ((s) < NUMSOCKETS) && (_sockets[s].handle != SOCKET_ERROR))
AxedaCorp 0:a725e8eab383 14 //! check for timeout
AxedaCorp 0:a725e8eab383 15 #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms()))
AxedaCorp 0:a725e8eab383 16 //! registration ok check helper
AxedaCorp 0:a725e8eab383 17 #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING))
AxedaCorp 0:a725e8eab383 18 //! registration done check helper (no need to poll further)
AxedaCorp 0:a725e8eab383 19 #define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED))
AxedaCorp 0:a725e8eab383 20 //! helper to make sure that lock unlock pair is always balaced
AxedaCorp 0:a725e8eab383 21 #define LOCK() { lock()
AxedaCorp 0:a725e8eab383 22 //! helper to make sure that lock unlock pair is always balaced
AxedaCorp 0:a725e8eab383 23 #define UNLOCK() } unlock()
AxedaCorp 0:a725e8eab383 24
AxedaCorp 0:a725e8eab383 25 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 26 #if 1 // colored terminal output using ANSI escape sequences
AxedaCorp 0:a725e8eab383 27 #define COL(c) "\033[" c
AxedaCorp 0:a725e8eab383 28 #else
AxedaCorp 0:a725e8eab383 29 #define COL(c)
AxedaCorp 0:a725e8eab383 30 #endif
AxedaCorp 0:a725e8eab383 31 #define DEF COL("39m")
AxedaCorp 0:a725e8eab383 32 #define BLA COL("30m")
AxedaCorp 0:a725e8eab383 33 #define RED COL("31m")
AxedaCorp 0:a725e8eab383 34 #define GRE COL("32m")
AxedaCorp 0:a725e8eab383 35 #define YEL COL("33m")
AxedaCorp 0:a725e8eab383 36 #define BLU COL("34m")
AxedaCorp 0:a725e8eab383 37 #define MAG COL("35m")
AxedaCorp 0:a725e8eab383 38 #define CYA COL("36m")
AxedaCorp 0:a725e8eab383 39 #define WHY COL("37m")
AxedaCorp 0:a725e8eab383 40
AxedaCorp 0:a725e8eab383 41 void dumpAtCmd(const char* buf, int len)
AxedaCorp 0:a725e8eab383 42 {
AxedaCorp 0:a725e8eab383 43 ::printf(" %3d \"", len);
AxedaCorp 0:a725e8eab383 44 while (len --) {
AxedaCorp 0:a725e8eab383 45 char ch = *buf++;
AxedaCorp 0:a725e8eab383 46 if ((ch > 0x1F) && (ch != 0x7F)) { // is printable
AxedaCorp 0:a725e8eab383 47 if (ch == '%') ::printf("%%");
AxedaCorp 0:a725e8eab383 48 else if (ch == '"') ::printf("\\\"");
AxedaCorp 0:a725e8eab383 49 else if (ch == '\\') ::printf("\\\\");
AxedaCorp 0:a725e8eab383 50 else putchar(ch);
AxedaCorp 0:a725e8eab383 51 } else {
AxedaCorp 0:a725e8eab383 52 if (ch == '\a') ::printf("\\a"); // BEL (0x07)
AxedaCorp 0:a725e8eab383 53 else if (ch == '\b') ::printf("\\b"); // Backspace (0x08)
AxedaCorp 0:a725e8eab383 54 else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09)
AxedaCorp 0:a725e8eab383 55 else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A)
AxedaCorp 0:a725e8eab383 56 else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B)
AxedaCorp 0:a725e8eab383 57 else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C)
AxedaCorp 0:a725e8eab383 58 else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D)
AxedaCorp 0:a725e8eab383 59 else ::printf("\\x%02x", (unsigned char)ch);
AxedaCorp 0:a725e8eab383 60 }
AxedaCorp 0:a725e8eab383 61 }
AxedaCorp 0:a725e8eab383 62 ::printf("\"\r\n");
AxedaCorp 0:a725e8eab383 63 }
AxedaCorp 0:a725e8eab383 64
AxedaCorp 0:a725e8eab383 65 #define ERROR(...) (_debugLevel < 0) ? : ::printf(RED), ::printf(__VA_ARGS__), ::printf(DEF)
AxedaCorp 0:a725e8eab383 66 #define TEST(...) ::printf(CYA), ::printf(__VA_ARGS__), ::printf(DEF)
AxedaCorp 0:a725e8eab383 67 #define INFO(...) (_debugLevel < 1) ? : ::printf(GRE), ::printf(__VA_ARGS__), ::printf(DEF)
AxedaCorp 0:a725e8eab383 68 #define TRACE(...) (_debugLevel < 2) ? : ::printf(__VA_ARGS__)
AxedaCorp 0:a725e8eab383 69
AxedaCorp 0:a725e8eab383 70 #else
AxedaCorp 0:a725e8eab383 71
AxedaCorp 0:a725e8eab383 72 #define ERROR(...) (void)0 // no tracing
AxedaCorp 0:a725e8eab383 73 #define TEST(...) (void)0 // no tracing
AxedaCorp 0:a725e8eab383 74 #define INFO(...) (void)0 // no tracing
AxedaCorp 0:a725e8eab383 75 #define TRACE(...) (void)0 // no tracing
AxedaCorp 0:a725e8eab383 76
AxedaCorp 0:a725e8eab383 77 #endif
AxedaCorp 0:a725e8eab383 78
AxedaCorp 0:a725e8eab383 79 MDMParser* MDMParser::inst;
AxedaCorp 0:a725e8eab383 80
AxedaCorp 0:a725e8eab383 81 MDMParser::MDMParser(void)
AxedaCorp 0:a725e8eab383 82 {
AxedaCorp 0:a725e8eab383 83 inst = this;
AxedaCorp 0:a725e8eab383 84 memset(&_dev, 0, sizeof(_dev));
AxedaCorp 0:a725e8eab383 85 memset(&_net, 0, sizeof(_net));
AxedaCorp 0:a725e8eab383 86 _net.lac = 0xFFFF;
AxedaCorp 0:a725e8eab383 87 _net.ci = 0xFFFFFFFF;
AxedaCorp 0:a725e8eab383 88 _ip = NOIP;
AxedaCorp 0:a725e8eab383 89 _init = false;
AxedaCorp 0:a725e8eab383 90 memset(_sockets, 0, sizeof(_sockets));
AxedaCorp 0:a725e8eab383 91 for (int socket = 0; socket < NUMSOCKETS; socket ++)
AxedaCorp 0:a725e8eab383 92 _sockets[socket].handle = SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 93 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 94 _debugLevel = 1;
AxedaCorp 0:a725e8eab383 95 _debugTime.start();
AxedaCorp 0:a725e8eab383 96 #endif
AxedaCorp 0:a725e8eab383 97 }
AxedaCorp 0:a725e8eab383 98
AxedaCorp 0:a725e8eab383 99 int MDMParser::send(const char* buf, int len)
AxedaCorp 0:a725e8eab383 100 {
AxedaCorp 0:a725e8eab383 101 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 102 if (_debugLevel >= 3) {
AxedaCorp 0:a725e8eab383 103 ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001);
AxedaCorp 0:a725e8eab383 104 dumpAtCmd(buf,len);
AxedaCorp 0:a725e8eab383 105 }
AxedaCorp 0:a725e8eab383 106 #endif
AxedaCorp 0:a725e8eab383 107 return _send(buf, len);
AxedaCorp 0:a725e8eab383 108 }
AxedaCorp 0:a725e8eab383 109
AxedaCorp 0:a725e8eab383 110 int MDMParser::sendFormated(const char* format, ...) {
AxedaCorp 0:a725e8eab383 111 char buf[MAX_SIZE];
AxedaCorp 0:a725e8eab383 112 va_list args;
AxedaCorp 0:a725e8eab383 113 va_start(args, format);
AxedaCorp 0:a725e8eab383 114 int len = vsnprintf(buf,sizeof(buf), format, args);
AxedaCorp 0:a725e8eab383 115 va_end(args);
AxedaCorp 0:a725e8eab383 116 return send(buf, len);
AxedaCorp 0:a725e8eab383 117 }
AxedaCorp 0:a725e8eab383 118
AxedaCorp 0:a725e8eab383 119 int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/,
AxedaCorp 0:a725e8eab383 120 void* param /* = NULL*/,
AxedaCorp 0:a725e8eab383 121 int timeout_ms /*= 5000*/)
AxedaCorp 0:a725e8eab383 122 {
AxedaCorp 0:a725e8eab383 123 char buf[MAX_SIZE + 64 /* add some more space for framing */];
AxedaCorp 0:a725e8eab383 124 Timer timer;
AxedaCorp 0:a725e8eab383 125 timer.start();
AxedaCorp 0:a725e8eab383 126 do {
AxedaCorp 0:a725e8eab383 127 int ret = getLine(buf, sizeof(buf));
AxedaCorp 0:a725e8eab383 128 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 129 if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND))
AxedaCorp 0:a725e8eab383 130 {
AxedaCorp 0:a725e8eab383 131 int len = LENGTH(ret);
AxedaCorp 0:a725e8eab383 132 int type = TYPE(ret);
AxedaCorp 0:a725e8eab383 133 const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF :
AxedaCorp 0:a725e8eab383 134 (type == TYPE_TEXT) ? MAG "TXT" DEF :
AxedaCorp 0:a725e8eab383 135 (type == TYPE_OK ) ? GRE "OK " DEF :
AxedaCorp 0:a725e8eab383 136 (type == TYPE_ERROR) ? RED "ERR" DEF :
AxedaCorp 0:a725e8eab383 137 (type == TYPE_PLUS) ? CYA " + " DEF :
AxedaCorp 0:a725e8eab383 138 (type == TYPE_PROMPT) ? BLU " > " DEF :
AxedaCorp 0:a725e8eab383 139 "..." ;
AxedaCorp 0:a725e8eab383 140 ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
AxedaCorp 0:a725e8eab383 141 dumpAtCmd(buf, len);
AxedaCorp 0:a725e8eab383 142 }
AxedaCorp 0:a725e8eab383 143 #endif
AxedaCorp 0:a725e8eab383 144 if ((ret != WAIT) && (ret != NOT_FOUND))
AxedaCorp 0:a725e8eab383 145 {
AxedaCorp 0:a725e8eab383 146 int type = TYPE(ret);
AxedaCorp 0:a725e8eab383 147 // handle unsolicited commands here
AxedaCorp 0:a725e8eab383 148 if (type == TYPE_PLUS) {
AxedaCorp 0:a725e8eab383 149 const char* cmd = buf+3;
AxedaCorp 0:a725e8eab383 150 int a, b, c, d, r;
AxedaCorp 0:a725e8eab383 151 char s[32];
AxedaCorp 0:a725e8eab383 152
AxedaCorp 0:a725e8eab383 153 // SMS Command ---------------------------------
AxedaCorp 0:a725e8eab383 154 // +CNMI: <mem>,<index>
AxedaCorp 0:a725e8eab383 155 if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) {
AxedaCorp 0:a725e8eab383 156 TRACE("New SMS at index %d\r\n", a);
AxedaCorp 0:a725e8eab383 157 // Socket Specific Command ---------------------------------
AxedaCorp 0:a725e8eab383 158 // +UUSORD: <socket>,<length>
AxedaCorp 0:a725e8eab383 159 } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2)) {
AxedaCorp 0:a725e8eab383 160 int socket = _findSocket(a);
AxedaCorp 0:a725e8eab383 161 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
AxedaCorp 0:a725e8eab383 162 if (socket != SOCKET_ERROR)
AxedaCorp 0:a725e8eab383 163 _sockets[socket].pending = b;
AxedaCorp 0:a725e8eab383 164 // +UUSORF: <socket>,<length>
AxedaCorp 0:a725e8eab383 165 } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2)) {
AxedaCorp 0:a725e8eab383 166 int socket = _findSocket(a);
AxedaCorp 0:a725e8eab383 167 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
AxedaCorp 0:a725e8eab383 168 if (socket != SOCKET_ERROR)
AxedaCorp 0:a725e8eab383 169 _sockets[socket].pending = b;
AxedaCorp 0:a725e8eab383 170 // +UUSOCL: <socket>
AxedaCorp 0:a725e8eab383 171 } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1)) {
AxedaCorp 0:a725e8eab383 172 int socket = _findSocket(a);
AxedaCorp 0:a725e8eab383 173 TRACE("Socket %d: handle %d closed by remote host\r\n", socket, a);
AxedaCorp 0:a725e8eab383 174 if ((socket != SOCKET_ERROR) && _sockets[socket].connected)
AxedaCorp 0:a725e8eab383 175 _sockets[socket].connected = false;
AxedaCorp 0:a725e8eab383 176 }
AxedaCorp 0:a725e8eab383 177 if (_dev.dev == DEV_LISA_C200) {
AxedaCorp 0:a725e8eab383 178 // CDMA Specific -------------------------------------------
AxedaCorp 0:a725e8eab383 179 // +CREG: <n><SID>,<NID>,<stat>
AxedaCorp 0:a725e8eab383 180 if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) {
AxedaCorp 0:a725e8eab383 181 // _net.sid = a;
AxedaCorp 0:a725e8eab383 182 // _net.nid = b;
AxedaCorp 0:a725e8eab383 183 if (c == 0) _net.csd = REG_NONE; // not registered, home network
AxedaCorp 0:a725e8eab383 184 else if (c == 1) _net.csd = REG_HOME; // registered, home network
AxedaCorp 0:a725e8eab383 185 else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to
AxedaCorp 0:a725e8eab383 186 else if (c == 3) _net.csd = REG_DENIED; // registration denied
AxedaCorp 0:a725e8eab383 187 else if (c == 5) _net.csd = REG_ROAMING; // registered, roaming
AxedaCorp 0:a725e8eab383 188 _net.psd = _net.csd; // fake PSD registration (CDMA is always registered)
AxedaCorp 0:a725e8eab383 189 _net.act = ACT_CDMA;
AxedaCorp 0:a725e8eab383 190 // +CSS: <mode>[,<format>,<oper>[,<AcT>]]
AxedaCorp 0:a725e8eab383 191 } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) {
AxedaCorp 0:a725e8eab383 192 //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME;
AxedaCorp 0:a725e8eab383 193 }
AxedaCorp 0:a725e8eab383 194 } else {
AxedaCorp 0:a725e8eab383 195 // GSM/UMTS Specific -------------------------------------------
AxedaCorp 0:a725e8eab383 196 // +UUPSDD: <profile_id>
AxedaCorp 0:a725e8eab383 197 if (sscanf(cmd, "UUPSDD: %d",&a) == 1) {
AxedaCorp 0:a725e8eab383 198 if (*PROFILE == a) _ip = NOIP;
AxedaCorp 0:a725e8eab383 199 } else {
AxedaCorp 0:a725e8eab383 200 // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG
AxedaCorp 0:a725e8eab383 201 // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC
AxedaCorp 0:a725e8eab383 202 b = 0xFFFF; c = 0xFFFFFFFF; d = -1;
AxedaCorp 0:a725e8eab383 203 r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
AxedaCorp 0:a725e8eab383 204 if (r <= 1)
AxedaCorp 0:a725e8eab383 205 r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
AxedaCorp 0:a725e8eab383 206 if (r >= 2) {
AxedaCorp 0:a725e8eab383 207 Reg *reg = !strcmp(s, "CREG:") ? &_net.csd :
AxedaCorp 0:a725e8eab383 208 !strcmp(s, "CGREG:") ? &_net.psd : NULL;
AxedaCorp 0:a725e8eab383 209 if (reg) {
AxedaCorp 0:a725e8eab383 210 // network status
AxedaCorp 0:a725e8eab383 211 if (a == 0) *reg = REG_NONE; // 0: not registered, home network
AxedaCorp 0:a725e8eab383 212 else if (a == 1) *reg = REG_HOME; // 1: registered, home network
AxedaCorp 0:a725e8eab383 213 else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to
AxedaCorp 0:a725e8eab383 214 else if (a == 3) *reg = REG_DENIED; // 3: registration denied
AxedaCorp 0:a725e8eab383 215 else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown
AxedaCorp 0:a725e8eab383 216 else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming
AxedaCorp 0:a725e8eab383 217 if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code
AxedaCorp 0:a725e8eab383 218 if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID
AxedaCorp 0:a725e8eab383 219 // access technology
AxedaCorp 0:a725e8eab383 220 if (r >= 5) {
AxedaCorp 0:a725e8eab383 221 if (d == 0) _net.act = ACT_GSM; // 0: GSM
AxedaCorp 0:a725e8eab383 222 else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT
AxedaCorp 0:a725e8eab383 223 else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN
AxedaCorp 0:a725e8eab383 224 else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability
AxedaCorp 0:a725e8eab383 225 else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability
AxedaCorp 0:a725e8eab383 226 else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability
AxedaCorp 0:a725e8eab383 227 else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability
AxedaCorp 0:a725e8eab383 228 }
AxedaCorp 0:a725e8eab383 229 }
AxedaCorp 0:a725e8eab383 230 }
AxedaCorp 0:a725e8eab383 231 }
AxedaCorp 0:a725e8eab383 232 }
AxedaCorp 0:a725e8eab383 233 }
AxedaCorp 0:a725e8eab383 234 if (cb) {
AxedaCorp 0:a725e8eab383 235 int len = LENGTH(ret);
AxedaCorp 0:a725e8eab383 236 int ret = cb(type, buf, len, param);
AxedaCorp 0:a725e8eab383 237 if (WAIT != ret)
AxedaCorp 0:a725e8eab383 238 return ret;
AxedaCorp 0:a725e8eab383 239 }
AxedaCorp 0:a725e8eab383 240 if (type == TYPE_OK)
AxedaCorp 0:a725e8eab383 241 return RESP_OK;
AxedaCorp 0:a725e8eab383 242 if (type == TYPE_ERROR)
AxedaCorp 0:a725e8eab383 243 return RESP_ERROR;
AxedaCorp 0:a725e8eab383 244 if (type == TYPE_PROMPT)
AxedaCorp 0:a725e8eab383 245 return RESP_PROMPT;
AxedaCorp 0:a725e8eab383 246 }
AxedaCorp 0:a725e8eab383 247 // relax a bit
AxedaCorp 0:a725e8eab383 248 wait_ms(10);
AxedaCorp 0:a725e8eab383 249 }
AxedaCorp 0:a725e8eab383 250 while (!TIMEOUT(timer, timeout_ms));
AxedaCorp 0:a725e8eab383 251 return WAIT;
AxedaCorp 0:a725e8eab383 252 }
AxedaCorp 0:a725e8eab383 253
AxedaCorp 0:a725e8eab383 254 int MDMParser::_cbString(int type, const char* buf, int len, char* str)
AxedaCorp 0:a725e8eab383 255 {
AxedaCorp 0:a725e8eab383 256 if (str && (type == TYPE_UNKNOWN)) {
AxedaCorp 0:a725e8eab383 257 if (sscanf(buf, "\r\n%s\r\n", str) == 1)
AxedaCorp 0:a725e8eab383 258 /*nothing*/;
AxedaCorp 0:a725e8eab383 259 }
AxedaCorp 0:a725e8eab383 260 return WAIT;
AxedaCorp 0:a725e8eab383 261 }
AxedaCorp 0:a725e8eab383 262
AxedaCorp 0:a725e8eab383 263 int MDMParser::_cbInt(int type, const char* buf, int len, int* val)
AxedaCorp 0:a725e8eab383 264 {
AxedaCorp 0:a725e8eab383 265 if (val && (type == TYPE_UNKNOWN)) {
AxedaCorp 0:a725e8eab383 266 if (sscanf(buf, "\r\n%d\r\n", val) == 1)
AxedaCorp 0:a725e8eab383 267 /*nothing*/;
AxedaCorp 0:a725e8eab383 268 }
AxedaCorp 0:a725e8eab383 269 return WAIT;
AxedaCorp 0:a725e8eab383 270 }
AxedaCorp 0:a725e8eab383 271
AxedaCorp 0:a725e8eab383 272 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 273
AxedaCorp 0:a725e8eab383 274 bool MDMParser::connect(
AxedaCorp 0:a725e8eab383 275 const char* simpin,
AxedaCorp 0:a725e8eab383 276 const char* apn, const char* username,
AxedaCorp 0:a725e8eab383 277 const char* password, Auth auth,
AxedaCorp 0:a725e8eab383 278 PinName pn)
AxedaCorp 0:a725e8eab383 279 {
AxedaCorp 0:a725e8eab383 280 bool ok = init(simpin, NULL, pn);
AxedaCorp 0:a725e8eab383 281 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 282 if (_debugLevel >= 1) dumpDevStatus(&_dev);
AxedaCorp 0:a725e8eab383 283 #endif
AxedaCorp 0:a725e8eab383 284 if (!ok)
AxedaCorp 0:a725e8eab383 285 return false;
AxedaCorp 0:a725e8eab383 286 ok = registerNet();
AxedaCorp 0:a725e8eab383 287 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 288 if (_debugLevel >= 1) dumpNetStatus(&_net);
AxedaCorp 0:a725e8eab383 289 #endif
AxedaCorp 0:a725e8eab383 290 if (!ok)
AxedaCorp 0:a725e8eab383 291 return false;
AxedaCorp 0:a725e8eab383 292 IP ip = join(apn,username,password,auth);
AxedaCorp 0:a725e8eab383 293 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 294 if (_debugLevel >= 1) dumpIp(ip);
AxedaCorp 0:a725e8eab383 295 #endif
AxedaCorp 0:a725e8eab383 296 if (ip == NOIP)
AxedaCorp 0:a725e8eab383 297 return false;
AxedaCorp 0:a725e8eab383 298 return true;
AxedaCorp 0:a725e8eab383 299 }
AxedaCorp 0:a725e8eab383 300
AxedaCorp 0:a725e8eab383 301 bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn)
AxedaCorp 0:a725e8eab383 302 {
AxedaCorp 0:a725e8eab383 303 int i = 10;
AxedaCorp 0:a725e8eab383 304 LOCK();
AxedaCorp 0:a725e8eab383 305 memset(&_dev, 0, sizeof(_dev));
AxedaCorp 0:a725e8eab383 306 if (pn != NC) {
AxedaCorp 0:a725e8eab383 307 INFO("Modem::wakeup\r\n");
AxedaCorp 0:a725e8eab383 308 DigitalOut pin(pn, 1);
AxedaCorp 0:a725e8eab383 309 while (i--) {
AxedaCorp 0:a725e8eab383 310 // SARA-U2/LISA-U2 50..80us
AxedaCorp 0:a725e8eab383 311 pin = 0; ::wait_us(50);
AxedaCorp 0:a725e8eab383 312 pin = 1; ::wait_ms(10);
AxedaCorp 0:a725e8eab383 313
AxedaCorp 0:a725e8eab383 314 // SARA-G35 >5ms, LISA-C2 > 150ms, LEON-G2 >5ms
AxedaCorp 0:a725e8eab383 315 pin = 0; ::wait_ms(150);
AxedaCorp 0:a725e8eab383 316 pin = 1; ::wait_ms(100);
AxedaCorp 0:a725e8eab383 317
AxedaCorp 0:a725e8eab383 318 // purge any messages
AxedaCorp 0:a725e8eab383 319 purge();
AxedaCorp 0:a725e8eab383 320
AxedaCorp 0:a725e8eab383 321 // check interface
AxedaCorp 0:a725e8eab383 322 sendFormated("AT\r\n");
AxedaCorp 0:a725e8eab383 323 int r = waitFinalResp(NULL,NULL,1000);
AxedaCorp 0:a725e8eab383 324 if(RESP_OK == r) break;
AxedaCorp 0:a725e8eab383 325 }
AxedaCorp 0:a725e8eab383 326 if (i < 0) {
AxedaCorp 0:a725e8eab383 327 ERROR("No Reply from Modem\r\n");
AxedaCorp 0:a725e8eab383 328 goto failure;
AxedaCorp 0:a725e8eab383 329 }
AxedaCorp 0:a725e8eab383 330 }
AxedaCorp 0:a725e8eab383 331 _init = true;
AxedaCorp 0:a725e8eab383 332
AxedaCorp 0:a725e8eab383 333 INFO("Modem::init\r\n");
AxedaCorp 0:a725e8eab383 334 // echo off
AxedaCorp 0:a725e8eab383 335 sendFormated("AT E0\r\n");
AxedaCorp 0:a725e8eab383 336 if(RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 337 goto failure;
AxedaCorp 0:a725e8eab383 338 // enable verbose error messages
AxedaCorp 0:a725e8eab383 339 sendFormated("AT+CMEE=2\r\n");
AxedaCorp 0:a725e8eab383 340 if(RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 341 goto failure;
AxedaCorp 0:a725e8eab383 342 // set baud rate
AxedaCorp 0:a725e8eab383 343 sendFormated("AT+IPR=115200\r\n");
AxedaCorp 0:a725e8eab383 344 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 345 goto failure;
AxedaCorp 0:a725e8eab383 346 wait_ms(40);
AxedaCorp 0:a725e8eab383 347 // identify the module
AxedaCorp 0:a725e8eab383 348 sendFormated("ATI\r\n");
AxedaCorp 0:a725e8eab383 349 if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev))
AxedaCorp 0:a725e8eab383 350 goto failure;
AxedaCorp 0:a725e8eab383 351 if (_dev.dev == DEV_UNKNOWN)
AxedaCorp 0:a725e8eab383 352 goto failure;
AxedaCorp 0:a725e8eab383 353 // device specific init
AxedaCorp 0:a725e8eab383 354 if (_dev.dev == DEV_LISA_C200) {
AxedaCorp 0:a725e8eab383 355 // get the manufacturer
AxedaCorp 0:a725e8eab383 356 sendFormated("AT+GMI\r\n");
AxedaCorp 0:a725e8eab383 357 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
AxedaCorp 0:a725e8eab383 358 goto failure;
AxedaCorp 0:a725e8eab383 359 // get the model identification
AxedaCorp 0:a725e8eab383 360 sendFormated("AT+GMM\r\n");
AxedaCorp 0:a725e8eab383 361 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
AxedaCorp 0:a725e8eab383 362 goto failure;
AxedaCorp 0:a725e8eab383 363 // get the sw version
AxedaCorp 0:a725e8eab383 364 sendFormated("AT+GMR\r\n");
AxedaCorp 0:a725e8eab383 365 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
AxedaCorp 0:a725e8eab383 366 goto failure;
AxedaCorp 0:a725e8eab383 367 // get the pseudo ESN or MEID
AxedaCorp 0:a725e8eab383 368 sendFormated("AT+GSN\r\n");
AxedaCorp 0:a725e8eab383 369 if (RESP_OK != waitFinalResp(_cbString, _dev.meid))
AxedaCorp 0:a725e8eab383 370 goto failure;
AxedaCorp 0:a725e8eab383 371 #if 0
AxedaCorp 0:a725e8eab383 372 // enable power saving
AxedaCorp 0:a725e8eab383 373 if (_dev.lpm != LPM_DISABLED) {
AxedaCorp 0:a725e8eab383 374 // enable power saving (requires flow control, cts at least)
AxedaCorp 0:a725e8eab383 375 sendFormated("AT+UPSV=1,1280\r\n");
AxedaCorp 0:a725e8eab383 376 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 377 goto failure;
AxedaCorp 0:a725e8eab383 378 _dev.lpm = LPM_ACTIVE;
AxedaCorp 0:a725e8eab383 379 }
AxedaCorp 0:a725e8eab383 380 #endif
AxedaCorp 0:a725e8eab383 381 } else {
AxedaCorp 0:a725e8eab383 382 if ((_dev.dev == DEV_LISA_U200) || (_dev.dev == DEV_LEON_G200)) {
AxedaCorp 0:a725e8eab383 383 // enable the network identification feature
AxedaCorp 0:a725e8eab383 384 sendFormated("AT+UGPIOC=20,2\r\n");
AxedaCorp 0:a725e8eab383 385 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 386 goto failure;
AxedaCorp 0:a725e8eab383 387 } else if ((_dev.dev == DEV_SARA_U260) || (_dev.dev == DEV_SARA_U270) ||
AxedaCorp 0:a725e8eab383 388 (_dev.dev == DEV_SARA_G350)) {
AxedaCorp 0:a725e8eab383 389 // enable the network identification feature
AxedaCorp 0:a725e8eab383 390 sendFormated("AT+UGPIOC=16,2\r\n");
AxedaCorp 0:a725e8eab383 391 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 392 goto failure;
AxedaCorp 0:a725e8eab383 393 }
AxedaCorp 0:a725e8eab383 394 // check the sim card
AxedaCorp 0:a725e8eab383 395 for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) {
AxedaCorp 0:a725e8eab383 396 sendFormated("AT+CPIN?\r\n");
AxedaCorp 0:a725e8eab383 397 int ret = waitFinalResp(_cbCPIN, &_dev.sim);
AxedaCorp 0:a725e8eab383 398 // having an error here is ok (sim may still be initializing)
AxedaCorp 0:a725e8eab383 399 if ((RESP_OK != ret) && (RESP_ERROR != ret))
AxedaCorp 0:a725e8eab383 400 goto failure;
AxedaCorp 0:a725e8eab383 401 // Enter PIN if needed
AxedaCorp 0:a725e8eab383 402 if (_dev.sim == SIM_PIN) {
AxedaCorp 0:a725e8eab383 403 if (!simpin) {
AxedaCorp 0:a725e8eab383 404 ERROR("SIM PIN not available\r\n");
AxedaCorp 0:a725e8eab383 405 goto failure;
AxedaCorp 0:a725e8eab383 406 }
AxedaCorp 0:a725e8eab383 407 sendFormated("AT+CPIN=%s\r\n", simpin);
AxedaCorp 0:a725e8eab383 408 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim))
AxedaCorp 0:a725e8eab383 409 goto failure;
AxedaCorp 0:a725e8eab383 410 } else if (_dev.sim != SIM_READY) {
AxedaCorp 0:a725e8eab383 411 wait_ms(1000);
AxedaCorp 0:a725e8eab383 412 }
AxedaCorp 0:a725e8eab383 413 }
AxedaCorp 0:a725e8eab383 414 if (_dev.sim != SIM_READY) {
AxedaCorp 0:a725e8eab383 415 if (_dev.sim == SIM_MISSING)
AxedaCorp 0:a725e8eab383 416 ERROR("SIM not inserted\r\n");
AxedaCorp 0:a725e8eab383 417 goto failure;
AxedaCorp 0:a725e8eab383 418 }
AxedaCorp 0:a725e8eab383 419 // get the manufacturer
AxedaCorp 0:a725e8eab383 420 sendFormated("AT+CGMI\r\n");
AxedaCorp 0:a725e8eab383 421 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
AxedaCorp 0:a725e8eab383 422 goto failure;
AxedaCorp 0:a725e8eab383 423 // get the model identification
AxedaCorp 0:a725e8eab383 424 sendFormated("AT+CGMM\r\n");
AxedaCorp 0:a725e8eab383 425 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
AxedaCorp 0:a725e8eab383 426 goto failure;
AxedaCorp 0:a725e8eab383 427 // get the
AxedaCorp 0:a725e8eab383 428 sendFormated("AT+CGMR\r\n");
AxedaCorp 0:a725e8eab383 429 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
AxedaCorp 0:a725e8eab383 430 goto failure;
AxedaCorp 0:a725e8eab383 431 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
AxedaCorp 0:a725e8eab383 432 // ICCID is a serial number identifying the SIM.
AxedaCorp 0:a725e8eab383 433 sendFormated("AT+CCID\r\n");
AxedaCorp 0:a725e8eab383 434 if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid))
AxedaCorp 0:a725e8eab383 435 goto failure;
AxedaCorp 0:a725e8eab383 436 // Returns the product serial number, IMEI (International Mobile Equipment Identity)
AxedaCorp 0:a725e8eab383 437 sendFormated("AT+CGSN\r\n");
AxedaCorp 0:a725e8eab383 438 if (RESP_OK != waitFinalResp(_cbString, _dev.imei))
AxedaCorp 0:a725e8eab383 439 goto failure;
AxedaCorp 0:a725e8eab383 440 // enable power saving
AxedaCorp 0:a725e8eab383 441 if (_dev.lpm != LPM_DISABLED) {
AxedaCorp 0:a725e8eab383 442 // enable power saving (requires flow control, cts at least)
AxedaCorp 0:a725e8eab383 443 sendFormated("AT+UPSV=1\r\n");
AxedaCorp 0:a725e8eab383 444 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 445 goto failure;
AxedaCorp 0:a725e8eab383 446 _dev.lpm = LPM_ACTIVE;
AxedaCorp 0:a725e8eab383 447 }
AxedaCorp 0:a725e8eab383 448 // enable the psd registration unsolicited result code
AxedaCorp 0:a725e8eab383 449 sendFormated("AT+CGREG=2\r\n");
AxedaCorp 0:a725e8eab383 450 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 451 goto failure;
AxedaCorp 0:a725e8eab383 452 }
AxedaCorp 0:a725e8eab383 453 // enable the network registration unsolicited result code
AxedaCorp 0:a725e8eab383 454 sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C200) ? 1 : 2);
AxedaCorp 0:a725e8eab383 455 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 456 goto failure;
AxedaCorp 0:a725e8eab383 457 // Setup SMS in text mode
AxedaCorp 0:a725e8eab383 458 sendFormated("AT+CMGF=1\r\n");
AxedaCorp 0:a725e8eab383 459 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 460 goto failure;
AxedaCorp 0:a725e8eab383 461 // setup new message indication
AxedaCorp 0:a725e8eab383 462 sendFormated("AT+CNMI=2,1\r\n");
AxedaCorp 0:a725e8eab383 463 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 464 goto failure;
AxedaCorp 0:a725e8eab383 465 // Request IMSI (International Mobile Subscriber Identification)
AxedaCorp 0:a725e8eab383 466 sendFormated("AT+CIMI\r\n");
AxedaCorp 0:a725e8eab383 467 if (RESP_OK != waitFinalResp(_cbString, _dev.imsi))
AxedaCorp 0:a725e8eab383 468 goto failure;
AxedaCorp 0:a725e8eab383 469 if (status)
AxedaCorp 0:a725e8eab383 470 memcpy(status, &_dev, sizeof(DevStatus));
AxedaCorp 0:a725e8eab383 471 UNLOCK();
AxedaCorp 0:a725e8eab383 472 return true;
AxedaCorp 0:a725e8eab383 473 failure:
AxedaCorp 0:a725e8eab383 474 unlock();
AxedaCorp 0:a725e8eab383 475 return false;
AxedaCorp 0:a725e8eab383 476 }
AxedaCorp 0:a725e8eab383 477
AxedaCorp 0:a725e8eab383 478 bool MDMParser::powerOff(void)
AxedaCorp 0:a725e8eab383 479 {
AxedaCorp 0:a725e8eab383 480 bool ok = false;
AxedaCorp 0:a725e8eab383 481 if (_init) {
AxedaCorp 0:a725e8eab383 482 LOCK();
AxedaCorp 0:a725e8eab383 483 INFO("Modem::powerOff\r\n");
AxedaCorp 0:a725e8eab383 484 sendFormated("AT+CPWROFF\r\n");
AxedaCorp 0:a725e8eab383 485 if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) {
AxedaCorp 0:a725e8eab383 486 _init = false;
AxedaCorp 0:a725e8eab383 487 ok = true;
AxedaCorp 0:a725e8eab383 488 }
AxedaCorp 0:a725e8eab383 489 UNLOCK();
AxedaCorp 0:a725e8eab383 490 }
AxedaCorp 0:a725e8eab383 491 return ok;
AxedaCorp 0:a725e8eab383 492 }
AxedaCorp 0:a725e8eab383 493
AxedaCorp 0:a725e8eab383 494 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev)
AxedaCorp 0:a725e8eab383 495 {
AxedaCorp 0:a725e8eab383 496 if ((type == TYPE_UNKNOWN) && dev) {
AxedaCorp 0:a725e8eab383 497 if (strstr(buf, "SARA-G350")) *dev = DEV_SARA_G350;
AxedaCorp 0:a725e8eab383 498 else if (strstr(buf, "LISA-U200")) *dev = DEV_LISA_U200;
AxedaCorp 0:a725e8eab383 499 else if (strstr(buf, "LISA-C200")) *dev = DEV_LISA_C200;
AxedaCorp 0:a725e8eab383 500 else if (strstr(buf, "SARA-U260")) *dev = DEV_SARA_U260;
AxedaCorp 0:a725e8eab383 501 else if (strstr(buf, "SARA-U270")) *dev = DEV_SARA_U270;
AxedaCorp 0:a725e8eab383 502 else if (strstr(buf, "LEON-G200")) *dev = DEV_LEON_G200;
AxedaCorp 0:a725e8eab383 503 }
AxedaCorp 0:a725e8eab383 504 return WAIT;
AxedaCorp 0:a725e8eab383 505 }
AxedaCorp 0:a725e8eab383 506
AxedaCorp 0:a725e8eab383 507 int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim)
AxedaCorp 0:a725e8eab383 508 {
AxedaCorp 0:a725e8eab383 509 if (sim) {
AxedaCorp 0:a725e8eab383 510 if (type == TYPE_PLUS){
AxedaCorp 0:a725e8eab383 511 char s[16];
AxedaCorp 0:a725e8eab383 512 if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1)
AxedaCorp 0:a725e8eab383 513 *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN;
AxedaCorp 0:a725e8eab383 514 } else if (type == TYPE_ERROR) {
AxedaCorp 0:a725e8eab383 515 if (strstr(buf, "+CME ERROR: SIM not inserted"))
AxedaCorp 0:a725e8eab383 516 *sim = SIM_MISSING;
AxedaCorp 0:a725e8eab383 517 }
AxedaCorp 0:a725e8eab383 518 }
AxedaCorp 0:a725e8eab383 519 return WAIT;
AxedaCorp 0:a725e8eab383 520 }
AxedaCorp 0:a725e8eab383 521
AxedaCorp 0:a725e8eab383 522 int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid)
AxedaCorp 0:a725e8eab383 523 {
AxedaCorp 0:a725e8eab383 524 if ((type == TYPE_PLUS) && ccid){
AxedaCorp 0:a725e8eab383 525 if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1)
AxedaCorp 0:a725e8eab383 526 /*TRACE("Got CCID: %s\r\n", ccid)*/;
AxedaCorp 0:a725e8eab383 527 }
AxedaCorp 0:a725e8eab383 528 return WAIT;
AxedaCorp 0:a725e8eab383 529 }
AxedaCorp 0:a725e8eab383 530
AxedaCorp 0:a725e8eab383 531 bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/)
AxedaCorp 0:a725e8eab383 532 {
AxedaCorp 0:a725e8eab383 533 Timer timer;
AxedaCorp 0:a725e8eab383 534 timer.start();
AxedaCorp 0:a725e8eab383 535 INFO("Modem::register\r\n");
AxedaCorp 0:a725e8eab383 536 while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms))
AxedaCorp 0:a725e8eab383 537 wait_ms(1000);
AxedaCorp 0:a725e8eab383 538 if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n");
AxedaCorp 0:a725e8eab383 539 if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n");
AxedaCorp 0:a725e8eab383 540 return REG_OK(_net.csd) || REG_OK(_net.psd);
AxedaCorp 0:a725e8eab383 541 }
AxedaCorp 0:a725e8eab383 542
AxedaCorp 0:a725e8eab383 543 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
AxedaCorp 0:a725e8eab383 544 {
AxedaCorp 0:a725e8eab383 545 bool ok = false;
AxedaCorp 0:a725e8eab383 546 LOCK();
AxedaCorp 0:a725e8eab383 547 memset(&_net, 0, sizeof(_net));
AxedaCorp 0:a725e8eab383 548 _net.lac = 0xFFFF;
AxedaCorp 0:a725e8eab383 549 _net.ci = 0xFFFFFFFF;
AxedaCorp 0:a725e8eab383 550 // check registration
AxedaCorp 0:a725e8eab383 551 sendFormated("AT+CREG?\r\n");
AxedaCorp 0:a725e8eab383 552 waitFinalResp(); // don't fail as service could be not subscribed
AxedaCorp 0:a725e8eab383 553 if (_dev.dev != DEV_LISA_C200) {
AxedaCorp 0:a725e8eab383 554 // check PSD registration
AxedaCorp 0:a725e8eab383 555 sendFormated("AT+CGREG?\r\n");
AxedaCorp 0:a725e8eab383 556 waitFinalResp(); // don't fail as service could be not subscribed
AxedaCorp 0:a725e8eab383 557 }
AxedaCorp 0:a725e8eab383 558 if (REG_OK(_net.csd) || REG_OK(_net.psd))
AxedaCorp 0:a725e8eab383 559 {
AxedaCorp 0:a725e8eab383 560 // check modem specific status messages
AxedaCorp 0:a725e8eab383 561 if (_dev.dev == DEV_LISA_C200) {
AxedaCorp 0:a725e8eab383 562 sendFormated("AT+CSS?\r\n");
AxedaCorp 0:a725e8eab383 563 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 564 goto failure;
AxedaCorp 0:a725e8eab383 565 while (1) {
AxedaCorp 0:a725e8eab383 566 // get the Telephone number
AxedaCorp 0:a725e8eab383 567 sendFormated("AT$MDN?\r\n");
AxedaCorp 0:a725e8eab383 568 if (RESP_OK != waitFinalResp(_cbString, _net.num))
AxedaCorp 0:a725e8eab383 569 goto failure;
AxedaCorp 0:a725e8eab383 570 // check if we have a Mobile Directory Number
AxedaCorp 0:a725e8eab383 571 if (*_net.num && (memcmp(_net.num, "000000", 6) != 0))
AxedaCorp 0:a725e8eab383 572 break;
AxedaCorp 0:a725e8eab383 573
AxedaCorp 0:a725e8eab383 574 INFO("Device not yet activated\r\n");
AxedaCorp 0:a725e8eab383 575 INFO("Make sure you have a valid contract with the network operator for this device.\r\n");
AxedaCorp 0:a725e8eab383 576 // Check if the the version contains a V for Verizon
AxedaCorp 0:a725e8eab383 577 // Verizon: E0.V.xx.00.xxR,
AxedaCorp 0:a725e8eab383 578 // Sprint E0.S.xx.00.xxR
AxedaCorp 0:a725e8eab383 579 if (_dev.ver[3] == 'V') {
AxedaCorp 0:a725e8eab383 580 int i;
AxedaCorp 0:a725e8eab383 581 INFO("Start device over-the-air activation (this can take a few minutes)\r\n");
AxedaCorp 0:a725e8eab383 582 sendFormated("AT+CDV=*22899\r\n");
AxedaCorp 0:a725e8eab383 583 i = 1;
AxedaCorp 0:a725e8eab383 584 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
AxedaCorp 0:a725e8eab383 585 ERROR("Device over-the-air activation failed\r\n");
AxedaCorp 0:a725e8eab383 586 goto failure;
AxedaCorp 0:a725e8eab383 587 }
AxedaCorp 0:a725e8eab383 588 INFO("Device over-the-air activation successful\r\n");
AxedaCorp 0:a725e8eab383 589
AxedaCorp 0:a725e8eab383 590 INFO("Start PRL over-the-air update (this can take a few minutes)\r\n");
AxedaCorp 0:a725e8eab383 591 sendFormated("AT+CDV=*22891\r\n");
AxedaCorp 0:a725e8eab383 592 i = 1;
AxedaCorp 0:a725e8eab383 593 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
AxedaCorp 0:a725e8eab383 594 ERROR("PRL over-the-air update failed\r\n");
AxedaCorp 0:a725e8eab383 595 goto failure;
AxedaCorp 0:a725e8eab383 596 }
AxedaCorp 0:a725e8eab383 597 INFO("PRL over-the-air update successful\r\n");
AxedaCorp 0:a725e8eab383 598
AxedaCorp 0:a725e8eab383 599 } else {
AxedaCorp 0:a725e8eab383 600 // Sprint or Aeris
AxedaCorp 0:a725e8eab383 601 INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n");
AxedaCorp 0:a725e8eab383 602 wait_ms(120*1000);
AxedaCorp 0:a725e8eab383 603 }
AxedaCorp 0:a725e8eab383 604 }
AxedaCorp 0:a725e8eab383 605 // get the the Network access identifier string
AxedaCorp 0:a725e8eab383 606 char nai[64];
AxedaCorp 0:a725e8eab383 607 sendFormated("AT$QCMIPNAI?\r\n");
AxedaCorp 0:a725e8eab383 608 if (RESP_OK != waitFinalResp(_cbString, nai))
AxedaCorp 0:a725e8eab383 609 goto failure;
AxedaCorp 0:a725e8eab383 610 } else {
AxedaCorp 0:a725e8eab383 611 sendFormated("AT+COPS?\r\n");
AxedaCorp 0:a725e8eab383 612 if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
AxedaCorp 0:a725e8eab383 613 goto failure;
AxedaCorp 0:a725e8eab383 614 // get the MSISDNs related to this subscriber
AxedaCorp 0:a725e8eab383 615 sendFormated("AT+CNUM\r\n");
AxedaCorp 0:a725e8eab383 616 if (RESP_OK != waitFinalResp(_cbCNUM, _net.num))
AxedaCorp 0:a725e8eab383 617 goto failure;
AxedaCorp 0:a725e8eab383 618 }
AxedaCorp 0:a725e8eab383 619 // get the signal strength indication
AxedaCorp 0:a725e8eab383 620 sendFormated("AT+CSQ\r\n");
AxedaCorp 0:a725e8eab383 621 if (RESP_OK != waitFinalResp(_cbCSQ, &_net))
AxedaCorp 0:a725e8eab383 622 goto failure;
AxedaCorp 0:a725e8eab383 623 }
AxedaCorp 0:a725e8eab383 624 if (status) {
AxedaCorp 0:a725e8eab383 625 memcpy(status, &_net, sizeof(NetStatus));
AxedaCorp 0:a725e8eab383 626 }
AxedaCorp 0:a725e8eab383 627 ok = REG_DONE(_net.csd) && REG_DONE(_net.psd);
AxedaCorp 0:a725e8eab383 628 UNLOCK();
AxedaCorp 0:a725e8eab383 629 return ok;
AxedaCorp 0:a725e8eab383 630 failure:
AxedaCorp 0:a725e8eab383 631 unlock();
AxedaCorp 0:a725e8eab383 632 return false;
AxedaCorp 0:a725e8eab383 633 }
AxedaCorp 0:a725e8eab383 634
AxedaCorp 0:a725e8eab383 635 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status)
AxedaCorp 0:a725e8eab383 636 {
AxedaCorp 0:a725e8eab383 637 if ((type == TYPE_PLUS) && status){
AxedaCorp 0:a725e8eab383 638 int act = 99;
AxedaCorp 0:a725e8eab383 639 // +COPS: <mode>[,<format>,<oper>[,<AcT>]]
AxedaCorp 0:a725e8eab383 640 if (sscanf(buf, "\r\n+COPS: %*d,%*d,\"%[^\"]\",%d",status->opr,&act) >= 1) {
AxedaCorp 0:a725e8eab383 641 if (act == 0) status->act = ACT_GSM; // 0: GSM,
AxedaCorp 0:a725e8eab383 642 else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN
AxedaCorp 0:a725e8eab383 643 }
AxedaCorp 0:a725e8eab383 644 }
AxedaCorp 0:a725e8eab383 645 return WAIT;
AxedaCorp 0:a725e8eab383 646 }
AxedaCorp 0:a725e8eab383 647
AxedaCorp 0:a725e8eab383 648 int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num)
AxedaCorp 0:a725e8eab383 649 {
AxedaCorp 0:a725e8eab383 650 if ((type == TYPE_PLUS) && num){
AxedaCorp 0:a725e8eab383 651 int a;
AxedaCorp 0:a725e8eab383 652 if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) &&
AxedaCorp 0:a725e8eab383 653 ((a == 129) || (a == 145))) {
AxedaCorp 0:a725e8eab383 654 }
AxedaCorp 0:a725e8eab383 655 }
AxedaCorp 0:a725e8eab383 656 return WAIT;
AxedaCorp 0:a725e8eab383 657 }
AxedaCorp 0:a725e8eab383 658
AxedaCorp 0:a725e8eab383 659 int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status)
AxedaCorp 0:a725e8eab383 660 {
AxedaCorp 0:a725e8eab383 661 if ((type == TYPE_PLUS) && status){
AxedaCorp 0:a725e8eab383 662 int a,b;
AxedaCorp 0:a725e8eab383 663 char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4
AxedaCorp 0:a725e8eab383 664 // +CSQ: <rssi>,<qual>
AxedaCorp 0:a725e8eab383 665 if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) {
AxedaCorp 0:a725e8eab383 666 if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps
AxedaCorp 0:a725e8eab383 667 if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; //
AxedaCorp 0:a725e8eab383 668 }
AxedaCorp 0:a725e8eab383 669 }
AxedaCorp 0:a725e8eab383 670 return WAIT;
AxedaCorp 0:a725e8eab383 671 }
AxedaCorp 0:a725e8eab383 672
AxedaCorp 0:a725e8eab383 673 int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i)
AxedaCorp 0:a725e8eab383 674 {
AxedaCorp 0:a725e8eab383 675 if ((type == TYPE_PLUS) && i){
AxedaCorp 0:a725e8eab383 676 int a;
AxedaCorp 0:a725e8eab383 677 if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) {
AxedaCorp 0:a725e8eab383 678 *i = a;
AxedaCorp 0:a725e8eab383 679 }
AxedaCorp 0:a725e8eab383 680 }
AxedaCorp 0:a725e8eab383 681 return WAIT;
AxedaCorp 0:a725e8eab383 682 }
AxedaCorp 0:a725e8eab383 683
AxedaCorp 0:a725e8eab383 684 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 685 // internet connection
AxedaCorp 0:a725e8eab383 686
AxedaCorp 0:a725e8eab383 687 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/,
AxedaCorp 0:a725e8eab383 688 const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/)
AxedaCorp 0:a725e8eab383 689 {
AxedaCorp 0:a725e8eab383 690 LOCK();
AxedaCorp 0:a725e8eab383 691 INFO("Modem::join\r\n");
AxedaCorp 0:a725e8eab383 692 _ip = NOIP;
AxedaCorp 0:a725e8eab383 693 if (_dev.dev == DEV_LISA_C200) {
AxedaCorp 0:a725e8eab383 694 // make a dumy dns lookup (which will fail, so ignore the result)
AxedaCorp 0:a725e8eab383 695 sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n");
AxedaCorp 0:a725e8eab383 696 waitFinalResp();
AxedaCorp 0:a725e8eab383 697 // This fake lookup will enable the IP connection and we
AxedaCorp 0:a725e8eab383 698 // should have an IP after this, so we check it
AxedaCorp 0:a725e8eab383 699
AxedaCorp 0:a725e8eab383 700 //Get local IP address
AxedaCorp 0:a725e8eab383 701 sendFormated("AT+CMIP?\r\n");
AxedaCorp 0:a725e8eab383 702 if (RESP_OK != waitFinalResp(_cbCMIP, &_ip))
AxedaCorp 0:a725e8eab383 703 goto failure;
AxedaCorp 0:a725e8eab383 704 } else {
AxedaCorp 0:a725e8eab383 705 // check gprs attach status
AxedaCorp 0:a725e8eab383 706 sendFormated("AT+CGATT=1\r\n");
AxedaCorp 0:a725e8eab383 707 if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000))
AxedaCorp 0:a725e8eab383 708 goto failure;
AxedaCorp 0:a725e8eab383 709
AxedaCorp 0:a725e8eab383 710 // Check the profile
AxedaCorp 0:a725e8eab383 711 int a = 0;
AxedaCorp 0:a725e8eab383 712 bool force = true;
AxedaCorp 0:a725e8eab383 713 sendFormated("AT+UPSND=" PROFILE ",8\r\n");
AxedaCorp 0:a725e8eab383 714 if (RESP_OK != waitFinalResp(_cbUPSND, &a))
AxedaCorp 0:a725e8eab383 715 goto failure;
AxedaCorp 0:a725e8eab383 716 if (a == 1 && force) {
AxedaCorp 0:a725e8eab383 717 // disconnect the profile already if it is connected
AxedaCorp 0:a725e8eab383 718 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
AxedaCorp 0:a725e8eab383 719 if (RESP_OK != waitFinalResp(NULL,NULL,40*1000))
AxedaCorp 0:a725e8eab383 720 goto failure;
AxedaCorp 0:a725e8eab383 721 a = 0;
AxedaCorp 0:a725e8eab383 722 }
AxedaCorp 0:a725e8eab383 723 if (a == 0) {
AxedaCorp 0:a725e8eab383 724 bool ok = false;
AxedaCorp 0:a725e8eab383 725 // try to lookup the apn settings from our local database by mccmnc
AxedaCorp 0:a725e8eab383 726 const char* config = NULL;
AxedaCorp 0:a725e8eab383 727 if (!apn && !username && !password)
AxedaCorp 0:a725e8eab383 728 config = apnconfig(_dev.imsi);
AxedaCorp 0:a725e8eab383 729
AxedaCorp 0:a725e8eab383 730 // Set up the dynamic IP address assignment.
AxedaCorp 0:a725e8eab383 731 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
AxedaCorp 0:a725e8eab383 732 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 733 goto failure;
AxedaCorp 0:a725e8eab383 734
AxedaCorp 0:a725e8eab383 735 do {
AxedaCorp 0:a725e8eab383 736 if (config) {
AxedaCorp 0:a725e8eab383 737 apn = _APN_GET(config);
AxedaCorp 0:a725e8eab383 738 username = _APN_GET(config);
AxedaCorp 0:a725e8eab383 739 password = _APN_GET(config);
AxedaCorp 0:a725e8eab383 740 TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\")\r\n", apn, username, password);
AxedaCorp 0:a725e8eab383 741 }
AxedaCorp 0:a725e8eab383 742 // Set up the APN
AxedaCorp 0:a725e8eab383 743 if (apn && *apn) {
AxedaCorp 0:a725e8eab383 744 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
AxedaCorp 0:a725e8eab383 745 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 746 goto failure;
AxedaCorp 0:a725e8eab383 747 }
AxedaCorp 0:a725e8eab383 748 if (username && *username) {
AxedaCorp 0:a725e8eab383 749 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
AxedaCorp 0:a725e8eab383 750 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 751 goto failure;
AxedaCorp 0:a725e8eab383 752 }
AxedaCorp 0:a725e8eab383 753 if (password && *password) {
AxedaCorp 0:a725e8eab383 754 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
AxedaCorp 0:a725e8eab383 755 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 756 goto failure;
AxedaCorp 0:a725e8eab383 757 }
AxedaCorp 0:a725e8eab383 758 // try different Authentication Protocols
AxedaCorp 0:a725e8eab383 759 // 0 = none
AxedaCorp 0:a725e8eab383 760 // 1 = PAP (Password Authentication Protocol)
AxedaCorp 0:a725e8eab383 761 // 2 = CHAP (Challenge Handshake Authentication Protocol)
AxedaCorp 0:a725e8eab383 762 for (int i = AUTH_NONE; i <= AUTH_CHAP && !ok; i ++) {
AxedaCorp 0:a725e8eab383 763 if ((auth == AUTH_DETECT) || (auth == i)) {
AxedaCorp 0:a725e8eab383 764 // Set up the Authentication Protocol
AxedaCorp 0:a725e8eab383 765 sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n", i);
AxedaCorp 0:a725e8eab383 766 if (RESP_OK != waitFinalResp())
AxedaCorp 0:a725e8eab383 767 goto failure;
AxedaCorp 0:a725e8eab383 768 // Activate the profile and make connection
AxedaCorp 0:a725e8eab383 769 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
AxedaCorp 0:a725e8eab383 770 if (RESP_OK == waitFinalResp(NULL,NULL,150*1000))
AxedaCorp 0:a725e8eab383 771 ok = true;
AxedaCorp 0:a725e8eab383 772 }
AxedaCorp 0:a725e8eab383 773 }
AxedaCorp 0:a725e8eab383 774 } while (!ok && config && *config); // maybe use next setting ?
AxedaCorp 0:a725e8eab383 775 if (!ok) {
AxedaCorp 0:a725e8eab383 776 ERROR("Your modem APN/password/username may be wrong\r\n");
AxedaCorp 0:a725e8eab383 777 goto failure;
AxedaCorp 0:a725e8eab383 778 }
AxedaCorp 0:a725e8eab383 779 }
AxedaCorp 0:a725e8eab383 780 //Get local IP address
AxedaCorp 0:a725e8eab383 781 sendFormated("AT+UPSND=" PROFILE ",0\r\n");
AxedaCorp 0:a725e8eab383 782 if (RESP_OK != waitFinalResp(_cbUPSND, &_ip))
AxedaCorp 0:a725e8eab383 783 goto failure;
AxedaCorp 0:a725e8eab383 784 }
AxedaCorp 0:a725e8eab383 785 UNLOCK();
AxedaCorp 0:a725e8eab383 786 return _ip;
AxedaCorp 0:a725e8eab383 787 failure:
AxedaCorp 0:a725e8eab383 788 unlock();
AxedaCorp 0:a725e8eab383 789 return NOIP;
AxedaCorp 0:a725e8eab383 790 }
AxedaCorp 0:a725e8eab383 791
AxedaCorp 0:a725e8eab383 792 int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc)
AxedaCorp 0:a725e8eab383 793 {
AxedaCorp 0:a725e8eab383 794 if ((type == TYPE_PLUS) && mccmnc) {
AxedaCorp 0:a725e8eab383 795 if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1)
AxedaCorp 0:a725e8eab383 796 ;
AxedaCorp 0:a725e8eab383 797 }
AxedaCorp 0:a725e8eab383 798 return WAIT;
AxedaCorp 0:a725e8eab383 799 }
AxedaCorp 0:a725e8eab383 800
AxedaCorp 0:a725e8eab383 801 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip)
AxedaCorp 0:a725e8eab383 802 {
AxedaCorp 0:a725e8eab383 803 if ((type == TYPE_UNKNOWN) && ip) {
AxedaCorp 0:a725e8eab383 804 int a,b,c,d;
AxedaCorp 0:a725e8eab383 805 if (sscanf(buf, "\r\n" IPSTR, &a,&b,&c,&d) == 4)
AxedaCorp 0:a725e8eab383 806 *ip = IPADR(a,b,c,d);
AxedaCorp 0:a725e8eab383 807 }
AxedaCorp 0:a725e8eab383 808 return WAIT;
AxedaCorp 0:a725e8eab383 809 }
AxedaCorp 0:a725e8eab383 810
AxedaCorp 0:a725e8eab383 811 int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act)
AxedaCorp 0:a725e8eab383 812 {
AxedaCorp 0:a725e8eab383 813 if ((type == TYPE_PLUS) && act) {
AxedaCorp 0:a725e8eab383 814 if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1)
AxedaCorp 0:a725e8eab383 815 /*nothing*/;
AxedaCorp 0:a725e8eab383 816 }
AxedaCorp 0:a725e8eab383 817 return WAIT;
AxedaCorp 0:a725e8eab383 818 }
AxedaCorp 0:a725e8eab383 819
AxedaCorp 0:a725e8eab383 820 int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip)
AxedaCorp 0:a725e8eab383 821 {
AxedaCorp 0:a725e8eab383 822 if ((type == TYPE_PLUS) && ip) {
AxedaCorp 0:a725e8eab383 823 int a,b,c,d;
AxedaCorp 0:a725e8eab383 824 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
AxedaCorp 0:a725e8eab383 825 if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4)
AxedaCorp 0:a725e8eab383 826 *ip = IPADR(a,b,c,d);
AxedaCorp 0:a725e8eab383 827 }
AxedaCorp 0:a725e8eab383 828 return WAIT;
AxedaCorp 0:a725e8eab383 829 }
AxedaCorp 0:a725e8eab383 830
AxedaCorp 0:a725e8eab383 831 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip)
AxedaCorp 0:a725e8eab383 832 {
AxedaCorp 0:a725e8eab383 833 if ((type == TYPE_PLUS) && ip) {
AxedaCorp 0:a725e8eab383 834 int a,b,c,d;
AxedaCorp 0:a725e8eab383 835 if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4)
AxedaCorp 0:a725e8eab383 836 *ip = IPADR(a,b,c,d);
AxedaCorp 0:a725e8eab383 837 }
AxedaCorp 0:a725e8eab383 838 return WAIT;
AxedaCorp 0:a725e8eab383 839 }
AxedaCorp 0:a725e8eab383 840
AxedaCorp 0:a725e8eab383 841 bool MDMParser::disconnect(void)
AxedaCorp 0:a725e8eab383 842 {
AxedaCorp 0:a725e8eab383 843 bool ok = false;
AxedaCorp 0:a725e8eab383 844 LOCK();
AxedaCorp 0:a725e8eab383 845 INFO("Modem::disconnect\r\n");
AxedaCorp 0:a725e8eab383 846 if (_ip != NOIP) {
AxedaCorp 0:a725e8eab383 847 if (_dev.dev == DEV_LISA_C200) {
AxedaCorp 0:a725e8eab383 848 // There something to do here
AxedaCorp 0:a725e8eab383 849 _ip = NOIP;
AxedaCorp 0:a725e8eab383 850 ok = true;
AxedaCorp 0:a725e8eab383 851 } else {
AxedaCorp 0:a725e8eab383 852 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
AxedaCorp 0:a725e8eab383 853 if (RESP_OK != waitFinalResp()) {
AxedaCorp 0:a725e8eab383 854 _ip = NOIP;
AxedaCorp 0:a725e8eab383 855 ok = true;
AxedaCorp 0:a725e8eab383 856 }
AxedaCorp 0:a725e8eab383 857 }
AxedaCorp 0:a725e8eab383 858 }
AxedaCorp 0:a725e8eab383 859 UNLOCK();
AxedaCorp 0:a725e8eab383 860 return ok;
AxedaCorp 0:a725e8eab383 861 }
AxedaCorp 0:a725e8eab383 862
AxedaCorp 0:a725e8eab383 863 MDMParser::IP MDMParser::gethostbyname(const char* host)
AxedaCorp 0:a725e8eab383 864 {
AxedaCorp 0:a725e8eab383 865 IP ip = NOIP;
AxedaCorp 0:a725e8eab383 866 int a,b,c,d;
AxedaCorp 0:a725e8eab383 867 if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4)
AxedaCorp 0:a725e8eab383 868 ip = IPADR(a,b,c,d);
AxedaCorp 0:a725e8eab383 869 else {
AxedaCorp 0:a725e8eab383 870 LOCK();
AxedaCorp 0:a725e8eab383 871 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host);
AxedaCorp 0:a725e8eab383 872 if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip))
AxedaCorp 0:a725e8eab383 873 ip = NOIP;
AxedaCorp 0:a725e8eab383 874 UNLOCK();
AxedaCorp 0:a725e8eab383 875 }
AxedaCorp 0:a725e8eab383 876 return ip;
AxedaCorp 0:a725e8eab383 877 }
AxedaCorp 0:a725e8eab383 878
AxedaCorp 0:a725e8eab383 879 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 880 // sockets
AxedaCorp 0:a725e8eab383 881
AxedaCorp 0:a725e8eab383 882 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* handle)
AxedaCorp 0:a725e8eab383 883 {
AxedaCorp 0:a725e8eab383 884 if ((type == TYPE_PLUS) && handle) {
AxedaCorp 0:a725e8eab383 885 const char* p = strstr(buf,"+USOCR: ");
AxedaCorp 0:a725e8eab383 886 if (p)
AxedaCorp 0:a725e8eab383 887 *handle = atoi(p+8);
AxedaCorp 0:a725e8eab383 888 }
AxedaCorp 0:a725e8eab383 889 return WAIT;
AxedaCorp 0:a725e8eab383 890 }
AxedaCorp 0:a725e8eab383 891
AxedaCorp 0:a725e8eab383 892 int MDMParser::socketSocket(IpProtocol ipproto, int port)
AxedaCorp 0:a725e8eab383 893 {
AxedaCorp 0:a725e8eab383 894 int socket;
AxedaCorp 0:a725e8eab383 895 LOCK();
AxedaCorp 0:a725e8eab383 896 // find an free socket
AxedaCorp 0:a725e8eab383 897 socket = _findSocket();
AxedaCorp 0:a725e8eab383 898 TRACE("socketSocket(%d)\r\n", ipproto);
AxedaCorp 0:a725e8eab383 899 if (socket != SOCKET_ERROR) {
AxedaCorp 0:a725e8eab383 900 if ((ipproto == IPPROTO_UDP) && (port == -1)){
AxedaCorp 0:a725e8eab383 901 sendFormated("AT+USOCR=17\r\n");
AxedaCorp 0:a725e8eab383 902 } else if (ipproto == IPPROTO_UDP){
AxedaCorp 0:a725e8eab383 903 sendFormated("AT+USOCR=17,%d\r\n", port);
AxedaCorp 0:a725e8eab383 904 } else /*(ipproto == IPPROTO_TCP)*/ {
AxedaCorp 0:a725e8eab383 905 sendFormated("AT+USOCR=6\r\n");
AxedaCorp 0:a725e8eab383 906 }
AxedaCorp 0:a725e8eab383 907 int handle = SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 908 if ((RESP_OK == waitFinalResp(_cbUSOCR, &handle)) &&
AxedaCorp 0:a725e8eab383 909 (handle != SOCKET_ERROR)) {
AxedaCorp 0:a725e8eab383 910 TRACE("Socket %d: handle %d was created\r\n", socket, handle);
AxedaCorp 0:a725e8eab383 911 _sockets[socket].handle = handle;
AxedaCorp 0:a725e8eab383 912 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
AxedaCorp 0:a725e8eab383 913 _sockets[socket].connected = false;
AxedaCorp 0:a725e8eab383 914 _sockets[socket].pending = 0;
AxedaCorp 0:a725e8eab383 915 }
AxedaCorp 0:a725e8eab383 916 else
AxedaCorp 0:a725e8eab383 917 socket = SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 918 }
AxedaCorp 0:a725e8eab383 919 UNLOCK();
AxedaCorp 0:a725e8eab383 920 return socket;
AxedaCorp 0:a725e8eab383 921 }
AxedaCorp 0:a725e8eab383 922
AxedaCorp 0:a725e8eab383 923 bool MDMParser::socketConnect(int socket, const char * host, int port)
AxedaCorp 0:a725e8eab383 924 {
AxedaCorp 0:a725e8eab383 925 IP ip = gethostbyname(host);
AxedaCorp 0:a725e8eab383 926 if (ip == NOIP)
AxedaCorp 0:a725e8eab383 927 return false;
AxedaCorp 0:a725e8eab383 928 // connect to socket
AxedaCorp 0:a725e8eab383 929 bool ok = false;
AxedaCorp 0:a725e8eab383 930 LOCK();
AxedaCorp 0:a725e8eab383 931 if (ISSOCKET(socket) && (!_sockets[socket].connected)) {
AxedaCorp 0:a725e8eab383 932 TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port);
AxedaCorp 0:a725e8eab383 933 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", _sockets[socket].handle, IPNUM(ip), port);
AxedaCorp 0:a725e8eab383 934 if (RESP_OK == waitFinalResp())
AxedaCorp 0:a725e8eab383 935 ok = _sockets[socket].connected = true;
AxedaCorp 0:a725e8eab383 936 }
AxedaCorp 0:a725e8eab383 937 UNLOCK();
AxedaCorp 0:a725e8eab383 938 return ok;
AxedaCorp 0:a725e8eab383 939 }
AxedaCorp 0:a725e8eab383 940
AxedaCorp 0:a725e8eab383 941 bool MDMParser::socketIsConnected(int socket)
AxedaCorp 0:a725e8eab383 942 {
AxedaCorp 0:a725e8eab383 943 bool ok = false;
AxedaCorp 0:a725e8eab383 944 LOCK();
AxedaCorp 0:a725e8eab383 945 TRACE("socketIsConnected(%d)\r\n", socket);
AxedaCorp 0:a725e8eab383 946 ok = ISSOCKET(socket) && _sockets[socket].connected;
AxedaCorp 0:a725e8eab383 947 UNLOCK();
AxedaCorp 0:a725e8eab383 948 return ok;
AxedaCorp 0:a725e8eab383 949 }
AxedaCorp 0:a725e8eab383 950
AxedaCorp 0:a725e8eab383 951 bool MDMParser::socketSetBlocking(int socket, int timeout_ms)
AxedaCorp 0:a725e8eab383 952 {
AxedaCorp 0:a725e8eab383 953 bool ok = false;
AxedaCorp 0:a725e8eab383 954 LOCK();
AxedaCorp 0:a725e8eab383 955 TRACE("socketSetBlocking(%d,%d)\r\n", socket,timeout_ms);
AxedaCorp 0:a725e8eab383 956 if (ISSOCKET(socket)) {
AxedaCorp 0:a725e8eab383 957 _sockets[socket].timeout_ms = timeout_ms;
AxedaCorp 0:a725e8eab383 958 ok = true;
AxedaCorp 0:a725e8eab383 959 }
AxedaCorp 0:a725e8eab383 960 UNLOCK();
AxedaCorp 0:a725e8eab383 961 return ok;
AxedaCorp 0:a725e8eab383 962 }
AxedaCorp 0:a725e8eab383 963
AxedaCorp 0:a725e8eab383 964 bool MDMParser::socketClose(int socket)
AxedaCorp 0:a725e8eab383 965 {
AxedaCorp 0:a725e8eab383 966 bool ok = false;
AxedaCorp 0:a725e8eab383 967 LOCK();
AxedaCorp 0:a725e8eab383 968 if (ISSOCKET(socket) && _sockets[socket].connected) {
AxedaCorp 0:a725e8eab383 969 TRACE("socketClose(%d)\r\n", socket);
AxedaCorp 0:a725e8eab383 970 sendFormated("AT+USOCL=%d\r\n", _sockets[socket].handle);
AxedaCorp 0:a725e8eab383 971 if (RESP_OK == waitFinalResp()) {
AxedaCorp 0:a725e8eab383 972 _sockets[socket].connected = false;
AxedaCorp 0:a725e8eab383 973 ok = true;
AxedaCorp 0:a725e8eab383 974 }
AxedaCorp 0:a725e8eab383 975 }
AxedaCorp 0:a725e8eab383 976 UNLOCK();
AxedaCorp 0:a725e8eab383 977 return ok;
AxedaCorp 0:a725e8eab383 978 }
AxedaCorp 0:a725e8eab383 979
AxedaCorp 0:a725e8eab383 980 bool MDMParser::socketFree(int socket)
AxedaCorp 0:a725e8eab383 981 {
AxedaCorp 0:a725e8eab383 982 // make sure it is closed
AxedaCorp 0:a725e8eab383 983 socketClose(socket);
AxedaCorp 0:a725e8eab383 984 bool ok = true;
AxedaCorp 0:a725e8eab383 985 LOCK();
AxedaCorp 0:a725e8eab383 986 if (ISSOCKET(socket)) {
AxedaCorp 0:a725e8eab383 987 TRACE("socketFree(%d)\r\n", socket);
AxedaCorp 0:a725e8eab383 988 _sockets[socket].handle = SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 989 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
AxedaCorp 0:a725e8eab383 990 _sockets[socket].connected = false;
AxedaCorp 0:a725e8eab383 991 _sockets[socket].pending = 0;
AxedaCorp 0:a725e8eab383 992 ok = true;
AxedaCorp 0:a725e8eab383 993 }
AxedaCorp 0:a725e8eab383 994 UNLOCK();
AxedaCorp 0:a725e8eab383 995 return ok;
AxedaCorp 0:a725e8eab383 996 }
AxedaCorp 0:a725e8eab383 997
AxedaCorp 0:a725e8eab383 998 #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket
AxedaCorp 0:a725e8eab383 999
AxedaCorp 0:a725e8eab383 1000 int MDMParser::socketSend(int socket, const char * buf, int len)
AxedaCorp 0:a725e8eab383 1001 {
AxedaCorp 0:a725e8eab383 1002 TRACE("socketSend(%d,%s,%d)\r\n", socket,buf,len);
AxedaCorp 0:a725e8eab383 1003 int cnt = len;
AxedaCorp 0:a725e8eab383 1004 while (cnt > 0) {
AxedaCorp 0:a725e8eab383 1005 int blk = USO_MAX_WRITE;
AxedaCorp 0:a725e8eab383 1006 if (cnt < blk)
AxedaCorp 0:a725e8eab383 1007 blk = cnt;
AxedaCorp 0:a725e8eab383 1008 bool ok = false;
AxedaCorp 0:a725e8eab383 1009 LOCK();
AxedaCorp 0:a725e8eab383 1010 if (ISSOCKET(socket)) {
AxedaCorp 0:a725e8eab383 1011 sendFormated("AT+USOWR=%d,%d\r\n",_sockets[socket].handle,blk);
AxedaCorp 0:a725e8eab383 1012 if (RESP_PROMPT == waitFinalResp()) {
AxedaCorp 0:a725e8eab383 1013 wait_ms(50);
AxedaCorp 0:a725e8eab383 1014 TRACE("SENT: %s", buf);
AxedaCorp 0:a725e8eab383 1015 send(buf, blk);
AxedaCorp 0:a725e8eab383 1016 if (RESP_OK == waitFinalResp())
AxedaCorp 0:a725e8eab383 1017 ok = true;
AxedaCorp 0:a725e8eab383 1018 }
AxedaCorp 0:a725e8eab383 1019 }
AxedaCorp 0:a725e8eab383 1020 UNLOCK();
AxedaCorp 0:a725e8eab383 1021 if (!ok)
AxedaCorp 0:a725e8eab383 1022 return SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 1023 buf += blk;
AxedaCorp 0:a725e8eab383 1024 cnt -= blk;
AxedaCorp 0:a725e8eab383 1025 }
AxedaCorp 0:a725e8eab383 1026 return (len - cnt);
AxedaCorp 0:a725e8eab383 1027 }
AxedaCorp 0:a725e8eab383 1028
AxedaCorp 0:a725e8eab383 1029 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len)
AxedaCorp 0:a725e8eab383 1030 {
AxedaCorp 0:a725e8eab383 1031 TRACE("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket,IPNUM(ip),port,len);
AxedaCorp 0:a725e8eab383 1032 int cnt = len;
AxedaCorp 0:a725e8eab383 1033 while (cnt > 0) {
AxedaCorp 0:a725e8eab383 1034 int blk = USO_MAX_WRITE;
AxedaCorp 0:a725e8eab383 1035 if (cnt < blk)
AxedaCorp 0:a725e8eab383 1036 blk = cnt;
AxedaCorp 0:a725e8eab383 1037 bool ok = false;
AxedaCorp 0:a725e8eab383 1038 LOCK();
AxedaCorp 0:a725e8eab383 1039 if (ISSOCKET(socket)) {
AxedaCorp 0:a725e8eab383 1040 sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",_sockets[socket].handle,IPNUM(ip),port,blk);
AxedaCorp 0:a725e8eab383 1041 if (RESP_PROMPT == waitFinalResp()) {
AxedaCorp 0:a725e8eab383 1042 wait_ms(50);
AxedaCorp 0:a725e8eab383 1043 send(buf, blk);
AxedaCorp 0:a725e8eab383 1044 if (RESP_OK == waitFinalResp())
AxedaCorp 0:a725e8eab383 1045 ok = true;
AxedaCorp 0:a725e8eab383 1046 }
AxedaCorp 0:a725e8eab383 1047 }
AxedaCorp 0:a725e8eab383 1048 UNLOCK();
AxedaCorp 0:a725e8eab383 1049 if (!ok)
AxedaCorp 0:a725e8eab383 1050 return SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 1051 buf += blk;
AxedaCorp 0:a725e8eab383 1052 cnt -= blk;
AxedaCorp 0:a725e8eab383 1053 }
AxedaCorp 0:a725e8eab383 1054 return (len - cnt);
AxedaCorp 0:a725e8eab383 1055 }
AxedaCorp 0:a725e8eab383 1056
AxedaCorp 0:a725e8eab383 1057 int MDMParser::socketReadable(int socket)
AxedaCorp 0:a725e8eab383 1058 {
AxedaCorp 0:a725e8eab383 1059 int pending = SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 1060 LOCK();
AxedaCorp 0:a725e8eab383 1061 if (ISSOCKET(socket) && _sockets[socket].connected) {
AxedaCorp 0:a725e8eab383 1062 TRACE("socketReadable(%d)\r\n", socket);
AxedaCorp 0:a725e8eab383 1063 // allow to receive unsolicited commands
AxedaCorp 0:a725e8eab383 1064 waitFinalResp(NULL, NULL, 0);
AxedaCorp 0:a725e8eab383 1065 if (_sockets[socket].connected)
AxedaCorp 0:a725e8eab383 1066 pending = _sockets[socket].pending;
AxedaCorp 0:a725e8eab383 1067 }
AxedaCorp 0:a725e8eab383 1068 UNLOCK();
AxedaCorp 0:a725e8eab383 1069 return pending;
AxedaCorp 0:a725e8eab383 1070 }
AxedaCorp 0:a725e8eab383 1071
AxedaCorp 0:a725e8eab383 1072 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out)
AxedaCorp 0:a725e8eab383 1073 {
AxedaCorp 0:a725e8eab383 1074 if ((type == TYPE_PLUS) && out) {
AxedaCorp 0:a725e8eab383 1075 int sz, sk;
AxedaCorp 0:a725e8eab383 1076 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) &&
AxedaCorp 0:a725e8eab383 1077 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
AxedaCorp 0:a725e8eab383 1078 memcpy(out, &buf[len-1-sz], sz);
AxedaCorp 0:a725e8eab383 1079 }
AxedaCorp 0:a725e8eab383 1080 }
AxedaCorp 0:a725e8eab383 1081 return WAIT;
AxedaCorp 0:a725e8eab383 1082 }
AxedaCorp 0:a725e8eab383 1083
AxedaCorp 0:a725e8eab383 1084 int MDMParser::socketRecv(int socket, char* buf, int len)
AxedaCorp 0:a725e8eab383 1085 {
AxedaCorp 0:a725e8eab383 1086 int cnt = 0;
AxedaCorp 0:a725e8eab383 1087 TRACE("socketRecv(%d,,%d)\r\n", socket, len);
AxedaCorp 0:a725e8eab383 1088 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 1089 memset(buf, '\0', len);
AxedaCorp 0:a725e8eab383 1090 #endif
AxedaCorp 0:a725e8eab383 1091 Timer timer;
AxedaCorp 0:a725e8eab383 1092 timer.start();
AxedaCorp 0:a725e8eab383 1093 while (len) {
AxedaCorp 0:a725e8eab383 1094 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
AxedaCorp 0:a725e8eab383 1095 if (len < blk) blk = len;
AxedaCorp 0:a725e8eab383 1096 bool ok = false;
AxedaCorp 0:a725e8eab383 1097 LOCK();
AxedaCorp 0:a725e8eab383 1098 if (ISSOCKET(socket)) {
AxedaCorp 0:a725e8eab383 1099 if (_sockets[socket].connected) {
AxedaCorp 0:a725e8eab383 1100 if (_sockets[socket].pending < blk)
AxedaCorp 0:a725e8eab383 1101 blk = _sockets[socket].pending;
AxedaCorp 0:a725e8eab383 1102 if (blk > 0) {
AxedaCorp 0:a725e8eab383 1103 sendFormated("AT+USORD=%d,%d\r\n",_sockets[socket].handle, blk);
AxedaCorp 0:a725e8eab383 1104 if (RESP_OK == waitFinalResp(_cbUSORD, buf)) {
AxedaCorp 0:a725e8eab383 1105 _sockets[socket].pending -= blk;
AxedaCorp 0:a725e8eab383 1106 len -= blk;
AxedaCorp 0:a725e8eab383 1107 cnt += blk;
AxedaCorp 0:a725e8eab383 1108 buf += blk;
AxedaCorp 0:a725e8eab383 1109 ok = true;
AxedaCorp 0:a725e8eab383 1110 }
AxedaCorp 0:a725e8eab383 1111 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
AxedaCorp 0:a725e8eab383 1112 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
AxedaCorp 0:a725e8eab383 1113 } else {
AxedaCorp 0:a725e8eab383 1114 len = 0;
AxedaCorp 0:a725e8eab383 1115 ok = true;
AxedaCorp 0:a725e8eab383 1116 }
AxedaCorp 0:a725e8eab383 1117 } else {
AxedaCorp 0:a725e8eab383 1118 len = 0;
AxedaCorp 0:a725e8eab383 1119 ok = true;
AxedaCorp 0:a725e8eab383 1120 }
AxedaCorp 0:a725e8eab383 1121 }
AxedaCorp 0:a725e8eab383 1122 UNLOCK();
AxedaCorp 0:a725e8eab383 1123 if (!ok)
AxedaCorp 0:a725e8eab383 1124 return SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 1125 }
AxedaCorp 0:a725e8eab383 1126 return cnt;
AxedaCorp 0:a725e8eab383 1127 }
AxedaCorp 0:a725e8eab383 1128
AxedaCorp 0:a725e8eab383 1129 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param)
AxedaCorp 0:a725e8eab383 1130 {
AxedaCorp 0:a725e8eab383 1131 if ((type == TYPE_PLUS) && param) {
AxedaCorp 0:a725e8eab383 1132 int sz, sk, p, a,b,c,d;
AxedaCorp 0:a725e8eab383 1133 int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,",
AxedaCorp 0:a725e8eab383 1134 &sk,&a,&b,&c,&d,&p,&sz);
AxedaCorp 0:a725e8eab383 1135 if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
AxedaCorp 0:a725e8eab383 1136 memcpy(param->buf, &buf[len-1-sz], sz);
AxedaCorp 0:a725e8eab383 1137 param->ip = IPADR(a,b,c,d);
AxedaCorp 0:a725e8eab383 1138 param->port = p;
AxedaCorp 0:a725e8eab383 1139 }
AxedaCorp 0:a725e8eab383 1140 }
AxedaCorp 0:a725e8eab383 1141 return WAIT;
AxedaCorp 0:a725e8eab383 1142 }
AxedaCorp 0:a725e8eab383 1143
AxedaCorp 0:a725e8eab383 1144 int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len)
AxedaCorp 0:a725e8eab383 1145 {
AxedaCorp 0:a725e8eab383 1146 int cnt = 0;
AxedaCorp 0:a725e8eab383 1147 TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len);
AxedaCorp 0:a725e8eab383 1148 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 1149 memset(buf, '\0', len);
AxedaCorp 0:a725e8eab383 1150 #endif
AxedaCorp 0:a725e8eab383 1151 Timer timer;
AxedaCorp 0:a725e8eab383 1152 timer.start();
AxedaCorp 0:a725e8eab383 1153 while (len) {
AxedaCorp 0:a725e8eab383 1154 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
AxedaCorp 0:a725e8eab383 1155 if (len < blk) blk = len;
AxedaCorp 0:a725e8eab383 1156 bool ok = false;
AxedaCorp 0:a725e8eab383 1157 LOCK();
AxedaCorp 0:a725e8eab383 1158 if (ISSOCKET(socket)) {
AxedaCorp 0:a725e8eab383 1159 if (_sockets[socket].pending < blk)
AxedaCorp 0:a725e8eab383 1160 blk = _sockets[socket].pending;
AxedaCorp 0:a725e8eab383 1161 if (blk > 0) {
AxedaCorp 0:a725e8eab383 1162 sendFormated("AT+USORF=%d,%d\r\n",_sockets[socket].handle, blk);
AxedaCorp 0:a725e8eab383 1163 USORFparam param;
AxedaCorp 0:a725e8eab383 1164 param.buf = buf;
AxedaCorp 0:a725e8eab383 1165 if (RESP_OK == waitFinalResp(_cbUSORF, &param)) {
AxedaCorp 0:a725e8eab383 1166 _sockets[socket].pending -= blk;
AxedaCorp 0:a725e8eab383 1167 *ip = param.ip;
AxedaCorp 0:a725e8eab383 1168 *port = param.port;
AxedaCorp 0:a725e8eab383 1169 len -= blk;
AxedaCorp 0:a725e8eab383 1170 cnt += blk;
AxedaCorp 0:a725e8eab383 1171 buf += blk;
AxedaCorp 0:a725e8eab383 1172 len = 0; // done
AxedaCorp 0:a725e8eab383 1173 ok = true;
AxedaCorp 0:a725e8eab383 1174 }
AxedaCorp 0:a725e8eab383 1175 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
AxedaCorp 0:a725e8eab383 1176 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
AxedaCorp 0:a725e8eab383 1177 } else {
AxedaCorp 0:a725e8eab383 1178 len = 0; // no more data and socket closed or timed-out
AxedaCorp 0:a725e8eab383 1179 ok = true;
AxedaCorp 0:a725e8eab383 1180 }
AxedaCorp 0:a725e8eab383 1181 }
AxedaCorp 0:a725e8eab383 1182 UNLOCK();
AxedaCorp 0:a725e8eab383 1183 if (!ok)
AxedaCorp 0:a725e8eab383 1184 return SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 1185 }
AxedaCorp 0:a725e8eab383 1186 timer.stop();
AxedaCorp 0:a725e8eab383 1187 timer.reset();
AxedaCorp 0:a725e8eab383 1188 return cnt;
AxedaCorp 0:a725e8eab383 1189 }
AxedaCorp 0:a725e8eab383 1190
AxedaCorp 0:a725e8eab383 1191 int MDMParser::_findSocket(int handle) {
AxedaCorp 0:a725e8eab383 1192 for (int socket = 0; socket < NUMSOCKETS; socket ++) {
AxedaCorp 0:a725e8eab383 1193 if (_sockets[socket].handle == handle)
AxedaCorp 0:a725e8eab383 1194 return socket;
AxedaCorp 0:a725e8eab383 1195 }
AxedaCorp 0:a725e8eab383 1196 return SOCKET_ERROR;
AxedaCorp 0:a725e8eab383 1197 }
AxedaCorp 0:a725e8eab383 1198
AxedaCorp 0:a725e8eab383 1199 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1200
AxedaCorp 0:a725e8eab383 1201 int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param)
AxedaCorp 0:a725e8eab383 1202 {
AxedaCorp 0:a725e8eab383 1203 if ((type == TYPE_PLUS) && param && param->num) {
AxedaCorp 0:a725e8eab383 1204 // +CMGL: <ix>,...
AxedaCorp 0:a725e8eab383 1205 int ix;
AxedaCorp 0:a725e8eab383 1206 if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1)
AxedaCorp 0:a725e8eab383 1207 {
AxedaCorp 0:a725e8eab383 1208 *param->ix++ = ix;
AxedaCorp 0:a725e8eab383 1209 param->num--;
AxedaCorp 0:a725e8eab383 1210 }
AxedaCorp 0:a725e8eab383 1211 }
AxedaCorp 0:a725e8eab383 1212 return WAIT;
AxedaCorp 0:a725e8eab383 1213 }
AxedaCorp 0:a725e8eab383 1214
AxedaCorp 0:a725e8eab383 1215 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) {
AxedaCorp 0:a725e8eab383 1216 int ret = -1;
AxedaCorp 0:a725e8eab383 1217 LOCK();
AxedaCorp 0:a725e8eab383 1218 sendFormated("AT+CMGL=\"%s\"\r\n", stat);
AxedaCorp 0:a725e8eab383 1219 CMGLparam param;
AxedaCorp 0:a725e8eab383 1220 param.ix = ix;
AxedaCorp 0:a725e8eab383 1221 param.num = num;
AxedaCorp 0:a725e8eab383 1222 if (RESP_OK == waitFinalResp(_cbCMGL, &param))
AxedaCorp 0:a725e8eab383 1223 ret = num - param.num;
AxedaCorp 0:a725e8eab383 1224 UNLOCK();
AxedaCorp 0:a725e8eab383 1225 return ret;
AxedaCorp 0:a725e8eab383 1226 }
AxedaCorp 0:a725e8eab383 1227
AxedaCorp 0:a725e8eab383 1228 bool MDMParser::smsSend(const char* num, const char* buf)
AxedaCorp 0:a725e8eab383 1229 {
AxedaCorp 0:a725e8eab383 1230 bool ok = false;
AxedaCorp 0:a725e8eab383 1231 LOCK();
AxedaCorp 0:a725e8eab383 1232 sendFormated("AT+CMGS=\"%s\"\r\n",num);
AxedaCorp 0:a725e8eab383 1233 if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) {
AxedaCorp 0:a725e8eab383 1234 send(buf, strlen(buf));
AxedaCorp 0:a725e8eab383 1235 const char ctrlZ = 0x1A;
AxedaCorp 0:a725e8eab383 1236 send(&ctrlZ, sizeof(ctrlZ));
AxedaCorp 0:a725e8eab383 1237 ok = (RESP_OK == waitFinalResp());
AxedaCorp 0:a725e8eab383 1238 }
AxedaCorp 0:a725e8eab383 1239 UNLOCK();
AxedaCorp 0:a725e8eab383 1240 return ok;
AxedaCorp 0:a725e8eab383 1241 }
AxedaCorp 0:a725e8eab383 1242
AxedaCorp 0:a725e8eab383 1243 bool MDMParser::smsDelete(int ix)
AxedaCorp 0:a725e8eab383 1244 {
AxedaCorp 0:a725e8eab383 1245 bool ok = false;
AxedaCorp 0:a725e8eab383 1246 LOCK();
AxedaCorp 0:a725e8eab383 1247 sendFormated("AT+CMGD=%d\r\n",ix);
AxedaCorp 0:a725e8eab383 1248 ok = (RESP_OK == waitFinalResp());
AxedaCorp 0:a725e8eab383 1249 UNLOCK();
AxedaCorp 0:a725e8eab383 1250 return ok;
AxedaCorp 0:a725e8eab383 1251 }
AxedaCorp 0:a725e8eab383 1252
AxedaCorp 0:a725e8eab383 1253 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param)
AxedaCorp 0:a725e8eab383 1254 {
AxedaCorp 0:a725e8eab383 1255 if (param) {
AxedaCorp 0:a725e8eab383 1256 if (type == TYPE_PLUS) {
AxedaCorp 0:a725e8eab383 1257 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) {
AxedaCorp 0:a725e8eab383 1258 }
AxedaCorp 0:a725e8eab383 1259 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) {
AxedaCorp 0:a725e8eab383 1260 memcpy(param->buf, buf, len-2);
AxedaCorp 0:a725e8eab383 1261 param->buf[len-2] = '\0';
AxedaCorp 0:a725e8eab383 1262 }
AxedaCorp 0:a725e8eab383 1263 }
AxedaCorp 0:a725e8eab383 1264 return WAIT;
AxedaCorp 0:a725e8eab383 1265 }
AxedaCorp 0:a725e8eab383 1266
AxedaCorp 0:a725e8eab383 1267 bool MDMParser::smsRead(int ix, char* num, char* buf, int len)
AxedaCorp 0:a725e8eab383 1268 {
AxedaCorp 0:a725e8eab383 1269 bool ok = false;
AxedaCorp 0:a725e8eab383 1270 LOCK();
AxedaCorp 0:a725e8eab383 1271 CMGRparam param;
AxedaCorp 0:a725e8eab383 1272 param.num = num;
AxedaCorp 0:a725e8eab383 1273 param.buf = buf;
AxedaCorp 0:a725e8eab383 1274 sendFormated("AT+CMGR=%d\r\n",ix);
AxedaCorp 0:a725e8eab383 1275 ok = (RESP_OK == waitFinalResp(_cbCMGR, &param));
AxedaCorp 0:a725e8eab383 1276 UNLOCK();
AxedaCorp 0:a725e8eab383 1277 return ok;
AxedaCorp 0:a725e8eab383 1278 }
AxedaCorp 0:a725e8eab383 1279
AxedaCorp 0:a725e8eab383 1280 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1281
AxedaCorp 0:a725e8eab383 1282 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp)
AxedaCorp 0:a725e8eab383 1283 {
AxedaCorp 0:a725e8eab383 1284 if ((type == TYPE_PLUS) && resp) {
AxedaCorp 0:a725e8eab383 1285 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..);
AxedaCorp 0:a725e8eab383 1286 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) {
AxedaCorp 0:a725e8eab383 1287 /*nothing*/
AxedaCorp 0:a725e8eab383 1288 }
AxedaCorp 0:a725e8eab383 1289 }
AxedaCorp 0:a725e8eab383 1290 return WAIT;
AxedaCorp 0:a725e8eab383 1291 }
AxedaCorp 0:a725e8eab383 1292
AxedaCorp 0:a725e8eab383 1293 bool MDMParser::ussdCommand(const char* cmd, char* buf)
AxedaCorp 0:a725e8eab383 1294 {
AxedaCorp 0:a725e8eab383 1295 bool ok = false;
AxedaCorp 0:a725e8eab383 1296 LOCK();
AxedaCorp 0:a725e8eab383 1297 *buf = '\0';
AxedaCorp 0:a725e8eab383 1298 if (_dev.dev != DEV_LISA_C200) {
AxedaCorp 0:a725e8eab383 1299 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
AxedaCorp 0:a725e8eab383 1300 ok = (RESP_OK == waitFinalResp(_cbCUSD, buf));
AxedaCorp 0:a725e8eab383 1301 }
AxedaCorp 0:a725e8eab383 1302 UNLOCK();
AxedaCorp 0:a725e8eab383 1303 return ok;
AxedaCorp 0:a725e8eab383 1304 }
AxedaCorp 0:a725e8eab383 1305
AxedaCorp 0:a725e8eab383 1306 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1307
AxedaCorp 0:a725e8eab383 1308 bool MDMParser::delFile(const char* filename)
AxedaCorp 0:a725e8eab383 1309 {
AxedaCorp 0:a725e8eab383 1310 bool ok = false;
AxedaCorp 0:a725e8eab383 1311 LOCK();
AxedaCorp 0:a725e8eab383 1312 sendFormated("AT+UDELFILE=\"%s\"\r\n", filename);
AxedaCorp 0:a725e8eab383 1313 ok = (RESP_OK == waitFinalResp());
AxedaCorp 0:a725e8eab383 1314 UNLOCK();
AxedaCorp 0:a725e8eab383 1315 return ok;
AxedaCorp 0:a725e8eab383 1316 }
AxedaCorp 0:a725e8eab383 1317
AxedaCorp 0:a725e8eab383 1318 int MDMParser::writeFile(const char* filename, const char* buf, int len)
AxedaCorp 0:a725e8eab383 1319 {
AxedaCorp 0:a725e8eab383 1320 bool ok = false;
AxedaCorp 0:a725e8eab383 1321 LOCK();
AxedaCorp 0:a725e8eab383 1322 sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len);
AxedaCorp 0:a725e8eab383 1323 if (RESP_PROMPT == waitFinalResp()) {
AxedaCorp 0:a725e8eab383 1324 send(buf, len);
AxedaCorp 0:a725e8eab383 1325 ok = (RESP_OK == waitFinalResp());
AxedaCorp 0:a725e8eab383 1326 }
AxedaCorp 0:a725e8eab383 1327 UNLOCK();
AxedaCorp 0:a725e8eab383 1328 return ok ? len : -1;
AxedaCorp 0:a725e8eab383 1329 }
AxedaCorp 0:a725e8eab383 1330
AxedaCorp 0:a725e8eab383 1331 int MDMParser::readFile(const char* filename, char* buf, int len)
AxedaCorp 0:a725e8eab383 1332 {
AxedaCorp 0:a725e8eab383 1333 URDFILEparam param;
AxedaCorp 0:a725e8eab383 1334 param.filename = filename;
AxedaCorp 0:a725e8eab383 1335 param.buf = buf;
AxedaCorp 0:a725e8eab383 1336 param.sz = len;
AxedaCorp 0:a725e8eab383 1337 param.len = 0;
AxedaCorp 0:a725e8eab383 1338 LOCK();
AxedaCorp 0:a725e8eab383 1339 sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len);
AxedaCorp 0:a725e8eab383 1340 if (RESP_OK != waitFinalResp(_cbURDFILE, &param))
AxedaCorp 0:a725e8eab383 1341 param.len = -1;
AxedaCorp 0:a725e8eab383 1342 UNLOCK();
AxedaCorp 0:a725e8eab383 1343 return param.len;
AxedaCorp 0:a725e8eab383 1344 }
AxedaCorp 0:a725e8eab383 1345
AxedaCorp 0:a725e8eab383 1346 int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param)
AxedaCorp 0:a725e8eab383 1347 {
AxedaCorp 0:a725e8eab383 1348 if ((type == TYPE_PLUS) && param && param->filename && param->buf) {
AxedaCorp 0:a725e8eab383 1349 char filename[48];
AxedaCorp 0:a725e8eab383 1350 int sz;
AxedaCorp 0:a725e8eab383 1351 if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) &&
AxedaCorp 0:a725e8eab383 1352 (0 == strcmp(param->filename, filename)) &&
AxedaCorp 0:a725e8eab383 1353 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
AxedaCorp 0:a725e8eab383 1354 param->len = (sz < param->sz) ? sz : param->sz;
AxedaCorp 0:a725e8eab383 1355 memcpy(param->buf, &buf[len-1-sz], param->len);
AxedaCorp 0:a725e8eab383 1356 }
AxedaCorp 0:a725e8eab383 1357 }
AxedaCorp 0:a725e8eab383 1358 return WAIT;
AxedaCorp 0:a725e8eab383 1359 }
AxedaCorp 0:a725e8eab383 1360
AxedaCorp 0:a725e8eab383 1361 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1362 bool MDMParser::setDebug(int level)
AxedaCorp 0:a725e8eab383 1363 {
AxedaCorp 0:a725e8eab383 1364 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 1365 if ((_debugLevel >= 0) && (level >= 0)) {
AxedaCorp 0:a725e8eab383 1366 _debugLevel = level;
AxedaCorp 0:a725e8eab383 1367 return true;
AxedaCorp 0:a725e8eab383 1368 }
AxedaCorp 0:a725e8eab383 1369 #endif
AxedaCorp 0:a725e8eab383 1370 return false;
AxedaCorp 0:a725e8eab383 1371 }
AxedaCorp 0:a725e8eab383 1372
AxedaCorp 0:a725e8eab383 1373 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status,
AxedaCorp 0:a725e8eab383 1374 _DPRINT dprint, void* param)
AxedaCorp 0:a725e8eab383 1375 {
AxedaCorp 0:a725e8eab383 1376 dprint(param, "Modem::devStatus\r\n");
AxedaCorp 0:a725e8eab383 1377 const char* txtDev[] = { "Unknown", "SARA-G350", "LISA-U200", "LISA-C200", "SARA-U260", "SARA-U270", "LEON-G200" };
AxedaCorp 0:a725e8eab383 1378 if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != DEV_UNKNOWN))
AxedaCorp 0:a725e8eab383 1379 dprint(param, " Device: %s\r\n", txtDev[status->dev]);
AxedaCorp 0:a725e8eab383 1380 const char* txtLpm[] = { "Disabled", "Enabled", "Active" };
AxedaCorp 0:a725e8eab383 1381 if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm))
AxedaCorp 0:a725e8eab383 1382 dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]);
AxedaCorp 0:a725e8eab383 1383 const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" };
AxedaCorp 0:a725e8eab383 1384 if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != SIM_UNKNOWN))
AxedaCorp 0:a725e8eab383 1385 dprint(param, " SIM: %s\r\n", txtSim[status->sim]);
AxedaCorp 0:a725e8eab383 1386 if (*status->ccid)
AxedaCorp 0:a725e8eab383 1387 dprint(param, " CCID: %s\r\n", status->ccid);
AxedaCorp 0:a725e8eab383 1388 if (*status->imei)
AxedaCorp 0:a725e8eab383 1389 dprint(param, " IMEI: %s\r\n", status->imei);
AxedaCorp 0:a725e8eab383 1390 if (*status->imsi)
AxedaCorp 0:a725e8eab383 1391 dprint(param, " IMSI: %s\r\n", status->imsi);
AxedaCorp 0:a725e8eab383 1392 if (*status->meid)
AxedaCorp 0:a725e8eab383 1393 dprint(param, " MEID: %s\r\n", status->meid); // LISA-C
AxedaCorp 0:a725e8eab383 1394 if (*status->manu)
AxedaCorp 0:a725e8eab383 1395 dprint(param, " Manufacturer: %s\r\n", status->manu);
AxedaCorp 0:a725e8eab383 1396 if (*status->model)
AxedaCorp 0:a725e8eab383 1397 dprint(param, " Model: %s\r\n", status->model);
AxedaCorp 0:a725e8eab383 1398 if (*status->ver)
AxedaCorp 0:a725e8eab383 1399 dprint(param, " Version: %s\r\n", status->ver);
AxedaCorp 0:a725e8eab383 1400 }
AxedaCorp 0:a725e8eab383 1401
AxedaCorp 0:a725e8eab383 1402 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status,
AxedaCorp 0:a725e8eab383 1403 _DPRINT dprint, void* param)
AxedaCorp 0:a725e8eab383 1404 {
AxedaCorp 0:a725e8eab383 1405 dprint(param, "Modem::netStatus\r\n");
AxedaCorp 0:a725e8eab383 1406 const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" };
AxedaCorp 0:a725e8eab383 1407 if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != REG_UNKNOWN))
AxedaCorp 0:a725e8eab383 1408 dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]);
AxedaCorp 0:a725e8eab383 1409 if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != REG_UNKNOWN))
AxedaCorp 0:a725e8eab383 1410 dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]);
AxedaCorp 0:a725e8eab383 1411 const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA" };
AxedaCorp 0:a725e8eab383 1412 if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != ACT_UNKNOWN))
AxedaCorp 0:a725e8eab383 1413 dprint(param, " Access Technology: %s\r\n", txtAct[status->act]);
AxedaCorp 0:a725e8eab383 1414 if (status->rssi)
AxedaCorp 0:a725e8eab383 1415 dprint(param, " Signal Strength: %d dBm\r\n", status->rssi);
AxedaCorp 0:a725e8eab383 1416 if (status->ber)
AxedaCorp 0:a725e8eab383 1417 dprint(param, " Bit Error Rate: %d\r\n", status->ber);
AxedaCorp 0:a725e8eab383 1418 if (*status->opr)
AxedaCorp 0:a725e8eab383 1419 dprint(param, " Operator: %s\r\n", status->opr);
AxedaCorp 0:a725e8eab383 1420 if (status->lac != 0xFFFF)
AxedaCorp 0:a725e8eab383 1421 dprint(param, " Location Area Code: %04X\r\n", status->lac);
AxedaCorp 0:a725e8eab383 1422 if (status->ci != 0xFFFFFFFF)
AxedaCorp 0:a725e8eab383 1423 dprint(param, " Cell ID: %08X\r\n", status->ci);
AxedaCorp 0:a725e8eab383 1424 if (*status->num)
AxedaCorp 0:a725e8eab383 1425 dprint(param, " Phone Number: %s\r\n", status->num);
AxedaCorp 0:a725e8eab383 1426 }
AxedaCorp 0:a725e8eab383 1427
AxedaCorp 0:a725e8eab383 1428 void MDMParser::dumpIp(MDMParser::IP ip,
AxedaCorp 0:a725e8eab383 1429 _DPRINT dprint, void* param)
AxedaCorp 0:a725e8eab383 1430 {
AxedaCorp 0:a725e8eab383 1431 if (ip != NOIP)
AxedaCorp 0:a725e8eab383 1432 dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip));
AxedaCorp 0:a725e8eab383 1433 }
AxedaCorp 0:a725e8eab383 1434
AxedaCorp 0:a725e8eab383 1435 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1436 int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end)
AxedaCorp 0:a725e8eab383 1437 {
AxedaCorp 0:a725e8eab383 1438 int o = 0;
AxedaCorp 0:a725e8eab383 1439 if (sta) {
AxedaCorp 0:a725e8eab383 1440 while (*sta) {
AxedaCorp 0:a725e8eab383 1441 if (++o > len) return WAIT;
AxedaCorp 0:a725e8eab383 1442 char ch = pipe->next();
AxedaCorp 0:a725e8eab383 1443 if (*sta++ != ch) return NOT_FOUND;
AxedaCorp 0:a725e8eab383 1444 }
AxedaCorp 0:a725e8eab383 1445 }
AxedaCorp 0:a725e8eab383 1446 if (!end) return o; // no termination
AxedaCorp 0:a725e8eab383 1447 // at least any char
AxedaCorp 0:a725e8eab383 1448 if (++o > len) return WAIT;
AxedaCorp 0:a725e8eab383 1449 pipe->next();
AxedaCorp 0:a725e8eab383 1450 // check the end
AxedaCorp 0:a725e8eab383 1451 int x = 0;
AxedaCorp 0:a725e8eab383 1452 while (end[x]) {
AxedaCorp 0:a725e8eab383 1453 if (++o > len) return WAIT;
AxedaCorp 0:a725e8eab383 1454 char ch = pipe->next();
AxedaCorp 0:a725e8eab383 1455 x = (end[x] == ch) ? x + 1 :
AxedaCorp 0:a725e8eab383 1456 (end[0] == ch) ? 1 :
AxedaCorp 0:a725e8eab383 1457 0;
AxedaCorp 0:a725e8eab383 1458 }
AxedaCorp 0:a725e8eab383 1459 return o;
AxedaCorp 0:a725e8eab383 1460 }
AxedaCorp 0:a725e8eab383 1461
AxedaCorp 0:a725e8eab383 1462 int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt)
AxedaCorp 0:a725e8eab383 1463 {
AxedaCorp 0:a725e8eab383 1464 int o = 0;
AxedaCorp 0:a725e8eab383 1465 int num = 0;
AxedaCorp 0:a725e8eab383 1466 if (fmt) {
AxedaCorp 0:a725e8eab383 1467 while (*fmt) {
AxedaCorp 0:a725e8eab383 1468 if (++o > len) return WAIT;
AxedaCorp 0:a725e8eab383 1469 char ch = pipe->next();
AxedaCorp 0:a725e8eab383 1470 if (*fmt == '%') {
AxedaCorp 0:a725e8eab383 1471 fmt++;
AxedaCorp 0:a725e8eab383 1472 if (*fmt == 'd') { // numeric
AxedaCorp 0:a725e8eab383 1473 fmt ++;
AxedaCorp 0:a725e8eab383 1474 num = 0;
AxedaCorp 0:a725e8eab383 1475 while (ch >= '0' && ch <= '9') {
AxedaCorp 0:a725e8eab383 1476 num = num * 10 + (ch - '0');
AxedaCorp 0:a725e8eab383 1477 if (++o > len) return WAIT;
AxedaCorp 0:a725e8eab383 1478 ch = pipe->next();
AxedaCorp 0:a725e8eab383 1479 }
AxedaCorp 0:a725e8eab383 1480 }
AxedaCorp 0:a725e8eab383 1481 else if (*fmt == 'c') { // char buffer (takes last numeric as length)
AxedaCorp 0:a725e8eab383 1482 fmt ++;
AxedaCorp 0:a725e8eab383 1483 while (num --) {
AxedaCorp 0:a725e8eab383 1484 if (++o > len) return WAIT;
AxedaCorp 0:a725e8eab383 1485 ch = pipe->next();
AxedaCorp 0:a725e8eab383 1486 }
AxedaCorp 0:a725e8eab383 1487 }
AxedaCorp 0:a725e8eab383 1488 else if (*fmt == 's') {
AxedaCorp 0:a725e8eab383 1489 fmt ++;
AxedaCorp 0:a725e8eab383 1490 if (ch != '\"') return NOT_FOUND;
AxedaCorp 0:a725e8eab383 1491 do {
AxedaCorp 0:a725e8eab383 1492 if (++o > len) return WAIT;
AxedaCorp 0:a725e8eab383 1493 ch = pipe->next();
AxedaCorp 0:a725e8eab383 1494 } while (ch != '\"');
AxedaCorp 0:a725e8eab383 1495 if (++o > len) return WAIT;
AxedaCorp 0:a725e8eab383 1496 ch = pipe->next();
AxedaCorp 0:a725e8eab383 1497 }
AxedaCorp 0:a725e8eab383 1498 }
AxedaCorp 0:a725e8eab383 1499 if (*fmt++ != ch) return NOT_FOUND;
AxedaCorp 0:a725e8eab383 1500 }
AxedaCorp 0:a725e8eab383 1501 }
AxedaCorp 0:a725e8eab383 1502 return o;
AxedaCorp 0:a725e8eab383 1503 }
AxedaCorp 0:a725e8eab383 1504
AxedaCorp 0:a725e8eab383 1505 int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len)
AxedaCorp 0:a725e8eab383 1506 {
AxedaCorp 0:a725e8eab383 1507 int unkn = 0;
AxedaCorp 0:a725e8eab383 1508 int sz = pipe->size();
AxedaCorp 0:a725e8eab383 1509 int fr = pipe->free();
AxedaCorp 0:a725e8eab383 1510 if (len > sz)
AxedaCorp 0:a725e8eab383 1511 len = sz;
AxedaCorp 0:a725e8eab383 1512 while (len > 0)
AxedaCorp 0:a725e8eab383 1513 {
AxedaCorp 0:a725e8eab383 1514 static struct {
AxedaCorp 0:a725e8eab383 1515 const char* fmt; int type;
AxedaCorp 0:a725e8eab383 1516 } lutF[] = {
AxedaCorp 0:a725e8eab383 1517 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS },
AxedaCorp 0:a725e8eab383 1518 { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS },
AxedaCorp 0:a725e8eab383 1519 { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS },
AxedaCorp 0:a725e8eab383 1520 };
AxedaCorp 0:a725e8eab383 1521 static struct {
AxedaCorp 0:a725e8eab383 1522 const char* sta; const char* end; int type;
AxedaCorp 0:a725e8eab383 1523 } lut[] = {
AxedaCorp 0:a725e8eab383 1524 { "\r\nOK\r\n", NULL, TYPE_OK },
AxedaCorp 0:a725e8eab383 1525 { "\r\nERROR\r\n", NULL, TYPE_ERROR },
AxedaCorp 0:a725e8eab383 1526 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR },
AxedaCorp 0:a725e8eab383 1527 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR },
AxedaCorp 0:a725e8eab383 1528 { "\r\nRING\r\n", NULL, TYPE_RING },
AxedaCorp 0:a725e8eab383 1529 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT },
AxedaCorp 0:a725e8eab383 1530 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER },
AxedaCorp 0:a725e8eab383 1531 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE },
AxedaCorp 0:a725e8eab383 1532 { "\r\nBUSY\r\n", NULL, TYPE_BUSY },
AxedaCorp 0:a725e8eab383 1533 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER },
AxedaCorp 0:a725e8eab383 1534 { "\r\n+", "\r\n", TYPE_PLUS },
AxedaCorp 0:a725e8eab383 1535 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets
AxedaCorp 0:a725e8eab383 1536 { "\r\n>", NULL, TYPE_PROMPT }, // SMS
AxedaCorp 0:a725e8eab383 1537 { "\n>", NULL, TYPE_PROMPT }, // File
AxedaCorp 0:a725e8eab383 1538 };
AxedaCorp 0:a725e8eab383 1539 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) {
AxedaCorp 0:a725e8eab383 1540 pipe->set(unkn);
AxedaCorp 0:a725e8eab383 1541 int ln = _parseFormated(pipe, len, lutF[i].fmt);
AxedaCorp 0:a725e8eab383 1542 if (ln == WAIT && fr)
AxedaCorp 0:a725e8eab383 1543 return WAIT;
AxedaCorp 0:a725e8eab383 1544 if ((ln != NOT_FOUND) && (unkn > 0))
AxedaCorp 0:a725e8eab383 1545 return TYPE_UNKNOWN | pipe->get(buf, unkn);
AxedaCorp 0:a725e8eab383 1546 if (ln > 0)
AxedaCorp 0:a725e8eab383 1547 return lutF[i].type | pipe->get(buf, ln);
AxedaCorp 0:a725e8eab383 1548 }
AxedaCorp 0:a725e8eab383 1549 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) {
AxedaCorp 0:a725e8eab383 1550 pipe->set(unkn);
AxedaCorp 0:a725e8eab383 1551 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end);
AxedaCorp 0:a725e8eab383 1552 if (ln == WAIT && fr)
AxedaCorp 0:a725e8eab383 1553 return WAIT;
AxedaCorp 0:a725e8eab383 1554 if ((ln != NOT_FOUND) && (unkn > 0))
AxedaCorp 0:a725e8eab383 1555 return TYPE_UNKNOWN | pipe->get(buf, unkn);
AxedaCorp 0:a725e8eab383 1556 if (ln > 0)
AxedaCorp 0:a725e8eab383 1557 return lut[i].type | pipe->get(buf, ln);
AxedaCorp 0:a725e8eab383 1558 }
AxedaCorp 0:a725e8eab383 1559 // UNKNOWN
AxedaCorp 0:a725e8eab383 1560 unkn ++;
AxedaCorp 0:a725e8eab383 1561 len--;
AxedaCorp 0:a725e8eab383 1562 }
AxedaCorp 0:a725e8eab383 1563 return WAIT;
AxedaCorp 0:a725e8eab383 1564 }
AxedaCorp 0:a725e8eab383 1565
AxedaCorp 0:a725e8eab383 1566 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1567 // Serial Implementation
AxedaCorp 0:a725e8eab383 1568 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1569
AxedaCorp 0:a725e8eab383 1570 /*! Helper Dev Null Device
AxedaCorp 0:a725e8eab383 1571 Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout
AxedaCorp 0:a725e8eab383 1572 is shared with the serial port of the modem. Having printfs inbetween the
AxedaCorp 0:a725e8eab383 1573 AT commands you cause a failure of the modem.
AxedaCorp 0:a725e8eab383 1574 */
AxedaCorp 0:a725e8eab383 1575 class DevNull : public Stream {
AxedaCorp 0:a725e8eab383 1576 public:
AxedaCorp 0:a725e8eab383 1577 DevNull() : Stream(_name+1) { } //!< Constructor
AxedaCorp 0:a725e8eab383 1578 void claim(const char* mode, FILE* file)
AxedaCorp 0:a725e8eab383 1579 { freopen(_name, mode, file); } //!< claim a stream
AxedaCorp 0:a725e8eab383 1580 protected:
AxedaCorp 0:a725e8eab383 1581 virtual int _getc() { return EOF; } //!< Nothing
AxedaCorp 0:a725e8eab383 1582 virtual int _putc(int c) { return c; } //!< Discard
AxedaCorp 0:a725e8eab383 1583 static const char* _name; //!< File name
AxedaCorp 0:a725e8eab383 1584 };
AxedaCorp 0:a725e8eab383 1585 const char* DevNull::_name = "/null"; //!< the null device name
AxedaCorp 0:a725e8eab383 1586 static DevNull null; //!< the null device
AxedaCorp 0:a725e8eab383 1587 MDMSerial* MDMSerial::mdmInst;
AxedaCorp 0:a725e8eab383 1588
AxedaCorp 0:a725e8eab383 1589 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/,
AxedaCorp 0:a725e8eab383 1590 int baudrate /*= MDMBAUD*/,
AxedaCorp 0:a725e8eab383 1591 #if DEVICE_SERIAL_FC
AxedaCorp 0:a725e8eab383 1592 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/,
AxedaCorp 0:a725e8eab383 1593 #endif
AxedaCorp 0:a725e8eab383 1594 int rxSize /*= 256*/, int txSize /*= 128*/) :
AxedaCorp 0:a725e8eab383 1595 SerialPipe(tx, rx, rxSize, txSize)
AxedaCorp 0:a725e8eab383 1596 { mdmInst=this;
AxedaCorp 0:a725e8eab383 1597 if (rx == USBRX)
AxedaCorp 0:a725e8eab383 1598 null.claim("r", stdin);
AxedaCorp 0:a725e8eab383 1599 if (tx == USBTX) {
AxedaCorp 0:a725e8eab383 1600 null.claim("w", stdout);
AxedaCorp 0:a725e8eab383 1601 null.claim("w", stderr);
AxedaCorp 0:a725e8eab383 1602 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 1603 _debugLevel = -1;
AxedaCorp 0:a725e8eab383 1604 #endif
AxedaCorp 0:a725e8eab383 1605 }
AxedaCorp 0:a725e8eab383 1606 #ifdef TARGET_UBLOX_C027
AxedaCorp 0:a725e8eab383 1607 _onboard = (tx == MDMTXD) && (rx == MDMRXD);
AxedaCorp 0:a725e8eab383 1608 if (_onboard)
AxedaCorp 0:a725e8eab383 1609 c027_mdm_powerOn(false);
AxedaCorp 0:a725e8eab383 1610 #endif
AxedaCorp 0:a725e8eab383 1611 baud(baudrate);
AxedaCorp 0:a725e8eab383 1612 #if DEVICE_SERIAL_FC
AxedaCorp 0:a725e8eab383 1613 if ((rts != NC) || (cts != NC))
AxedaCorp 0:a725e8eab383 1614 {
AxedaCorp 0:a725e8eab383 1615 Flow flow = (cts == NC) ? RTS :
AxedaCorp 0:a725e8eab383 1616 (rts == NC) ? CTS : RTSCTS ;
AxedaCorp 0:a725e8eab383 1617 set_flow_control(flow, rts, cts);
AxedaCorp 0:a725e8eab383 1618 if (cts != NC) _dev.lpm = LPM_ENABLED;
AxedaCorp 0:a725e8eab383 1619 }
AxedaCorp 0:a725e8eab383 1620 #endif
AxedaCorp 0:a725e8eab383 1621 }
AxedaCorp 0:a725e8eab383 1622
AxedaCorp 0:a725e8eab383 1623 MDMSerial::~MDMSerial(void)
AxedaCorp 0:a725e8eab383 1624 {
AxedaCorp 0:a725e8eab383 1625 powerOff();
AxedaCorp 0:a725e8eab383 1626 #ifdef TARGET_UBLOX_C027
AxedaCorp 0:a725e8eab383 1627 if (_onboard)
AxedaCorp 0:a725e8eab383 1628 c027_mdm_powerOff();
AxedaCorp 0:a725e8eab383 1629 #endif
AxedaCorp 0:a725e8eab383 1630 }
AxedaCorp 0:a725e8eab383 1631
AxedaCorp 0:a725e8eab383 1632 int MDMSerial::_send(const void* buf, int len)
AxedaCorp 0:a725e8eab383 1633 {
AxedaCorp 0:a725e8eab383 1634 return put((const char*)buf, len, true/*=blocking*/);
AxedaCorp 0:a725e8eab383 1635 }
AxedaCorp 0:a725e8eab383 1636
AxedaCorp 0:a725e8eab383 1637 int MDMSerial::getLine(char* buffer, int length)
AxedaCorp 0:a725e8eab383 1638 {
AxedaCorp 0:a725e8eab383 1639 return _getLine(&_pipeRx, buffer, length);
AxedaCorp 0:a725e8eab383 1640 }
AxedaCorp 0:a725e8eab383 1641
AxedaCorp 0:a725e8eab383 1642 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1643 // USB Implementation
AxedaCorp 0:a725e8eab383 1644 // ----------------------------------------------------------------
AxedaCorp 0:a725e8eab383 1645
AxedaCorp 0:a725e8eab383 1646 #ifdef HAVE_MDMUSB
AxedaCorp 0:a725e8eab383 1647 MDMUsb::MDMUsb(void)
AxedaCorp 0:a725e8eab383 1648 {
AxedaCorp 0:a725e8eab383 1649 #ifdef MDM_DEBUG
AxedaCorp 0:a725e8eab383 1650 _debugLevel = 1;
AxedaCorp 0:a725e8eab383 1651 #endif
AxedaCorp 0:a725e8eab383 1652 #ifdef TARGET_UBLOX_C027
AxedaCorp 0:a725e8eab383 1653 _onboard = true;
AxedaCorp 0:a725e8eab383 1654 c027_mdm_powerOn(true);
AxedaCorp 0:a725e8eab383 1655 #endif
AxedaCorp 0:a725e8eab383 1656 }
AxedaCorp 0:a725e8eab383 1657
AxedaCorp 0:a725e8eab383 1658 MDMUsb::~MDMUsb(void)
AxedaCorp 0:a725e8eab383 1659 {
AxedaCorp 0:a725e8eab383 1660 powerOff();
AxedaCorp 0:a725e8eab383 1661 #ifdef TARGET_UBLOX_C027
AxedaCorp 0:a725e8eab383 1662 if (_onboard)
AxedaCorp 0:a725e8eab383 1663 c027_mdm_powerOff();
AxedaCorp 0:a725e8eab383 1664 #endif
AxedaCorp 0:a725e8eab383 1665 }
AxedaCorp 0:a725e8eab383 1666
AxedaCorp 0:a725e8eab383 1667 int MDMUsb::_send(const void* buf, int len) { return 0; }
AxedaCorp 0:a725e8eab383 1668
AxedaCorp 0:a725e8eab383 1669 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; }
AxedaCorp 0:a725e8eab383 1670
AxedaCorp 0:a725e8eab383 1671 #endif