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:
Thu Apr 20 08:44:47 2017 +0000
Revision:
139:fd9fe498f142
Parent:
137:6a7a5c4f35f6
update for additional baud rate parameter in new mbed 5

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mazgch 18:e5697801df29 1 #include "mbed.h"
mazgch 18:e5697801df29 2 #include "MDM.h"
mazgch 74:208e3e32d263 3 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 4 #include "C027_api.h"
mazgch 74:208e3e32d263 5 #endif
mazgch 85:dd8f4f0d0ca9 6 #include "MDMAPN.h"
mazgch 125:25a292afbac6 7
mazgch 74:208e3e32d263 8 #define PROFILE "0" //!< this is the psd profile used
mazgch 74:208e3e32d263 9 #define MAX_SIZE 128 //!< max expected messages
mazgch 103:197fa7920ad8 10 // num sockets
mazgch 104:c64ba749a422 11 #define NUMSOCKETS (sizeof(_sockets)/sizeof(*_sockets))
mazgch 104:c64ba749a422 12 //! test if it is a socket is ok to use
mazgch 104:c64ba749a422 13 #define ISSOCKET(s) (((s) >= 0) && ((s) < NUMSOCKETS) && (_sockets[s].handle != SOCKET_ERROR))
mazgch 75:ce6e12067d0c 14 //! check for timeout
mazgch 75:ce6e12067d0c 15 #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms()))
fdilenarda 135:cbccf4052d45 16 // num HTTP profiles
fdilenarda 135:cbccf4052d45 17 #define NUMPROFILES (sizeof(_httpProfiles)/sizeof(*_httpProfiles))
fdilenarda 135:cbccf4052d45 18 //! test if it is an HTTP profile is ok to use
fdilenarda 135:cbccf4052d45 19 #define ISPROFILE(p) (((p) >= 0) && ((p) < NUMPROFILES) && (_httpProfiles[p].handle != HTTP_PROF_ERROR))
mazgch 80:34985b4d821e 20 //! registration ok check helper
mazgch 79:291df065e345 21 #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING))
mazgch 80:34985b4d821e 22 //! registration done check helper (no need to poll further)
mazgch 79:291df065e345 23 #define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED))
mazgch 95:8282dbbe1492 24 //! helper to make sure that lock unlock pair is always balaced
mazgch 95:8282dbbe1492 25 #define LOCK() { lock()
mazgch 95:8282dbbe1492 26 //! helper to make sure that lock unlock pair is always balaced
mazgch 95:8282dbbe1492 27 #define UNLOCK() } unlock()
mazgch 79:291df065e345 28
mazgch 74:208e3e32d263 29 #ifdef MDM_DEBUG
mazgch 95:8282dbbe1492 30 #if 1 // colored terminal output using ANSI escape sequences
mazgch 95:8282dbbe1492 31 #define COL(c) "\033[" c
mazgch 95:8282dbbe1492 32 #else
mazgch 95:8282dbbe1492 33 #define COL(c)
mazgch 95:8282dbbe1492 34 #endif
mazgch 95:8282dbbe1492 35 #define DEF COL("39m")
mazgch 95:8282dbbe1492 36 #define BLA COL("30m")
mazgch 95:8282dbbe1492 37 #define RED COL("31m")
mazgch 95:8282dbbe1492 38 #define GRE COL("32m")
mazgch 95:8282dbbe1492 39 #define YEL COL("33m")
mazgch 95:8282dbbe1492 40 #define BLU COL("34m")
mazgch 95:8282dbbe1492 41 #define MAG COL("35m")
mazgch 95:8282dbbe1492 42 #define CYA COL("36m")
mazgch 95:8282dbbe1492 43 #define WHY COL("37m")
mazgch 95:8282dbbe1492 44
mazgch 74:208e3e32d263 45 void dumpAtCmd(const char* buf, int len)
mazgch 21:c4d64830bf02 46 {
mazgch 75:ce6e12067d0c 47 ::printf(" %3d \"", len);
mazgch 21:c4d64830bf02 48 while (len --) {
mazgch 21:c4d64830bf02 49 char ch = *buf++;
mazgch 75:ce6e12067d0c 50 if ((ch > 0x1F) && (ch != 0x7F)) { // is printable
mazgch 75:ce6e12067d0c 51 if (ch == '%') ::printf("%%");
mazgch 75:ce6e12067d0c 52 else if (ch == '"') ::printf("\\\"");
mazgch 75:ce6e12067d0c 53 else if (ch == '\\') ::printf("\\\\");
mazgch 75:ce6e12067d0c 54 else putchar(ch);
mazgch 75:ce6e12067d0c 55 } else {
mazgch 75:ce6e12067d0c 56 if (ch == '\a') ::printf("\\a"); // BEL (0x07)
mazgch 75:ce6e12067d0c 57 else if (ch == '\b') ::printf("\\b"); // Backspace (0x08)
mazgch 75:ce6e12067d0c 58 else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09)
mazgch 75:ce6e12067d0c 59 else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A)
mazgch 75:ce6e12067d0c 60 else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B)
mazgch 75:ce6e12067d0c 61 else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C)
mazgch 75:ce6e12067d0c 62 else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D)
mazgch 76:f7c3dd568dae 63 else ::printf("\\x%02x", (unsigned char)ch);
mazgch 75:ce6e12067d0c 64 }
mazgch 21:c4d64830bf02 65 }
mazgch 75:ce6e12067d0c 66 ::printf("\"\r\n");
mazgch 21:c4d64830bf02 67 }
mazgch 74:208e3e32d263 68
mazgch 117:74e4e0109a9e 69 void MDMParser::_debugPrint(int level, const char* color, const char* format, ...)
mazgch 117:74e4e0109a9e 70 {
mazgch 117:74e4e0109a9e 71 if (_debugLevel >= level)
mazgch 117:74e4e0109a9e 72 {
mazgch 117:74e4e0109a9e 73 va_list args;
mazgch 117:74e4e0109a9e 74 va_start (args, format);
mazgch 117:74e4e0109a9e 75 if (color) ::printf(color);
mazgch 117:74e4e0109a9e 76 ::vprintf(format, args);
mazgch 117:74e4e0109a9e 77 if (color) ::printf(DEF);
mazgch 117:74e4e0109a9e 78 va_end (args);
mazgch 117:74e4e0109a9e 79 }
mazgch 117:74e4e0109a9e 80 }
mazgch 117:74e4e0109a9e 81
mazgch 117:74e4e0109a9e 82 #define ERROR(...) _debugPrint(0, RED, __VA_ARGS__)
mazgch 117:74e4e0109a9e 83 #define INFO(...) _debugPrint(1, GRE, __VA_ARGS__)
mazgch 117:74e4e0109a9e 84 #define TRACE(...) _debugPrint(2, DEF, __VA_ARGS__)
mazgch 117:74e4e0109a9e 85 #define TEST(...) _debugPrint(3, CYA, __VA_ARGS__)
mazgch 74:208e3e32d263 86
mazgch 74:208e3e32d263 87 #else
mazgch 74:208e3e32d263 88
mazgch 75:ce6e12067d0c 89 #define ERROR(...) (void)0 // no tracing
mazgch 95:8282dbbe1492 90 #define TEST(...) (void)0 // no tracing
mazgch 74:208e3e32d263 91 #define INFO(...) (void)0 // no tracing
mazgch 74:208e3e32d263 92 #define TRACE(...) (void)0 // no tracing
mazgch 74:208e3e32d263 93
mazgch 31:a0bed6c1e05d 94 #endif
mazgch 21:c4d64830bf02 95
mazgch 44:9d12223b78ff 96 MDMParser* MDMParser::inst;
mazgch 44:9d12223b78ff 97
mazgch 21:c4d64830bf02 98 MDMParser::MDMParser(void)
mazgch 21:c4d64830bf02 99 {
mazgch 44:9d12223b78ff 100 inst = this;
mazgch 31:a0bed6c1e05d 101 memset(&_dev, 0, sizeof(_dev));
mazgch 31:a0bed6c1e05d 102 memset(&_net, 0, sizeof(_net));
mazgch 54:7ba8e4c218e2 103 _net.lac = 0xFFFF;
mazgch 54:7ba8e4c218e2 104 _net.ci = 0xFFFFFFFF;
mazgch 35:9275215a3a5b 105 _ip = NOIP;
mazgch 76:f7c3dd568dae 106 _init = false;
mazgch 31:a0bed6c1e05d 107 memset(_sockets, 0, sizeof(_sockets));
mazgch 104:c64ba749a422 108 for (int socket = 0; socket < NUMSOCKETS; socket ++)
mazgch 103:197fa7920ad8 109 _sockets[socket].handle = SOCKET_ERROR;
fdilenarda 135:cbccf4052d45 110 memset(_httpProfiles, 0, sizeof(_httpProfiles));
fdilenarda 135:cbccf4052d45 111 for (int profile = 0; profile < NUMPROFILES; profile ++)
fdilenarda 135:cbccf4052d45 112 _httpProfiles[profile].handle = HTTP_PROF_ERROR;
mazgch 74:208e3e32d263 113 #ifdef MDM_DEBUG
mazgch 76:f7c3dd568dae 114 _debugLevel = 1;
mazgch 74:208e3e32d263 115 _debugTime.start();
mazgch 74:208e3e32d263 116 #endif
mazgch 74:208e3e32d263 117 }
mazgch 74:208e3e32d263 118
mazgch 18:e5697801df29 119 int MDMParser::send(const char* buf, int len)
mazgch 18:e5697801df29 120 {
mazgch 74:208e3e32d263 121 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 122 if (_debugLevel >= 3) {
mazgch 75:ce6e12067d0c 123 ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001);
mazgch 74:208e3e32d263 124 dumpAtCmd(buf,len);
mazgch 74:208e3e32d263 125 }
mazgch 21:c4d64830bf02 126 #endif
mazgch 18:e5697801df29 127 return _send(buf, len);
mazgch 18:e5697801df29 128 }
mazgch 18:e5697801df29 129
mazgch 21:c4d64830bf02 130 int MDMParser::sendFormated(const char* format, ...) {
mazgch 21:c4d64830bf02 131 char buf[MAX_SIZE];
mazgch 21:c4d64830bf02 132 va_list args;
mazgch 21:c4d64830bf02 133 va_start(args, format);
mazgch 21:c4d64830bf02 134 int len = vsnprintf(buf,sizeof(buf), format, args);
mazgch 21:c4d64830bf02 135 va_end(args);
mazgch 21:c4d64830bf02 136 return send(buf, len);
mazgch 21:c4d64830bf02 137 }
mazgch 21:c4d64830bf02 138
mazgch 26:07be5faf8925 139 int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/,
mazgch 26:07be5faf8925 140 void* param /* = NULL*/,
mazgch 26:07be5faf8925 141 int timeout_ms /*= 5000*/)
mazgch 26:07be5faf8925 142 {
mazgch 69:4d6fa520dfca 143 char buf[MAX_SIZE + 64 /* add some more space for framing */];
mazgch 21:c4d64830bf02 144 Timer timer;
mazgch 21:c4d64830bf02 145 timer.start();
mazgch 21:c4d64830bf02 146 do {
mazgch 21:c4d64830bf02 147 int ret = getLine(buf, sizeof(buf));
mazgch 74:208e3e32d263 148 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 149 if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND))
mazgch 21:c4d64830bf02 150 {
mazgch 31:a0bed6c1e05d 151 int len = LENGTH(ret);
mazgch 31:a0bed6c1e05d 152 int type = TYPE(ret);
mazgch 95:8282dbbe1492 153 const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF :
mazgch 95:8282dbbe1492 154 (type == TYPE_TEXT) ? MAG "TXT" DEF :
mazgch 95:8282dbbe1492 155 (type == TYPE_OK ) ? GRE "OK " DEF :
mazgch 95:8282dbbe1492 156 (type == TYPE_ERROR) ? RED "ERR" DEF :
mazgch 95:8282dbbe1492 157 (type == TYPE_PLUS) ? CYA " + " DEF :
mazgch 95:8282dbbe1492 158 (type == TYPE_PROMPT) ? BLU " > " DEF :
mazgch 95:8282dbbe1492 159 "..." ;
mazgch 75:ce6e12067d0c 160 ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
mazgch 74:208e3e32d263 161 dumpAtCmd(buf, len);
mazgch 21:c4d64830bf02 162 }
mazgch 21:c4d64830bf02 163 #endif
mazgch 21:c4d64830bf02 164 if ((ret != WAIT) && (ret != NOT_FOUND))
mazgch 18:e5697801df29 165 {
mazgch 21:c4d64830bf02 166 int type = TYPE(ret);
mazgch 21:c4d64830bf02 167 // handle unsolicited commands here
mazgch 21:c4d64830bf02 168 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 169 const char* cmd = buf+3;
mazgch 54:7ba8e4c218e2 170 int a, b, c, d, r;
mazgch 23:05a1aeeb5fd9 171 char s[32];
msinig 133:57b208dd96fb 172
mazgch 31:a0bed6c1e05d 173 // SMS Command ---------------------------------
mazgch 31:a0bed6c1e05d 174 // +CNMI: <mem>,<index>
mazgch 31:a0bed6c1e05d 175 if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) {
mazgch 31:a0bed6c1e05d 176 TRACE("New SMS at index %d\r\n", a);
mazgch 21:c4d64830bf02 177 // Socket Specific Command ---------------------------------
mazgch 21:c4d64830bf02 178 // +UUSORD: <socket>,<length>
mazgch 103:197fa7920ad8 179 } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2)) {
mazgch 103:197fa7920ad8 180 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 181 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
mazgch 103:197fa7920ad8 182 if (socket != SOCKET_ERROR)
mazgch 103:197fa7920ad8 183 _sockets[socket].pending = b;
mazgch 69:4d6fa520dfca 184 // +UUSORF: <socket>,<length>
mazgch 103:197fa7920ad8 185 } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2)) {
mazgch 103:197fa7920ad8 186 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 187 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
mazgch 103:197fa7920ad8 188 if (socket != SOCKET_ERROR)
mazgch 103:197fa7920ad8 189 _sockets[socket].pending = b;
mazgch 21:c4d64830bf02 190 // +UUSOCL: <socket>
mazgch 103:197fa7920ad8 191 } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1)) {
mazgch 103:197fa7920ad8 192 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 193 TRACE("Socket %d: handle %d closed by remote host\r\n", socket, a);
mazgch 103:197fa7920ad8 194 if ((socket != SOCKET_ERROR) && _sockets[socket].connected)
msinig 136:8dc8f48275fc 195 _sockets[socket].connected = false;
msinig 133:57b208dd96fb 196 // +UULOC: <date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,<sensor_used>,<SV_used>,<antenna_status>, <jamming_status>
msinig 133:57b208dd96fb 197 }else if (sscanf(cmd, "UULOC: %d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%d,%*d,%*d",\
msinig 136:8dc8f48275fc 198 &_loc[0].time.tm_mday, &_loc[0].time.tm_mon, &_loc[0].time.tm_year, &_loc[0].time.tm_hour, &_loc[0].time.tm_min, &_loc[0].time.tm_sec,\
msinig 136:8dc8f48275fc 199 &_loc[0].latitude, &_loc[0].longitude, &_loc[0].altitutude, &_loc[0].uncertainty, &_loc[0].speed, &_loc[0].direction, &_loc[0].verticalAcc, \
msinig 136:8dc8f48275fc 200 &b, &_loc[0].svUsed) == 15) {
msinig 136:8dc8f48275fc 201 TRACE("Parsed UULOC position at index 0\r\n");
msinig 136:8dc8f48275fc 202 _loc[0].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST;
msinig 136:8dc8f48275fc 203 _loc[0].time.tm_mon -= 1;
msinig 136:8dc8f48275fc 204 _loc[0].time.tm_wday=0;
msinig 136:8dc8f48275fc 205 _loc[0].time.tm_yday=0;
msinig 136:8dc8f48275fc 206 _loc[0].validData = true;
msinig 136:8dc8f48275fc 207 _locExpPos=1;
msinig 136:8dc8f48275fc 208 _locRcvPos++;
msinig 136:8dc8f48275fc 209 // +UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,,<SV_used>,<antenna_status>, <jamming_status>
msinig 136:8dc8f48275fc 210 }else if (sscanf(cmd, "UULOC: %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%*d,%*d",\
msinig 136:8dc8f48275fc 211 &a,&_locExpPos,&b, \
msinig 136:8dc8f48275fc 212 &_loc[CELL_MAX_HYP-1].time.tm_mday, &_loc[CELL_MAX_HYP-1].time.tm_mon, &_loc[CELL_MAX_HYP-1].time.tm_year, &_loc[CELL_MAX_HYP-1].time.tm_hour, &_loc[CELL_MAX_HYP-1].time.tm_min, &_loc[CELL_MAX_HYP-1].time.tm_sec,\
msinig 136:8dc8f48275fc 213 &_loc[CELL_MAX_HYP-1].latitude, &_loc[CELL_MAX_HYP-1].longitude, &_loc[CELL_MAX_HYP-1].altitutude, &_loc[CELL_MAX_HYP-1].uncertainty, &_loc[CELL_MAX_HYP-1].speed, &_loc[CELL_MAX_HYP-1].direction, &_loc[CELL_MAX_HYP-1].verticalAcc, \
msinig 136:8dc8f48275fc 214 &_loc[CELL_MAX_HYP-1].svUsed) == 17) {
msinig 136:8dc8f48275fc 215 if (--a>=0){
msinig 136:8dc8f48275fc 216 TRACE("Parsed UULOC position at index %d\r\n",a);
msinig 136:8dc8f48275fc 217 memcpy(&_loc[a], &_loc[CELL_MAX_HYP-1], sizeof(*_loc));
msinig 136:8dc8f48275fc 218 _loc[a].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST;
msinig 136:8dc8f48275fc 219 _loc[a].time.tm_mon -= 1;
msinig 136:8dc8f48275fc 220 _loc[a].time.tm_wday=0;
msinig 136:8dc8f48275fc 221 _loc[a].time.tm_yday=0;
msinig 136:8dc8f48275fc 222 _loc[a].validData = true;
msinig 136:8dc8f48275fc 223 _locRcvPos++;
msinig 136:8dc8f48275fc 224 }
msinig 136:8dc8f48275fc 225 //+UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<lat50>,<long50>,<major50>,<minor50>,<orientation50>,<confidence50>[,<lat95>,<long95>,<major95>,<minor95>,<orientation95>,<confidence95>]
msinig 136:8dc8f48275fc 226 }else if (sscanf(cmd, "UULOC: %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%*f,%*f,%d,%*d,%*d,%*d",\
msinig 136:8dc8f48275fc 227 &a,&_locExpPos,&b, \
msinig 136:8dc8f48275fc 228 &_loc[CELL_MAX_HYP-1].time.tm_mday, &_loc[CELL_MAX_HYP-1].time.tm_mon, &_loc[CELL_MAX_HYP-1].time.tm_year, &_loc[CELL_MAX_HYP-1].time.tm_hour, &_loc[CELL_MAX_HYP-1].time.tm_min, &_loc[CELL_MAX_HYP-1].time.tm_sec,\
msinig 136:8dc8f48275fc 229 &_loc[CELL_MAX_HYP-1].latitude, &_loc[CELL_MAX_HYP-1].longitude, &_loc[CELL_MAX_HYP-1].altitutude, &_loc[CELL_MAX_HYP-1].uncertainty) == 13) {
msinig 136:8dc8f48275fc 230 if (--a>=0){
msinig 136:8dc8f48275fc 231 TRACE("Parsed UULOC position at index %d\r\n",a);
msinig 136:8dc8f48275fc 232 memcpy(&_loc[a], &_loc[CELL_MAX_HYP-1], sizeof(*_loc));
msinig 136:8dc8f48275fc 233 _loc[a].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST;
msinig 136:8dc8f48275fc 234 _loc[a].time.tm_mon -= 1;
msinig 136:8dc8f48275fc 235 _loc[a].time.tm_wday=0;
msinig 136:8dc8f48275fc 236 _loc[a].time.tm_yday=0;
msinig 136:8dc8f48275fc 237 _loc[a].validData = true;
msinig 136:8dc8f48275fc 238 _locRcvPos++;
msinig 136:8dc8f48275fc 239 }
fdilenarda 135:cbccf4052d45 240 // +UHTTPCR: <profile_id>,<op_code>,<param_val>
fdilenarda 135:cbccf4052d45 241 } else if ((sscanf(cmd, "UUHTTPCR: %d,%d,%d", &a, &b, &c) == 3)) {
fdilenarda 135:cbccf4052d45 242 _httpProfiles[a].cmd = b; //command
fdilenarda 135:cbccf4052d45 243 _httpProfiles[a].result = c; //result
fdilenarda 135:cbccf4052d45 244 TRACE("%s for profile %d: result code is %d\r\n", getHTTPcmd(b), a, c);
fdilenarda 135:cbccf4052d45 245 }
fdilenarda 135:cbccf4052d45 246 if (_dev.dev == DEV_LISA_C2) {
mazgch 21:c4d64830bf02 247 // CDMA Specific -------------------------------------------
mazgch 21:c4d64830bf02 248 // +CREG: <n><SID>,<NID>,<stat>
mazgch 54:7ba8e4c218e2 249 if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) {
mazgch 54:7ba8e4c218e2 250 // _net.sid = a;
mazgch 54:7ba8e4c218e2 251 // _net.nid = b;
mazgch 79:291df065e345 252 if (c == 0) _net.csd = REG_NONE; // not registered, home network
mazgch 79:291df065e345 253 else if (c == 1) _net.csd = REG_HOME; // registered, home network
mazgch 79:291df065e345 254 else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to
mazgch 79:291df065e345 255 else if (c == 3) _net.csd = REG_DENIED; // registration denied
mazgch 79:291df065e345 256 else if (c == 5) _net.csd = REG_ROAMING; // registered, roaming
mazgch 79:291df065e345 257 _net.psd = _net.csd; // fake PSD registration (CDMA is always registered)
mazgch 31:a0bed6c1e05d 258 _net.act = ACT_CDMA;
mazgch 84:a05edb010176 259 // +CSS: <mode>[,<format>,<oper>[,<AcT>]]
mazgch 21:c4d64830bf02 260 } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) {
mazgch 31:a0bed6c1e05d 261 //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME;
mazgch 21:c4d64830bf02 262 }
mazgch 21:c4d64830bf02 263 } else {
mazgch 21:c4d64830bf02 264 // GSM/UMTS Specific -------------------------------------------
mazgch 79:291df065e345 265 // +UUPSDD: <profile_id>
mazgch 79:291df065e345 266 if (sscanf(cmd, "UUPSDD: %d",&a) == 1) {
mazgch 79:291df065e345 267 if (*PROFILE == a) _ip = NOIP;
mazgch 79:291df065e345 268 } else {
mazgch 79:291df065e345 269 // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG
mazgch 79:291df065e345 270 // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC
mazgch 79:291df065e345 271 b = 0xFFFF; c = 0xFFFFFFFF; d = -1;
mazgch 79:291df065e345 272 r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
mazgch 79:291df065e345 273 if (r <= 1)
mazgch 79:291df065e345 274 r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
mazgch 79:291df065e345 275 if (r >= 2) {
mazgch 79:291df065e345 276 Reg *reg = !strcmp(s, "CREG:") ? &_net.csd :
mazgch 123:66cef6353b13 277 !strcmp(s, "CGREG:") ? &_net.psd :
mazgch 123:66cef6353b13 278 !strcmp(s, "CEREG:") ? &_net.eps : NULL;
mazgch 79:291df065e345 279 if (reg) {
mazgch 79:291df065e345 280 // network status
mazgch 79:291df065e345 281 if (a == 0) *reg = REG_NONE; // 0: not registered, home network
mazgch 79:291df065e345 282 else if (a == 1) *reg = REG_HOME; // 1: registered, home network
mazgch 79:291df065e345 283 else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to
mazgch 79:291df065e345 284 else if (a == 3) *reg = REG_DENIED; // 3: registration denied
mazgch 79:291df065e345 285 else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown
mazgch 79:291df065e345 286 else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming
mazgch 123:66cef6353b13 287 else if (a == 6) *reg = REG_HOME; // 6: registered, sms only, home
mazgch 79:291df065e345 288 if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code
msinig 136:8dc8f48275fc 289 if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID
mazgch 79:291df065e345 290 // access technology
mazgch 79:291df065e345 291 if (r >= 5) {
mazgch 79:291df065e345 292 if (d == 0) _net.act = ACT_GSM; // 0: GSM
mazgch 79:291df065e345 293 else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT
mazgch 79:291df065e345 294 else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN
mazgch 79:291df065e345 295 else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability
mazgch 79:291df065e345 296 else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability
mazgch 79:291df065e345 297 else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability
mazgch 79:291df065e345 298 else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability
mazgch 123:66cef6353b13 299 else if (d == 7) _net.act = ACT_LTE; // 7: LTE
mazgch 79:291df065e345 300 }
mazgch 79:291df065e345 301 }
mazgch 54:7ba8e4c218e2 302 }
mazgch 21:c4d64830bf02 303 }
mazgch 21:c4d64830bf02 304 }
mazgch 21:c4d64830bf02 305 }
mazgch 21:c4d64830bf02 306 if (cb) {
mazgch 21:c4d64830bf02 307 int len = LENGTH(ret);
mazgch 21:c4d64830bf02 308 int ret = cb(type, buf, len, param);
mazgch 21:c4d64830bf02 309 if (WAIT != ret)
mazgch 21:c4d64830bf02 310 return ret;
mazgch 21:c4d64830bf02 311 }
mazgch 95:8282dbbe1492 312 if (type == TYPE_OK)
mazgch 95:8282dbbe1492 313 return RESP_OK;
mazgch 95:8282dbbe1492 314 if (type == TYPE_ERROR)
mazgch 95:8282dbbe1492 315 return RESP_ERROR;
msinig 134:2fbd5723e063 316 if (type == TYPE_ERROR_CME)
msinig 134:2fbd5723e063 317 return RESP_ERROR_CME;
mazgch 95:8282dbbe1492 318 if (type == TYPE_PROMPT)
mazgch 95:8282dbbe1492 319 return RESP_PROMPT;
mazgch 21:c4d64830bf02 320 }
mazgch 21:c4d64830bf02 321 // relax a bit
mazgch 95:8282dbbe1492 322 wait_ms(10);
mazgch 21:c4d64830bf02 323 }
mazgch 75:ce6e12067d0c 324 while (!TIMEOUT(timer, timeout_ms));
mazgch 21:c4d64830bf02 325 return WAIT;
mazgch 21:c4d64830bf02 326 }
mazgch 21:c4d64830bf02 327
mazgch 31:a0bed6c1e05d 328 int MDMParser::_cbString(int type, const char* buf, int len, char* str)
mazgch 21:c4d64830bf02 329 {
mazgch 37:cc3433329d66 330 if (str && (type == TYPE_UNKNOWN)) {
mazgch 31:a0bed6c1e05d 331 if (sscanf(buf, "\r\n%s\r\n", str) == 1)
mazgch 31:a0bed6c1e05d 332 /*nothing*/;
mazgch 21:c4d64830bf02 333 }
mazgch 21:c4d64830bf02 334 return WAIT;
mazgch 21:c4d64830bf02 335 }
mazgch 21:c4d64830bf02 336
mazgch 31:a0bed6c1e05d 337 int MDMParser::_cbInt(int type, const char* buf, int len, int* val)
mazgch 31:a0bed6c1e05d 338 {
mazgch 37:cc3433329d66 339 if (val && (type == TYPE_UNKNOWN)) {
mazgch 31:a0bed6c1e05d 340 if (sscanf(buf, "\r\n%d\r\n", val) == 1)
mazgch 31:a0bed6c1e05d 341 /*nothing*/;
mazgch 31:a0bed6c1e05d 342 }
mazgch 31:a0bed6c1e05d 343 return WAIT;
mazgch 31:a0bed6c1e05d 344 }
mazgch 31:a0bed6c1e05d 345
mazgch 31:a0bed6c1e05d 346 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 347
mazgch 57:869bd35f44cc 348 bool MDMParser::connect(
mazgch 57:869bd35f44cc 349 const char* simpin,
mazgch 80:34985b4d821e 350 const char* apn, const char* username,
mazgch 80:34985b4d821e 351 const char* password, Auth auth,
mazgch 74:208e3e32d263 352 PinName pn)
mazgch 57:869bd35f44cc 353 {
mazgch 75:ce6e12067d0c 354 bool ok = init(simpin, NULL, pn);
mazgch 74:208e3e32d263 355 #ifdef MDM_DEBUG
mazgch 75:ce6e12067d0c 356 if (_debugLevel >= 1) dumpDevStatus(&_dev);
mazgch 74:208e3e32d263 357 #endif
mazgch 75:ce6e12067d0c 358 if (!ok)
mazgch 57:869bd35f44cc 359 return false;
mazgch 75:ce6e12067d0c 360 ok = registerNet();
mazgch 74:208e3e32d263 361 #ifdef MDM_DEBUG
mazgch 75:ce6e12067d0c 362 if (_debugLevel >= 1) dumpNetStatus(&_net);
mazgch 74:208e3e32d263 363 #endif
mazgch 75:ce6e12067d0c 364 if (!ok)
mazgch 57:869bd35f44cc 365 return false;
mazgch 80:34985b4d821e 366 IP ip = join(apn,username,password,auth);
mazgch 74:208e3e32d263 367 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 368 if (_debugLevel >= 1) dumpIp(ip);
mazgch 74:208e3e32d263 369 #endif
mazgch 57:869bd35f44cc 370 if (ip == NOIP)
mazgch 57:869bd35f44cc 371 return false;
mazgch 57:869bd35f44cc 372 return true;
mazgch 57:869bd35f44cc 373 }
mazgch 57:869bd35f44cc 374
mazgch 74:208e3e32d263 375 bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn)
mazgch 21:c4d64830bf02 376 {
mazgch 74:208e3e32d263 377 int i = 10;
mazgch 95:8282dbbe1492 378 LOCK();
mazgch 76:f7c3dd568dae 379 memset(&_dev, 0, sizeof(_dev));
mazgch 74:208e3e32d263 380 if (pn != NC) {
mazgch 74:208e3e32d263 381 INFO("Modem::wakeup\r\n");
mazgch 74:208e3e32d263 382 DigitalOut pin(pn, 1);
mazgch 74:208e3e32d263 383 while (i--) {
mazgch 79:291df065e345 384 // SARA-U2/LISA-U2 50..80us
mazgch 95:8282dbbe1492 385 pin = 0; ::wait_us(50);
mazgch 95:8282dbbe1492 386 pin = 1; ::wait_ms(10);
mazgch 79:291df065e345 387
mazgch 98:c786461edd40 388 // SARA-G35 >5ms, LISA-C2 > 150ms, LEON-G2 >5ms
mazgch 95:8282dbbe1492 389 pin = 0; ::wait_ms(150);
mazgch 95:8282dbbe1492 390 pin = 1; ::wait_ms(100);
mazgch 79:291df065e345 391
mazgch 79:291df065e345 392 // purge any messages
mazgch 101:edfeb8af206e 393 purge();
mazgch 95:8282dbbe1492 394
mazgch 101:edfeb8af206e 395 // check interface
mazgch 74:208e3e32d263 396 sendFormated("AT\r\n");
mazgch 101:edfeb8af206e 397 int r = waitFinalResp(NULL,NULL,1000);
mazgch 95:8282dbbe1492 398 if(RESP_OK == r) break;
mazgch 74:208e3e32d263 399 }
mazgch 75:ce6e12067d0c 400 if (i < 0) {
mazgch 95:8282dbbe1492 401 ERROR("No Reply from Modem\r\n");
mazgch 95:8282dbbe1492 402 goto failure;
mazgch 75:ce6e12067d0c 403 }
mazgch 21:c4d64830bf02 404 }
mazgch 76:f7c3dd568dae 405 _init = true;
mazgch 75:ce6e12067d0c 406
mazgch 74:208e3e32d263 407 INFO("Modem::init\r\n");
mazgch 21:c4d64830bf02 408 // echo off
mazgch 21:c4d64830bf02 409 sendFormated("AT E0\r\n");
mazgch 52:8071747a7cb3 410 if(RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 411 goto failure;
mazgch 21:c4d64830bf02 412 // enable verbose error messages
mazgch 21:c4d64830bf02 413 sendFormated("AT+CMEE=2\r\n");
mazgch 52:8071747a7cb3 414 if(RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 415 goto failure;
mazgch 21:c4d64830bf02 416 // set baud rate
mazgch 21:c4d64830bf02 417 sendFormated("AT+IPR=115200\r\n");
mazgch 52:8071747a7cb3 418 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 419 goto failure;
mazgch 112:89b5b21db71e 420 // wait some time until baudrate is applied
mazgch 112:89b5b21db71e 421 wait_ms(200); // SARA-G > 40ms
mazgch 21:c4d64830bf02 422 // identify the module
mazgch 21:c4d64830bf02 423 sendFormated("ATI\r\n");
mazgch 52:8071747a7cb3 424 if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev))
mazgch 95:8282dbbe1492 425 goto failure;
mazgch 32:8f12ac182bbb 426 if (_dev.dev == DEV_UNKNOWN)
mazgch 95:8282dbbe1492 427 goto failure;
mazgch 32:8f12ac182bbb 428 // device specific init
mazgch 125:25a292afbac6 429 if (_dev.dev == DEV_LISA_C2) {
mazgch 32:8f12ac182bbb 430 // get the manufacturer
mazgch 32:8f12ac182bbb 431 sendFormated("AT+GMI\r\n");
mazgch 52:8071747a7cb3 432 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
mazgch 95:8282dbbe1492 433 goto failure;
mazgch 32:8f12ac182bbb 434 // get the model identification
mazgch 32:8f12ac182bbb 435 sendFormated("AT+GMM\r\n");
mazgch 52:8071747a7cb3 436 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
mazgch 95:8282dbbe1492 437 goto failure;
mazgch 32:8f12ac182bbb 438 // get the sw version
mazgch 32:8f12ac182bbb 439 sendFormated("AT+GMR\r\n");
mazgch 52:8071747a7cb3 440 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
mazgch 95:8282dbbe1492 441 goto failure;
mazgch 95:8282dbbe1492 442 // get the pseudo ESN or MEID
mazgch 21:c4d64830bf02 443 sendFormated("AT+GSN\r\n");
mazgch 52:8071747a7cb3 444 if (RESP_OK != waitFinalResp(_cbString, _dev.meid))
mazgch 95:8282dbbe1492 445 goto failure;
mazgch 50:d76aece8038f 446 #if 0
mazgch 50:d76aece8038f 447 // enable power saving
mazgch 50:d76aece8038f 448 if (_dev.lpm != LPM_DISABLED) {
mazgch 50:d76aece8038f 449 // enable power saving (requires flow control, cts at least)
mazgch 50:d76aece8038f 450 sendFormated("AT+UPSV=1,1280\r\n");
mazgch 52:8071747a7cb3 451 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 452 goto failure;
mazgch 50:d76aece8038f 453 _dev.lpm = LPM_ACTIVE;
mazgch 50:d76aece8038f 454 }
mazgch 50:d76aece8038f 455 #endif
mazgch 26:07be5faf8925 456 } else {
mazgch 125:25a292afbac6 457 if ((_dev.dev == DEV_LISA_U2) || (_dev.dev == DEV_LEON_G2) ||
mazgch 125:25a292afbac6 458 (_dev.dev == DEV_TOBY_L2)) {
mazgch 35:9275215a3a5b 459 // enable the network identification feature
mazgch 21:c4d64830bf02 460 sendFormated("AT+UGPIOC=20,2\r\n");
mazgch 52:8071747a7cb3 461 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 462 goto failure;
mazgch 125:25a292afbac6 463 } else if ((_dev.dev == DEV_SARA_U2) || (_dev.dev == DEV_SARA_G35)) {
mazgch 35:9275215a3a5b 464 // enable the network identification feature
mazgch 21:c4d64830bf02 465 sendFormated("AT+UGPIOC=16,2\r\n");
mazgch 52:8071747a7cb3 466 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 467 goto failure;
mazgch 21:c4d64830bf02 468 }
mazgch 21:c4d64830bf02 469 // check the sim card
mazgch 31:a0bed6c1e05d 470 for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) {
mazgch 21:c4d64830bf02 471 sendFormated("AT+CPIN?\r\n");
mazgch 31:a0bed6c1e05d 472 int ret = waitFinalResp(_cbCPIN, &_dev.sim);
mazgch 62:a02f026bdd7c 473 // having an error here is ok (sim may still be initializing)
mazgch 52:8071747a7cb3 474 if ((RESP_OK != ret) && (RESP_ERROR != ret))
mazgch 95:8282dbbe1492 475 goto failure;
mazgch 31:a0bed6c1e05d 476 // Enter PIN if needed
mazgch 77:55788e619858 477 if (_dev.sim == SIM_PIN) {
mazgch 57:869bd35f44cc 478 if (!simpin) {
mazgch 75:ce6e12067d0c 479 ERROR("SIM PIN not available\r\n");
mazgch 95:8282dbbe1492 480 goto failure;
mazgch 31:a0bed6c1e05d 481 }
mazgch 130:3189949981ec 482 sendFormated("AT+CPIN=\"%s\"\r\n", simpin);
mazgch 52:8071747a7cb3 483 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim))
mazgch 95:8282dbbe1492 484 goto failure;
mazgch 62:a02f026bdd7c 485 } else if (_dev.sim != SIM_READY) {
mazgch 95:8282dbbe1492 486 wait_ms(1000);
mazgch 62:a02f026bdd7c 487 }
mazgch 21:c4d64830bf02 488 }
mazgch 77:55788e619858 489 if (_dev.sim != SIM_READY) {
mazgch 77:55788e619858 490 if (_dev.sim == SIM_MISSING)
mazgch 77:55788e619858 491 ERROR("SIM not inserted\r\n");
mazgch 95:8282dbbe1492 492 goto failure;
mazgch 77:55788e619858 493 }
mazgch 32:8f12ac182bbb 494 // get the manufacturer
mazgch 32:8f12ac182bbb 495 sendFormated("AT+CGMI\r\n");
mazgch 52:8071747a7cb3 496 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
mazgch 95:8282dbbe1492 497 goto failure;
mazgch 32:8f12ac182bbb 498 // get the model identification
mazgch 32:8f12ac182bbb 499 sendFormated("AT+CGMM\r\n");
mazgch 52:8071747a7cb3 500 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
mazgch 95:8282dbbe1492 501 goto failure;
mazgch 126:bfbb9e19f6e0 502 // get the version
mazgch 126:bfbb9e19f6e0 503 sendFormated("ATI9\r\n");
mazgch 52:8071747a7cb3 504 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
mazgch 126:bfbb9e19f6e0 505 goto failure;
mazgch 21:c4d64830bf02 506 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
mazgch 21:c4d64830bf02 507 // ICCID is a serial number identifying the SIM.
mazgch 21:c4d64830bf02 508 sendFormated("AT+CCID\r\n");
mazgch 52:8071747a7cb3 509 if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid))
mazgch 95:8282dbbe1492 510 goto failure;
mazgch 21:c4d64830bf02 511 // Returns the product serial number, IMEI (International Mobile Equipment Identity)
mazgch 21:c4d64830bf02 512 sendFormated("AT+CGSN\r\n");
mazgch 52:8071747a7cb3 513 if (RESP_OK != waitFinalResp(_cbString, _dev.imei))
mazgch 95:8282dbbe1492 514 goto failure;
mazgch 50:d76aece8038f 515 // enable power saving
mazgch 50:d76aece8038f 516 if (_dev.lpm != LPM_DISABLED) {
mazgch 50:d76aece8038f 517 // enable power saving (requires flow control, cts at least)
mazgch 50:d76aece8038f 518 sendFormated("AT+UPSV=1\r\n");
mazgch 52:8071747a7cb3 519 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 520 goto failure;
mazgch 50:d76aece8038f 521 _dev.lpm = LPM_ACTIVE;
mazgch 50:d76aece8038f 522 }
mazgch 79:291df065e345 523 // enable the psd registration unsolicited result code
mazgch 79:291df065e345 524 sendFormated("AT+CGREG=2\r\n");
mazgch 79:291df065e345 525 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 526 goto failure;
mazgch 21:c4d64830bf02 527 }
mazgch 79:291df065e345 528 // enable the network registration unsolicited result code
mazgch 125:25a292afbac6 529 sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C2) ? 1 : 2);
mazgch 79:291df065e345 530 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 531 goto failure;
mazgch 31:a0bed6c1e05d 532 // Setup SMS in text mode
mazgch 31:a0bed6c1e05d 533 sendFormated("AT+CMGF=1\r\n");
mazgch 52:8071747a7cb3 534 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 535 goto failure;
mazgch 31:a0bed6c1e05d 536 // setup new message indication
mazgch 75:ce6e12067d0c 537 sendFormated("AT+CNMI=2,1\r\n");
mazgch 52:8071747a7cb3 538 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 539 goto failure;
mazgch 21:c4d64830bf02 540 // Request IMSI (International Mobile Subscriber Identification)
mazgch 21:c4d64830bf02 541 sendFormated("AT+CIMI\r\n");
mazgch 52:8071747a7cb3 542 if (RESP_OK != waitFinalResp(_cbString, _dev.imsi))
mazgch 95:8282dbbe1492 543 goto failure;
mazgch 28:4d9509e3b1cf 544 if (status)
mazgch 31:a0bed6c1e05d 545 memcpy(status, &_dev, sizeof(DevStatus));
mazgch 95:8282dbbe1492 546 UNLOCK();
mazgch 31:a0bed6c1e05d 547 return true;
mazgch 95:8282dbbe1492 548 failure:
mazgch 95:8282dbbe1492 549 unlock();
mazgch 95:8282dbbe1492 550 return false;
mazgch 31:a0bed6c1e05d 551 }
mazgch 31:a0bed6c1e05d 552
mazgch 74:208e3e32d263 553 bool MDMParser::powerOff(void)
mazgch 74:208e3e32d263 554 {
mazgch 95:8282dbbe1492 555 bool ok = false;
mazgch 76:f7c3dd568dae 556 if (_init) {
mazgch 95:8282dbbe1492 557 LOCK();
mazgch 76:f7c3dd568dae 558 INFO("Modem::powerOff\r\n");
mazgch 76:f7c3dd568dae 559 sendFormated("AT+CPWROFF\r\n");
mazgch 95:8282dbbe1492 560 if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) {
mazgch 95:8282dbbe1492 561 _init = false;
mazgch 95:8282dbbe1492 562 ok = true;
mazgch 95:8282dbbe1492 563 }
mazgch 95:8282dbbe1492 564 UNLOCK();
mazgch 76:f7c3dd568dae 565 }
mazgch 95:8282dbbe1492 566 return ok;
mazgch 74:208e3e32d263 567 }
mazgch 74:208e3e32d263 568
mazgch 32:8f12ac182bbb 569 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev)
mazgch 31:a0bed6c1e05d 570 {
mazgch 37:cc3433329d66 571 if ((type == TYPE_UNKNOWN) && dev) {
mazgch 125:25a292afbac6 572 if (strstr(buf, "SARA-G35")) *dev = DEV_SARA_G35;
msinig 133:57b208dd96fb 573 else if (strstr(buf, "LISA-U200-03S")) *dev = DEV_LISA_U2_03S;
msinig 133:57b208dd96fb 574 else if (strstr(buf, "LISA-U2")) *dev = DEV_LISA_U2;
mazgch 125:25a292afbac6 575 else if (strstr(buf, "LISA-C2")) *dev = DEV_LISA_C2;
mazgch 125:25a292afbac6 576 else if (strstr(buf, "SARA-U2")) *dev = DEV_SARA_U2;
mazgch 125:25a292afbac6 577 else if (strstr(buf, "LEON-G2")) *dev = DEV_LEON_G2;
mazgch 125:25a292afbac6 578 else if (strstr(buf, "TOBY-L2")) *dev = DEV_TOBY_L2;
mazgch 125:25a292afbac6 579 else if (strstr(buf, "MPCI-L2")) *dev = DEV_MPCI_L2;
mazgch 28:4d9509e3b1cf 580 }
mazgch 31:a0bed6c1e05d 581 return WAIT;
mazgch 31:a0bed6c1e05d 582 }
mazgch 31:a0bed6c1e05d 583
mazgch 31:a0bed6c1e05d 584 int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim)
mazgch 31:a0bed6c1e05d 585 {
mazgch 75:ce6e12067d0c 586 if (sim) {
mazgch 75:ce6e12067d0c 587 if (type == TYPE_PLUS){
mazgch 75:ce6e12067d0c 588 char s[16];
mazgch 75:ce6e12067d0c 589 if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1)
mazgch 75:ce6e12067d0c 590 *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN;
mazgch 75:ce6e12067d0c 591 } else if (type == TYPE_ERROR) {
mazgch 75:ce6e12067d0c 592 if (strstr(buf, "+CME ERROR: SIM not inserted"))
mazgch 75:ce6e12067d0c 593 *sim = SIM_MISSING;
mazgch 31:a0bed6c1e05d 594 }
mazgch 31:a0bed6c1e05d 595 }
mazgch 31:a0bed6c1e05d 596 return WAIT;
mazgch 21:c4d64830bf02 597 }
mazgch 21:c4d64830bf02 598
mazgch 26:07be5faf8925 599 int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid)
mazgch 26:07be5faf8925 600 {
mazgch 26:07be5faf8925 601 if ((type == TYPE_PLUS) && ccid){
mazgch 26:07be5faf8925 602 if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1)
mazgch 31:a0bed6c1e05d 603 /*TRACE("Got CCID: %s\r\n", ccid)*/;
mazgch 26:07be5faf8925 604 }
mazgch 26:07be5faf8925 605 return WAIT;
mazgch 26:07be5faf8925 606 }
mazgch 26:07be5faf8925 607
mazgch 75:ce6e12067d0c 608 bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/)
mazgch 75:ce6e12067d0c 609 {
mazgch 75:ce6e12067d0c 610 Timer timer;
mazgch 75:ce6e12067d0c 611 timer.start();
mazgch 75:ce6e12067d0c 612 INFO("Modem::register\r\n");
mazgch 75:ce6e12067d0c 613 while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms))
mazgch 95:8282dbbe1492 614 wait_ms(1000);
mazgch 79:291df065e345 615 if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n");
mazgch 79:291df065e345 616 if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n");
mazgch 123:66cef6353b13 617 if (_net.eps == REG_DENIED) ERROR("EPS Registration Denied\r\n");
mazgch 123:66cef6353b13 618 return REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps);
mazgch 75:ce6e12067d0c 619 }
mazgch 75:ce6e12067d0c 620
mazgch 28:4d9509e3b1cf 621 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
mazgch 21:c4d64830bf02 622 {
mazgch 95:8282dbbe1492 623 bool ok = false;
mazgch 95:8282dbbe1492 624 LOCK();
mazgch 75:ce6e12067d0c 625 memset(&_net, 0, sizeof(_net));
mazgch 75:ce6e12067d0c 626 _net.lac = 0xFFFF;
mazgch 75:ce6e12067d0c 627 _net.ci = 0xFFFFFFFF;
mazgch 21:c4d64830bf02 628 // check registration
mazgch 21:c4d64830bf02 629 sendFormated("AT+CREG?\r\n");
mazgch 88:135fb4bb7aac 630 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 631 if (_dev.dev != DEV_LISA_C2) {
mazgch 79:291df065e345 632 // check PSD registration
mazgch 79:291df065e345 633 sendFormated("AT+CGREG?\r\n");
mazgch 88:135fb4bb7aac 634 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 635 if ((_dev.dev == DEV_TOBY_L2) || (_dev.dev == DEV_MPCI_L2)) {
mazgch 125:25a292afbac6 636 // check EPS network registration
mazgch 125:25a292afbac6 637 sendFormated("AT+CEREG?\r\n");
mazgch 125:25a292afbac6 638 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 639 }
mazgch 79:291df065e345 640 }
mazgch 123:66cef6353b13 641 if (REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps))
mazgch 75:ce6e12067d0c 642 {
mazgch 75:ce6e12067d0c 643 // check modem specific status messages
mazgch 125:25a292afbac6 644 if (_dev.dev == DEV_LISA_C2) {
mazgch 75:ce6e12067d0c 645 sendFormated("AT+CSS?\r\n");
mazgch 75:ce6e12067d0c 646 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 647 goto failure;
mazgch 81:3966a5c17037 648 while (1) {
mazgch 81:3966a5c17037 649 // get the Telephone number
mazgch 81:3966a5c17037 650 sendFormated("AT$MDN?\r\n");
mazgch 81:3966a5c17037 651 if (RESP_OK != waitFinalResp(_cbString, _net.num))
mazgch 95:8282dbbe1492 652 goto failure;
mazgch 81:3966a5c17037 653 // check if we have a Mobile Directory Number
mazgch 81:3966a5c17037 654 if (*_net.num && (memcmp(_net.num, "000000", 6) != 0))
mazgch 81:3966a5c17037 655 break;
mazgch 81:3966a5c17037 656
mazgch 81:3966a5c17037 657 INFO("Device not yet activated\r\n");
mazgch 81:3966a5c17037 658 INFO("Make sure you have a valid contract with the network operator for this device.\r\n");
mazgch 81:3966a5c17037 659 // Check if the the version contains a V for Verizon
mazgch 81:3966a5c17037 660 // Verizon: E0.V.xx.00.xxR,
mazgch 81:3966a5c17037 661 // Sprint E0.S.xx.00.xxR
mazgch 81:3966a5c17037 662 if (_dev.ver[3] == 'V') {
mazgch 81:3966a5c17037 663 int i;
mazgch 81:3966a5c17037 664 INFO("Start device over-the-air activation (this can take a few minutes)\r\n");
mazgch 81:3966a5c17037 665 sendFormated("AT+CDV=*22899\r\n");
mazgch 81:3966a5c17037 666 i = 1;
mazgch 82:055dcfcf9dcc 667 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
mazgch 81:3966a5c17037 668 ERROR("Device over-the-air activation failed\r\n");
mazgch 95:8282dbbe1492 669 goto failure;
mazgch 81:3966a5c17037 670 }
mazgch 81:3966a5c17037 671 INFO("Device over-the-air activation successful\r\n");
mazgch 81:3966a5c17037 672
mazgch 81:3966a5c17037 673 INFO("Start PRL over-the-air update (this can take a few minutes)\r\n");
mazgch 81:3966a5c17037 674 sendFormated("AT+CDV=*22891\r\n");
mazgch 81:3966a5c17037 675 i = 1;
mazgch 82:055dcfcf9dcc 676 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
mazgch 81:3966a5c17037 677 ERROR("PRL over-the-air update failed\r\n");
mazgch 95:8282dbbe1492 678 goto failure;
mazgch 81:3966a5c17037 679 }
mazgch 81:3966a5c17037 680 INFO("PRL over-the-air update successful\r\n");
mazgch 81:3966a5c17037 681
mazgch 81:3966a5c17037 682 } else {
mazgch 81:3966a5c17037 683 // Sprint or Aeris
mazgch 81:3966a5c17037 684 INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n");
mazgch 95:8282dbbe1492 685 wait_ms(120*1000);
mazgch 81:3966a5c17037 686 }
mazgch 81:3966a5c17037 687 }
mazgch 75:ce6e12067d0c 688 // get the the Network access identifier string
mazgch 75:ce6e12067d0c 689 char nai[64];
mazgch 75:ce6e12067d0c 690 sendFormated("AT$QCMIPNAI?\r\n");
mazgch 75:ce6e12067d0c 691 if (RESP_OK != waitFinalResp(_cbString, nai))
mazgch 95:8282dbbe1492 692 goto failure;
mazgch 75:ce6e12067d0c 693 } else {
mazgch 75:ce6e12067d0c 694 sendFormated("AT+COPS?\r\n");
mazgch 75:ce6e12067d0c 695 if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
mazgch 95:8282dbbe1492 696 goto failure;
mazgch 95:8282dbbe1492 697 // get the MSISDNs related to this subscriber
mazgch 75:ce6e12067d0c 698 sendFormated("AT+CNUM\r\n");
mazgch 75:ce6e12067d0c 699 if (RESP_OK != waitFinalResp(_cbCNUM, _net.num))
mazgch 95:8282dbbe1492 700 goto failure;
mazgch 75:ce6e12067d0c 701 }
mazgch 95:8282dbbe1492 702 // get the signal strength indication
mazgch 75:ce6e12067d0c 703 sendFormated("AT+CSQ\r\n");
mazgch 75:ce6e12067d0c 704 if (RESP_OK != waitFinalResp(_cbCSQ, &_net))
mazgch 95:8282dbbe1492 705 goto failure;
mazgch 75:ce6e12067d0c 706 }
mazgch 28:4d9509e3b1cf 707 if (status) {
mazgch 31:a0bed6c1e05d 708 memcpy(status, &_net, sizeof(NetStatus));
mazgch 25:4045d02e44f1 709 }
mazgch 123:66cef6353b13 710 ok = REG_DONE(_net.csd) &&
mazgch 123:66cef6353b13 711 (REG_DONE(_net.psd) || REG_DONE(_net.eps));
mazgch 95:8282dbbe1492 712 UNLOCK();
mazgch 95:8282dbbe1492 713 return ok;
mazgch 95:8282dbbe1492 714 failure:
mazgch 95:8282dbbe1492 715 unlock();
mazgch 95:8282dbbe1492 716 return false;
mazgch 31:a0bed6c1e05d 717 }
mazgch 31:a0bed6c1e05d 718
mazgch 31:a0bed6c1e05d 719 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status)
mazgch 31:a0bed6c1e05d 720 {
mazgch 31:a0bed6c1e05d 721 if ((type == TYPE_PLUS) && status){
mazgch 31:a0bed6c1e05d 722 int act = 99;
msinig 134:2fbd5723e063 723 int mode = 99;
mazgch 31:a0bed6c1e05d 724 // +COPS: <mode>[,<format>,<oper>[,<AcT>]]
msinig 134:2fbd5723e063 725 if (sscanf(buf, "\r\n+COPS: %d,%*d,\"%[^\"]\",%d",&mode,status->opr,&act) >= 1) {
mazgch 31:a0bed6c1e05d 726 if (act == 0) status->act = ACT_GSM; // 0: GSM,
mazgch 31:a0bed6c1e05d 727 else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN
mazgch 123:66cef6353b13 728 else if (act == 7) status->act = ACT_LTE; // 2: UTRAN
msinig 134:2fbd5723e063 729 if (mode == 0) status->regStatus = COPS_AUTOMATIC_REG;
msinig 134:2fbd5723e063 730 else if (mode == 1) status->regStatus = COPS_MANUAL_REG;
msinig 134:2fbd5723e063 731 else if (mode == 2) status->regStatus = COPS_DISABLED_REG;
mazgch 31:a0bed6c1e05d 732 }
mazgch 31:a0bed6c1e05d 733 }
mazgch 31:a0bed6c1e05d 734 return WAIT;
mazgch 31:a0bed6c1e05d 735 }
mazgch 31:a0bed6c1e05d 736
mazgch 31:a0bed6c1e05d 737 int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num)
mazgch 31:a0bed6c1e05d 738 {
mazgch 31:a0bed6c1e05d 739 if ((type == TYPE_PLUS) && num){
mazgch 31:a0bed6c1e05d 740 int a;
mazgch 31:a0bed6c1e05d 741 if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) &&
mazgch 31:a0bed6c1e05d 742 ((a == 129) || (a == 145))) {
mazgch 31:a0bed6c1e05d 743 }
mazgch 31:a0bed6c1e05d 744 }
mazgch 31:a0bed6c1e05d 745 return WAIT;
mazgch 31:a0bed6c1e05d 746 }
mazgch 31:a0bed6c1e05d 747
mazgch 54:7ba8e4c218e2 748 int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status)
mazgch 31:a0bed6c1e05d 749 {
mazgch 54:7ba8e4c218e2 750 if ((type == TYPE_PLUS) && status){
mazgch 54:7ba8e4c218e2 751 int a,b;
mazgch 54:7ba8e4c218e2 752 char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4
mazgch 31:a0bed6c1e05d 753 // +CSQ: <rssi>,<qual>
mazgch 54:7ba8e4c218e2 754 if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) {
mazgch 121:8da935c2c08c 755 if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps, 31: >-51 dBm
mazgch 54:7ba8e4c218e2 756 if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; //
mazgch 31:a0bed6c1e05d 757 }
mazgch 31:a0bed6c1e05d 758 }
mazgch 31:a0bed6c1e05d 759 return WAIT;
mazgch 31:a0bed6c1e05d 760 }
mazgch 21:c4d64830bf02 761
mazgch 124:65eb7d58f2da 762
mazgch 124:65eb7d58f2da 763 int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i)
mazgch 124:65eb7d58f2da 764 {
mazgch 124:65eb7d58f2da 765 if ((type == TYPE_PLUS) && i){
mazgch 124:65eb7d58f2da 766 int a;
mazgch 124:65eb7d58f2da 767 if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) {
mazgch 124:65eb7d58f2da 768 *i = a;
mazgch 124:65eb7d58f2da 769 }
mazgch 124:65eb7d58f2da 770 }
mazgch 124:65eb7d58f2da 771 return WAIT;
mazgch 124:65eb7d58f2da 772 }
mazgch 124:65eb7d58f2da 773
mazgch 21:c4d64830bf02 774 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 775 // internet connection
mazgch 21:c4d64830bf02 776
mazgch 128:0415646a9934 777 bool MDMParser::_activateProfile(const char* apn, const char* username, const char* password, Auth auth)
mazgch 128:0415646a9934 778 {
mazgch 128:0415646a9934 779 // Set up the APN
mazgch 128:0415646a9934 780 if (*apn) {
mazgch 128:0415646a9934 781 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
mazgch 128:0415646a9934 782 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 783 return false;
mazgch 128:0415646a9934 784 }
mazgch 128:0415646a9934 785 if (*username) {
mazgch 128:0415646a9934 786 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
mazgch 128:0415646a9934 787 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 788 return false;
mazgch 128:0415646a9934 789 }
mazgch 128:0415646a9934 790 if (*password) {
mazgch 128:0415646a9934 791 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
mazgch 128:0415646a9934 792 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 793 return false;
mazgch 128:0415646a9934 794 }
mazgch 128:0415646a9934 795 // Set up the dynamic IP address assignment.
mazgch 128:0415646a9934 796 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
mazgch 128:0415646a9934 797 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 798 return false;
mazgch 128:0415646a9934 799 // try different Authentication Protocols
mazgch 128:0415646a9934 800 // 0 = none
mazgch 128:0415646a9934 801 // 1 = PAP (Password Authentication Protocol)
mazgch 128:0415646a9934 802 // 2 = CHAP (Challenge Handshake Authentication Protocol)
mazgch 128:0415646a9934 803 for (int i = AUTH_NONE; i <= AUTH_CHAP; i ++) {
mazgch 128:0415646a9934 804 if ((auth == AUTH_DETECT) || (auth == i)) {
mazgch 128:0415646a9934 805 // Set up the Authentication Protocol
mazgch 128:0415646a9934 806 sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n",i);
mazgch 128:0415646a9934 807 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 808 return false;
mazgch 128:0415646a9934 809 // Activate the profile and make connection
mazgch 128:0415646a9934 810 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 128:0415646a9934 811 if (RESP_OK == waitFinalResp(NULL,NULL,150*1000))
mazgch 128:0415646a9934 812 return true;
mazgch 128:0415646a9934 813 }
mazgch 128:0415646a9934 814 }
mazgch 128:0415646a9934 815 return false;
mazgch 128:0415646a9934 816 }
mazgch 128:0415646a9934 817
mazgch 131:965a7cbc1e58 818 bool MDMParser::_activateProfileReuseExternal(void)
mazgch 131:965a7cbc1e58 819 {
mazgch 131:965a7cbc1e58 820 int cid = -1;
mazgch 131:965a7cbc1e58 821 sendFormated("AT+CGDCONT?\r\n");
mazgch 131:965a7cbc1e58 822 if (RESP_OK != waitFinalResp(_cbCGDCONT, &cid))
mazgch 131:965a7cbc1e58 823 return false;
mazgch 131:965a7cbc1e58 824 if (cid == -1)
mazgch 131:965a7cbc1e58 825 return false;
mazgch 131:965a7cbc1e58 826 // we found a context that provides us a valid IP so lets reuse it for the internal IP stack
mazgch 131:965a7cbc1e58 827 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid);
mazgch 131:965a7cbc1e58 828 if (RESP_OK != waitFinalResp())
mazgch 131:965a7cbc1e58 829 return false;
mazgch 131:965a7cbc1e58 830 // Activate the profile and make connection
mazgch 131:965a7cbc1e58 831 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 131:965a7cbc1e58 832 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000));
mazgch 131:965a7cbc1e58 833 }
mazgch 131:965a7cbc1e58 834
mazgch 128:0415646a9934 835 bool MDMParser::_activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth)
mazgch 128:0415646a9934 836 {
mazgch 128:0415646a9934 837 sendFormated("AT+CGDCONT=%d,\"IP\",\"%s\"\r\n", cid, apn);
mazgch 128:0415646a9934 838 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 839 return false;
mazgch 128:0415646a9934 840 sendFormated("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"\r\n", cid, auth, username, password);
mazgch 128:0415646a9934 841 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 842 return false;
mazgch 128:0415646a9934 843 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid);
mazgch 128:0415646a9934 844 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 845 return false;
mazgch 128:0415646a9934 846 // Activate the profile and make connection
mazgch 128:0415646a9934 847 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 128:0415646a9934 848 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000));
mazgch 128:0415646a9934 849 }
mazgch 128:0415646a9934 850
mazgch 131:965a7cbc1e58 851 int MDMParser::_cbCGDCONT(int type, const char* buf, int len, int* cid)
mazgch 131:965a7cbc1e58 852 {
mazgch 131:965a7cbc1e58 853 // accept with and without leading \r\n in +CGDCONT:
mazgch 131:965a7cbc1e58 854 if ((type == TYPE_PLUS) && (buf[0] == '\r') && (buf[1] == '\n') && (len >= 2))
mazgch 131:965a7cbc1e58 855 buf += 2, len -= 2, type = TYPE_UNKNOWN;
mazgch 131:965a7cbc1e58 856 if (type == TYPE_UNKNOWN) {
mazgch 131:965a7cbc1e58 857 int a,b,c,d,t;
mazgch 131:965a7cbc1e58 858 //+CGDCONT: <cid>,"IP","<apn name>","<ip adr>",0,0,0,0,0,0
mazgch 131:965a7cbc1e58 859 if (sscanf(buf, "+CGDCONT: %d,\"IP\",\"%*[^\"]\",\"" IPSTR "\",%*d,%*d,%*d,%*d,%*d,%*d", &t, &a,&b,&c,&d) == 5) {
mazgch 131:965a7cbc1e58 860 if (IPADR(a,b,c,d) != NOIP)
mazgch 131:965a7cbc1e58 861 *cid = t;
mazgch 131:965a7cbc1e58 862 }
mazgch 131:965a7cbc1e58 863 }
mazgch 131:965a7cbc1e58 864 return WAIT;
mazgch 131:965a7cbc1e58 865 }
mazgch 131:965a7cbc1e58 866
mazgch 79:291df065e345 867 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/,
mazgch 79:291df065e345 868 const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/)
mazgch 21:c4d64830bf02 869 {
mazgch 95:8282dbbe1492 870 LOCK();
mazgch 78:caf0014375cb 871 INFO("Modem::join\r\n");
mazgch 32:8f12ac182bbb 872 _ip = NOIP;
mazgch 125:25a292afbac6 873 if (_dev.dev == DEV_LISA_C2) {
mazgch 76:f7c3dd568dae 874 // make a dumy dns lookup (which will fail, so ignore the result)
mazgch 76:f7c3dd568dae 875 sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n");
mazgch 76:f7c3dd568dae 876 waitFinalResp();
mazgch 76:f7c3dd568dae 877 // This fake lookup will enable the IP connection and we
mazgch 76:f7c3dd568dae 878 // should have an IP after this, so we check it
mazgch 76:f7c3dd568dae 879
mazgch 21:c4d64830bf02 880 //Get local IP address
mazgch 21:c4d64830bf02 881 sendFormated("AT+CMIP?\r\n");
mazgch 52:8071747a7cb3 882 if (RESP_OK != waitFinalResp(_cbCMIP, &_ip))
mazgch 95:8282dbbe1492 883 goto failure;
mazgch 125:25a292afbac6 884
mazgch 21:c4d64830bf02 885 } else {
mazgch 21:c4d64830bf02 886 // check gprs attach status
mazgch 72:d1e943ad6558 887 sendFormated("AT+CGATT=1\r\n");
mazgch 74:208e3e32d263 888 if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000))
mazgch 95:8282dbbe1492 889 goto failure;
mazgch 31:a0bed6c1e05d 890 // Check the profile
mazgch 31:a0bed6c1e05d 891 int a = 0;
mazgch 79:291df065e345 892 bool force = true;
mazgch 31:a0bed6c1e05d 893 sendFormated("AT+UPSND=" PROFILE ",8\r\n");
mazgch 52:8071747a7cb3 894 if (RESP_OK != waitFinalResp(_cbUPSND, &a))
mazgch 95:8282dbbe1492 895 goto failure;
mazgch 79:291df065e345 896 if (a == 1 && force) {
mazgch 31:a0bed6c1e05d 897 // disconnect the profile already if it is connected
mazgch 31:a0bed6c1e05d 898 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 58:e38a2e942fbb 899 if (RESP_OK != waitFinalResp(NULL,NULL,40*1000))
mazgch 95:8282dbbe1492 900 goto failure;
mazgch 79:291df065e345 901 a = 0;
mazgch 31:a0bed6c1e05d 902 }
mazgch 79:291df065e345 903 if (a == 0) {
mazgch 84:a05edb010176 904 bool ok = false;
mazgch 84:a05edb010176 905 // try to lookup the apn settings from our local database by mccmnc
mazgch 84:a05edb010176 906 const char* config = NULL;
mazgch 88:135fb4bb7aac 907 if (!apn && !username && !password)
mazgch 88:135fb4bb7aac 908 config = apnconfig(_dev.imsi);
mazgch 84:a05edb010176 909 do {
mazgch 84:a05edb010176 910 if (config) {
mazgch 85:dd8f4f0d0ca9 911 apn = _APN_GET(config);
mazgch 85:dd8f4f0d0ca9 912 username = _APN_GET(config);
mazgch 85:dd8f4f0d0ca9 913 password = _APN_GET(config);
mazgch 79:291df065e345 914 }
mazgch 125:25a292afbac6 915 // convert pointer to empty strings
mazgch 125:25a292afbac6 916 apn = apn ? apn : "";
mazgch 125:25a292afbac6 917 username = username ? username : "";
mazgch 125:25a292afbac6 918 password = password ? password : "";
mazgch 125:25a292afbac6 919 auth = (*username && *password) ? auth : AUTH_NONE;
mazgch 125:25a292afbac6 920 TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\",%d)\r\n", apn, username, password, auth);
mazgch 128:0415646a9934 921 if ((_dev.dev != DEV_TOBY_L2) && (_dev.dev != DEV_MPCI_L2))
mazgch 128:0415646a9934 922 ok = _activateProfile(apn, username, password, auth);
mazgch 131:965a7cbc1e58 923 else {
mazgch 131:965a7cbc1e58 924 ok = _activateProfileReuseExternal();
mazgch 131:965a7cbc1e58 925 if (ok)
mazgch 131:965a7cbc1e58 926 TRACE("Reusing External Context\r\n");
mazgch 131:965a7cbc1e58 927 else
mazgch 131:965a7cbc1e58 928 ok = _activateProfileByCid(1, apn, username, password, auth);
mazgch 131:965a7cbc1e58 929 }
mazgch 99:3116d3e900ed 930 } while (!ok && config && *config); // maybe use next setting ?
mazgch 84:a05edb010176 931 if (!ok) {
mazgch 79:291df065e345 932 ERROR("Your modem APN/password/username may be wrong\r\n");
mazgch 95:8282dbbe1492 933 goto failure;
mazgch 79:291df065e345 934 }
mazgch 74:208e3e32d263 935 }
mazgch 21:c4d64830bf02 936 //Get local IP address
mazgch 21:c4d64830bf02 937 sendFormated("AT+UPSND=" PROFILE ",0\r\n");
mazgch 52:8071747a7cb3 938 if (RESP_OK != waitFinalResp(_cbUPSND, &_ip))
mazgch 95:8282dbbe1492 939 goto failure;
mazgch 31:a0bed6c1e05d 940 }
mazgch 95:8282dbbe1492 941 UNLOCK();
mazgch 32:8f12ac182bbb 942 return _ip;
mazgch 95:8282dbbe1492 943 failure:
mazgch 95:8282dbbe1492 944 unlock();
mazgch 95:8282dbbe1492 945 return NOIP;
mazgch 31:a0bed6c1e05d 946 }
mazgch 31:a0bed6c1e05d 947
mazgch 84:a05edb010176 948 int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc)
mazgch 84:a05edb010176 949 {
mazgch 84:a05edb010176 950 if ((type == TYPE_PLUS) && mccmnc) {
mazgch 84:a05edb010176 951 if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1)
mazgch 84:a05edb010176 952 ;
mazgch 84:a05edb010176 953 }
mazgch 84:a05edb010176 954 return WAIT;
mazgch 84:a05edb010176 955 }
mazgch 84:a05edb010176 956
mazgch 32:8f12ac182bbb 957 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip)
mazgch 32:8f12ac182bbb 958 {
mazgch 102:fb982ff9da82 959 if ((type == TYPE_UNKNOWN) && ip) {
mazgch 32:8f12ac182bbb 960 int a,b,c,d;
mazgch 102:fb982ff9da82 961 if (sscanf(buf, "\r\n" IPSTR, &a,&b,&c,&d) == 4)
mazgch 32:8f12ac182bbb 962 *ip = IPADR(a,b,c,d);
mazgch 32:8f12ac182bbb 963 }
mazgch 32:8f12ac182bbb 964 return WAIT;
mazgch 32:8f12ac182bbb 965 }
mazgch 32:8f12ac182bbb 966
mazgch 31:a0bed6c1e05d 967 int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act)
mazgch 31:a0bed6c1e05d 968 {
mazgch 31:a0bed6c1e05d 969 if ((type == TYPE_PLUS) && act) {
mazgch 31:a0bed6c1e05d 970 if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1)
mazgch 31:a0bed6c1e05d 971 /*nothing*/;
mazgch 21:c4d64830bf02 972 }
mazgch 31:a0bed6c1e05d 973 return WAIT;
mazgch 31:a0bed6c1e05d 974 }
mazgch 31:a0bed6c1e05d 975
mazgch 31:a0bed6c1e05d 976 int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 977 {
mazgch 31:a0bed6c1e05d 978 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 979 int a,b,c,d;
mazgch 31:a0bed6c1e05d 980 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
mazgch 31:a0bed6c1e05d 981 if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 982 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 983 }
mazgch 31:a0bed6c1e05d 984 return WAIT;
mazgch 31:a0bed6c1e05d 985 }
mazgch 31:a0bed6c1e05d 986
mazgch 31:a0bed6c1e05d 987 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 988 {
mazgch 31:a0bed6c1e05d 989 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 990 int a,b,c,d;
mazgch 95:8282dbbe1492 991 if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 992 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 993 }
mazgch 31:a0bed6c1e05d 994 return WAIT;
mazgch 21:c4d64830bf02 995 }
mazgch 21:c4d64830bf02 996
mazgch 21:c4d64830bf02 997 bool MDMParser::disconnect(void)
mazgch 21:c4d64830bf02 998 {
mazgch 95:8282dbbe1492 999 bool ok = false;
mazgch 95:8282dbbe1492 1000 LOCK();
mazgch 74:208e3e32d263 1001 INFO("Modem::disconnect\r\n");
mazgch 95:8282dbbe1492 1002 if (_ip != NOIP) {
mazgch 125:25a292afbac6 1003 if (_dev.dev == DEV_LISA_C2) {
mazgch 95:8282dbbe1492 1004 // There something to do here
mazgch 95:8282dbbe1492 1005 _ip = NOIP;
mazgch 95:8282dbbe1492 1006 ok = true;
mazgch 95:8282dbbe1492 1007 } else {
mazgch 95:8282dbbe1492 1008 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 95:8282dbbe1492 1009 if (RESP_OK != waitFinalResp()) {
mazgch 95:8282dbbe1492 1010 _ip = NOIP;
mazgch 95:8282dbbe1492 1011 ok = true;
mazgch 95:8282dbbe1492 1012 }
mazgch 95:8282dbbe1492 1013 }
mazgch 21:c4d64830bf02 1014 }
mazgch 95:8282dbbe1492 1015 UNLOCK();
mazgch 95:8282dbbe1492 1016 return ok;
mazgch 21:c4d64830bf02 1017 }
mazgch 21:c4d64830bf02 1018
mazgch 31:a0bed6c1e05d 1019 MDMParser::IP MDMParser::gethostbyname(const char* host)
mazgch 21:c4d64830bf02 1020 {
mazgch 31:a0bed6c1e05d 1021 IP ip = NOIP;
mazgch 31:a0bed6c1e05d 1022 int a,b,c,d;
mazgch 31:a0bed6c1e05d 1023 if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 1024 ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 1025 else {
mazgch 95:8282dbbe1492 1026 LOCK();
mazgch 31:a0bed6c1e05d 1027 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host);
mazgch 52:8071747a7cb3 1028 if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip))
mazgch 95:8282dbbe1492 1029 ip = NOIP;
mazgch 95:8282dbbe1492 1030 UNLOCK();
mazgch 21:c4d64830bf02 1031 }
mazgch 31:a0bed6c1e05d 1032 return ip;
mazgch 21:c4d64830bf02 1033 }
mazgch 21:c4d64830bf02 1034
mazgch 21:c4d64830bf02 1035 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 1036 // sockets
mazgch 21:c4d64830bf02 1037
mazgch 103:197fa7920ad8 1038 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* handle)
mazgch 21:c4d64830bf02 1039 {
mazgch 103:197fa7920ad8 1040 if ((type == TYPE_PLUS) && handle) {
mazgch 108:254bf037f83f 1041 // +USOCR: socket
mazgch 108:254bf037f83f 1042 if (sscanf(buf, "\r\n+USOCR: %d", handle) == 1)
mazgch 108:254bf037f83f 1043 /*nothing*/;
mazgch 21:c4d64830bf02 1044 }
mazgch 21:c4d64830bf02 1045 return WAIT;
mazgch 21:c4d64830bf02 1046 }
mazgch 21:c4d64830bf02 1047
mazgch 63:42cb563a25bc 1048 int MDMParser::socketSocket(IpProtocol ipproto, int port)
mazgch 21:c4d64830bf02 1049 {
mazgch 103:197fa7920ad8 1050 int socket;
mazgch 95:8282dbbe1492 1051 LOCK();
mazgch 103:197fa7920ad8 1052 // find an free socket
mazgch 103:197fa7920ad8 1053 socket = _findSocket();
mazgch 47:9a89e5195721 1054 TRACE("socketSocket(%d)\r\n", ipproto);
mazgch 95:8282dbbe1492 1055 if (socket != SOCKET_ERROR) {
mazgch 106:18aeacdae391 1056 if (ipproto == IPPROTO_UDP) {
mazgch 106:18aeacdae391 1057 // sending port can only be set on 2G/3G modules
mazgch 125:25a292afbac6 1058 if ((port != -1) && (_dev.dev != DEV_LISA_C2)) {
mazgch 106:18aeacdae391 1059 sendFormated("AT+USOCR=17,%d\r\n", port);
mazgch 106:18aeacdae391 1060 } else {
mazgch 106:18aeacdae391 1061 sendFormated("AT+USOCR=17\r\n");
mazgch 106:18aeacdae391 1062 }
mazgch 103:197fa7920ad8 1063 } else /*(ipproto == IPPROTO_TCP)*/ {
mazgch 103:197fa7920ad8 1064 sendFormated("AT+USOCR=6\r\n");
mazgch 103:197fa7920ad8 1065 }
mazgch 103:197fa7920ad8 1066 int handle = SOCKET_ERROR;
mazgch 103:197fa7920ad8 1067 if ((RESP_OK == waitFinalResp(_cbUSOCR, &handle)) &&
mazgch 103:197fa7920ad8 1068 (handle != SOCKET_ERROR)) {
mazgch 103:197fa7920ad8 1069 TRACE("Socket %d: handle %d was created\r\n", socket, handle);
mazgch 103:197fa7920ad8 1070 _sockets[socket].handle = handle;
mazgch 103:197fa7920ad8 1071 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
mazgch 103:197fa7920ad8 1072 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 1073 _sockets[socket].pending = 0;
mazgch 103:197fa7920ad8 1074 }
mazgch 103:197fa7920ad8 1075 else
mazgch 103:197fa7920ad8 1076 socket = SOCKET_ERROR;
mazgch 95:8282dbbe1492 1077 }
mazgch 95:8282dbbe1492 1078 UNLOCK();
mazgch 21:c4d64830bf02 1079 return socket;
mazgch 21:c4d64830bf02 1080 }
mazgch 21:c4d64830bf02 1081
mazgch 21:c4d64830bf02 1082 bool MDMParser::socketConnect(int socket, const char * host, int port)
mazgch 21:c4d64830bf02 1083 {
mazgch 31:a0bed6c1e05d 1084 IP ip = gethostbyname(host);
mazgch 31:a0bed6c1e05d 1085 if (ip == NOIP)
mazgch 21:c4d64830bf02 1086 return false;
mazgch 21:c4d64830bf02 1087 // connect to socket
mazgch 95:8282dbbe1492 1088 bool ok = false;
mazgch 95:8282dbbe1492 1089 LOCK();
mazgch 103:197fa7920ad8 1090 if (ISSOCKET(socket) && (!_sockets[socket].connected)) {
mazgch 95:8282dbbe1492 1091 TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port);
mazgch 103:197fa7920ad8 1092 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", _sockets[socket].handle, IPNUM(ip), port);
mazgch 95:8282dbbe1492 1093 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1094 ok = _sockets[socket].connected = true;
mazgch 95:8282dbbe1492 1095 }
mazgch 95:8282dbbe1492 1096 UNLOCK();
mazgch 95:8282dbbe1492 1097 return ok;
mazgch 21:c4d64830bf02 1098 }
mazgch 21:c4d64830bf02 1099
mazgch 44:9d12223b78ff 1100 bool MDMParser::socketIsConnected(int socket)
mazgch 44:9d12223b78ff 1101 {
mazgch 95:8282dbbe1492 1102 bool ok = false;
mazgch 95:8282dbbe1492 1103 LOCK();
mazgch 103:197fa7920ad8 1104 ok = ISSOCKET(socket) && _sockets[socket].connected;
mazgch 107:436ee320efd6 1105 TRACE("socketIsConnected(%d) %s\r\n", socket, ok?"yes":"no");
mazgch 95:8282dbbe1492 1106 UNLOCK();
mazgch 95:8282dbbe1492 1107 return ok;
mazgch 44:9d12223b78ff 1108 }
mazgch 44:9d12223b78ff 1109
mazgch 66:69072b3c5bca 1110 bool MDMParser::socketSetBlocking(int socket, int timeout_ms)
mazgch 44:9d12223b78ff 1111 {
mazgch 95:8282dbbe1492 1112 bool ok = false;
mazgch 95:8282dbbe1492 1113 LOCK();
mazgch 103:197fa7920ad8 1114 TRACE("socketSetBlocking(%d,%d)\r\n", socket,timeout_ms);
mazgch 95:8282dbbe1492 1115 if (ISSOCKET(socket)) {
mazgch 95:8282dbbe1492 1116 _sockets[socket].timeout_ms = timeout_ms;
mazgch 95:8282dbbe1492 1117 ok = true;
mazgch 95:8282dbbe1492 1118 }
mazgch 95:8282dbbe1492 1119 UNLOCK();
mazgch 95:8282dbbe1492 1120 return ok;
mazgch 44:9d12223b78ff 1121 }
mazgch 44:9d12223b78ff 1122
mazgch 21:c4d64830bf02 1123 bool MDMParser::socketClose(int socket)
mazgch 21:c4d64830bf02 1124 {
mazgch 95:8282dbbe1492 1125 bool ok = false;
mazgch 95:8282dbbe1492 1126 LOCK();
mazgch 103:197fa7920ad8 1127 if (ISSOCKET(socket) && _sockets[socket].connected) {
mazgch 95:8282dbbe1492 1128 TRACE("socketClose(%d)\r\n", socket);
mazgch 103:197fa7920ad8 1129 sendFormated("AT+USOCL=%d\r\n", _sockets[socket].handle);
mazgch 95:8282dbbe1492 1130 if (RESP_OK == waitFinalResp()) {
mazgch 103:197fa7920ad8 1131 _sockets[socket].connected = false;
mazgch 95:8282dbbe1492 1132 ok = true;
mazgch 95:8282dbbe1492 1133 }
mazgch 95:8282dbbe1492 1134 }
mazgch 95:8282dbbe1492 1135 UNLOCK();
mazgch 95:8282dbbe1492 1136 return ok;
mazgch 21:c4d64830bf02 1137 }
mazgch 21:c4d64830bf02 1138
mazgch 21:c4d64830bf02 1139 bool MDMParser::socketFree(int socket)
mazgch 21:c4d64830bf02 1140 {
mazgch 95:8282dbbe1492 1141 // make sure it is closed
mazgch 21:c4d64830bf02 1142 socketClose(socket);
mazgch 95:8282dbbe1492 1143 bool ok = true;
mazgch 95:8282dbbe1492 1144 LOCK();
mazgch 103:197fa7920ad8 1145 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1146 TRACE("socketFree(%d)\r\n", socket);
mazgch 103:197fa7920ad8 1147 _sockets[socket].handle = SOCKET_ERROR;
mazgch 103:197fa7920ad8 1148 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
mazgch 103:197fa7920ad8 1149 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 1150 _sockets[socket].pending = 0;
mazgch 95:8282dbbe1492 1151 ok = true;
mazgch 95:8282dbbe1492 1152 }
mazgch 95:8282dbbe1492 1153 UNLOCK();
mazgch 95:8282dbbe1492 1154 return ok;
mazgch 21:c4d64830bf02 1155 }
mazgch 21:c4d64830bf02 1156
mazgch 69:4d6fa520dfca 1157 #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket
mazgch 69:4d6fa520dfca 1158
mazgch 21:c4d64830bf02 1159 int MDMParser::socketSend(int socket, const char * buf, int len)
mazgch 21:c4d64830bf02 1160 {
mazgch 47:9a89e5195721 1161 TRACE("socketSend(%d,,%d)\r\n", socket,len);
mazgch 68:33a96cf64986 1162 int cnt = len;
mazgch 68:33a96cf64986 1163 while (cnt > 0) {
mazgch 69:4d6fa520dfca 1164 int blk = USO_MAX_WRITE;
mazgch 68:33a96cf64986 1165 if (cnt < blk)
mazgch 68:33a96cf64986 1166 blk = cnt;
mazgch 95:8282dbbe1492 1167 bool ok = false;
mazgch 95:8282dbbe1492 1168 LOCK();
mazgch 103:197fa7920ad8 1169 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1170 sendFormated("AT+USOWR=%d,%d\r\n",_sockets[socket].handle,blk);
mazgch 103:197fa7920ad8 1171 if (RESP_PROMPT == waitFinalResp()) {
mazgch 103:197fa7920ad8 1172 wait_ms(50);
mazgch 103:197fa7920ad8 1173 send(buf, blk);
mazgch 103:197fa7920ad8 1174 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1175 ok = true;
mazgch 103:197fa7920ad8 1176 }
mazgch 95:8282dbbe1492 1177 }
mazgch 95:8282dbbe1492 1178 UNLOCK();
mazgch 95:8282dbbe1492 1179 if (!ok)
mazgch 21:c4d64830bf02 1180 return SOCKET_ERROR;
mazgch 68:33a96cf64986 1181 buf += blk;
mazgch 68:33a96cf64986 1182 cnt -= blk;
mazgch 21:c4d64830bf02 1183 }
mazgch 68:33a96cf64986 1184 return (len - cnt);
mazgch 21:c4d64830bf02 1185 }
mazgch 21:c4d64830bf02 1186
mazgch 21:c4d64830bf02 1187 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len)
mazgch 21:c4d64830bf02 1188 {
mazgch 103:197fa7920ad8 1189 TRACE("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket,IPNUM(ip),port,len);
mazgch 68:33a96cf64986 1190 int cnt = len;
mazgch 68:33a96cf64986 1191 while (cnt > 0) {
mazgch 69:4d6fa520dfca 1192 int blk = USO_MAX_WRITE;
mazgch 68:33a96cf64986 1193 if (cnt < blk)
mazgch 68:33a96cf64986 1194 blk = cnt;
mazgch 95:8282dbbe1492 1195 bool ok = false;
mazgch 95:8282dbbe1492 1196 LOCK();
mazgch 103:197fa7920ad8 1197 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1198 sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",_sockets[socket].handle,IPNUM(ip),port,blk);
mazgch 103:197fa7920ad8 1199 if (RESP_PROMPT == waitFinalResp()) {
mazgch 103:197fa7920ad8 1200 wait_ms(50);
mazgch 103:197fa7920ad8 1201 send(buf, blk);
mazgch 103:197fa7920ad8 1202 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1203 ok = true;
mazgch 103:197fa7920ad8 1204 }
mazgch 95:8282dbbe1492 1205 }
mazgch 95:8282dbbe1492 1206 UNLOCK();
mazgch 95:8282dbbe1492 1207 if (!ok)
mazgch 21:c4d64830bf02 1208 return SOCKET_ERROR;
mazgch 68:33a96cf64986 1209 buf += blk;
mazgch 68:33a96cf64986 1210 cnt -= blk;
mazgch 21:c4d64830bf02 1211 }
mazgch 68:33a96cf64986 1212 return (len - cnt);
mazgch 21:c4d64830bf02 1213 }
mazgch 21:c4d64830bf02 1214
mazgch 21:c4d64830bf02 1215 int MDMParser::socketReadable(int socket)
mazgch 21:c4d64830bf02 1216 {
mazgch 95:8282dbbe1492 1217 int pending = SOCKET_ERROR;
mazgch 95:8282dbbe1492 1218 LOCK();
mazgch 103:197fa7920ad8 1219 if (ISSOCKET(socket) && _sockets[socket].connected) {
mazgch 95:8282dbbe1492 1220 TRACE("socketReadable(%d)\r\n", socket);
mazgch 95:8282dbbe1492 1221 // allow to receive unsolicited commands
mazgch 95:8282dbbe1492 1222 waitFinalResp(NULL, NULL, 0);
mazgch 103:197fa7920ad8 1223 if (_sockets[socket].connected)
mazgch 95:8282dbbe1492 1224 pending = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1225 }
mazgch 95:8282dbbe1492 1226 UNLOCK();
mazgch 95:8282dbbe1492 1227 return pending;
mazgch 21:c4d64830bf02 1228 }
mazgch 21:c4d64830bf02 1229
mazgch 21:c4d64830bf02 1230 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out)
mazgch 21:c4d64830bf02 1231 {
mazgch 21:c4d64830bf02 1232 if ((type == TYPE_PLUS) && out) {
mazgch 21:c4d64830bf02 1233 int sz, sk;
mazgch 21:c4d64830bf02 1234 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) &&
mazgch 21:c4d64830bf02 1235 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 1236 memcpy(out, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 1237 }
mazgch 21:c4d64830bf02 1238 }
mazgch 21:c4d64830bf02 1239 return WAIT;
mazgch 21:c4d64830bf02 1240 }
mazgch 21:c4d64830bf02 1241
mazgch 21:c4d64830bf02 1242 int MDMParser::socketRecv(int socket, char* buf, int len)
mazgch 21:c4d64830bf02 1243 {
mazgch 21:c4d64830bf02 1244 int cnt = 0;
mazgch 47:9a89e5195721 1245 TRACE("socketRecv(%d,,%d)\r\n", socket, len);
mazgch 95:8282dbbe1492 1246 #ifdef MDM_DEBUG
mazgch 21:c4d64830bf02 1247 memset(buf, '\0', len);
mazgch 95:8282dbbe1492 1248 #endif
mazgch 44:9d12223b78ff 1249 Timer timer;
mazgch 44:9d12223b78ff 1250 timer.start();
mazgch 21:c4d64830bf02 1251 while (len) {
mazgch 69:4d6fa520dfca 1252 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 1253 if (len < blk) blk = len;
mazgch 95:8282dbbe1492 1254 bool ok = false;
mazgch 95:8282dbbe1492 1255 LOCK();
mazgch 95:8282dbbe1492 1256 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1257 if (_sockets[socket].connected) {
mazgch 95:8282dbbe1492 1258 if (_sockets[socket].pending < blk)
mazgch 95:8282dbbe1492 1259 blk = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1260 if (blk > 0) {
mazgch 103:197fa7920ad8 1261 sendFormated("AT+USORD=%d,%d\r\n",_sockets[socket].handle, blk);
mazgch 95:8282dbbe1492 1262 if (RESP_OK == waitFinalResp(_cbUSORD, buf)) {
mazgch 95:8282dbbe1492 1263 _sockets[socket].pending -= blk;
mazgch 95:8282dbbe1492 1264 len -= blk;
mazgch 95:8282dbbe1492 1265 cnt += blk;
mazgch 95:8282dbbe1492 1266 buf += blk;
mazgch 95:8282dbbe1492 1267 ok = true;
mazgch 95:8282dbbe1492 1268 }
mazgch 95:8282dbbe1492 1269 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
mazgch 95:8282dbbe1492 1270 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
mazgch 95:8282dbbe1492 1271 } else {
mazgch 95:8282dbbe1492 1272 len = 0;
mazgch 95:8282dbbe1492 1273 ok = true;
mazgch 95:8282dbbe1492 1274 }
mazgch 103:197fa7920ad8 1275 } else {
mazgch 95:8282dbbe1492 1276 len = 0;
mazgch 95:8282dbbe1492 1277 ok = true;
mazgch 21:c4d64830bf02 1278 }
mazgch 21:c4d64830bf02 1279 }
mazgch 95:8282dbbe1492 1280 UNLOCK();
mazgch 107:436ee320efd6 1281 if (!ok) {
mazgch 107:436ee320efd6 1282 TRACE("socketRecv: ERROR\r\n");
mazgch 95:8282dbbe1492 1283 return SOCKET_ERROR;
mazgch 107:436ee320efd6 1284 }
mazgch 21:c4d64830bf02 1285 }
mazgch 107:436ee320efd6 1286 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt);
mazgch 21:c4d64830bf02 1287 return cnt;
mazgch 21:c4d64830bf02 1288 }
mazgch 21:c4d64830bf02 1289
mazgch 21:c4d64830bf02 1290 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param)
mazgch 21:c4d64830bf02 1291 {
mazgch 21:c4d64830bf02 1292 if ((type == TYPE_PLUS) && param) {
mazgch 21:c4d64830bf02 1293 int sz, sk, p, a,b,c,d;
mazgch 95:8282dbbe1492 1294 int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,",
mazgch 95:8282dbbe1492 1295 &sk,&a,&b,&c,&d,&p,&sz);
mazgch 95:8282dbbe1492 1296 if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 1297 memcpy(param->buf, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 1298 param->ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 1299 param->port = p;
mazgch 21:c4d64830bf02 1300 }
mazgch 21:c4d64830bf02 1301 }
mazgch 21:c4d64830bf02 1302 return WAIT;
mazgch 21:c4d64830bf02 1303 }
mazgch 21:c4d64830bf02 1304
mazgch 63:42cb563a25bc 1305 int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len)
mazgch 21:c4d64830bf02 1306 {
mazgch 21:c4d64830bf02 1307 int cnt = 0;
mazgch 63:42cb563a25bc 1308 TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len);
mazgch 95:8282dbbe1492 1309 #ifdef MDM_DEBUG
mazgch 21:c4d64830bf02 1310 memset(buf, '\0', len);
mazgch 95:8282dbbe1492 1311 #endif
mazgch 44:9d12223b78ff 1312 Timer timer;
mazgch 44:9d12223b78ff 1313 timer.start();
mazgch 21:c4d64830bf02 1314 while (len) {
mazgch 69:4d6fa520dfca 1315 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 1316 if (len < blk) blk = len;
mazgch 95:8282dbbe1492 1317 bool ok = false;
mazgch 95:8282dbbe1492 1318 LOCK();
mazgch 95:8282dbbe1492 1319 if (ISSOCKET(socket)) {
mazgch 95:8282dbbe1492 1320 if (_sockets[socket].pending < blk)
mazgch 95:8282dbbe1492 1321 blk = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1322 if (blk > 0) {
mazgch 103:197fa7920ad8 1323 sendFormated("AT+USORF=%d,%d\r\n",_sockets[socket].handle, blk);
mazgch 95:8282dbbe1492 1324 USORFparam param;
mazgch 95:8282dbbe1492 1325 param.buf = buf;
mazgch 95:8282dbbe1492 1326 if (RESP_OK == waitFinalResp(_cbUSORF, &param)) {
mazgch 95:8282dbbe1492 1327 _sockets[socket].pending -= blk;
mazgch 95:8282dbbe1492 1328 *ip = param.ip;
mazgch 95:8282dbbe1492 1329 *port = param.port;
mazgch 95:8282dbbe1492 1330 len -= blk;
mazgch 95:8282dbbe1492 1331 cnt += blk;
mazgch 95:8282dbbe1492 1332 buf += blk;
mazgch 95:8282dbbe1492 1333 len = 0; // done
mazgch 95:8282dbbe1492 1334 ok = true;
mazgch 95:8282dbbe1492 1335 }
mazgch 95:8282dbbe1492 1336 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
mazgch 95:8282dbbe1492 1337 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
mazgch 95:8282dbbe1492 1338 } else {
mazgch 95:8282dbbe1492 1339 len = 0; // no more data and socket closed or timed-out
mazgch 95:8282dbbe1492 1340 ok = true;
mazgch 21:c4d64830bf02 1341 }
mazgch 95:8282dbbe1492 1342 }
mazgch 95:8282dbbe1492 1343 UNLOCK();
mazgch 107:436ee320efd6 1344 if (!ok) {
mazgch 107:436ee320efd6 1345 TRACE("socketRecv: ERROR\r\n");
mazgch 95:8282dbbe1492 1346 return SOCKET_ERROR;
mazgch 107:436ee320efd6 1347 }
mazgch 21:c4d64830bf02 1348 }
mazgch 44:9d12223b78ff 1349 timer.stop();
mazgch 44:9d12223b78ff 1350 timer.reset();
mazgch 107:436ee320efd6 1351 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt);
mazgch 21:c4d64830bf02 1352 return cnt;
mazgch 21:c4d64830bf02 1353 }
mazgch 21:c4d64830bf02 1354
mazgch 103:197fa7920ad8 1355 int MDMParser::_findSocket(int handle) {
mazgch 104:c64ba749a422 1356 for (int socket = 0; socket < NUMSOCKETS; socket ++) {
mazgch 103:197fa7920ad8 1357 if (_sockets[socket].handle == handle)
mazgch 103:197fa7920ad8 1358 return socket;
mazgch 103:197fa7920ad8 1359 }
mazgch 103:197fa7920ad8 1360 return SOCKET_ERROR;
mazgch 103:197fa7920ad8 1361 }
mazgch 103:197fa7920ad8 1362
mazgch 21:c4d64830bf02 1363 // ----------------------------------------------------------------
fdilenarda 135:cbccf4052d45 1364 // HTTP
fdilenarda 135:cbccf4052d45 1365
fdilenarda 135:cbccf4052d45 1366 int MDMParser::httpFindProfile()
fdilenarda 135:cbccf4052d45 1367 {
fdilenarda 135:cbccf4052d45 1368 int profile = HTTP_PROF_ERROR; //default value
fdilenarda 135:cbccf4052d45 1369 LOCK();
fdilenarda 135:cbccf4052d45 1370 // find a free HTTP profile
fdilenarda 135:cbccf4052d45 1371 profile = _findProfile();
fdilenarda 135:cbccf4052d45 1372 TRACE("httpFindProfile: profile is %d\r\n", profile);
fdilenarda 135:cbccf4052d45 1373 if (profile != HTTP_PROF_ERROR) {
fdilenarda 135:cbccf4052d45 1374 _httpProfiles[profile].handle = 1;
fdilenarda 135:cbccf4052d45 1375 _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING;
fdilenarda 135:cbccf4052d45 1376 _httpProfiles[profile].pending = false;
fdilenarda 135:cbccf4052d45 1377 _httpProfiles[profile].cmd = -1;
fdilenarda 135:cbccf4052d45 1378 _httpProfiles[profile].result = -1;
fdilenarda 135:cbccf4052d45 1379 }
fdilenarda 135:cbccf4052d45 1380 UNLOCK();
fdilenarda 135:cbccf4052d45 1381 return profile;
fdilenarda 135:cbccf4052d45 1382 }
fdilenarda 135:cbccf4052d45 1383
fdilenarda 135:cbccf4052d45 1384 int MDMParser::_findProfile(int handle) {
fdilenarda 135:cbccf4052d45 1385 for (int profile = 0; profile < NUMPROFILES; profile++) {
fdilenarda 135:cbccf4052d45 1386 if (_httpProfiles[profile].handle == handle)
fdilenarda 135:cbccf4052d45 1387 return profile;
fdilenarda 135:cbccf4052d45 1388 }
fdilenarda 135:cbccf4052d45 1389 return HTTP_PROF_ERROR;
fdilenarda 135:cbccf4052d45 1390 }
fdilenarda 135:cbccf4052d45 1391
fdilenarda 135:cbccf4052d45 1392 bool MDMParser::httpSetBlocking(int profile, int timeout_ms)
fdilenarda 135:cbccf4052d45 1393 {
fdilenarda 135:cbccf4052d45 1394 bool ok = false;
fdilenarda 135:cbccf4052d45 1395 LOCK();
fdilenarda 135:cbccf4052d45 1396 TRACE("httpSetBlocking(%d,%d)\r\n", profile, timeout_ms);
fdilenarda 135:cbccf4052d45 1397 if (ISPROFILE(profile)) {
fdilenarda 135:cbccf4052d45 1398 _httpProfiles[profile].timeout_ms = timeout_ms;
fdilenarda 135:cbccf4052d45 1399 ok = true;
fdilenarda 135:cbccf4052d45 1400 }
fdilenarda 135:cbccf4052d45 1401 UNLOCK();
fdilenarda 135:cbccf4052d45 1402 return ok;
fdilenarda 135:cbccf4052d45 1403 }
fdilenarda 135:cbccf4052d45 1404
fdilenarda 135:cbccf4052d45 1405 bool MDMParser::httpSetProfileForCmdMng(int profile)
fdilenarda 135:cbccf4052d45 1406 {
fdilenarda 135:cbccf4052d45 1407 bool ok = false;
fdilenarda 135:cbccf4052d45 1408 LOCK();
fdilenarda 135:cbccf4052d45 1409 TRACE("httpSetProfileForCmdMng(%d)\r\n", profile);
fdilenarda 135:cbccf4052d45 1410 if (ISPROFILE(profile)) {
fdilenarda 135:cbccf4052d45 1411 _httpProfiles[profile].pending = true;
fdilenarda 135:cbccf4052d45 1412 _httpProfiles[profile].result = -1;
fdilenarda 135:cbccf4052d45 1413 ok = true;
fdilenarda 135:cbccf4052d45 1414 }
fdilenarda 135:cbccf4052d45 1415 UNLOCK();
fdilenarda 135:cbccf4052d45 1416 return ok;
fdilenarda 135:cbccf4052d45 1417 }
fdilenarda 135:cbccf4052d45 1418
fdilenarda 135:cbccf4052d45 1419 bool MDMParser::httpFreeProfile(int profile)
fdilenarda 135:cbccf4052d45 1420 {
fdilenarda 135:cbccf4052d45 1421 bool ok = true;
fdilenarda 135:cbccf4052d45 1422 LOCK();
fdilenarda 135:cbccf4052d45 1423 if (ISPROFILE(profile)) {
fdilenarda 135:cbccf4052d45 1424 TRACE("httpFreeProfile(%d)\r\n", profile);
fdilenarda 135:cbccf4052d45 1425 _httpProfiles[profile].handle = HTTP_PROF_ERROR;
fdilenarda 135:cbccf4052d45 1426 _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING;
fdilenarda 135:cbccf4052d45 1427 _httpProfiles[profile].pending = false;
fdilenarda 135:cbccf4052d45 1428 _httpProfiles[profile].cmd = -1;
fdilenarda 135:cbccf4052d45 1429 _httpProfiles[profile].result = -1;
fdilenarda 135:cbccf4052d45 1430 ok = true;
fdilenarda 135:cbccf4052d45 1431 }
fdilenarda 135:cbccf4052d45 1432 UNLOCK();
fdilenarda 135:cbccf4052d45 1433 return ok;
fdilenarda 135:cbccf4052d45 1434 }
fdilenarda 135:cbccf4052d45 1435
fdilenarda 135:cbccf4052d45 1436 bool MDMParser::httpResetProfile(int httpProfile)
fdilenarda 135:cbccf4052d45 1437 {
fdilenarda 135:cbccf4052d45 1438 bool ok = false;
fdilenarda 135:cbccf4052d45 1439
fdilenarda 135:cbccf4052d45 1440 LOCK();
fdilenarda 135:cbccf4052d45 1441 TRACE("httpResetProfile(%d)\r\n", httpProfile);
fdilenarda 135:cbccf4052d45 1442 sendFormated("AT+UHTTP=%d\r\n", httpProfile);
fdilenarda 135:cbccf4052d45 1443 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1444 ok = true;
fdilenarda 135:cbccf4052d45 1445 UNLOCK();
fdilenarda 135:cbccf4052d45 1446
fdilenarda 135:cbccf4052d45 1447 return ok;
fdilenarda 135:cbccf4052d45 1448 }
fdilenarda 135:cbccf4052d45 1449
fdilenarda 135:cbccf4052d45 1450 bool MDMParser::httpSetPar(int httpProfile, HttpOpCode httpOpCode, const char * httpInPar)
fdilenarda 135:cbccf4052d45 1451 {
fdilenarda 135:cbccf4052d45 1452 bool ok = false;
fdilenarda 135:cbccf4052d45 1453 IP ip = NOIP;
fdilenarda 135:cbccf4052d45 1454 int httpInParNum = 0;
fdilenarda 135:cbccf4052d45 1455
fdilenarda 135:cbccf4052d45 1456 LOCK();
fdilenarda 135:cbccf4052d45 1457 TRACE("httpSetPar(%d,%d,\"%s\")\r\n", httpProfile, httpOpCode, httpInPar);
fdilenarda 135:cbccf4052d45 1458 switch(httpOpCode){
fdilenarda 135:cbccf4052d45 1459 case HTTP_IP_ADDRESS: //0
fdilenarda 135:cbccf4052d45 1460 ip = gethostbyname(httpInPar);
fdilenarda 135:cbccf4052d45 1461 if (ip == NOIP)
fdilenarda 135:cbccf4052d45 1462 return false;
fdilenarda 135:cbccf4052d45 1463
fdilenarda 135:cbccf4052d45 1464 sendFormated("AT+UHTTP=%d,%d,\"" IPSTR "\"\r\n", httpProfile, httpOpCode, IPNUM(ip));
fdilenarda 135:cbccf4052d45 1465 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1466 ok = true;
fdilenarda 135:cbccf4052d45 1467 break;
fdilenarda 135:cbccf4052d45 1468
fdilenarda 135:cbccf4052d45 1469 case HTTP_SERVER_NAME: //1
fdilenarda 135:cbccf4052d45 1470 case HTTP_USER_NAME: //2
fdilenarda 135:cbccf4052d45 1471 case HTTP_PASSWORD: //3
fdilenarda 135:cbccf4052d45 1472 sendFormated("AT+UHTTP=%d,%d,\"%s\"\r\n", httpProfile, httpOpCode, httpInPar);
fdilenarda 135:cbccf4052d45 1473 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1474 ok = true;
fdilenarda 135:cbccf4052d45 1475 break;
fdilenarda 135:cbccf4052d45 1476
fdilenarda 135:cbccf4052d45 1477 case HTTP_AUTH_TYPE: //4
fdilenarda 137:6a7a5c4f35f6 1478 case HTTP_SERVER_PORT: //5
fdilenarda 135:cbccf4052d45 1479 httpInParNum = atoi(httpInPar);
fdilenarda 135:cbccf4052d45 1480 sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum);
fdilenarda 135:cbccf4052d45 1481 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1482 ok = true;
fdilenarda 135:cbccf4052d45 1483 break;
fdilenarda 135:cbccf4052d45 1484
fdilenarda 135:cbccf4052d45 1485 case HTTP_SECURE: //6
fdilenarda 135:cbccf4052d45 1486 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1487 {
fdilenarda 135:cbccf4052d45 1488 httpInParNum = atoi(httpInPar);
fdilenarda 135:cbccf4052d45 1489 sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum);
fdilenarda 135:cbccf4052d45 1490 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1491 ok = true;
fdilenarda 135:cbccf4052d45 1492 } else {
fdilenarda 135:cbccf4052d45 1493 TRACE("httpSetPar: HTTP secure option not supported by module\r\n");
fdilenarda 135:cbccf4052d45 1494 ok = false;
fdilenarda 135:cbccf4052d45 1495 }
fdilenarda 135:cbccf4052d45 1496 break;
fdilenarda 135:cbccf4052d45 1497
fdilenarda 135:cbccf4052d45 1498 default:
fdilenarda 135:cbccf4052d45 1499 TRACE("httpSetPar: unknown httpOpCode %s\r\n", httpOpCode);
fdilenarda 135:cbccf4052d45 1500 ok = false;
fdilenarda 135:cbccf4052d45 1501 break;
fdilenarda 135:cbccf4052d45 1502 }
fdilenarda 135:cbccf4052d45 1503 UNLOCK();
fdilenarda 135:cbccf4052d45 1504 return ok;
fdilenarda 135:cbccf4052d45 1505 }
fdilenarda 135:cbccf4052d45 1506
fdilenarda 135:cbccf4052d45 1507 bool MDMParser::httpCommand(int httpProfile, HttpCmd httpCmdCode, const char* httpPath, const char* httpOut, \
fdilenarda 135:cbccf4052d45 1508 const char* httpIn, int httpContentType, const char* httpCustomPar, char* buf, int len)
fdilenarda 135:cbccf4052d45 1509 {
fdilenarda 135:cbccf4052d45 1510 bool ok = false;
fdilenarda 135:cbccf4052d45 1511 #ifdef MDM_DEBUG
fdilenarda 135:cbccf4052d45 1512 memset(buf, '\0', len);
fdilenarda 135:cbccf4052d45 1513 #endif
fdilenarda 135:cbccf4052d45 1514 LOCK();
fdilenarda 135:cbccf4052d45 1515 TRACE("%s\r\n", getHTTPcmd(httpCmdCode));
fdilenarda 135:cbccf4052d45 1516 switch (httpCmdCode)
fdilenarda 135:cbccf4052d45 1517 {
fdilenarda 135:cbccf4052d45 1518 case HTTP_HEAD:
fdilenarda 135:cbccf4052d45 1519 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_HEAD, httpPath, httpOut);
fdilenarda 135:cbccf4052d45 1520 break;
fdilenarda 135:cbccf4052d45 1521
fdilenarda 135:cbccf4052d45 1522 case HTTP_GET:
fdilenarda 135:cbccf4052d45 1523 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_GET, httpPath, httpOut);
fdilenarda 135:cbccf4052d45 1524 break;
fdilenarda 135:cbccf4052d45 1525
fdilenarda 135:cbccf4052d45 1526 case HTTP_DELETE:
fdilenarda 135:cbccf4052d45 1527 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_DELETE, httpPath, httpOut);
fdilenarda 135:cbccf4052d45 1528 break;
fdilenarda 135:cbccf4052d45 1529
fdilenarda 135:cbccf4052d45 1530 case HTTP_PUT:
fdilenarda 135:cbccf4052d45 1531 //in this case the parameter httpIn is a filename
fdilenarda 135:cbccf4052d45 1532 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\"\r\n", httpProfile, HTTP_PUT, httpPath, httpOut, httpIn);
fdilenarda 135:cbccf4052d45 1533 break;
fdilenarda 135:cbccf4052d45 1534
fdilenarda 135:cbccf4052d45 1535 case HTTP_POST_FILE:
fdilenarda 135:cbccf4052d45 1536 //in this case the parameter httpIn is a filename
fdilenarda 135:cbccf4052d45 1537 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1538 {
fdilenarda 135:cbccf4052d45 1539 if(httpContentType != 6)
fdilenarda 135:cbccf4052d45 1540 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \
fdilenarda 135:cbccf4052d45 1541 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType);
fdilenarda 135:cbccf4052d45 1542 else
fdilenarda 135:cbccf4052d45 1543 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \
fdilenarda 135:cbccf4052d45 1544 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType, httpCustomPar);
fdilenarda 135:cbccf4052d45 1545 }
fdilenarda 135:cbccf4052d45 1546 else{
fdilenarda 135:cbccf4052d45 1547 if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL))
fdilenarda 135:cbccf4052d45 1548 {
fdilenarda 135:cbccf4052d45 1549 //parameters values consistent with the AT commands specs of LISA-C200
fdilenarda 135:cbccf4052d45 1550 //(in particular httpCustomPar has to be not defined)
fdilenarda 135:cbccf4052d45 1551 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \
fdilenarda 135:cbccf4052d45 1552 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType);
fdilenarda 135:cbccf4052d45 1553 } else {
fdilenarda 135:cbccf4052d45 1554 TRACE("httpCommand: command not supported by module");
fdilenarda 135:cbccf4052d45 1555 return ok; //error
fdilenarda 135:cbccf4052d45 1556 }
fdilenarda 135:cbccf4052d45 1557 }
fdilenarda 135:cbccf4052d45 1558 break;
fdilenarda 135:cbccf4052d45 1559
fdilenarda 135:cbccf4052d45 1560 case HTTP_POST_DATA:
fdilenarda 135:cbccf4052d45 1561 //in this case the parameter httpIn is a string containing data
fdilenarda 135:cbccf4052d45 1562 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1563 {
fdilenarda 135:cbccf4052d45 1564 if(httpContentType != 6)
fdilenarda 135:cbccf4052d45 1565 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \
fdilenarda 135:cbccf4052d45 1566 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType);
fdilenarda 135:cbccf4052d45 1567 else
fdilenarda 135:cbccf4052d45 1568 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \
fdilenarda 135:cbccf4052d45 1569 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType, httpCustomPar);
fdilenarda 135:cbccf4052d45 1570 } else {
fdilenarda 135:cbccf4052d45 1571 if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL))
fdilenarda 135:cbccf4052d45 1572 {
fdilenarda 135:cbccf4052d45 1573 //parameters values consistent with the AT commands specs of LISA-C200
fdilenarda 135:cbccf4052d45 1574 //(in particular httpCustomPar has to be not defined)
fdilenarda 135:cbccf4052d45 1575 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \
fdilenarda 135:cbccf4052d45 1576 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType);
fdilenarda 135:cbccf4052d45 1577 } else {
fdilenarda 135:cbccf4052d45 1578 TRACE("httpCommand: command not supported by module");
fdilenarda 135:cbccf4052d45 1579 return ok; //error
fdilenarda 135:cbccf4052d45 1580 }
fdilenarda 135:cbccf4052d45 1581 }
fdilenarda 135:cbccf4052d45 1582 break;
fdilenarda 135:cbccf4052d45 1583
fdilenarda 135:cbccf4052d45 1584 default:
fdilenarda 135:cbccf4052d45 1585 TRACE("HTTP command not recognized\r\n");
fdilenarda 135:cbccf4052d45 1586 return ok; //error
fdilenarda 135:cbccf4052d45 1587 }
fdilenarda 135:cbccf4052d45 1588
fdilenarda 135:cbccf4052d45 1589 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1590 {
fdilenarda 135:cbccf4052d45 1591 Timer timer;
fdilenarda 135:cbccf4052d45 1592 timer.start();
fdilenarda 135:cbccf4052d45 1593 httpSetProfileForCmdMng(httpProfile);
fdilenarda 135:cbccf4052d45 1594 while (_httpProfiles[httpProfile].pending) //waiting for unsolicited
fdilenarda 135:cbccf4052d45 1595 {
fdilenarda 135:cbccf4052d45 1596 ok = false; //reset variable
fdilenarda 135:cbccf4052d45 1597 if(_httpProfiles[httpProfile].result != -1)
fdilenarda 135:cbccf4052d45 1598 {
fdilenarda 135:cbccf4052d45 1599 //received unsolicited: starting its analysis
fdilenarda 135:cbccf4052d45 1600 _httpProfiles[httpProfile].pending = false;
fdilenarda 135:cbccf4052d45 1601 if(_httpProfiles[httpProfile].result == 1)
fdilenarda 135:cbccf4052d45 1602 {
fdilenarda 135:cbccf4052d45 1603 //HTTP command successfully executed
fdilenarda 135:cbccf4052d45 1604 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1605 {
fdilenarda 135:cbccf4052d45 1606 TRACE("httpCommand: reading files with a dimension " \
fdilenarda 135:cbccf4052d45 1607 "also greater than MAX_SIZE bytes\r\n");
fdilenarda 135:cbccf4052d45 1608 if(readFileNew(httpOut,buf,len) >=0 )
fdilenarda 135:cbccf4052d45 1609 ok = true;
fdilenarda 135:cbccf4052d45 1610 } else {
fdilenarda 135:cbccf4052d45 1611 TRACE("httpCommand: reading files with a dimension " \
fdilenarda 135:cbccf4052d45 1612 "less than MAX_SIZE bytes, otherwise error\r\n");
fdilenarda 135:cbccf4052d45 1613 if(readFile(httpOut,buf,len) >=0 )
fdilenarda 135:cbccf4052d45 1614 ok = true;
fdilenarda 135:cbccf4052d45 1615 }
fdilenarda 135:cbccf4052d45 1616 } else {
fdilenarda 135:cbccf4052d45 1617 //HTTP command not successfully executed
fdilenarda 135:cbccf4052d45 1618 ok = false;
fdilenarda 135:cbccf4052d45 1619 }
fdilenarda 135:cbccf4052d45 1620 } else if (!TIMEOUT(timer, _httpProfiles[httpProfile].timeout_ms)) {
fdilenarda 135:cbccf4052d45 1621 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
fdilenarda 135:cbccf4052d45 1622 } else {
fdilenarda 135:cbccf4052d45 1623 //not received unsolicited and expired timer
fdilenarda 135:cbccf4052d45 1624 TRACE("httpCommand: not received unsolicited and expired timer\r\n");
fdilenarda 135:cbccf4052d45 1625 ok = false;
fdilenarda 135:cbccf4052d45 1626 }
fdilenarda 135:cbccf4052d45 1627 if (!ok) {
fdilenarda 135:cbccf4052d45 1628 TRACE("%s: ERROR\r\n", getHTTPcmd(httpCmdCode));
fdilenarda 135:cbccf4052d45 1629 _httpProfiles[httpProfile].pending = false; //no more while loops
fdilenarda 135:cbccf4052d45 1630 }
fdilenarda 135:cbccf4052d45 1631 }
fdilenarda 135:cbccf4052d45 1632 }
fdilenarda 135:cbccf4052d45 1633 UNLOCK();
fdilenarda 135:cbccf4052d45 1634 return ok;
fdilenarda 135:cbccf4052d45 1635 }
fdilenarda 135:cbccf4052d45 1636
fdilenarda 135:cbccf4052d45 1637 const char* MDMParser::getHTTPcmd(int httpCmdCode)
fdilenarda 135:cbccf4052d45 1638 {
fdilenarda 135:cbccf4052d45 1639 switch (httpCmdCode)
fdilenarda 135:cbccf4052d45 1640 {
fdilenarda 135:cbccf4052d45 1641 case HTTP_HEAD:
fdilenarda 135:cbccf4052d45 1642 return "HTTP HEAD command";
fdilenarda 135:cbccf4052d45 1643 case HTTP_GET:
fdilenarda 135:cbccf4052d45 1644 return "HTTP GET command";
fdilenarda 135:cbccf4052d45 1645 case HTTP_DELETE:
fdilenarda 135:cbccf4052d45 1646 return "HTTP DELETE command";
fdilenarda 135:cbccf4052d45 1647 case HTTP_PUT:
fdilenarda 135:cbccf4052d45 1648 return "HTTP PUT command";
fdilenarda 135:cbccf4052d45 1649 case HTTP_POST_FILE:
fdilenarda 135:cbccf4052d45 1650 return "HTTP POST file command";
fdilenarda 135:cbccf4052d45 1651 case HTTP_POST_DATA:
fdilenarda 135:cbccf4052d45 1652 return "HTTP POST data command";
fdilenarda 135:cbccf4052d45 1653 default:
fdilenarda 135:cbccf4052d45 1654 return "HTTP command not recognized";
fdilenarda 135:cbccf4052d45 1655 }
fdilenarda 135:cbccf4052d45 1656 }
fdilenarda 135:cbccf4052d45 1657
fdilenarda 135:cbccf4052d45 1658 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 1659
mazgch 31:a0bed6c1e05d 1660 int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param)
mazgch 21:c4d64830bf02 1661 {
mazgch 31:a0bed6c1e05d 1662 if ((type == TYPE_PLUS) && param && param->num) {
mazgch 31:a0bed6c1e05d 1663 // +CMGL: <ix>,...
mazgch 31:a0bed6c1e05d 1664 int ix;
mazgch 31:a0bed6c1e05d 1665 if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1)
mazgch 31:a0bed6c1e05d 1666 {
mazgch 31:a0bed6c1e05d 1667 *param->ix++ = ix;
mazgch 31:a0bed6c1e05d 1668 param->num--;
mazgch 31:a0bed6c1e05d 1669 }
mazgch 29:53d346010624 1670 }
mazgch 29:53d346010624 1671 return WAIT;
mazgch 21:c4d64830bf02 1672 }
mazgch 21:c4d64830bf02 1673
mazgch 31:a0bed6c1e05d 1674 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) {
mazgch 95:8282dbbe1492 1675 int ret = -1;
mazgch 95:8282dbbe1492 1676 LOCK();
mazgch 31:a0bed6c1e05d 1677 sendFormated("AT+CMGL=\"%s\"\r\n", stat);
mazgch 31:a0bed6c1e05d 1678 CMGLparam param;
mazgch 31:a0bed6c1e05d 1679 param.ix = ix;
mazgch 31:a0bed6c1e05d 1680 param.num = num;
mazgch 95:8282dbbe1492 1681 if (RESP_OK == waitFinalResp(_cbCMGL, &param))
mazgch 95:8282dbbe1492 1682 ret = num - param.num;
mazgch 95:8282dbbe1492 1683 UNLOCK();
mazgch 95:8282dbbe1492 1684 return ret;
mazgch 21:c4d64830bf02 1685 }
mazgch 21:c4d64830bf02 1686
mazgch 21:c4d64830bf02 1687 bool MDMParser::smsSend(const char* num, const char* buf)
mazgch 21:c4d64830bf02 1688 {
mazgch 95:8282dbbe1492 1689 bool ok = false;
mazgch 95:8282dbbe1492 1690 LOCK();
mazgch 80:34985b4d821e 1691 sendFormated("AT+CMGS=\"%s\"\r\n",num);
mazgch 95:8282dbbe1492 1692 if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) {
mazgch 95:8282dbbe1492 1693 send(buf, strlen(buf));
mazgch 95:8282dbbe1492 1694 const char ctrlZ = 0x1A;
mazgch 95:8282dbbe1492 1695 send(&ctrlZ, sizeof(ctrlZ));
mazgch 95:8282dbbe1492 1696 ok = (RESP_OK == waitFinalResp());
mazgch 21:c4d64830bf02 1697 }
mazgch 95:8282dbbe1492 1698 UNLOCK();
mazgch 95:8282dbbe1492 1699 return ok;
mazgch 21:c4d64830bf02 1700 }
mazgch 21:c4d64830bf02 1701
mazgch 21:c4d64830bf02 1702 bool MDMParser::smsDelete(int ix)
mazgch 21:c4d64830bf02 1703 {
mazgch 95:8282dbbe1492 1704 bool ok = false;
mazgch 95:8282dbbe1492 1705 LOCK();
mazgch 21:c4d64830bf02 1706 sendFormated("AT+CMGD=%d\r\n",ix);
mazgch 95:8282dbbe1492 1707 ok = (RESP_OK == waitFinalResp());
mazgch 95:8282dbbe1492 1708 UNLOCK();
mazgch 95:8282dbbe1492 1709 return ok;
mazgch 21:c4d64830bf02 1710 }
mazgch 21:c4d64830bf02 1711
mazgch 21:c4d64830bf02 1712 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param)
mazgch 21:c4d64830bf02 1713 {
mazgch 21:c4d64830bf02 1714 if (param) {
mazgch 21:c4d64830bf02 1715 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 1716 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) {
mazgch 21:c4d64830bf02 1717 }
mazgch 37:cc3433329d66 1718 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) {
mazgch 21:c4d64830bf02 1719 memcpy(param->buf, buf, len-2);
mazgch 21:c4d64830bf02 1720 param->buf[len-2] = '\0';
mazgch 21:c4d64830bf02 1721 }
mazgch 21:c4d64830bf02 1722 }
mazgch 21:c4d64830bf02 1723 return WAIT;
mazgch 21:c4d64830bf02 1724 }
mazgch 21:c4d64830bf02 1725
mazgch 21:c4d64830bf02 1726 bool MDMParser::smsRead(int ix, char* num, char* buf, int len)
mazgch 21:c4d64830bf02 1727 {
mazgch 95:8282dbbe1492 1728 bool ok = false;
mazgch 95:8282dbbe1492 1729 LOCK();
mazgch 21:c4d64830bf02 1730 CMGRparam param;
mazgch 21:c4d64830bf02 1731 param.num = num;
mazgch 21:c4d64830bf02 1732 param.buf = buf;
mazgch 21:c4d64830bf02 1733 sendFormated("AT+CMGR=%d\r\n",ix);
mazgch 95:8282dbbe1492 1734 ok = (RESP_OK == waitFinalResp(_cbCMGR, &param));
mazgch 95:8282dbbe1492 1735 UNLOCK();
mazgch 95:8282dbbe1492 1736 return ok;
mazgch 21:c4d64830bf02 1737 }
mazgch 54:7ba8e4c218e2 1738
mazgch 54:7ba8e4c218e2 1739 // ----------------------------------------------------------------
mazgch 70:0a87d256cd24 1740
mazgch 70:0a87d256cd24 1741 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp)
mazgch 70:0a87d256cd24 1742 {
mazgch 70:0a87d256cd24 1743 if ((type == TYPE_PLUS) && resp) {
mazgch 70:0a87d256cd24 1744 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..);
mazgch 70:0a87d256cd24 1745 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) {
mazgch 70:0a87d256cd24 1746 /*nothing*/
mazgch 70:0a87d256cd24 1747 }
mazgch 70:0a87d256cd24 1748 }
mazgch 70:0a87d256cd24 1749 return WAIT;
mazgch 70:0a87d256cd24 1750 }
mazgch 70:0a87d256cd24 1751
mazgch 70:0a87d256cd24 1752 bool MDMParser::ussdCommand(const char* cmd, char* buf)
mazgch 70:0a87d256cd24 1753 {
mazgch 95:8282dbbe1492 1754 bool ok = false;
mazgch 95:8282dbbe1492 1755 LOCK();
mazgch 70:0a87d256cd24 1756 *buf = '\0';
mazgch 125:25a292afbac6 1757 if (_dev.dev != DEV_LISA_C2) {
mazgch 95:8282dbbe1492 1758 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
mazgch 95:8282dbbe1492 1759 ok = (RESP_OK == waitFinalResp(_cbCUSD, buf));
mazgch 70:0a87d256cd24 1760 }
mazgch 95:8282dbbe1492 1761 UNLOCK();
mazgch 95:8282dbbe1492 1762 return ok;
mazgch 70:0a87d256cd24 1763 }
mazgch 80:34985b4d821e 1764
mazgch 80:34985b4d821e 1765 // ----------------------------------------------------------------
mazgch 70:0a87d256cd24 1766
mazgch 115:d8d94b73c725 1767 int MDMParser::_cbUDELFILE(int type, const char* buf, int len, void*)
mazgch 115:d8d94b73c725 1768 {
mazgch 115:d8d94b73c725 1769 if ((type == TYPE_ERROR) && strstr(buf, "+CME ERROR: FILE NOT FOUND"))
mazgch 115:d8d94b73c725 1770 return RESP_OK; // file does not exist, so all ok...
mazgch 115:d8d94b73c725 1771 return WAIT;
mazgch 115:d8d94b73c725 1772 }
mazgch 115:d8d94b73c725 1773
mazgch 80:34985b4d821e 1774 bool MDMParser::delFile(const char* filename)
mazgch 80:34985b4d821e 1775 {
mazgch 95:8282dbbe1492 1776 bool ok = false;
mazgch 95:8282dbbe1492 1777 LOCK();
mazgch 80:34985b4d821e 1778 sendFormated("AT+UDELFILE=\"%s\"\r\n", filename);
mazgch 115:d8d94b73c725 1779 ok = (RESP_OK == waitFinalResp(_cbUDELFILE));
mazgch 95:8282dbbe1492 1780 UNLOCK();
mazgch 95:8282dbbe1492 1781 return ok;
mazgch 80:34985b4d821e 1782 }
mazgch 80:34985b4d821e 1783
mazgch 80:34985b4d821e 1784 int MDMParser::writeFile(const char* filename, const char* buf, int len)
mazgch 80:34985b4d821e 1785 {
mazgch 95:8282dbbe1492 1786 bool ok = false;
mazgch 95:8282dbbe1492 1787 LOCK();
mazgch 80:34985b4d821e 1788 sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len);
mazgch 95:8282dbbe1492 1789 if (RESP_PROMPT == waitFinalResp()) {
mazgch 95:8282dbbe1492 1790 send(buf, len);
mazgch 95:8282dbbe1492 1791 ok = (RESP_OK == waitFinalResp());
mazgch 95:8282dbbe1492 1792 }
mazgch 95:8282dbbe1492 1793 UNLOCK();
mazgch 95:8282dbbe1492 1794 return ok ? len : -1;
mazgch 80:34985b4d821e 1795 }
mazgch 80:34985b4d821e 1796
mazgch 80:34985b4d821e 1797 int MDMParser::readFile(const char* filename, char* buf, int len)
mazgch 80:34985b4d821e 1798 {
mazgch 80:34985b4d821e 1799 URDFILEparam param;
mazgch 80:34985b4d821e 1800 param.filename = filename;
mazgch 80:34985b4d821e 1801 param.buf = buf;
mazgch 80:34985b4d821e 1802 param.sz = len;
mazgch 80:34985b4d821e 1803 param.len = 0;
mazgch 95:8282dbbe1492 1804 LOCK();
mazgch 95:8282dbbe1492 1805 sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len);
mazgch 105:f6bb2a20de70 1806 if (RESP_OK != waitFinalResp(_cbURDFILE, &param))
mazgch 95:8282dbbe1492 1807 param.len = -1;
mazgch 95:8282dbbe1492 1808 UNLOCK();
mazgch 80:34985b4d821e 1809 return param.len;
mazgch 80:34985b4d821e 1810 }
mazgch 80:34985b4d821e 1811
mazgch 80:34985b4d821e 1812 int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param)
mazgch 80:34985b4d821e 1813 {
mazgch 80:34985b4d821e 1814 if ((type == TYPE_PLUS) && param && param->filename && param->buf) {
mazgch 80:34985b4d821e 1815 char filename[48];
mazgch 80:34985b4d821e 1816 int sz;
mazgch 80:34985b4d821e 1817 if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) &&
mazgch 80:34985b4d821e 1818 (0 == strcmp(param->filename, filename)) &&
mazgch 80:34985b4d821e 1819 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 80:34985b4d821e 1820 param->len = (sz < param->sz) ? sz : param->sz;
mazgch 80:34985b4d821e 1821 memcpy(param->buf, &buf[len-1-sz], param->len);
mazgch 80:34985b4d821e 1822 }
mazgch 80:34985b4d821e 1823 }
mazgch 80:34985b4d821e 1824 return WAIT;
mazgch 80:34985b4d821e 1825 }
fdilenarda 135:cbccf4052d45 1826
fdilenarda 135:cbccf4052d45 1827 //The following function is useful for reading files with a dimension greater than MAX_SIZE bytes
fdilenarda 135:cbccf4052d45 1828 int MDMParser::readFileNew(const char* filename, char* buf, int len)
fdilenarda 135:cbccf4052d45 1829 {
fdilenarda 135:cbccf4052d45 1830 int countBytes = -1; //counter for file reading (default value)
fdilenarda 135:cbccf4052d45 1831
fdilenarda 135:cbccf4052d45 1832 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1833 {
fdilenarda 135:cbccf4052d45 1834 //retrieve information about the file, in particular its size
fdilenarda 135:cbccf4052d45 1835 int filesize = infoFile(filename);
fdilenarda 135:cbccf4052d45 1836 TRACE("readFileNew: filename is %s; filesize is %d\r\n", filename, filesize);
fdilenarda 135:cbccf4052d45 1837
fdilenarda 135:cbccf4052d45 1838 if (len < filesize)
fdilenarda 135:cbccf4052d45 1839 TRACE("readFileNew: WARNING. Buffer dimension is %d bytes," \
fdilenarda 135:cbccf4052d45 1840 "while file size is %d bytes\r\n", len, filesize);
fdilenarda 135:cbccf4052d45 1841
fdilenarda 135:cbccf4052d45 1842 if (filesize > 0)
fdilenarda 135:cbccf4052d45 1843 {
fdilenarda 135:cbccf4052d45 1844 #ifdef MDM_DEBUG
fdilenarda 135:cbccf4052d45 1845 memset(buf, '\0', len);
fdilenarda 135:cbccf4052d45 1846 #endif
fdilenarda 135:cbccf4052d45 1847 int offset = 0; //start reading from 0
fdilenarda 135:cbccf4052d45 1848 int blockSize = MAX_SIZE; //still need space for headers and unsolicited commands
fdilenarda 135:cbccf4052d45 1849 int bytesToRead = filesize; //bytes to read
fdilenarda 135:cbccf4052d45 1850
fdilenarda 135:cbccf4052d45 1851 while (bytesToRead)
fdilenarda 135:cbccf4052d45 1852 {
fdilenarda 135:cbccf4052d45 1853 bool ok = false;
fdilenarda 135:cbccf4052d45 1854
fdilenarda 135:cbccf4052d45 1855 if (bytesToRead < blockSize)
fdilenarda 135:cbccf4052d45 1856 blockSize = bytesToRead;
fdilenarda 135:cbccf4052d45 1857
fdilenarda 135:cbccf4052d45 1858 LOCK();
fdilenarda 135:cbccf4052d45 1859 if (blockSize > 0) {
fdilenarda 135:cbccf4052d45 1860
fdilenarda 135:cbccf4052d45 1861 sendFormated("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize);
fdilenarda 135:cbccf4052d45 1862
fdilenarda 135:cbccf4052d45 1863 if (RESP_OK == waitFinalResp(_cbURDBLOCK, buf)) {
fdilenarda 135:cbccf4052d45 1864 bytesToRead -= blockSize;
fdilenarda 135:cbccf4052d45 1865 offset += blockSize;
fdilenarda 135:cbccf4052d45 1866 buf += blockSize;
fdilenarda 135:cbccf4052d45 1867 ok = true;
fdilenarda 135:cbccf4052d45 1868 } else {
fdilenarda 135:cbccf4052d45 1869 //error condition
fdilenarda 135:cbccf4052d45 1870 countBytes = -1;
fdilenarda 135:cbccf4052d45 1871 ok = false;
fdilenarda 135:cbccf4052d45 1872 }
fdilenarda 135:cbccf4052d45 1873 }
fdilenarda 135:cbccf4052d45 1874 UNLOCK();
fdilenarda 135:cbccf4052d45 1875
fdilenarda 135:cbccf4052d45 1876 if (!ok) {
fdilenarda 135:cbccf4052d45 1877 TRACE("readFileNew: ERROR\r\n");
fdilenarda 135:cbccf4052d45 1878 return countBytes; //in this case countBytes is -1
fdilenarda 135:cbccf4052d45 1879 }
fdilenarda 135:cbccf4052d45 1880 }
fdilenarda 135:cbccf4052d45 1881
fdilenarda 135:cbccf4052d45 1882 countBytes = offset; //total read bytes
fdilenarda 135:cbccf4052d45 1883 return countBytes;
fdilenarda 135:cbccf4052d45 1884 }
fdilenarda 135:cbccf4052d45 1885 } else {
fdilenarda 135:cbccf4052d45 1886 TRACE("httpCommand: command not supported by module");
fdilenarda 135:cbccf4052d45 1887 }
fdilenarda 135:cbccf4052d45 1888 return countBytes; //it could be 0 or -1 (possible error)
fdilenarda 135:cbccf4052d45 1889 }
fdilenarda 135:cbccf4052d45 1890
fdilenarda 135:cbccf4052d45 1891 int MDMParser::_cbURDBLOCK(int type, const char* buf, int len, char* out)
fdilenarda 135:cbccf4052d45 1892 {
fdilenarda 135:cbccf4052d45 1893 char fileNameRes[48];
fdilenarda 135:cbccf4052d45 1894 int sizeRes;
fdilenarda 135:cbccf4052d45 1895
fdilenarda 135:cbccf4052d45 1896 if ((type == TYPE_PLUS) && out) {
fdilenarda 135:cbccf4052d45 1897 if ((sscanf(buf, "\r\n+URDBLOCK: \"%[^\"]\",%d,", fileNameRes, &sizeRes) == 2) &&
fdilenarda 135:cbccf4052d45 1898 (buf[len-sizeRes-2] == '\"') && (buf[len-1] == '\"')) {
fdilenarda 135:cbccf4052d45 1899 memcpy(out, &buf[len-1-sizeRes], sizeRes);
fdilenarda 135:cbccf4052d45 1900 }
fdilenarda 135:cbccf4052d45 1901 }
fdilenarda 135:cbccf4052d45 1902
fdilenarda 135:cbccf4052d45 1903 return WAIT;
fdilenarda 135:cbccf4052d45 1904 }
fdilenarda 135:cbccf4052d45 1905
fdilenarda 135:cbccf4052d45 1906 int MDMParser::infoFile(const char* filename)
fdilenarda 135:cbccf4052d45 1907 {
fdilenarda 135:cbccf4052d45 1908 int infoFile = 0; //default value
fdilenarda 135:cbccf4052d45 1909
fdilenarda 135:cbccf4052d45 1910 LOCK();
fdilenarda 135:cbccf4052d45 1911 sendFormated("AT+ULSTFILE=2,\"%s\"\r\n", filename);
fdilenarda 135:cbccf4052d45 1912 if (RESP_OK != waitFinalResp(_cbULSTFILE, &infoFile))
fdilenarda 135:cbccf4052d45 1913 infoFile = -1; //error condition
fdilenarda 135:cbccf4052d45 1914 UNLOCK();
fdilenarda 135:cbccf4052d45 1915
fdilenarda 135:cbccf4052d45 1916 return infoFile;
fdilenarda 135:cbccf4052d45 1917 }
fdilenarda 135:cbccf4052d45 1918
fdilenarda 135:cbccf4052d45 1919 int MDMParser::_cbULSTFILE(int type, const char* buf, int len, int* infoFile)
fdilenarda 135:cbccf4052d45 1920 {
fdilenarda 135:cbccf4052d45 1921 if (infoFile) {
fdilenarda 135:cbccf4052d45 1922 if (type == TYPE_PLUS) {
fdilenarda 135:cbccf4052d45 1923 if (sscanf(buf, "\r\n+ULSTFILE: %d\r\n", infoFile) == 1) {
fdilenarda 135:cbccf4052d45 1924 }
fdilenarda 135:cbccf4052d45 1925 }
fdilenarda 135:cbccf4052d45 1926 }
fdilenarda 135:cbccf4052d45 1927 return WAIT;
fdilenarda 135:cbccf4052d45 1928 }
fdilenarda 135:cbccf4052d45 1929
msinig 133:57b208dd96fb 1930 // ----------------------------------------------------------------
msinig 136:8dc8f48275fc 1931 int MDMParser::cellLocSrvTcp(const char* token, const char* server_1, const char* server_2, int days/* = 14*/, \
msinig 133:57b208dd96fb 1932 int period/* = 4*/, int resolution/* = 1*/)
msinig 133:57b208dd96fb 1933 {
msinig 133:57b208dd96fb 1934 bool ok = false;
msinig 133:57b208dd96fb 1935 LOCK();
msinig 133:57b208dd96fb 1936 if (_dev.dev == DEV_LISA_U2_03S || _dev.dev == DEV_SARA_U2 ){
msinig 133:57b208dd96fb 1937 sendFormated("AT+UGSRV=\"%s\",\"%s\",\"%s\"\r\n", server_1, server_2, token, days, period, resolution);
msinig 133:57b208dd96fb 1938 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1939 } else
msinig 136:8dc8f48275fc 1940 ERROR("Command not supported\r\n");
msinig 133:57b208dd96fb 1941 UNLOCK();
msinig 133:57b208dd96fb 1942 return ok;
msinig 133:57b208dd96fb 1943 }
msinig 133:57b208dd96fb 1944
msinig 133:57b208dd96fb 1945 int MDMParser::cellLocSrvUdp(const char* server_1 /*= "cell-live1.services.u-blox.com"*/, int port /*= 46434*/, \
msinig 133:57b208dd96fb 1946 int latency/* = 1000*/, int mode/* = 0*/)
msinig 133:57b208dd96fb 1947 {
msinig 133:57b208dd96fb 1948 bool ok = false;
msinig 133:57b208dd96fb 1949 LOCK();
msinig 133:57b208dd96fb 1950 if (_dev.dev != DEV_TOBY_L2){
msinig 133:57b208dd96fb 1951 sendFormated("AT+UGAOP=\"%s\",%d,%d,%d\r\n", server_1, port, latency, mode);
msinig 133:57b208dd96fb 1952 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1953 } else
msinig 136:8dc8f48275fc 1954 ERROR("Command not supported\r\n");
msinig 133:57b208dd96fb 1955 UNLOCK();
msinig 133:57b208dd96fb 1956 return ok;
msinig 133:57b208dd96fb 1957 }
msinig 133:57b208dd96fb 1958
msinig 136:8dc8f48275fc 1959 int MDMParser::cellLocUnsol(int mode)
msinig 133:57b208dd96fb 1960 {
msinig 133:57b208dd96fb 1961 bool ok = false;
msinig 133:57b208dd96fb 1962 LOCK();
msinig 133:57b208dd96fb 1963 if (_dev.dev == DEV_LISA_U2_03S){
msinig 133:57b208dd96fb 1964 sendFormated("AT+ULOCIND=%d\r\n", mode);
msinig 133:57b208dd96fb 1965 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1966 } else
msinig 136:8dc8f48275fc 1967 ERROR("Command not supported\r\n");
msinig 133:57b208dd96fb 1968 UNLOCK();
msinig 133:57b208dd96fb 1969 return ok;
msinig 133:57b208dd96fb 1970 }
msinig 133:57b208dd96fb 1971
msinig 136:8dc8f48275fc 1972 int MDMParser::cellLocConfig(int scanMode)
msinig 133:57b208dd96fb 1973 {
msinig 133:57b208dd96fb 1974 bool ok = false;
msinig 133:57b208dd96fb 1975 LOCK();
msinig 133:57b208dd96fb 1976 if (_dev.dev != DEV_TOBY_L2){
msinig 133:57b208dd96fb 1977 sendFormated("AT+ULOCCELL=%d\r\n", scanMode);
msinig 133:57b208dd96fb 1978 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1979 }else
msinig 136:8dc8f48275fc 1980 ERROR("Command not supported\r\n");
msinig 133:57b208dd96fb 1981 UNLOCK();
msinig 133:57b208dd96fb 1982 return ok;
msinig 133:57b208dd96fb 1983 }
msinig 133:57b208dd96fb 1984
msinig 136:8dc8f48275fc 1985 int MDMParser::cellLocRequest(CellSensType sensor, int timeout, int accuracy, CellRespType type/* =1*/, int hypotesis/* =1*/)
msinig 133:57b208dd96fb 1986 {
msinig 133:57b208dd96fb 1987 bool ok = false;
msinig 133:57b208dd96fb 1988
msinig 136:8dc8f48275fc 1989 if (hypotesis > 1 && type != CELL_MULTIHYP){
msinig 136:8dc8f48275fc 1990 ERROR("Num hypotesis is not set accordelying to CellRespType\r\n");
msinig 136:8dc8f48275fc 1991 return false;
msinig 136:8dc8f48275fc 1992 }
msinig 136:8dc8f48275fc 1993 if (hypotesis > CELL_MAX_HYP){
msinig 136:8dc8f48275fc 1994 ERROR("Number of hypotesis is too big\r\n");
msinig 136:8dc8f48275fc 1995 return false;
msinig 136:8dc8f48275fc 1996 }
msinig 136:8dc8f48275fc 1997 LOCK();
msinig 136:8dc8f48275fc 1998 _locRcvPos=0;
msinig 136:8dc8f48275fc 1999 _locExpPos=0;
msinig 136:8dc8f48275fc 2000 for (int i=0; i < hypotesis; i++)
msinig 136:8dc8f48275fc 2001 _loc[i].validData = false;
msinig 133:57b208dd96fb 2002 if (_dev.dev == DEV_LISA_U2_03S){
msinig 136:8dc8f48275fc 2003 sendFormated("AT+ULOC=2,%d,%d,%d,%d,%d\r\n", sensor, type, timeout, accuracy, hypotesis);
msinig 133:57b208dd96fb 2004 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 2005 } else if (_dev.dev != DEV_TOBY_L2){
msinig 133:57b208dd96fb 2006 sendFormated("AT+ULOC=2,%d,1,%d,%d\r\n", sensor, timeout, accuracy);
msinig 133:57b208dd96fb 2007 ok = (RESP_OK == waitFinalResp());
msinig 136:8dc8f48275fc 2008 } else
msinig 136:8dc8f48275fc 2009 ERROR("Command not supported\r\n");
msinig 133:57b208dd96fb 2010 UNLOCK();
msinig 133:57b208dd96fb 2011 return ok;
msinig 133:57b208dd96fb 2012 }
msinig 136:8dc8f48275fc 2013 int MDMParser::cellLocGetRes()
msinig 136:8dc8f48275fc 2014 {
msinig 136:8dc8f48275fc 2015 return _locRcvPos;
msinig 136:8dc8f48275fc 2016 }
msinig 136:8dc8f48275fc 2017 int MDMParser::cellLocGetExpRes()
msinig 136:8dc8f48275fc 2018 {
msinig 136:8dc8f48275fc 2019 int res=0;
msinig 133:57b208dd96fb 2020 waitFinalResp(NULL,NULL,0);
msinig 136:8dc8f48275fc 2021 LOCK();
msinig 136:8dc8f48275fc 2022 if (_locRcvPos>0)
msinig 136:8dc8f48275fc 2023 res = _locExpPos;
msinig 136:8dc8f48275fc 2024 UNLOCK();
msinig 136:8dc8f48275fc 2025 return res;
msinig 136:8dc8f48275fc 2026 }
msinig 136:8dc8f48275fc 2027
msinig 136:8dc8f48275fc 2028 int MDMParser::cellLocGetData(CellLocData *data, int index/*=0*/){
msinig 136:8dc8f48275fc 2029
msinig 136:8dc8f48275fc 2030 if (!_loc[index].validData)
msinig 136:8dc8f48275fc 2031 return false;
msinig 136:8dc8f48275fc 2032 LOCK();
msinig 136:8dc8f48275fc 2033 memcpy(data, &_loc[index], sizeof(*_loc));
msinig 136:8dc8f48275fc 2034 UNLOCK();
msinig 136:8dc8f48275fc 2035 return true;
msinig 133:57b208dd96fb 2036 }
msinig 133:57b208dd96fb 2037
mazgch 70:0a87d256cd24 2038 // ----------------------------------------------------------------
mazgch 74:208e3e32d263 2039 bool MDMParser::setDebug(int level)
mazgch 74:208e3e32d263 2040 {
mazgch 74:208e3e32d263 2041 #ifdef MDM_DEBUG
mazgch 123:66cef6353b13 2042 _debugLevel = (level < -1) ? -1 :
mazgch 123:66cef6353b13 2043 (level > 3) ? 3 :
mazgch 123:66cef6353b13 2044 level;
mazgch 74:208e3e32d263 2045 #endif
mazgch 123:66cef6353b13 2046 return _debugLevel == level;
mazgch 74:208e3e32d263 2047 }
mazgch 74:208e3e32d263 2048
mazgch 73:2b32e0a21df2 2049 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status,
mazgch 73:2b32e0a21df2 2050 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 2051 {
mazgch 75:ce6e12067d0c 2052 dprint(param, "Modem::devStatus\r\n");
msinig 133:57b208dd96fb 2053 const char* txtDev[] = { "Unknown", "SARA-G35", "LISA-U2", "LISA-U2-03S", "LISA-C2",
mazgch 125:25a292afbac6 2054 "SARA-U2", "LEON-G2", "TOBY-L2", "MPCI-L2" };
mazgch 98:c786461edd40 2055 if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != DEV_UNKNOWN))
mazgch 73:2b32e0a21df2 2056 dprint(param, " Device: %s\r\n", txtDev[status->dev]);
mazgch 54:7ba8e4c218e2 2057 const char* txtLpm[] = { "Disabled", "Enabled", "Active" };
mazgch 54:7ba8e4c218e2 2058 if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm))
mazgch 73:2b32e0a21df2 2059 dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]);
mazgch 75:ce6e12067d0c 2060 const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" };
mazgch 98:c786461edd40 2061 if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != SIM_UNKNOWN))
mazgch 73:2b32e0a21df2 2062 dprint(param, " SIM: %s\r\n", txtSim[status->sim]);
mazgch 54:7ba8e4c218e2 2063 if (*status->ccid)
mazgch 73:2b32e0a21df2 2064 dprint(param, " CCID: %s\r\n", status->ccid);
mazgch 54:7ba8e4c218e2 2065 if (*status->imei)
mazgch 73:2b32e0a21df2 2066 dprint(param, " IMEI: %s\r\n", status->imei);
mazgch 54:7ba8e4c218e2 2067 if (*status->imsi)
mazgch 73:2b32e0a21df2 2068 dprint(param, " IMSI: %s\r\n", status->imsi);
mazgch 54:7ba8e4c218e2 2069 if (*status->meid)
mazgch 73:2b32e0a21df2 2070 dprint(param, " MEID: %s\r\n", status->meid); // LISA-C
mazgch 54:7ba8e4c218e2 2071 if (*status->manu)
mazgch 73:2b32e0a21df2 2072 dprint(param, " Manufacturer: %s\r\n", status->manu);
mazgch 54:7ba8e4c218e2 2073 if (*status->model)
mazgch 73:2b32e0a21df2 2074 dprint(param, " Model: %s\r\n", status->model);
mazgch 54:7ba8e4c218e2 2075 if (*status->ver)
mazgch 73:2b32e0a21df2 2076 dprint(param, " Version: %s\r\n", status->ver);
mazgch 54:7ba8e4c218e2 2077 }
mazgch 54:7ba8e4c218e2 2078
mazgch 73:2b32e0a21df2 2079 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status,
mazgch 73:2b32e0a21df2 2080 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 2081 {
mazgch 75:ce6e12067d0c 2082 dprint(param, "Modem::netStatus\r\n");
mazgch 54:7ba8e4c218e2 2083 const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" };
mazgch 98:c786461edd40 2084 if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != REG_UNKNOWN))
mazgch 79:291df065e345 2085 dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]);
mazgch 98:c786461edd40 2086 if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != REG_UNKNOWN))
mazgch 79:291df065e345 2087 dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]);
mazgch 123:66cef6353b13 2088 if (status->eps < sizeof(txtReg)/sizeof(*txtReg) && (status->eps != REG_UNKNOWN))
mazgch 123:66cef6353b13 2089 dprint(param, " EPS Registration: %s\r\n", txtReg[status->eps]);
mazgch 123:66cef6353b13 2090 const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA", "LTE" };
mazgch 98:c786461edd40 2091 if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != ACT_UNKNOWN))
mazgch 73:2b32e0a21df2 2092 dprint(param, " Access Technology: %s\r\n", txtAct[status->act]);
mazgch 54:7ba8e4c218e2 2093 if (status->rssi)
mazgch 73:2b32e0a21df2 2094 dprint(param, " Signal Strength: %d dBm\r\n", status->rssi);
mazgch 54:7ba8e4c218e2 2095 if (status->ber)
mazgch 73:2b32e0a21df2 2096 dprint(param, " Bit Error Rate: %d\r\n", status->ber);
mazgch 54:7ba8e4c218e2 2097 if (*status->opr)
mazgch 73:2b32e0a21df2 2098 dprint(param, " Operator: %s\r\n", status->opr);
mazgch 54:7ba8e4c218e2 2099 if (status->lac != 0xFFFF)
mazgch 73:2b32e0a21df2 2100 dprint(param, " Location Area Code: %04X\r\n", status->lac);
mazgch 54:7ba8e4c218e2 2101 if (status->ci != 0xFFFFFFFF)
mazgch 73:2b32e0a21df2 2102 dprint(param, " Cell ID: %08X\r\n", status->ci);
mazgch 54:7ba8e4c218e2 2103 if (*status->num)
mazgch 73:2b32e0a21df2 2104 dprint(param, " Phone Number: %s\r\n", status->num);
mazgch 54:7ba8e4c218e2 2105 }
mazgch 54:7ba8e4c218e2 2106
mazgch 73:2b32e0a21df2 2107 void MDMParser::dumpIp(MDMParser::IP ip,
mazgch 73:2b32e0a21df2 2108 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 2109 {
mazgch 57:869bd35f44cc 2110 if (ip != NOIP)
mazgch 75:ce6e12067d0c 2111 dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip));
mazgch 54:7ba8e4c218e2 2112 }
mazgch 70:0a87d256cd24 2113
mazgch 21:c4d64830bf02 2114 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 2115 int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end)
mazgch 18:e5697801df29 2116 {
mazgch 18:e5697801df29 2117 int o = 0;
mazgch 21:c4d64830bf02 2118 if (sta) {
mazgch 21:c4d64830bf02 2119 while (*sta) {
mazgch 21:c4d64830bf02 2120 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2121 char ch = pipe->next();
mazgch 21:c4d64830bf02 2122 if (*sta++ != ch) return NOT_FOUND;
mazgch 21:c4d64830bf02 2123 }
mazgch 21:c4d64830bf02 2124 }
mazgch 21:c4d64830bf02 2125 if (!end) return o; // no termination
mazgch 35:9275215a3a5b 2126 // at least any char
mazgch 35:9275215a3a5b 2127 if (++o > len) return WAIT;
mazgch 35:9275215a3a5b 2128 pipe->next();
mazgch 35:9275215a3a5b 2129 // check the end
mazgch 21:c4d64830bf02 2130 int x = 0;
mazgch 21:c4d64830bf02 2131 while (end[x]) {
mazgch 21:c4d64830bf02 2132 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2133 char ch = pipe->next();
mazgch 21:c4d64830bf02 2134 x = (end[x] == ch) ? x + 1 :
mazgch 21:c4d64830bf02 2135 (end[0] == ch) ? 1 :
mazgch 21:c4d64830bf02 2136 0;
mazgch 21:c4d64830bf02 2137 }
mazgch 21:c4d64830bf02 2138 return o;
mazgch 21:c4d64830bf02 2139 }
mazgch 21:c4d64830bf02 2140
mazgch 21:c4d64830bf02 2141 int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt)
mazgch 21:c4d64830bf02 2142 {
mazgch 21:c4d64830bf02 2143 int o = 0;
mazgch 21:c4d64830bf02 2144 int num = 0;
mazgch 21:c4d64830bf02 2145 if (fmt) {
mazgch 21:c4d64830bf02 2146 while (*fmt) {
mazgch 21:c4d64830bf02 2147 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2148 char ch = pipe->next();
mazgch 21:c4d64830bf02 2149 if (*fmt == '%') {
mazgch 21:c4d64830bf02 2150 fmt++;
mazgch 21:c4d64830bf02 2151 if (*fmt == 'd') { // numeric
mazgch 21:c4d64830bf02 2152 fmt ++;
mazgch 21:c4d64830bf02 2153 num = 0;
mazgch 21:c4d64830bf02 2154 while (ch >= '0' && ch <= '9') {
mazgch 21:c4d64830bf02 2155 num = num * 10 + (ch - '0');
mazgch 21:c4d64830bf02 2156 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2157 ch = pipe->next();
mazgch 21:c4d64830bf02 2158 }
mazgch 21:c4d64830bf02 2159 }
mazgch 21:c4d64830bf02 2160 else if (*fmt == 'c') { // char buffer (takes last numeric as length)
mazgch 21:c4d64830bf02 2161 fmt ++;
mazgch 21:c4d64830bf02 2162 while (num --) {
mazgch 21:c4d64830bf02 2163 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2164 ch = pipe->next();
mazgch 21:c4d64830bf02 2165 }
mazgch 21:c4d64830bf02 2166 }
mazgch 80:34985b4d821e 2167 else if (*fmt == 's') {
mazgch 80:34985b4d821e 2168 fmt ++;
mazgch 80:34985b4d821e 2169 if (ch != '\"') return NOT_FOUND;
mazgch 80:34985b4d821e 2170 do {
mazgch 80:34985b4d821e 2171 if (++o > len) return WAIT;
mazgch 80:34985b4d821e 2172 ch = pipe->next();
mazgch 80:34985b4d821e 2173 } while (ch != '\"');
mazgch 80:34985b4d821e 2174 if (++o > len) return WAIT;
mazgch 80:34985b4d821e 2175 ch = pipe->next();
mazgch 80:34985b4d821e 2176 }
mazgch 21:c4d64830bf02 2177 }
mazgch 21:c4d64830bf02 2178 if (*fmt++ != ch) return NOT_FOUND;
mazgch 18:e5697801df29 2179 }
mazgch 18:e5697801df29 2180 }
mazgch 21:c4d64830bf02 2181 return o;
mazgch 21:c4d64830bf02 2182 }
mazgch 21:c4d64830bf02 2183
mazgch 21:c4d64830bf02 2184 int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len)
mazgch 21:c4d64830bf02 2185 {
mazgch 21:c4d64830bf02 2186 int unkn = 0;
mazgch 21:c4d64830bf02 2187 int sz = pipe->size();
mazgch 21:c4d64830bf02 2188 int fr = pipe->free();
mazgch 21:c4d64830bf02 2189 if (len > sz)
mazgch 21:c4d64830bf02 2190 len = sz;
mazgch 21:c4d64830bf02 2191 while (len > 0)
mazgch 21:c4d64830bf02 2192 {
mazgch 21:c4d64830bf02 2193 static struct {
mazgch 21:c4d64830bf02 2194 const char* fmt; int type;
mazgch 21:c4d64830bf02 2195 } lutF[] = {
mazgch 21:c4d64830bf02 2196 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS },
mazgch 95:8282dbbe1492 2197 { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS },
mazgch 80:34985b4d821e 2198 { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS },
fdilenarda 135:cbccf4052d45 2199 { "\r\n+URDBLOCK: %s,%d,\"%c\"", TYPE_PLUS },
mazgch 21:c4d64830bf02 2200 };
mazgch 21:c4d64830bf02 2201 static struct {
mazgch 21:c4d64830bf02 2202 const char* sta; const char* end; int type;
mazgch 21:c4d64830bf02 2203 } lut[] = {
mazgch 21:c4d64830bf02 2204 { "\r\nOK\r\n", NULL, TYPE_OK },
mazgch 21:c4d64830bf02 2205 { "\r\nERROR\r\n", NULL, TYPE_ERROR },
msinig 134:2fbd5723e063 2206 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR_CME },
mazgch 21:c4d64830bf02 2207 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 2208 { "\r\nRING\r\n", NULL, TYPE_RING },
mazgch 21:c4d64830bf02 2209 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT },
mazgch 21:c4d64830bf02 2210 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER },
mazgch 21:c4d64830bf02 2211 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE },
mazgch 21:c4d64830bf02 2212 { "\r\nBUSY\r\n", NULL, TYPE_BUSY },
mazgch 21:c4d64830bf02 2213 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER },
mazgch 21:c4d64830bf02 2214 { "\r\n+", "\r\n", TYPE_PLUS },
mazgch 21:c4d64830bf02 2215 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets
mazgch 21:c4d64830bf02 2216 { "\r\n>", NULL, TYPE_PROMPT }, // SMS
mazgch 80:34985b4d821e 2217 { "\n>", NULL, TYPE_PROMPT }, // File
mazgch 21:c4d64830bf02 2218 };
mazgch 21:c4d64830bf02 2219 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) {
mazgch 21:c4d64830bf02 2220 pipe->set(unkn);
mazgch 21:c4d64830bf02 2221 int ln = _parseFormated(pipe, len, lutF[i].fmt);
mazgch 21:c4d64830bf02 2222 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 2223 return WAIT;
mazgch 21:c4d64830bf02 2224 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 2225 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 2226 if (ln > 0)
mazgch 21:c4d64830bf02 2227 return lutF[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 2228 }
mazgch 21:c4d64830bf02 2229 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) {
mazgch 21:c4d64830bf02 2230 pipe->set(unkn);
mazgch 21:c4d64830bf02 2231 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end);
mazgch 21:c4d64830bf02 2232 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 2233 return WAIT;
mazgch 21:c4d64830bf02 2234 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 2235 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 2236 if (ln > 0)
mazgch 21:c4d64830bf02 2237 return lut[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 2238 }
mazgch 21:c4d64830bf02 2239 // UNKNOWN
mazgch 21:c4d64830bf02 2240 unkn ++;
mazgch 21:c4d64830bf02 2241 len--;
mazgch 21:c4d64830bf02 2242 }
mazgch 18:e5697801df29 2243 return WAIT;
mazgch 18:e5697801df29 2244 }
mazgch 18:e5697801df29 2245
mazgch 18:e5697801df29 2246 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2247 // Serial Implementation
mazgch 18:e5697801df29 2248 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2249
mazgch 76:f7c3dd568dae 2250 /*! Helper Dev Null Device
mazgch 76:f7c3dd568dae 2251 Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout
mazgch 76:f7c3dd568dae 2252 is shared with the serial port of the modem. Having printfs inbetween the
mazgch 76:f7c3dd568dae 2253 AT commands you cause a failure of the modem.
mazgch 76:f7c3dd568dae 2254 */
mazgch 76:f7c3dd568dae 2255 class DevNull : public Stream {
mazgch 76:f7c3dd568dae 2256 public:
mazgch 76:f7c3dd568dae 2257 DevNull() : Stream(_name+1) { } //!< Constructor
mazgch 76:f7c3dd568dae 2258 void claim(const char* mode, FILE* file)
mazgch 76:f7c3dd568dae 2259 { freopen(_name, mode, file); } //!< claim a stream
mazgch 76:f7c3dd568dae 2260 protected:
mazgch 76:f7c3dd568dae 2261 virtual int _getc() { return EOF; } //!< Nothing
mazgch 76:f7c3dd568dae 2262 virtual int _putc(int c) { return c; } //!< Discard
mazgch 76:f7c3dd568dae 2263 static const char* _name; //!< File name
mazgch 76:f7c3dd568dae 2264 };
mazgch 76:f7c3dd568dae 2265 const char* DevNull::_name = "/null"; //!< the null device name
mazgch 76:f7c3dd568dae 2266 static DevNull null; //!< the null device
mazgch 76:f7c3dd568dae 2267
mazgch 19:2b5d097ca15d 2268 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/,
mazgch 19:2b5d097ca15d 2269 int baudrate /*= MDMBAUD*/,
mazgch 43:a89a7a505991 2270 #if DEVICE_SERIAL_FC
mazgch 19:2b5d097ca15d 2271 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/,
mazgch 43:a89a7a505991 2272 #endif
mazgch 18:e5697801df29 2273 int rxSize /*= 256*/, int txSize /*= 128*/) :
mazgch 139:fd9fe498f142 2274 SerialPipe(tx, rx, baudrate, rxSize, txSize)
mazgch 18:e5697801df29 2275 {
mazgch 76:f7c3dd568dae 2276 if (rx == USBRX)
mazgch 76:f7c3dd568dae 2277 null.claim("r", stdin);
mazgch 76:f7c3dd568dae 2278 if (tx == USBTX) {
mazgch 76:f7c3dd568dae 2279 null.claim("w", stdout);
mazgch 76:f7c3dd568dae 2280 null.claim("w", stderr);
mazgch 74:208e3e32d263 2281 #ifdef MDM_DEBUG
mazgch 76:f7c3dd568dae 2282 _debugLevel = -1;
mazgch 76:f7c3dd568dae 2283 #endif
mazgch 76:f7c3dd568dae 2284 }
mazgch 74:208e3e32d263 2285 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 2286 _onboard = (tx == MDMTXD) && (rx == MDMRXD);
mazgch 74:208e3e32d263 2287 if (_onboard)
mazgch 74:208e3e32d263 2288 c027_mdm_powerOn(false);
mazgch 74:208e3e32d263 2289 #endif
mazgch 18:e5697801df29 2290 baud(baudrate);
mazgch 35:9275215a3a5b 2291 #if DEVICE_SERIAL_FC
mazgch 35:9275215a3a5b 2292 if ((rts != NC) || (cts != NC))
mazgch 35:9275215a3a5b 2293 {
mazgch 35:9275215a3a5b 2294 Flow flow = (cts == NC) ? RTS :
mazgch 35:9275215a3a5b 2295 (rts == NC) ? CTS : RTSCTS ;
mazgch 35:9275215a3a5b 2296 set_flow_control(flow, rts, cts);
mazgch 35:9275215a3a5b 2297 if (cts != NC) _dev.lpm = LPM_ENABLED;
mazgch 35:9275215a3a5b 2298 }
mazgch 35:9275215a3a5b 2299 #endif
mazgch 18:e5697801df29 2300 }
mazgch 18:e5697801df29 2301
mazgch 76:f7c3dd568dae 2302 MDMSerial::~MDMSerial(void)
mazgch 76:f7c3dd568dae 2303 {
mazgch 76:f7c3dd568dae 2304 powerOff();
mazgch 76:f7c3dd568dae 2305 #ifdef TARGET_UBLOX_C027
mazgch 76:f7c3dd568dae 2306 if (_onboard)
mazgch 76:f7c3dd568dae 2307 c027_mdm_powerOff();
mazgch 76:f7c3dd568dae 2308 #endif
mazgch 76:f7c3dd568dae 2309 }
mazgch 76:f7c3dd568dae 2310
mazgch 18:e5697801df29 2311 int MDMSerial::_send(const void* buf, int len)
mazgch 18:e5697801df29 2312 {
mazgch 35:9275215a3a5b 2313 return put((const char*)buf, len, true/*=blocking*/);
mazgch 18:e5697801df29 2314 }
mazgch 18:e5697801df29 2315
mazgch 18:e5697801df29 2316 int MDMSerial::getLine(char* buffer, int length)
mazgch 18:e5697801df29 2317 {
mazgch 18:e5697801df29 2318 return _getLine(&_pipeRx, buffer, length);
mazgch 18:e5697801df29 2319 }
mazgch 18:e5697801df29 2320
mazgch 18:e5697801df29 2321 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2322 // USB Implementation
mazgch 18:e5697801df29 2323 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2324
mazgch 18:e5697801df29 2325 #ifdef HAVE_MDMUSB
mazgch 76:f7c3dd568dae 2326 MDMUsb::MDMUsb(void)
mazgch 74:208e3e32d263 2327 {
mazgch 74:208e3e32d263 2328 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 2329 _debugLevel = 1;
mazgch 74:208e3e32d263 2330 #endif
mazgch 74:208e3e32d263 2331 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 2332 _onboard = true;
mazgch 74:208e3e32d263 2333 c027_mdm_powerOn(true);
mazgch 74:208e3e32d263 2334 #endif
mazgch 74:208e3e32d263 2335 }
mazgch 76:f7c3dd568dae 2336
mazgch 76:f7c3dd568dae 2337 MDMUsb::~MDMUsb(void)
mazgch 76:f7c3dd568dae 2338 {
mazgch 76:f7c3dd568dae 2339 powerOff();
mazgch 76:f7c3dd568dae 2340 #ifdef TARGET_UBLOX_C027
mazgch 76:f7c3dd568dae 2341 if (_onboard)
mazgch 76:f7c3dd568dae 2342 c027_mdm_powerOff();
mazgch 76:f7c3dd568dae 2343 #endif
mazgch 76:f7c3dd568dae 2344 }
mazgch 76:f7c3dd568dae 2345
mazgch 76:f7c3dd568dae 2346 int MDMUsb::_send(const void* buf, int len) { return 0; }
mazgch 76:f7c3dd568dae 2347
mazgch 18:e5697801df29 2348 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; }
mazgch 76:f7c3dd568dae 2349
msinig 133:57b208dd96fb 2350 #endif