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

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

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

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

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

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

Committer:
mazgch
Date:
Tue Apr 08 15:48:16 2014 +0000
Revision:
29:53d346010624
Parent:
28:4d9509e3b1cf
Child:
30:1a647403171b
add sms count api

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mazgch 18:e5697801df29 1 #include "mbed.h"
mazgch 18:e5697801df29 2 #include <ctype.h>
mazgch 18:e5697801df29 3 #include "MDM.h"
mazgch 18:e5697801df29 4
mazgch 23:05a1aeeb5fd9 5 #define TRACE (0)?:printf
mazgch 29:53d346010624 6 #define DEBUG // enable this for AT command debugging
mazgch 21:c4d64830bf02 7 #define PROFILE "0" // this is the psd profile used
mazgch 21:c4d64830bf02 8 #define MAX_SIZE 256 // max expected messages
mazgch 21:c4d64830bf02 9 // some helper
mazgch 21:c4d64830bf02 10 #define ISSOCKET(s) (((s) >= 0) && ((s) < (sizeof(_sockets)/sizeof(*_sockets))))
mazgch 21:c4d64830bf02 11 #define IPSTR "%d.%d.%d.%d"
mazgch 21:c4d64830bf02 12 #define IPNUM(addr) (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff
mazgch 21:c4d64830bf02 13 #define IPADR(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d)
mazgch 21:c4d64830bf02 14
mazgch 21:c4d64830bf02 15 #ifdef DEBUG
mazgch 21:c4d64830bf02 16 void dump(const char* buf, int len)
mazgch 21:c4d64830bf02 17 {
mazgch 21:c4d64830bf02 18 while (len --) {
mazgch 21:c4d64830bf02 19 char ch = *buf++;
mazgch 21:c4d64830bf02 20 if (ch == '\r') printf("\\r");
mazgch 21:c4d64830bf02 21 else if (ch == '\n') printf("\\n");
mazgch 21:c4d64830bf02 22 else if (ch >= 0x20) printf("%c", ch);
mazgch 21:c4d64830bf02 23 else printf("\\x%02x", ch);
mazgch 21:c4d64830bf02 24 }
mazgch 21:c4d64830bf02 25 }
mazgch 21:c4d64830bf02 26 #endif
mazgch 21:c4d64830bf02 27
mazgch 21:c4d64830bf02 28 MDMParser::MDMParser(void)
mazgch 21:c4d64830bf02 29 {
mazgch 26:07be5faf8925 30 // device info
mazgch 21:c4d64830bf02 31 _model = MODEL_UNKNOWN;
mazgch 21:c4d64830bf02 32 _sim = SIM_UNKNOWN;
mazgch 26:07be5faf8925 33 *_ccid = '\0';
mazgch 26:07be5faf8925 34 *_imsi = '\0';
mazgch 26:07be5faf8925 35 *_imei = '\0';
mazgch 26:07be5faf8925 36 // network info
mazgch 21:c4d64830bf02 37 _net = NET_UNKNOWN;
mazgch 25:4045d02e44f1 38 _act = ACT_UNKNOWN;
mazgch 21:c4d64830bf02 39 _rssi = 0;
mazgch 23:05a1aeeb5fd9 40 *_num = '\0';
mazgch 25:4045d02e44f1 41 *_opr = '\0';
mazgch 26:07be5faf8925 42 // data network info
mazgch 26:07be5faf8925 43 _ip = 0;
mazgch 21:c4d64830bf02 44 for (int socket = 0; socket < sizeof(_sockets)/sizeof(*_sockets); socket++) {
mazgch 21:c4d64830bf02 45 _sockets[socket].state = SOCK_FREE;
mazgch 21:c4d64830bf02 46 _sockets[socket].pending = 0;
mazgch 21:c4d64830bf02 47 }
mazgch 21:c4d64830bf02 48 }
mazgch 18:e5697801df29 49
mazgch 18:e5697801df29 50 int MDMParser::send(const char* buf, int len)
mazgch 18:e5697801df29 51 {
mazgch 21:c4d64830bf02 52 #ifdef DEBUG
mazgch 21:c4d64830bf02 53 printf(" send \"");
mazgch 21:c4d64830bf02 54 dump(buf,len);
mazgch 21:c4d64830bf02 55 printf("\"\n");
mazgch 21:c4d64830bf02 56 #endif
mazgch 18:e5697801df29 57 return _send(buf, len);
mazgch 18:e5697801df29 58 }
mazgch 18:e5697801df29 59
mazgch 21:c4d64830bf02 60 int MDMParser::sendFormated(const char* format, ...) {
mazgch 21:c4d64830bf02 61 char buf[MAX_SIZE];
mazgch 21:c4d64830bf02 62 va_list args;
mazgch 21:c4d64830bf02 63 va_start(args, format);
mazgch 21:c4d64830bf02 64 int len = vsnprintf(buf,sizeof(buf), format, args);
mazgch 21:c4d64830bf02 65 va_end(args);
mazgch 21:c4d64830bf02 66 return send(buf, len);
mazgch 21:c4d64830bf02 67 }
mazgch 21:c4d64830bf02 68
mazgch 26:07be5faf8925 69 int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/,
mazgch 26:07be5faf8925 70 void* param /* = NULL*/,
mazgch 26:07be5faf8925 71 int timeout_ms /*= 5000*/)
mazgch 26:07be5faf8925 72 {
mazgch 21:c4d64830bf02 73 char buf[MAX_SIZE];
mazgch 21:c4d64830bf02 74 Timer timer;
mazgch 21:c4d64830bf02 75 timer.start();
mazgch 21:c4d64830bf02 76 do {
mazgch 21:c4d64830bf02 77 int ret = getLine(buf, sizeof(buf));
mazgch 21:c4d64830bf02 78 #ifdef DEBUG
mazgch 21:c4d64830bf02 79 if ((ret != WAIT) && (ret != NOT_FOUND))
mazgch 21:c4d64830bf02 80 {
mazgch 21:c4d64830bf02 81 printf(" line %06X \"", ret);
mazgch 21:c4d64830bf02 82 dump(buf, LENGTH(ret));
mazgch 21:c4d64830bf02 83 printf("\"\n");
mazgch 21:c4d64830bf02 84 }
mazgch 21:c4d64830bf02 85 #endif
mazgch 21:c4d64830bf02 86 if ((ret != WAIT) && (ret != NOT_FOUND))
mazgch 18:e5697801df29 87 {
mazgch 21:c4d64830bf02 88 int type = TYPE(ret);
mazgch 21:c4d64830bf02 89 if (type == TYPE_OK) return OK;
mazgch 21:c4d64830bf02 90 if (type == TYPE_ERROR) return ERROR;
mazgch 21:c4d64830bf02 91 if (type == TYPE_PROMPT) return PROMPT;
mazgch 21:c4d64830bf02 92 // handle unsolicited commands here
mazgch 21:c4d64830bf02 93 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 94 const char* cmd = buf+3;
mazgch 21:c4d64830bf02 95 int a, b, c, d;
mazgch 23:05a1aeeb5fd9 96 char s[32];
mazgch 21:c4d64830bf02 97
mazgch 21:c4d64830bf02 98 // +CSQ: <rssi>,<qual>
mazgch 21:c4d64830bf02 99 if (sscanf(cmd, "CSQ: %d,%d",&a,&b) == 2) {
mazgch 23:05a1aeeb5fd9 100 if (a != 99) _rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps
mazgch 21:c4d64830bf02 101 //if (b != 99) int qual = b; //
mazgch 21:c4d64830bf02 102 // Socket Specific Command ---------------------------------
mazgch 21:c4d64830bf02 103 // +UUSORD: <socket>,<length>
mazgch 21:c4d64830bf02 104 } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2) &&
mazgch 21:c4d64830bf02 105 ISSOCKET(a) && (_sockets[a].state == SOCK_CONNECTED)) {
mazgch 21:c4d64830bf02 106 TRACE("Socket %d: %d bytes pending\n", a, b);
mazgch 21:c4d64830bf02 107 _sockets[a].pending = b;
mazgch 21:c4d64830bf02 108 // +UUSORF: <socket>,<length>
mazgch 21:c4d64830bf02 109 } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2) &&
mazgch 21:c4d64830bf02 110 ISSOCKET(a) && (_sockets[a].state == SOCK_CONNECTED)) {
mazgch 21:c4d64830bf02 111 TRACE("Socket %d: %d bytes pending\n", a, b);
mazgch 21:c4d64830bf02 112 _sockets[a].pending = b;
mazgch 21:c4d64830bf02 113 // +UUSOCL: <socket>
mazgch 21:c4d64830bf02 114 } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1) &&
mazgch 21:c4d64830bf02 115 ISSOCKET(a) && (_sockets[a].state == SOCK_CONNECTED)) {
mazgch 21:c4d64830bf02 116 TRACE("Socket %d: closed by remote host\n", a);
mazgch 21:c4d64830bf02 117 _sockets[a].state = SOCK_CREATED/*=CLOSED*/;
mazgch 21:c4d64830bf02 118 }
mazgch 21:c4d64830bf02 119 if (_model == MODEL_LISA_C200) {
mazgch 21:c4d64830bf02 120 // CDMA Specific -------------------------------------------
mazgch 21:c4d64830bf02 121 // +CREG: <n><SID>,<NID>,<stat>
mazgch 21:c4d64830bf02 122 if (sscanf(cmd, "CREG: %*d,%*d,%*d,%d",&a) == 1) {
mazgch 21:c4d64830bf02 123 if (a == 0) _net = NET_NONE; // not registered, home network
mazgch 21:c4d64830bf02 124 else if (a == 1) _net = NET_HOME; // registered, home network
mazgch 21:c4d64830bf02 125 else if (a == 2) _net = NET_NONE; // not registered, but MT is currently searching a new operator to register to
mazgch 21:c4d64830bf02 126 else if (a == 3) _net = NET_DENIED; // registration denied
mazgch 21:c4d64830bf02 127 else if (a == 5) _net = NET_ROAMING; // registered, roaming
mazgch 25:4045d02e44f1 128 _act = ACT_CDMA;
mazgch 21:c4d64830bf02 129 // +CSS: <mode>[,<format>,<oper>[,<AcT>]]
mazgch 21:c4d64830bf02 130 } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) {
mazgch 21:c4d64830bf02 131 //_net = (strcmp("Z", s) == 0) ? NET_UNKNOWN : NET_HOME;
mazgch 21:c4d64830bf02 132 // +CMIP: xxx.xxx.xxx.xxx
mazgch 21:c4d64830bf02 133 } else if (sscanf(cmd, "CMIP: " IPSTR, &a,&b,&c,&d) == 4) {
mazgch 21:c4d64830bf02 134 _ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 135 }
mazgch 21:c4d64830bf02 136 } else {
mazgch 21:c4d64830bf02 137 // GSM/UMTS Specific -------------------------------------------
mazgch 21:c4d64830bf02 138 // +CREG: <n>, <stat>[,<lac>,<ci>[,AcT]]
mazgch 21:c4d64830bf02 139 b = 255;
mazgch 21:c4d64830bf02 140 if (sscanf(cmd, "CREG: %*d,%d,%*d,%d",&a,&b) >= 1) {
mazgch 21:c4d64830bf02 141 // network status
mazgch 21:c4d64830bf02 142 if (a == 0) _net = NET_NONE; // 0: not registered, home network
mazgch 21:c4d64830bf02 143 else if (a == 1) _net = NET_HOME; // 1: registered, home network
mazgch 21:c4d64830bf02 144 else if (a == 2) _net = NET_NONE; // 2: not registered, but MT is currently searching a new operator to register to
mazgch 21:c4d64830bf02 145 else if (a == 3) _net = NET_DENIED; // 3: registration denied
mazgch 21:c4d64830bf02 146 else if (a == 4) _net = NET_UNKNOWN; // 4: unknown
mazgch 21:c4d64830bf02 147 else if (a == 5) _net = NET_ROAMING; // 5: registered, roaming
mazgch 21:c4d64830bf02 148 // access technology
mazgch 25:4045d02e44f1 149 if (b == 0) _act = ACT_GSM; // 0: GSM
mazgch 25:4045d02e44f1 150 else if (b == 1) _act = ACT_GSM; // 1: GSM COMPACT
mazgch 25:4045d02e44f1 151 else if (b == 2) _act = ACT_UTRAN; // 2: UTRAN
mazgch 25:4045d02e44f1 152 else if (b == 3) _act = ACT_EDGE; // 3: GSM with EDGE availability
mazgch 25:4045d02e44f1 153 else if (b == 4) _act = ACT_UTRAN; // 4: UTRAN with HSDPA availability
mazgch 25:4045d02e44f1 154 else if (b == 5) _act = ACT_UTRAN; // 5: UTRAN with HSUPA availability
mazgch 25:4045d02e44f1 155 else if (b == 6) _act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability
mazgch 21:c4d64830bf02 156 // +COPS: <mode>[,<format>,<oper>[,<AcT>]]
mazgch 25:4045d02e44f1 157 } else if (sscanf(cmd, "COPS: %*d,%*d,\"%[^\"]\",%d",s,&b) >= 1) {
mazgch 25:4045d02e44f1 158 strcpy(_opr,s);
mazgch 25:4045d02e44f1 159 if (a == 0) _act = ACT_GSM; // 0: GSM,
mazgch 25:4045d02e44f1 160 else if (a == 2) _act = ACT_UTRAN; // 2: UTRAN
mazgch 21:c4d64830bf02 161 // +CPIN: <code>
mazgch 23:05a1aeeb5fd9 162 } else if (sscanf(cmd, "CPIN: %7s",s) == 1) {
mazgch 21:c4d64830bf02 163 _sim = (strcmp("READY", s) == 0) ? SIM_READY : SIM_UNKNOWN;
mazgch 23:05a1aeeb5fd9 164 // +CNUM: <code>
mazgch 23:05a1aeeb5fd9 165 } else if (sscanf(cmd, "CNUM: \"My Number\",\"%31[^\"]\",%d", s, &a) == 2) {
mazgch 23:05a1aeeb5fd9 166 if ((a == 129) || (a == 145)) strncpy(_num, s, sizeof(_num));
mazgch 21:c4d64830bf02 167 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
mazgch 21:c4d64830bf02 168 } else if (sscanf(cmd, "UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4) {
mazgch 21:c4d64830bf02 169 _ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 170 // +UUPSDD: <profile_id>
mazgch 21:c4d64830bf02 171 } else if (sscanf(cmd, "UUPSDD: %d",&a) == 1) {
mazgch 21:c4d64830bf02 172 if (*PROFILE == a) _ip = 0;
mazgch 21:c4d64830bf02 173 }
mazgch 21:c4d64830bf02 174 }
mazgch 21:c4d64830bf02 175 }
mazgch 21:c4d64830bf02 176 if (cb) {
mazgch 21:c4d64830bf02 177 int len = LENGTH(ret);
mazgch 21:c4d64830bf02 178 int ret = cb(type, buf, len, param);
mazgch 21:c4d64830bf02 179 if (WAIT != ret)
mazgch 21:c4d64830bf02 180 return ret;
mazgch 21:c4d64830bf02 181 }
mazgch 21:c4d64830bf02 182 }
mazgch 21:c4d64830bf02 183 // relax a bit
mazgch 21:c4d64830bf02 184 wait_ms(10);
mazgch 21:c4d64830bf02 185 }
mazgch 21:c4d64830bf02 186 while (timer.read_ms() < timeout_ms);
mazgch 21:c4d64830bf02 187 timer.stop();
mazgch 21:c4d64830bf02 188 timer.reset();
mazgch 21:c4d64830bf02 189 return WAIT;
mazgch 21:c4d64830bf02 190 }
mazgch 21:c4d64830bf02 191
mazgch 21:c4d64830bf02 192 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 193
mazgch 21:c4d64830bf02 194 int MDMParser::_cbATI(int type, const char* buf, int len, Model* model)
mazgch 21:c4d64830bf02 195 {
mazgch 21:c4d64830bf02 196 if ((type == TYPE_UNKNOWN) && model) {
mazgch 21:c4d64830bf02 197 if (strstr(buf, "SARA-G350")) {
mazgch 21:c4d64830bf02 198 *model = MODEL_SARA_G350;
mazgch 28:4d9509e3b1cf 199 /*TRACE("Identified Model: SARA-G350 2G\n")*/;
mazgch 21:c4d64830bf02 200 } else if (strstr(buf, "LISA-U200")) {
mazgch 21:c4d64830bf02 201 *model = MODEL_LISA_U200;
mazgch 28:4d9509e3b1cf 202 /*TRACE("Identified Model: LISA-U200 2G/3G\n")*/;
mazgch 21:c4d64830bf02 203 } else if (strstr(buf, "LISA-C200")) {
mazgch 21:c4d64830bf02 204 *model= MODEL_LISA_C200;
mazgch 28:4d9509e3b1cf 205 /*TRACE("Identified Model: LISA-C200 CDMA\n")*/;
mazgch 21:c4d64830bf02 206 }
mazgch 21:c4d64830bf02 207 }
mazgch 21:c4d64830bf02 208 return WAIT;
mazgch 21:c4d64830bf02 209 }
mazgch 21:c4d64830bf02 210
mazgch 28:4d9509e3b1cf 211 bool MDMParser::init(const char* pin, DevStatus* status)
mazgch 21:c4d64830bf02 212 {
mazgch 21:c4d64830bf02 213 for(int i = 0; i < 5; i++) {
mazgch 21:c4d64830bf02 214 // check interface and disable local echo
mazgch 21:c4d64830bf02 215 sendFormated("AT\r\n");
mazgch 21:c4d64830bf02 216 if(OK == waitFinalResp())
mazgch 21:c4d64830bf02 217 break;
mazgch 21:c4d64830bf02 218 }
mazgch 21:c4d64830bf02 219 // echo off
mazgch 21:c4d64830bf02 220 sendFormated("AT E0\r\n");
mazgch 21:c4d64830bf02 221 if(OK != waitFinalResp())
mazgch 21:c4d64830bf02 222 return false;
mazgch 21:c4d64830bf02 223 // enable verbose error messages
mazgch 21:c4d64830bf02 224 sendFormated("AT+CMEE=2\r\n");
mazgch 21:c4d64830bf02 225 if(OK != waitFinalResp())
mazgch 21:c4d64830bf02 226 return false;
mazgch 21:c4d64830bf02 227 // set baud rate
mazgch 21:c4d64830bf02 228 sendFormated("AT+IPR=115200\r\n");
mazgch 21:c4d64830bf02 229 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 230 return false;
mazgch 21:c4d64830bf02 231 wait_ms(40);
mazgch 21:c4d64830bf02 232 // identify the module
mazgch 21:c4d64830bf02 233 sendFormated("ATI\r\n");
mazgch 26:07be5faf8925 234 if (OK != waitFinalResp(_cbATI, &_model))
mazgch 21:c4d64830bf02 235 return false;
mazgch 21:c4d64830bf02 236 if (_model == MODEL_UNKNOWN)
mazgch 21:c4d64830bf02 237 return false;
mazgch 21:c4d64830bf02 238 // model specific init
mazgch 21:c4d64830bf02 239 if (_model == MODEL_LISA_C200) {
mazgch 26:07be5faf8925 240 // disable flow control
mazgch 26:07be5faf8925 241 sendFormated("AT+IFC=0,0\r\n");
mazgch 26:07be5faf8925 242 if (OK != waitFinalResp())
mazgch 26:07be5faf8925 243 return false;
mazgch 21:c4d64830bf02 244 // Return the pseudo ESN or MEID
mazgch 21:c4d64830bf02 245 sendFormated("AT+GSN\r\n");
mazgch 26:07be5faf8925 246 if (OK != waitFinalResp(_cbGSN, _imei))
mazgch 26:07be5faf8925 247 return false;
mazgch 26:07be5faf8925 248 } else {
mazgch 26:07be5faf8925 249 // disable flow control
mazgch 26:07be5faf8925 250 sendFormated("AT&K0\r\n");
mazgch 21:c4d64830bf02 251 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 252 return false;
mazgch 21:c4d64830bf02 253 // enable power saving
mazgch 21:c4d64830bf02 254 sendFormated("AT+UPSV=1\r\n");
mazgch 21:c4d64830bf02 255 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 256 return false;
mazgch 21:c4d64830bf02 257 // enable the network identification feature
mazgch 21:c4d64830bf02 258 if (_model == MODEL_LISA_U200) {
mazgch 21:c4d64830bf02 259 sendFormated("AT+UGPIOC=20,2\r\n");
mazgch 21:c4d64830bf02 260 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 261 return false;
mazgch 21:c4d64830bf02 262 } else {
mazgch 21:c4d64830bf02 263 sendFormated("AT+UGPIOC=16,2\r\n");
mazgch 21:c4d64830bf02 264 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 265 return false;
mazgch 21:c4d64830bf02 266 }
mazgch 21:c4d64830bf02 267 // Enter PIN if needed
mazgch 21:c4d64830bf02 268 if (pin) {
mazgch 21:c4d64830bf02 269 sendFormated("AT+CPIN=%s\r\n", pin);
mazgch 21:c4d64830bf02 270 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 271 return false;
mazgch 18:e5697801df29 272 }
mazgch 21:c4d64830bf02 273 // check the sim card
mazgch 21:c4d64830bf02 274 for (int i = 0; i < 5; i++) {
mazgch 21:c4d64830bf02 275 sendFormated("AT+CPIN?\r\n");
mazgch 21:c4d64830bf02 276 int ret = waitFinalResp();
mazgch 21:c4d64830bf02 277 if ((OK != ret) && (ERROR != ret))
mazgch 21:c4d64830bf02 278 return false;
mazgch 21:c4d64830bf02 279 if (_sim != SIM_UNKNOWN)
mazgch 21:c4d64830bf02 280 break;
mazgch 21:c4d64830bf02 281 wait_ms(1000);
mazgch 21:c4d64830bf02 282 }
mazgch 21:c4d64830bf02 283 if (_sim != SIM_READY)
mazgch 21:c4d64830bf02 284 return false;
mazgch 21:c4d64830bf02 285 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
mazgch 21:c4d64830bf02 286 // ICCID is a serial number identifying the SIM.
mazgch 21:c4d64830bf02 287 sendFormated("AT+CCID\r\n");
mazgch 26:07be5faf8925 288 if (OK != waitFinalResp(_cbCCID, _ccid))
mazgch 21:c4d64830bf02 289 return false;
mazgch 21:c4d64830bf02 290 // Returns the product serial number, IMEI (International Mobile Equipment Identity)
mazgch 21:c4d64830bf02 291 sendFormated("AT+CGSN\r\n");
mazgch 26:07be5faf8925 292 if (OK != waitFinalResp(_cbCGSN, _imei))
mazgch 21:c4d64830bf02 293 return false;
mazgch 21:c4d64830bf02 294 // Setup SMS in text mode
mazgch 21:c4d64830bf02 295 sendFormated("AT+CMGF=1\r\n");
mazgch 21:c4d64830bf02 296 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 297 return false;
mazgch 21:c4d64830bf02 298 // Configure New message indication
mazgch 21:c4d64830bf02 299 //sendFormated("AT+CNMI=2,1,0,0,0\r\n");
mazgch 21:c4d64830bf02 300 //if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 301 // return false;
mazgch 21:c4d64830bf02 302
mazgch 21:c4d64830bf02 303 }
mazgch 21:c4d64830bf02 304 // Request IMSI (International Mobile Subscriber Identification)
mazgch 21:c4d64830bf02 305 sendFormated("AT+CIMI\r\n");
mazgch 26:07be5faf8925 306 if (OK != waitFinalResp(_cbCIMI, _imsi))
mazgch 21:c4d64830bf02 307 return false;
mazgch 28:4d9509e3b1cf 308 if (status)
mazgch 28:4d9509e3b1cf 309 {
mazgch 28:4d9509e3b1cf 310 status->model = _model;
mazgch 28:4d9509e3b1cf 311 status->sim = _sim;
mazgch 28:4d9509e3b1cf 312 status->ccid = _ccid;
mazgch 28:4d9509e3b1cf 313 status->imsi = _imsi;
mazgch 28:4d9509e3b1cf 314 status->imei = _imei;
mazgch 28:4d9509e3b1cf 315 }
mazgch 21:c4d64830bf02 316 return true;
mazgch 21:c4d64830bf02 317 }
mazgch 21:c4d64830bf02 318
mazgch 26:07be5faf8925 319 int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid)
mazgch 26:07be5faf8925 320 {
mazgch 26:07be5faf8925 321 if ((type == TYPE_PLUS) && ccid){
mazgch 26:07be5faf8925 322 if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1)
mazgch 28:4d9509e3b1cf 323 /*TRACE("Got CCID: %s\n", ccid)*/;
mazgch 26:07be5faf8925 324 }
mazgch 26:07be5faf8925 325 return WAIT;
mazgch 26:07be5faf8925 326 }
mazgch 26:07be5faf8925 327
mazgch 26:07be5faf8925 328 int MDMParser::_cbGSN(int type, const char* buf, int len, char* imei)
mazgch 26:07be5faf8925 329 {
mazgch 26:07be5faf8925 330 if ((type == TYPE_UNKNOWN) && imei){
mazgch 26:07be5faf8925 331 if (sscanf(buf, "\r\n%[^\r]\r\n%*[^\r]\r\n", imei) == 1)
mazgch 28:4d9509e3b1cf 332 /*TRACE("Got IMEI: %s\n", imei)*/;
mazgch 26:07be5faf8925 333 }
mazgch 26:07be5faf8925 334 return WAIT;
mazgch 26:07be5faf8925 335 }
mazgch 26:07be5faf8925 336
mazgch 26:07be5faf8925 337 int MDMParser::_cbCGSN(int type, const char* buf, int len, char* imei)
mazgch 26:07be5faf8925 338 {
mazgch 26:07be5faf8925 339 if ((type == TYPE_UNKNOWN) && imei){
mazgch 26:07be5faf8925 340 if (sscanf(buf, "\r\n%[^\r]\r\n", imei) == 1)
mazgch 28:4d9509e3b1cf 341 /*TRACE("Got IMEI: %s\n", imei)*/;
mazgch 26:07be5faf8925 342 }
mazgch 26:07be5faf8925 343 return WAIT;
mazgch 26:07be5faf8925 344 }
mazgch 26:07be5faf8925 345
mazgch 26:07be5faf8925 346 int MDMParser::_cbCIMI(int type, const char* buf, int len, char* imsi)
mazgch 26:07be5faf8925 347 {
mazgch 26:07be5faf8925 348 if ((type == TYPE_UNKNOWN) && imsi) {
mazgch 26:07be5faf8925 349 if (sscanf(buf, "\r\n%[^\r]\r\n", imsi) == 1)
mazgch 28:4d9509e3b1cf 350 /*TRACE("Got IMSI: %s\n", imsi)*/;
mazgch 26:07be5faf8925 351 }
mazgch 26:07be5faf8925 352 return WAIT;
mazgch 26:07be5faf8925 353 }
mazgch 26:07be5faf8925 354
mazgch 28:4d9509e3b1cf 355 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
mazgch 21:c4d64830bf02 356 {
mazgch 21:c4d64830bf02 357 // check registration
mazgch 21:c4d64830bf02 358 sendFormated("AT+CREG?\r\n");
mazgch 21:c4d64830bf02 359 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 360 return false;
mazgch 21:c4d64830bf02 361 if ((_net != NET_ROAMING) && (_net != NET_HOME))
mazgch 21:c4d64830bf02 362 return false;
mazgch 21:c4d64830bf02 363 // check modem specific status messages
mazgch 21:c4d64830bf02 364 if (_model == MODEL_LISA_C200) {
mazgch 21:c4d64830bf02 365 sendFormated("AT+CSS?\r\n");
mazgch 21:c4d64830bf02 366 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 367 return false;
mazgch 21:c4d64830bf02 368 if ((_net != NET_ROAMING) && (_net != NET_HOME))
mazgch 21:c4d64830bf02 369 return false;
mazgch 21:c4d64830bf02 370 } else {
mazgch 21:c4d64830bf02 371 // check operator selection
mazgch 21:c4d64830bf02 372 sendFormated("AT+COPS?\r\n");
mazgch 21:c4d64830bf02 373 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 374 return false;
mazgch 21:c4d64830bf02 375 // Returns the MSISDNs related to this subscriber
mazgch 21:c4d64830bf02 376 sendFormated("AT+CNUM\r\n");
mazgch 21:c4d64830bf02 377 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 378 return false;
mazgch 21:c4d64830bf02 379 }
mazgch 21:c4d64830bf02 380 // Returns the signal strength indication
mazgch 21:c4d64830bf02 381 sendFormated("AT+CSQ\r\n");
mazgch 21:c4d64830bf02 382 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 383 return false;
mazgch 28:4d9509e3b1cf 384 if (status) {
mazgch 28:4d9509e3b1cf 385 status->num = _num;
mazgch 28:4d9509e3b1cf 386 status->opr = _opr;
mazgch 28:4d9509e3b1cf 387 status->rssi = _rssi;
mazgch 28:4d9509e3b1cf 388 status->net = _net;
mazgch 28:4d9509e3b1cf 389 status->act = _act;
mazgch 25:4045d02e44f1 390 }
mazgch 21:c4d64830bf02 391 return true;
mazgch 21:c4d64830bf02 392 }
mazgch 21:c4d64830bf02 393
mazgch 21:c4d64830bf02 394 bool MDMParser::powerOff(void)
mazgch 21:c4d64830bf02 395 {
mazgch 21:c4d64830bf02 396 sendFormated("AT+CPWROFF\r\n");
mazgch 21:c4d64830bf02 397 if (OK != waitFinalResp(NULL,NULL,120))
mazgch 21:c4d64830bf02 398 return false;
mazgch 21:c4d64830bf02 399 return true;
mazgch 21:c4d64830bf02 400 }
mazgch 21:c4d64830bf02 401
mazgch 21:c4d64830bf02 402 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 403 // internet connection
mazgch 21:c4d64830bf02 404
mazgch 22:29322c22577e 405 MDMParser::IP MDMParser::strToIp(const char* str)
mazgch 21:c4d64830bf02 406 {
mazgch 21:c4d64830bf02 407 IP ip = 0;
mazgch 21:c4d64830bf02 408 char* p = (char*)str;
mazgch 21:c4d64830bf02 409 for(int i = 0; i < 4; i++) {
mazgch 21:c4d64830bf02 410 ip |= atoi(p);
mazgch 21:c4d64830bf02 411 p = strchr(p, '.');
mazgch 21:c4d64830bf02 412 if (p == NULL) {
mazgch 21:c4d64830bf02 413 break;
mazgch 21:c4d64830bf02 414 }
mazgch 21:c4d64830bf02 415 ip <<= 8;
mazgch 21:c4d64830bf02 416 p++;
mazgch 18:e5697801df29 417 }
mazgch 21:c4d64830bf02 418 return ip;
mazgch 21:c4d64830bf02 419 }
mazgch 21:c4d64830bf02 420
mazgch 28:4d9509e3b1cf 421 bool MDMParser::join(const char* apn /*= NULL*/, const char* user /*= NULL*/, const char* password /*= NULL*/)
mazgch 21:c4d64830bf02 422 {
mazgch 21:c4d64830bf02 423 if (_model == MODEL_LISA_C200) {
mazgch 21:c4d64830bf02 424 #ifdef TODO // TODO implement
mazgch 21:c4d64830bf02 425 // enable the
mazgch 21:c4d64830bf02 426 sendFormated("AT$QCMIPEP=1\r\n");
mazgch 21:c4d64830bf02 427 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 428 return false;
mazgch 21:c4d64830bf02 429 //Get local IP address
mazgch 21:c4d64830bf02 430 sendFormated("AT+CMIP?\r\n");
mazgch 21:c4d64830bf02 431 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 432 return false;
mazgch 21:c4d64830bf02 433 #endif
mazgch 21:c4d64830bf02 434 } else {
mazgch 21:c4d64830bf02 435 // check gprs attach status
mazgch 21:c4d64830bf02 436 sendFormated("AT+CGATT?\r\n");
mazgch 21:c4d64830bf02 437 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 438 return false;
mazgch 21:c4d64830bf02 439 // Set up the APN
mazgch 21:c4d64830bf02 440 if (apn) {
mazgch 21:c4d64830bf02 441 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
mazgch 21:c4d64830bf02 442 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 443 return false;
mazgch 21:c4d64830bf02 444 }
mazgch 21:c4d64830bf02 445 if (user) {
mazgch 21:c4d64830bf02 446 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", user);
mazgch 21:c4d64830bf02 447 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 448 return false;
mazgch 21:c4d64830bf02 449 }
mazgch 21:c4d64830bf02 450 if (password) {
mazgch 21:c4d64830bf02 451 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
mazgch 21:c4d64830bf02 452 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 453 return false;
mazgch 21:c4d64830bf02 454 }
mazgch 21:c4d64830bf02 455 // Set up the dynamic IP address assignment.
mazgch 21:c4d64830bf02 456 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
mazgch 21:c4d64830bf02 457 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 458 return false;
mazgch 21:c4d64830bf02 459 // Activate the profile and make connection
mazgch 21:c4d64830bf02 460 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 21:c4d64830bf02 461 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 462 return false;
mazgch 21:c4d64830bf02 463 //Get local IP address
mazgch 21:c4d64830bf02 464 sendFormated("AT+UPSND=" PROFILE ",0\r\n");
mazgch 21:c4d64830bf02 465 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 466 return false;
mazgch 21:c4d64830bf02 467 }
mazgch 21:c4d64830bf02 468 if (!_ip)
mazgch 21:c4d64830bf02 469 return false;
mazgch 23:05a1aeeb5fd9 470 TRACE("Got IP address: " IPSTR "\n", IPNUM(_ip));
mazgch 21:c4d64830bf02 471 return true;
mazgch 21:c4d64830bf02 472 }
mazgch 21:c4d64830bf02 473
mazgch 21:c4d64830bf02 474 bool MDMParser::disconnect(void)
mazgch 21:c4d64830bf02 475 {
mazgch 21:c4d64830bf02 476 if (_ip == 0)
mazgch 21:c4d64830bf02 477 return true;
mazgch 21:c4d64830bf02 478 if (_model == MODEL_LISA_C200) {
mazgch 21:c4d64830bf02 479 #ifdef TODO // TODO implement
mazgch 21:c4d64830bf02 480 sendFormated("AT$QCMIPEP=0\r\n");
mazgch 21:c4d64830bf02 481 #endif
mazgch 21:c4d64830bf02 482 } else {
mazgch 21:c4d64830bf02 483 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 21:c4d64830bf02 484 }
mazgch 21:c4d64830bf02 485 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 486 return false;
mazgch 21:c4d64830bf02 487 _ip = 0;
mazgch 21:c4d64830bf02 488 return true;
mazgch 21:c4d64830bf02 489 }
mazgch 21:c4d64830bf02 490
mazgch 21:c4d64830bf02 491 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip)
mazgch 21:c4d64830bf02 492 {
mazgch 21:c4d64830bf02 493 if ((type == TYPE_PLUS) && ip) {
mazgch 21:c4d64830bf02 494 buf += 3;
mazgch 21:c4d64830bf02 495 int a,b,c,d;
mazgch 21:c4d64830bf02 496 if (sscanf(buf, "UDNSRN: \""IPSTR"\"", &a,&b,&c,&d) == 4)
mazgch 21:c4d64830bf02 497 *ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 498 }
mazgch 18:e5697801df29 499 return WAIT;
mazgch 18:e5697801df29 500 }
mazgch 18:e5697801df29 501
mazgch 21:c4d64830bf02 502 bool MDMParser::gethostbyname(const char* host, IP* ip)
mazgch 21:c4d64830bf02 503 {
mazgch 21:c4d64830bf02 504 char ipstr[16];
mazgch 21:c4d64830bf02 505 IP addr = strToIp(host);
mazgch 21:c4d64830bf02 506 *ip = 0;
mazgch 21:c4d64830bf02 507 snprintf(ipstr, sizeof(ipstr), IPSTR, IPNUM(addr));
mazgch 21:c4d64830bf02 508 if (strcmp(ipstr, host) == 0) {
mazgch 21:c4d64830bf02 509 *ip = addr;
mazgch 21:c4d64830bf02 510 return true;
mazgch 21:c4d64830bf02 511 }
mazgch 21:c4d64830bf02 512 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host);
mazgch 26:07be5faf8925 513 if (OK != waitFinalResp(_cbUDNSRN, ip))
mazgch 21:c4d64830bf02 514 return false;
mazgch 21:c4d64830bf02 515 return *ip != 0;
mazgch 21:c4d64830bf02 516 }
mazgch 21:c4d64830bf02 517
mazgch 21:c4d64830bf02 518 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 519 // sockets
mazgch 21:c4d64830bf02 520
mazgch 21:c4d64830bf02 521 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* socket)
mazgch 21:c4d64830bf02 522 {
mazgch 21:c4d64830bf02 523 if ((type == TYPE_PLUS) && socket) {
mazgch 21:c4d64830bf02 524 const char* p = strstr(buf,"+USOCR: ");
mazgch 21:c4d64830bf02 525 if (p)
mazgch 21:c4d64830bf02 526 *socket = atoi(p+8);
mazgch 21:c4d64830bf02 527 }
mazgch 21:c4d64830bf02 528 return WAIT;
mazgch 21:c4d64830bf02 529 }
mazgch 21:c4d64830bf02 530
mazgch 21:c4d64830bf02 531 int MDMParser::socketSocket(IpProtocol ipproto)
mazgch 21:c4d64830bf02 532 {
mazgch 21:c4d64830bf02 533 const char* cmd;
mazgch 21:c4d64830bf02 534 if(ipproto == IPPROTO_TCP) {
mazgch 21:c4d64830bf02 535 cmd = "AT+USOCR=6\r\n";
mazgch 21:c4d64830bf02 536 } else if(ipproto == IPPROTO_UDP) {
mazgch 21:c4d64830bf02 537 cmd = "AT+USOCR=17\r\n";
mazgch 21:c4d64830bf02 538 } else { // other types not supported
mazgch 21:c4d64830bf02 539 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 540 }
mazgch 21:c4d64830bf02 541 sendFormated(cmd);
mazgch 21:c4d64830bf02 542 int socket = -1;
mazgch 26:07be5faf8925 543 if (OK != waitFinalResp(_cbUSOCR, &socket))
mazgch 21:c4d64830bf02 544 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 545 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_FREE))
mazgch 21:c4d64830bf02 546 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 547 // successfull
mazgch 21:c4d64830bf02 548 _sockets[socket].state = SOCK_CREATED;
mazgch 21:c4d64830bf02 549 _sockets[socket].pending = 0;
mazgch 21:c4d64830bf02 550 return socket;
mazgch 21:c4d64830bf02 551 }
mazgch 21:c4d64830bf02 552
mazgch 21:c4d64830bf02 553 bool MDMParser::socketConnect(int socket, const char * host, int port)
mazgch 21:c4d64830bf02 554 {
mazgch 21:c4d64830bf02 555 IP ip;
mazgch 21:c4d64830bf02 556 if (!gethostbyname(host, &ip))
mazgch 21:c4d64830bf02 557 return false;
mazgch 21:c4d64830bf02 558 // connect to socket
mazgch 21:c4d64830bf02 559 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED))
mazgch 21:c4d64830bf02 560 return false;
mazgch 21:c4d64830bf02 561 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", socket, IPNUM(ip), port);
mazgch 21:c4d64830bf02 562 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 563 return false;
mazgch 21:c4d64830bf02 564 _sockets[socket].state = SOCK_CONNECTED;
mazgch 21:c4d64830bf02 565 return true;
mazgch 21:c4d64830bf02 566 }
mazgch 21:c4d64830bf02 567
mazgch 21:c4d64830bf02 568 bool MDMParser::socketClose(int socket)
mazgch 21:c4d64830bf02 569 {
mazgch 21:c4d64830bf02 570 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED))
mazgch 21:c4d64830bf02 571 return false;
mazgch 21:c4d64830bf02 572 sendFormated("AT+USOCL=%d\r\n", socket);
mazgch 21:c4d64830bf02 573 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 574 return false;
mazgch 21:c4d64830bf02 575 return true;
mazgch 21:c4d64830bf02 576 }
mazgch 21:c4d64830bf02 577
mazgch 21:c4d64830bf02 578 bool MDMParser::socketFree(int socket)
mazgch 21:c4d64830bf02 579 {
mazgch 21:c4d64830bf02 580 socketClose(socket);
mazgch 21:c4d64830bf02 581 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED))
mazgch 21:c4d64830bf02 582 return false;
mazgch 21:c4d64830bf02 583 _sockets[socket].state = SOCK_FREE;
mazgch 21:c4d64830bf02 584 return true;
mazgch 21:c4d64830bf02 585 }
mazgch 21:c4d64830bf02 586
mazgch 21:c4d64830bf02 587 int MDMParser::socketSend(int socket, const char * buf, int len)
mazgch 21:c4d64830bf02 588 {
mazgch 21:c4d64830bf02 589 if(len > 0) {
mazgch 21:c4d64830bf02 590 sendFormated("AT+USOWR=%d,%d\r\n",socket,len);
mazgch 21:c4d64830bf02 591 if (PROMPT != waitFinalResp())
mazgch 21:c4d64830bf02 592 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 593 wait_ms(50);
mazgch 21:c4d64830bf02 594 send(buf, len);
mazgch 21:c4d64830bf02 595 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 596 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 597 }
mazgch 21:c4d64830bf02 598 return len;
mazgch 21:c4d64830bf02 599 }
mazgch 21:c4d64830bf02 600
mazgch 21:c4d64830bf02 601 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len)
mazgch 21:c4d64830bf02 602 {
mazgch 21:c4d64830bf02 603 if(len > 0) {
mazgch 21:c4d64830bf02 604 sendFormated("AT+USOWR=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,len);
mazgch 21:c4d64830bf02 605 if (PROMPT != waitFinalResp())
mazgch 21:c4d64830bf02 606 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 607 wait_ms(50);
mazgch 21:c4d64830bf02 608 send(buf, len);
mazgch 21:c4d64830bf02 609 if (OK != waitFinalResp())
mazgch 21:c4d64830bf02 610 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 611 }
mazgch 21:c4d64830bf02 612 return len;
mazgch 21:c4d64830bf02 613 }
mazgch 21:c4d64830bf02 614
mazgch 21:c4d64830bf02 615 int MDMParser::socketReadable(int socket)
mazgch 21:c4d64830bf02 616 {
mazgch 21:c4d64830bf02 617 if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED))
mazgch 21:c4d64830bf02 618 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 619 // allow to receive unsolicited commands
mazgch 21:c4d64830bf02 620 waitFinalResp(NULL, NULL, 0);
mazgch 21:c4d64830bf02 621 if (_sockets[socket].state != SOCK_CONNECTED)
mazgch 21:c4d64830bf02 622 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 623 return _sockets[socket].pending;
mazgch 21:c4d64830bf02 624 }
mazgch 21:c4d64830bf02 625
mazgch 21:c4d64830bf02 626 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out)
mazgch 21:c4d64830bf02 627 {
mazgch 21:c4d64830bf02 628 if ((type == TYPE_PLUS) && out) {
mazgch 21:c4d64830bf02 629 int sz, sk;
mazgch 21:c4d64830bf02 630 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) &&
mazgch 21:c4d64830bf02 631 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 632 memcpy(out, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 633 }
mazgch 21:c4d64830bf02 634 }
mazgch 21:c4d64830bf02 635 return WAIT;
mazgch 21:c4d64830bf02 636 }
mazgch 21:c4d64830bf02 637
mazgch 21:c4d64830bf02 638 int MDMParser::socketRecv(int socket, char* buf, int len)
mazgch 21:c4d64830bf02 639 {
mazgch 21:c4d64830bf02 640 int cnt = 0;
mazgch 21:c4d64830bf02 641 if (!ISSOCKET(socket))
mazgch 21:c4d64830bf02 642 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 643 memset(buf, '\0', len);
mazgch 21:c4d64830bf02 644 while (len) {
mazgch 21:c4d64830bf02 645 int blk = MAX_SIZE - 64; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 646 if (_sockets[socket].state != SOCK_CONNECTED)
mazgch 21:c4d64830bf02 647 return cnt ? cnt : SOCKET_ERROR;
mazgch 21:c4d64830bf02 648 if (_sockets[socket].pending < blk)
mazgch 21:c4d64830bf02 649 blk = _sockets[socket].pending;
mazgch 21:c4d64830bf02 650 if (len < blk) blk = len;
mazgch 21:c4d64830bf02 651 if (blk) {
mazgch 21:c4d64830bf02 652 sendFormated("AT+USORD=%d,%d\r\n",socket, blk);
mazgch 26:07be5faf8925 653 if (OK != waitFinalResp(_cbUSORD, buf)) {
mazgch 21:c4d64830bf02 654 return cnt ? cnt : SOCKET_ERROR;
mazgch 21:c4d64830bf02 655 }
mazgch 21:c4d64830bf02 656 len -= blk;
mazgch 21:c4d64830bf02 657 cnt += blk;
mazgch 21:c4d64830bf02 658 buf += blk;
mazgch 21:c4d64830bf02 659 _sockets[socket].pending -= blk;
mazgch 21:c4d64830bf02 660 } else {
mazgch 21:c4d64830bf02 661 // allow to receive unsolicited commands
mazgch 21:c4d64830bf02 662 waitFinalResp(NULL, NULL, 10);
mazgch 21:c4d64830bf02 663 }
mazgch 21:c4d64830bf02 664 }
mazgch 21:c4d64830bf02 665 return cnt;
mazgch 21:c4d64830bf02 666 }
mazgch 21:c4d64830bf02 667
mazgch 21:c4d64830bf02 668 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param)
mazgch 21:c4d64830bf02 669 {
mazgch 21:c4d64830bf02 670 if ((type == TYPE_PLUS) && param) {
mazgch 21:c4d64830bf02 671 int sz, sk, p, a,b,c,d;
mazgch 21:c4d64830bf02 672 if ((sscanf(buf, "\r\n+USORF: %d,\""IPSTR"\",%d,%d,",
mazgch 21:c4d64830bf02 673 &sk,&a,&b,&c,&d,&p,&sz) == 7) &&
mazgch 21:c4d64830bf02 674 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 675 memcpy(param->buf, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 676 param->ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 677 param->port = p;
mazgch 21:c4d64830bf02 678 }
mazgch 21:c4d64830bf02 679 }
mazgch 21:c4d64830bf02 680 return WAIT;
mazgch 21:c4d64830bf02 681 }
mazgch 21:c4d64830bf02 682
mazgch 21:c4d64830bf02 683 int MDMParser::socketRecvFrom(int socket, char* buf, int len, IP* ip)
mazgch 21:c4d64830bf02 684 {
mazgch 21:c4d64830bf02 685 int cnt = 0;
mazgch 21:c4d64830bf02 686 if (!ISSOCKET(socket))
mazgch 21:c4d64830bf02 687 return SOCKET_ERROR;
mazgch 21:c4d64830bf02 688 memset(buf, '\0', len);
mazgch 21:c4d64830bf02 689 while (len) {
mazgch 21:c4d64830bf02 690 int blk = MAX_SIZE - 64; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 691 if (_sockets[socket].state != SOCK_CONNECTED)
mazgch 21:c4d64830bf02 692 return cnt ? cnt : SOCKET_ERROR;
mazgch 21:c4d64830bf02 693 if (_sockets[socket].pending < blk)
mazgch 21:c4d64830bf02 694 blk = _sockets[socket].pending;
mazgch 21:c4d64830bf02 695 if (len < blk) blk = len;
mazgch 21:c4d64830bf02 696 if (blk) {
mazgch 21:c4d64830bf02 697 sendFormated("AT+USORF=%d,%d\r\n",socket, blk);
mazgch 21:c4d64830bf02 698 USORFparam param;
mazgch 21:c4d64830bf02 699 param.buf = buf;
mazgch 26:07be5faf8925 700 if (OK != waitFinalResp(_cbUSORF, &param)) {
mazgch 21:c4d64830bf02 701 return cnt ? cnt : SOCKET_ERROR;
mazgch 21:c4d64830bf02 702 }
mazgch 21:c4d64830bf02 703 *ip = param.ip;
mazgch 21:c4d64830bf02 704 //*port = param.port;
mazgch 21:c4d64830bf02 705 len -= blk;
mazgch 21:c4d64830bf02 706 cnt += blk;
mazgch 21:c4d64830bf02 707 buf += blk;
mazgch 21:c4d64830bf02 708 _sockets[socket].pending -= blk;
mazgch 21:c4d64830bf02 709 } else {
mazgch 21:c4d64830bf02 710 // allow to receive unsolicited commands
mazgch 21:c4d64830bf02 711 waitFinalResp(NULL, NULL, 10);
mazgch 21:c4d64830bf02 712 }
mazgch 21:c4d64830bf02 713 }
mazgch 21:c4d64830bf02 714 return cnt;
mazgch 21:c4d64830bf02 715 }
mazgch 21:c4d64830bf02 716
mazgch 21:c4d64830bf02 717 // ----------------------------------------------------------------
mazgch 29:53d346010624 718 int MDMParser::_cbCPMS(int type, const char* buf, int len, int* num)
mazgch 21:c4d64830bf02 719 {
mazgch 29:53d346010624 720 if ((type == TYPE_PLUS) && num) {
mazgch 29:53d346010624 721 // AT+CPMS: <used1>,<total1>,<used2>,<total2>,<used3>,<total3>;
mazgch 29:53d346010624 722 if (sscanf(buf, "\r\n+CPMS: %d,%*d", num) == 1)
mazgch 29:53d346010624 723 /*nothing*/;
mazgch 29:53d346010624 724 }
mazgch 29:53d346010624 725 return WAIT;
mazgch 21:c4d64830bf02 726 }
mazgch 21:c4d64830bf02 727
mazgch 21:c4d64830bf02 728 int MDMParser::smsCount(void)
mazgch 21:c4d64830bf02 729 {
mazgch 21:c4d64830bf02 730 int num = 0;
mazgch 29:53d346010624 731 sendFormated("AT+CPMS=\"ME\"\r\n");
mazgch 29:53d346010624 732 if (OK != waitFinalResp(_cbCPMS,&num)) {
mazgch 29:53d346010624 733 return 0;
mazgch 21:c4d64830bf02 734 }
mazgch 29:53d346010624 735 return num;
mazgch 21:c4d64830bf02 736 }
mazgch 21:c4d64830bf02 737
mazgch 21:c4d64830bf02 738 bool MDMParser::smsSend(const char* num, const char* buf)
mazgch 21:c4d64830bf02 739 {
mazgch 21:c4d64830bf02 740 sendFormated("AT+CMGS=\"%s\"\r",num);
mazgch 21:c4d64830bf02 741 if (PROMPT != waitFinalResp()) {
mazgch 21:c4d64830bf02 742 return false;
mazgch 21:c4d64830bf02 743 }
mazgch 21:c4d64830bf02 744 send(buf, strlen(buf));
mazgch 21:c4d64830bf02 745 const char ctrlZ = 0x1A;
mazgch 21:c4d64830bf02 746 send(&ctrlZ, sizeof(ctrlZ));
mazgch 21:c4d64830bf02 747 if (OK != waitFinalResp()) {
mazgch 21:c4d64830bf02 748 return false;
mazgch 21:c4d64830bf02 749 }
mazgch 21:c4d64830bf02 750 return true;
mazgch 21:c4d64830bf02 751 }
mazgch 21:c4d64830bf02 752
mazgch 21:c4d64830bf02 753 bool MDMParser::smsDelete(int ix)
mazgch 21:c4d64830bf02 754 {
mazgch 21:c4d64830bf02 755 sendFormated("AT+CMGD=%d\r\n",ix);
mazgch 21:c4d64830bf02 756 if (OK != waitFinalResp()) {
mazgch 21:c4d64830bf02 757 return false;
mazgch 21:c4d64830bf02 758 }
mazgch 21:c4d64830bf02 759 return true;
mazgch 21:c4d64830bf02 760 }
mazgch 21:c4d64830bf02 761
mazgch 21:c4d64830bf02 762 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param)
mazgch 21:c4d64830bf02 763 {
mazgch 21:c4d64830bf02 764 if (param) {
mazgch 21:c4d64830bf02 765 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 766 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) {
mazgch 21:c4d64830bf02 767 }
mazgch 21:c4d64830bf02 768 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) {
mazgch 21:c4d64830bf02 769 memcpy(param->buf, buf, len-2);
mazgch 21:c4d64830bf02 770 param->buf[len-2] = '\0';
mazgch 21:c4d64830bf02 771 }
mazgch 21:c4d64830bf02 772 }
mazgch 21:c4d64830bf02 773 return WAIT;
mazgch 21:c4d64830bf02 774 }
mazgch 21:c4d64830bf02 775
mazgch 21:c4d64830bf02 776 bool MDMParser::smsRead(int ix, char* num, char* buf, int len)
mazgch 21:c4d64830bf02 777 {
mazgch 21:c4d64830bf02 778 CMGRparam param;
mazgch 21:c4d64830bf02 779 param.num = num;
mazgch 21:c4d64830bf02 780 param.buf = buf;
mazgch 21:c4d64830bf02 781 sendFormated("AT+CMGR=%d\r\n",ix);
mazgch 26:07be5faf8925 782 if (OK != waitFinalResp(_cbCMGR, &param)) {
mazgch 21:c4d64830bf02 783 return false;
mazgch 21:c4d64830bf02 784 }
mazgch 21:c4d64830bf02 785 return true;
mazgch 21:c4d64830bf02 786 }
mazgch 21:c4d64830bf02 787
mazgch 21:c4d64830bf02 788 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 789
mazgch 21:c4d64830bf02 790 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp)
mazgch 21:c4d64830bf02 791 {
mazgch 21:c4d64830bf02 792 if ((type == TYPE_PLUS) && resp) {
mazgch 21:c4d64830bf02 793 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..);
mazgch 21:c4d64830bf02 794 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) {
mazgch 21:c4d64830bf02 795 /*nothing*/
mazgch 21:c4d64830bf02 796 }
mazgch 21:c4d64830bf02 797 }
mazgch 21:c4d64830bf02 798 return WAIT;
mazgch 21:c4d64830bf02 799 }
mazgch 21:c4d64830bf02 800 int MDMParser::ussdCommand(const char* cmd, char* buf, int len)
mazgch 21:c4d64830bf02 801 {
mazgch 21:c4d64830bf02 802 *buf = '\0';
mazgch 21:c4d64830bf02 803 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
mazgch 26:07be5faf8925 804 if (OK != waitFinalResp(_cbCUSD, buf)) {
mazgch 21:c4d64830bf02 805 return -1;
mazgch 21:c4d64830bf02 806 }
mazgch 21:c4d64830bf02 807 return strlen(buf);
mazgch 21:c4d64830bf02 808 }
mazgch 26:07be5faf8925 809
mazgch 21:c4d64830bf02 810 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 811 int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end)
mazgch 18:e5697801df29 812 {
mazgch 18:e5697801df29 813 int o = 0;
mazgch 21:c4d64830bf02 814 if (sta) {
mazgch 21:c4d64830bf02 815 while (*sta) {
mazgch 21:c4d64830bf02 816 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 817 char ch = pipe->next();
mazgch 21:c4d64830bf02 818 if (*sta++ != ch) return NOT_FOUND;
mazgch 21:c4d64830bf02 819 }
mazgch 21:c4d64830bf02 820 }
mazgch 21:c4d64830bf02 821 if (!end) return o; // no termination
mazgch 21:c4d64830bf02 822 int x = 0;
mazgch 21:c4d64830bf02 823 while (end[x]) {
mazgch 21:c4d64830bf02 824 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 825 char ch = pipe->next();
mazgch 21:c4d64830bf02 826 x = (end[x] == ch) ? x + 1 :
mazgch 21:c4d64830bf02 827 (end[0] == ch) ? 1 :
mazgch 21:c4d64830bf02 828 0;
mazgch 21:c4d64830bf02 829 }
mazgch 21:c4d64830bf02 830 return o;
mazgch 21:c4d64830bf02 831 }
mazgch 21:c4d64830bf02 832
mazgch 21:c4d64830bf02 833 int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt)
mazgch 21:c4d64830bf02 834 {
mazgch 21:c4d64830bf02 835 int o = 0;
mazgch 21:c4d64830bf02 836 int num = 0;
mazgch 21:c4d64830bf02 837 if (fmt) {
mazgch 21:c4d64830bf02 838 while (*fmt) {
mazgch 21:c4d64830bf02 839 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 840 char ch = pipe->next();
mazgch 21:c4d64830bf02 841 if (*fmt == '%') {
mazgch 21:c4d64830bf02 842 fmt++;
mazgch 21:c4d64830bf02 843 if (*fmt == 'd') { // numeric
mazgch 21:c4d64830bf02 844 fmt ++;
mazgch 21:c4d64830bf02 845 num = 0;
mazgch 21:c4d64830bf02 846 while (ch >= '0' && ch <= '9') {
mazgch 21:c4d64830bf02 847 num = num * 10 + (ch - '0');
mazgch 21:c4d64830bf02 848 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 849 ch = pipe->next();
mazgch 21:c4d64830bf02 850 }
mazgch 21:c4d64830bf02 851 }
mazgch 21:c4d64830bf02 852 else if (*fmt == 'c') { // char buffer (takes last numeric as length)
mazgch 21:c4d64830bf02 853 fmt ++;
mazgch 21:c4d64830bf02 854 while (num --) {
mazgch 21:c4d64830bf02 855 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 856 ch = pipe->next();
mazgch 21:c4d64830bf02 857 }
mazgch 21:c4d64830bf02 858 }
mazgch 21:c4d64830bf02 859 }
mazgch 21:c4d64830bf02 860 if (*fmt++ != ch) return NOT_FOUND;
mazgch 18:e5697801df29 861 }
mazgch 18:e5697801df29 862 }
mazgch 21:c4d64830bf02 863 return o;
mazgch 21:c4d64830bf02 864 }
mazgch 21:c4d64830bf02 865
mazgch 21:c4d64830bf02 866
mazgch 21:c4d64830bf02 867 int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len)
mazgch 21:c4d64830bf02 868 {
mazgch 21:c4d64830bf02 869 int unkn = 0;
mazgch 21:c4d64830bf02 870 int sz = pipe->size();
mazgch 21:c4d64830bf02 871 int fr = pipe->free();
mazgch 21:c4d64830bf02 872 if (len > sz)
mazgch 21:c4d64830bf02 873 len = sz;
mazgch 21:c4d64830bf02 874 while (len > 0)
mazgch 21:c4d64830bf02 875 {
mazgch 21:c4d64830bf02 876 static struct {
mazgch 21:c4d64830bf02 877 const char* fmt; int type;
mazgch 21:c4d64830bf02 878 } lutF[] = {
mazgch 21:c4d64830bf02 879 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS },
mazgch 21:c4d64830bf02 880 { "\r\n+USORF: %d,\""IPSTR"\",%d,%d,\"%c\"", TYPE_PLUS },
mazgch 21:c4d64830bf02 881 };
mazgch 21:c4d64830bf02 882 static struct {
mazgch 21:c4d64830bf02 883 const char* sta; const char* end; int type;
mazgch 21:c4d64830bf02 884 } lut[] = {
mazgch 21:c4d64830bf02 885 { "\r\nOK\r\n", NULL, TYPE_OK },
mazgch 21:c4d64830bf02 886 { "\r\nERROR\r\n", NULL, TYPE_ERROR },
mazgch 21:c4d64830bf02 887 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 888 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 889 { "\r\nRING\r\n", NULL, TYPE_RING },
mazgch 21:c4d64830bf02 890 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT },
mazgch 21:c4d64830bf02 891 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER },
mazgch 21:c4d64830bf02 892 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE },
mazgch 21:c4d64830bf02 893 { "\r\nBUSY\r\n", NULL, TYPE_BUSY },
mazgch 21:c4d64830bf02 894 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER },
mazgch 21:c4d64830bf02 895 { "\r\n+", "\r\n", TYPE_PLUS },
mazgch 21:c4d64830bf02 896 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets
mazgch 21:c4d64830bf02 897 { "\r\n>", NULL, TYPE_PROMPT }, // SMS
mazgch 21:c4d64830bf02 898 };
mazgch 21:c4d64830bf02 899 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) {
mazgch 21:c4d64830bf02 900 pipe->set(unkn);
mazgch 21:c4d64830bf02 901 int ln = _parseFormated(pipe, len, lutF[i].fmt);
mazgch 21:c4d64830bf02 902 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 903 return WAIT;
mazgch 21:c4d64830bf02 904 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 21:c4d64830bf02 905 return pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 906 if (ln > 0)
mazgch 21:c4d64830bf02 907 return lutF[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 908 }
mazgch 21:c4d64830bf02 909 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) {
mazgch 21:c4d64830bf02 910 pipe->set(unkn);
mazgch 21:c4d64830bf02 911 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end);
mazgch 21:c4d64830bf02 912 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 913 return WAIT;
mazgch 21:c4d64830bf02 914 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 21:c4d64830bf02 915 return pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 916 if (ln > 0)
mazgch 21:c4d64830bf02 917 return lut[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 918 }
mazgch 21:c4d64830bf02 919 // UNKNOWN
mazgch 21:c4d64830bf02 920 unkn ++;
mazgch 21:c4d64830bf02 921 len--;
mazgch 21:c4d64830bf02 922 }
mazgch 18:e5697801df29 923 return WAIT;
mazgch 18:e5697801df29 924 }
mazgch 18:e5697801df29 925
mazgch 18:e5697801df29 926 // ----------------------------------------------------------------
mazgch 18:e5697801df29 927 // Serial Implementation
mazgch 18:e5697801df29 928 // ----------------------------------------------------------------
mazgch 18:e5697801df29 929
mazgch 19:2b5d097ca15d 930 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/,
mazgch 19:2b5d097ca15d 931 int baudrate /*= MDMBAUD*/,
mazgch 19:2b5d097ca15d 932 #if DEVICE_SERIAL_FC
mazgch 19:2b5d097ca15d 933 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/,
mazgch 19:2b5d097ca15d 934 #endif
mazgch 18:e5697801df29 935 int rxSize /*= 256*/, int txSize /*= 128*/) :
mazgch 19:2b5d097ca15d 936 #if DEVICE_SERIAL_FC
mazgch 18:e5697801df29 937 SerialPipe(tx, rx, rts, cts, rxSize, txSize)
mazgch 19:2b5d097ca15d 938 #else
mazgch 18:e5697801df29 939 SerialPipe(tx, rx, rxSize, txSize)
mazgch 19:2b5d097ca15d 940 #endif
mazgch 18:e5697801df29 941 {
mazgch 18:e5697801df29 942 baud(baudrate);
mazgch 18:e5697801df29 943 }
mazgch 18:e5697801df29 944
mazgch 18:e5697801df29 945 int MDMSerial::_send(const void* buf, int len)
mazgch 18:e5697801df29 946 {
mazgch 18:e5697801df29 947 return put((const char*)buf, len, true/*=blocking*/);
mazgch 18:e5697801df29 948 }
mazgch 18:e5697801df29 949
mazgch 18:e5697801df29 950 int MDMSerial::getLine(char* buffer, int length)
mazgch 18:e5697801df29 951 {
mazgch 18:e5697801df29 952 return _getLine(&_pipeRx, buffer, length);
mazgch 18:e5697801df29 953 }
mazgch 18:e5697801df29 954
mazgch 18:e5697801df29 955 // ----------------------------------------------------------------
mazgch 18:e5697801df29 956 // USB Implementation
mazgch 18:e5697801df29 957 // ----------------------------------------------------------------
mazgch 18:e5697801df29 958
mazgch 18:e5697801df29 959 #ifdef HAVE_MDMUSB
mazgch 18:e5697801df29 960 // TODO properly implement with USB
mazgch 18:e5697801df29 961 MDMUsb::MDMUsb(void) { }
mazgch 18:e5697801df29 962 int MDMUsb::_send(const void* buf, int len) { return len; }
mazgch 18:e5697801df29 963 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; }
mazgch 18:e5697801df29 964 #endif