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 11:59:28 2014 +0000
Revision:
25:4045d02e44f1
Parent:
24:0e287a85ac9e
Child:
26:07be5faf8925
added possibility to get network status struct

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