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:11:20 2014 +0000
Revision:
23:05a1aeeb5fd9
Parent:
22:29322c22577e
Child:
24:0e287a85ac9e
parse phone number and fix rssi

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