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 09:17:50 2014 +0000
Revision:
22:29322c22577e
Parent:
21:c4d64830bf02
Child:
23:05a1aeeb5fd9
make IP a local type

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