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 13:53:27 2014 +0000
Revision:
27:e35f2118368f
Parent:
26:07be5faf8925
Child:
28:4d9509e3b1cf
disable debug

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