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