test

Dependents:   mbed-os-example-blinky-1stDevDemo

Committer:
karen801
Date:
Wed May 23 14:37:10 2018 +0000
Revision:
0:79ce2b184a43
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
karen801 0:79ce2b184a43 1 /* SPWFSA04 Device
karen801 0:79ce2b184a43 2 * Copyright (c) 2015 ARM Limited
karen801 0:79ce2b184a43 3 *
karen801 0:79ce2b184a43 4 * Licensed under the Apache License, Version 2.0 (the "License");
karen801 0:79ce2b184a43 5 * you may not use this file except in compliance with the License.
karen801 0:79ce2b184a43 6 * You may obtain a copy of the License at
karen801 0:79ce2b184a43 7 *
karen801 0:79ce2b184a43 8 * http://www.apache.org/licenses/LICENSE-2.0
karen801 0:79ce2b184a43 9 *
karen801 0:79ce2b184a43 10 * Unless required by applicable law or agreed to in writing, software
karen801 0:79ce2b184a43 11 * distributed under the License is distributed on an "AS IS" BASIS,
karen801 0:79ce2b184a43 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
karen801 0:79ce2b184a43 13 * See the License for the specific language governing permissions and
karen801 0:79ce2b184a43 14 * limitations under the License.
karen801 0:79ce2b184a43 15 */
karen801 0:79ce2b184a43 16
karen801 0:79ce2b184a43 17 #include "SPWFSA04.h"
karen801 0:79ce2b184a43 18 #include "SpwfSAInterface.h"
karen801 0:79ce2b184a43 19 #include "mbed_debug.h"
karen801 0:79ce2b184a43 20
karen801 0:79ce2b184a43 21 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
karen801 0:79ce2b184a43 22
karen801 0:79ce2b184a43 23 SPWFSA04::SPWFSA04(PinName tx, PinName rx,
karen801 0:79ce2b184a43 24 PinName rts, PinName cts,
karen801 0:79ce2b184a43 25 SpwfSAInterface &ifce, bool debug,
karen801 0:79ce2b184a43 26 PinName wakeup, PinName reset)
karen801 0:79ce2b184a43 27 : SPWFSAxx(tx, rx, rts, cts, ifce, debug, wakeup, reset) {
karen801 0:79ce2b184a43 28 }
karen801 0:79ce2b184a43 29
karen801 0:79ce2b184a43 30 bool SPWFSA04::open(const char *type, int* spwf_id, const char* addr, int port)
karen801 0:79ce2b184a43 31 {
karen801 0:79ce2b184a43 32 int socket_id;
karen801 0:79ce2b184a43 33 int value;
karen801 0:79ce2b184a43 34 int trials;
karen801 0:79ce2b184a43 35
karen801 0:79ce2b184a43 36 if(!_parser.send("AT+S.SOCKON=%s,%d,NULL,%s", addr, port, type))
karen801 0:79ce2b184a43 37 {
karen801 0:79ce2b184a43 38 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
karen801 0:79ce2b184a43 39 return false;
karen801 0:79ce2b184a43 40 }
karen801 0:79ce2b184a43 41
karen801 0:79ce2b184a43 42 /* handle both response possibilities here before returning
karen801 0:79ce2b184a43 43 * otherwise module seems to remain in inconsistent state.
karen801 0:79ce2b184a43 44 */
karen801 0:79ce2b184a43 45
karen801 0:79ce2b184a43 46 if(!_parser.recv("AT-S.")) { // get prefix
karen801 0:79ce2b184a43 47 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
karen801 0:79ce2b184a43 48 empty_rx_buffer();
karen801 0:79ce2b184a43 49 return false;
karen801 0:79ce2b184a43 50 }
karen801 0:79ce2b184a43 51
karen801 0:79ce2b184a43 52 /* wait for next character */
karen801 0:79ce2b184a43 53 trials = 0;
karen801 0:79ce2b184a43 54 while((value = _parser.getc()) < 0) {
karen801 0:79ce2b184a43 55 if(++trials >= SPWFXX_MAX_TRIALS) {
karen801 0:79ce2b184a43 56 debug("\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
karen801 0:79ce2b184a43 57 empty_rx_buffer();
karen801 0:79ce2b184a43 58 return false;
karen801 0:79ce2b184a43 59 }
karen801 0:79ce2b184a43 60 }
karen801 0:79ce2b184a43 61
karen801 0:79ce2b184a43 62 switch(value) {
karen801 0:79ce2b184a43 63 case 'O':
karen801 0:79ce2b184a43 64 /* get next character */
karen801 0:79ce2b184a43 65 value = _parser.getc();
karen801 0:79ce2b184a43 66 if(value != 'n') {
karen801 0:79ce2b184a43 67 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d) (%d, \'%c\')\r\n",
karen801 0:79ce2b184a43 68 __LINE__, value, value);
karen801 0:79ce2b184a43 69 empty_rx_buffer();
karen801 0:79ce2b184a43 70 return false;
karen801 0:79ce2b184a43 71 }
karen801 0:79ce2b184a43 72
karen801 0:79ce2b184a43 73 /* get socket id */
karen801 0:79ce2b184a43 74 if(!(_parser.recv(":%*u.%*u.%*u.%*u:%d\n", &socket_id)
karen801 0:79ce2b184a43 75 && _recv_delim_lf()
karen801 0:79ce2b184a43 76 && _recv_ok())) {
karen801 0:79ce2b184a43 77 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
karen801 0:79ce2b184a43 78 empty_rx_buffer();
karen801 0:79ce2b184a43 79 return false;
karen801 0:79ce2b184a43 80 }
karen801 0:79ce2b184a43 81 debug_if(_dbg_on, "AT^ AT-S.On:%s:%d\r\n", addr, socket_id);
karen801 0:79ce2b184a43 82
karen801 0:79ce2b184a43 83 *spwf_id = socket_id;
karen801 0:79ce2b184a43 84 return true;
karen801 0:79ce2b184a43 85 case 'E':
karen801 0:79ce2b184a43 86 int err_nr;
karen801 0:79ce2b184a43 87 if(_parser.recv("RROR:%d:%255[^\n]\n", &err_nr, _msg_buffer) && _recv_delim_lf()) {
karen801 0:79ce2b184a43 88 debug_if(_dbg_on, "AT^ AT-S.ERROR:%d:%s (%d)\r\n", err_nr, _msg_buffer, __LINE__);
karen801 0:79ce2b184a43 89 } else {
karen801 0:79ce2b184a43 90 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
karen801 0:79ce2b184a43 91 empty_rx_buffer();
karen801 0:79ce2b184a43 92 }
karen801 0:79ce2b184a43 93 break;
karen801 0:79ce2b184a43 94 default:
karen801 0:79ce2b184a43 95 debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d) (%d, \'%c\')\r\n",
karen801 0:79ce2b184a43 96 __LINE__, value, value);
karen801 0:79ce2b184a43 97 empty_rx_buffer();
karen801 0:79ce2b184a43 98 break;
karen801 0:79ce2b184a43 99 }
karen801 0:79ce2b184a43 100
karen801 0:79ce2b184a43 101 return false;
karen801 0:79ce2b184a43 102 }
karen801 0:79ce2b184a43 103
karen801 0:79ce2b184a43 104 int SPWFSA04::_read_in(char* buffer, int spwf_id, uint32_t amount) {
karen801 0:79ce2b184a43 105 int ret = -1;
karen801 0:79ce2b184a43 106 int received, cumulative;
karen801 0:79ce2b184a43 107
karen801 0:79ce2b184a43 108 MBED_ASSERT(buffer != NULL);
karen801 0:79ce2b184a43 109
karen801 0:79ce2b184a43 110 /* block asynchronous indications */
karen801 0:79ce2b184a43 111 if(!_winds_off()) {
karen801 0:79ce2b184a43 112 return -1;
karen801 0:79ce2b184a43 113 }
karen801 0:79ce2b184a43 114
karen801 0:79ce2b184a43 115 /* read in data */
karen801 0:79ce2b184a43 116 if(_parser.send("AT+S.SOCKR=%d,%d", spwf_id, (unsigned int)amount)) {
karen801 0:79ce2b184a43 117 if(!(_parser.recv("AT-S.Reading:%d:%d\n", &received, &cumulative) &&
karen801 0:79ce2b184a43 118 _recv_delim_lf())) {
karen801 0:79ce2b184a43 119 debug_if(_dbg_on, "\r\nSPWF> failed to receive AT-S.Reading (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 120 empty_rx_buffer();
karen801 0:79ce2b184a43 121 } else {
karen801 0:79ce2b184a43 122 /* set high timeout */
karen801 0:79ce2b184a43 123 _parser.set_timeout(SPWF_READ_BIN_TIMEOUT);
karen801 0:79ce2b184a43 124 /* read in binary data */
karen801 0:79ce2b184a43 125 int read = _parser.read(buffer, amount);
karen801 0:79ce2b184a43 126 /* reset timeout value */
karen801 0:79ce2b184a43 127 _parser.set_timeout(_timeout);
karen801 0:79ce2b184a43 128 if(read > 0) {
karen801 0:79ce2b184a43 129 if(_recv_ok()) {
karen801 0:79ce2b184a43 130 ret = amount;
karen801 0:79ce2b184a43 131
karen801 0:79ce2b184a43 132 /* remove from pending sizes
karen801 0:79ce2b184a43 133 * (MUST be done before next async indications handling (e.g. `_winds_on()`)) */
karen801 0:79ce2b184a43 134 _remove_pending_pkt_size(spwf_id, amount);
karen801 0:79ce2b184a43 135 } else {
karen801 0:79ce2b184a43 136 debug_if(_dbg_on, "\r\nSPWF> failed to receive OK (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 137 empty_rx_buffer();
karen801 0:79ce2b184a43 138 }
karen801 0:79ce2b184a43 139 } else {
karen801 0:79ce2b184a43 140 debug_if(_dbg_on, "\r\nSPWF> failed to read binary data (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 141 empty_rx_buffer();
karen801 0:79ce2b184a43 142 }
karen801 0:79ce2b184a43 143 }
karen801 0:79ce2b184a43 144 } else {
karen801 0:79ce2b184a43 145 debug_if(_dbg_on, "%s(%d): failed to send SOCKR\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 146 }
karen801 0:79ce2b184a43 147
karen801 0:79ce2b184a43 148 debug_if(_dbg_on, "\r\nSPWF> %s():\t%d:%d\r\n", __func__, spwf_id, amount);
karen801 0:79ce2b184a43 149
karen801 0:79ce2b184a43 150 /* unblock asynchronous indications */
karen801 0:79ce2b184a43 151 _winds_on();
karen801 0:79ce2b184a43 152
karen801 0:79ce2b184a43 153 return ret;
karen801 0:79ce2b184a43 154 }
karen801 0:79ce2b184a43 155
karen801 0:79ce2b184a43 156 /* betzw - TODO: improve performance! */
karen801 0:79ce2b184a43 157 bool SPWFSA04::_recv_ap(nsapi_wifi_ap_t *ap)
karen801 0:79ce2b184a43 158 {
karen801 0:79ce2b184a43 159 bool ret;
karen801 0:79ce2b184a43 160 int curr;
karen801 0:79ce2b184a43 161 unsigned int channel;
karen801 0:79ce2b184a43 162 int trials;
karen801 0:79ce2b184a43 163
karen801 0:79ce2b184a43 164 ap->security = NSAPI_SECURITY_UNKNOWN;
karen801 0:79ce2b184a43 165
karen801 0:79ce2b184a43 166 /* determine list end */
karen801 0:79ce2b184a43 167 curr = _parser.getc();
karen801 0:79ce2b184a43 168 if(curr == 'A') { // assume end of list ("AT-S.OK")
karen801 0:79ce2b184a43 169 if(!(_parser.recv("T-S.OK\n") && _recv_delim_lf())) {
karen801 0:79ce2b184a43 170 empty_rx_buffer();
karen801 0:79ce2b184a43 171 }
karen801 0:79ce2b184a43 172 return false;
karen801 0:79ce2b184a43 173 }
karen801 0:79ce2b184a43 174
karen801 0:79ce2b184a43 175 /* run to 'horizontal tab' */
karen801 0:79ce2b184a43 176 trials = 0;
karen801 0:79ce2b184a43 177 while(_parser.getc() != '\x09') {
karen801 0:79ce2b184a43 178 if(trials++ > SPWFXX_MAX_TRIALS) {
karen801 0:79ce2b184a43 179 debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 180 empty_rx_buffer();
karen801 0:79ce2b184a43 181 return false;
karen801 0:79ce2b184a43 182 }
karen801 0:79ce2b184a43 183 }
karen801 0:79ce2b184a43 184
karen801 0:79ce2b184a43 185 /* read in next line */
karen801 0:79ce2b184a43 186 ret = _parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf();
karen801 0:79ce2b184a43 187
karen801 0:79ce2b184a43 188 /* parse line - first phase */
karen801 0:79ce2b184a43 189 if(ret) {
karen801 0:79ce2b184a43 190 int val = sscanf(_msg_buffer,
karen801 0:79ce2b184a43 191 " %*s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx CHAN: %u RSSI: %hhd SSID: \'%*255[^\']\'",
karen801 0:79ce2b184a43 192 &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
karen801 0:79ce2b184a43 193 &channel, &ap->rssi);
karen801 0:79ce2b184a43 194 if(val < 8) {
karen801 0:79ce2b184a43 195 ret = false;
karen801 0:79ce2b184a43 196 }
karen801 0:79ce2b184a43 197 }
karen801 0:79ce2b184a43 198
karen801 0:79ce2b184a43 199 /* parse line - second phase */
karen801 0:79ce2b184a43 200 if(ret) { // ret == true
karen801 0:79ce2b184a43 201 char value;
karen801 0:79ce2b184a43 202 char *rest, *first, *last;
karen801 0:79ce2b184a43 203
karen801 0:79ce2b184a43 204 /* decide about position of `CAPS:` */
karen801 0:79ce2b184a43 205 first = strchr(_msg_buffer, '\'');
karen801 0:79ce2b184a43 206 if(first == NULL) {
karen801 0:79ce2b184a43 207 debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 208 empty_rx_buffer();
karen801 0:79ce2b184a43 209 return false;
karen801 0:79ce2b184a43 210 }
karen801 0:79ce2b184a43 211 last = strrchr(_msg_buffer, '\'');
karen801 0:79ce2b184a43 212 if((last == NULL) || (last < (first+1))) {
karen801 0:79ce2b184a43 213 debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 214 empty_rx_buffer();
karen801 0:79ce2b184a43 215 return false;
karen801 0:79ce2b184a43 216 }
karen801 0:79ce2b184a43 217 rest = strstr(last, "CAPS:");
karen801 0:79ce2b184a43 218 if(rest == NULL) {
karen801 0:79ce2b184a43 219 debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 220 empty_rx_buffer();
karen801 0:79ce2b184a43 221 return false;
karen801 0:79ce2b184a43 222 }
karen801 0:79ce2b184a43 223
karen801 0:79ce2b184a43 224 /* substitute '\'' with '\0' */
karen801 0:79ce2b184a43 225 *last = '\0';
karen801 0:79ce2b184a43 226
karen801 0:79ce2b184a43 227 /* copy values */
karen801 0:79ce2b184a43 228 memcpy(&ap->ssid, first+1, sizeof(ap->ssid)-1);
karen801 0:79ce2b184a43 229 ap->ssid[sizeof(ap->ssid)-1] = '\0';
karen801 0:79ce2b184a43 230 ap->channel = channel;
karen801 0:79ce2b184a43 231
karen801 0:79ce2b184a43 232 /* skip `CAPS: 0421 ` */
karen801 0:79ce2b184a43 233 if(strlen(rest) < 11) {
karen801 0:79ce2b184a43 234 debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 235 empty_rx_buffer();
karen801 0:79ce2b184a43 236 return false;
karen801 0:79ce2b184a43 237 }
karen801 0:79ce2b184a43 238 rest += 11;
karen801 0:79ce2b184a43 239
karen801 0:79ce2b184a43 240 /* get next character */
karen801 0:79ce2b184a43 241 value = *rest++;
karen801 0:79ce2b184a43 242 if(value != 'W') { // no security
karen801 0:79ce2b184a43 243 ap->security = NSAPI_SECURITY_NONE;
karen801 0:79ce2b184a43 244 return true;
karen801 0:79ce2b184a43 245 }
karen801 0:79ce2b184a43 246
karen801 0:79ce2b184a43 247 /* determine security */
karen801 0:79ce2b184a43 248 {
karen801 0:79ce2b184a43 249 char buffer[10];
karen801 0:79ce2b184a43 250
karen801 0:79ce2b184a43 251 if(!(sscanf(rest, "%s%*[\x20]", (char*)&buffer) > 0)) { // '\0x20' == <space>
karen801 0:79ce2b184a43 252 return true;
karen801 0:79ce2b184a43 253 } else if(strncmp("EP", buffer, 10) == 0) {
karen801 0:79ce2b184a43 254 ap->security = NSAPI_SECURITY_WEP;
karen801 0:79ce2b184a43 255 return true;
karen801 0:79ce2b184a43 256 } else if(strncmp("PA2", buffer, 10) == 0) {
karen801 0:79ce2b184a43 257 ap->security = NSAPI_SECURITY_WPA2;
karen801 0:79ce2b184a43 258 return true;
karen801 0:79ce2b184a43 259 } else if(strncmp("PA", buffer, 10) != 0) {
karen801 0:79ce2b184a43 260 return true;
karen801 0:79ce2b184a43 261 }
karen801 0:79ce2b184a43 262
karen801 0:79ce2b184a43 263 /* got a "WPA", check for "WPA2" */
karen801 0:79ce2b184a43 264 rest += strlen(buffer);
karen801 0:79ce2b184a43 265 value = *rest++;
karen801 0:79ce2b184a43 266 if(value == '\0') { // no further protocol
karen801 0:79ce2b184a43 267 ap->security = NSAPI_SECURITY_WPA;
karen801 0:79ce2b184a43 268 return true;
karen801 0:79ce2b184a43 269 } else { // assume "WPA2"
karen801 0:79ce2b184a43 270 ap->security = NSAPI_SECURITY_WPA_WPA2;
karen801 0:79ce2b184a43 271 return true;
karen801 0:79ce2b184a43 272 }
karen801 0:79ce2b184a43 273 }
karen801 0:79ce2b184a43 274 } else { // ret == false
karen801 0:79ce2b184a43 275 debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__);
karen801 0:79ce2b184a43 276 empty_rx_buffer();
karen801 0:79ce2b184a43 277 }
karen801 0:79ce2b184a43 278
karen801 0:79ce2b184a43 279 return ret;
karen801 0:79ce2b184a43 280 }
karen801 0:79ce2b184a43 281
karen801 0:79ce2b184a43 282 nsapi_size_or_error_t SPWFSA04::scan(WiFiAccessPoint *res, unsigned limit)
karen801 0:79ce2b184a43 283 {
karen801 0:79ce2b184a43 284 unsigned int cnt = 0, found;
karen801 0:79ce2b184a43 285 nsapi_wifi_ap_t ap;
karen801 0:79ce2b184a43 286
karen801 0:79ce2b184a43 287 if (!_parser.send("AT+S.SCAN=s,")) {
karen801 0:79ce2b184a43 288 return NSAPI_ERROR_DEVICE_ERROR;
karen801 0:79ce2b184a43 289 }
karen801 0:79ce2b184a43 290
karen801 0:79ce2b184a43 291 if(!(_parser.recv("AT-S.Parsing Networks:%u\n", &found) && _recv_delim_lf())) {
karen801 0:79ce2b184a43 292 debug_if(_dbg_on, "SPWF> error start network scanning\r\n");
karen801 0:79ce2b184a43 293 empty_rx_buffer();
karen801 0:79ce2b184a43 294 return NSAPI_ERROR_DEVICE_ERROR;
karen801 0:79ce2b184a43 295 }
karen801 0:79ce2b184a43 296
karen801 0:79ce2b184a43 297 debug_if(_dbg_on, "AT^ AT-S.Parsing Networks:%u\r\n", found);
karen801 0:79ce2b184a43 298
karen801 0:79ce2b184a43 299 if(found > 0) {
karen801 0:79ce2b184a43 300 while (_recv_ap(&ap)) {
karen801 0:79ce2b184a43 301 if (cnt < limit) {
karen801 0:79ce2b184a43 302 res[cnt] = WiFiAccessPoint(ap);
karen801 0:79ce2b184a43 303 }
karen801 0:79ce2b184a43 304
karen801 0:79ce2b184a43 305 if (!((limit != 0) && ((cnt + 1) > limit))) {
karen801 0:79ce2b184a43 306 cnt++;
karen801 0:79ce2b184a43 307 }
karen801 0:79ce2b184a43 308 }
karen801 0:79ce2b184a43 309 } else {
karen801 0:79ce2b184a43 310 if(!_recv_ok()) {
karen801 0:79ce2b184a43 311 empty_rx_buffer();
karen801 0:79ce2b184a43 312 }
karen801 0:79ce2b184a43 313 }
karen801 0:79ce2b184a43 314
karen801 0:79ce2b184a43 315 return cnt;
karen801 0:79ce2b184a43 316 }
karen801 0:79ce2b184a43 317
karen801 0:79ce2b184a43 318 #endif // MBED_CONF_IDW0XX1_EXPANSION_BOARD