MODIFIED from mbed official WiflyInterface (interface for Roving Networks Wifly modules). Numerous performance and reliability improvements (see the detailed documentation). Also, tracking changes in mbed official version to retain functional parity.

Dependents:   Smart-WiFly-WebServer PUB_WiflyInterface_Demo

Fork of WiflyInterface by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Wifly.cpp Source File

Wifly.cpp

00001 /* Copyright (C) 2012 mbed.org, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 
00019 #include "mbed.h"
00020 #include "Wifly.h"
00021 #include <string>
00022 #include <algorithm>
00023 #include <ctype.h>
00024 
00025 // Defined to disable remote configuration via telnet which increases security of this device.
00026 // Available in Wifly module SW 2.27 and higher. If you want to retain remote telnet, undefine
00027 // or comment this.
00028 #define INCREASE_SECURITY
00029 
00030 
00031 //#define DEBUG "WiFi"      //Debug is disabled by default
00032 
00033 // How to use this debug macro
00034 //
00035 // ...
00036 // INFO("Stuff to show %d", var); // new-line is automatically appended
00037 // [I myfile  23] Stuff to show 23\r\n
00038 //
00039 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
00040 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00041 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00042 #define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00043 #else
00044 #define INFO(x, ...)
00045 #define WARN(x, ...)
00046 #define ERR(x, ...)
00047 #endif
00048 
00049 
00050 #define MAX_TRY_JOIN 3
00051 
00052 Wifly * Wifly::inst;
00053 
00054 Wifly::Wifly(   PinName tx, PinName rx, PinName _reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec):
00055     wifi(tx, rx), reset_pin(_reset), tcp_status(tcp_status), baudrate(9600), buf_wifly(256)
00056 {
00057     INFO("Wifly constructor");
00058     SetSecurity(ssid, phrase, sec);
00059     inst = this;
00060     attach_rx(false);
00061     state.cmd_mode = false;
00062     wiflyVersionString = NULL;
00063     INFO("  const. exit");
00064 }
00065 
00066 Wifly::~Wifly()
00067 {
00068     INFO("~Wifly()");
00069     if (wiflyVersionString) {
00070         free(wiflyVersionString);
00071         wiflyVersionString = NULL;
00072     }
00073 }
00074 
00075 
00076 void Wifly::SetSecurity(const char * ssid, const char * phrase, Security sec)
00077 {
00078     memset(&state, 0, sizeof(state));
00079     state.sec = sec;
00080     FixPhrase(this->ssid, sizeof(this->ssid), ssid);
00081     FixPhrase(this->phrase, sizeof(this->phrase), phrase);
00082 }
00083 
00084 
00085 bool Wifly::configure()
00086 {
00087     char cmd[80];   // room for command with maximum ssid or passphrase
00088 
00089     INFO("configure");
00090     for (int i= 0; i < MAX_TRY_JOIN; i++) {
00091 
00092         // no auto join
00093         if (!sendCommand("set w j 0\r", "AOK"))
00094             continue;
00095 
00096         // no echo
00097         if (!sendCommand("set u m 1\r", "AOK"))
00098             continue;
00099 
00100         // set comm time to flush (ms)
00101         if (!sendCommand("set c t 30\r", "AOK"))
00102             continue;
00103 
00104         // set comm size to auto-send
00105         if (!sendCommand("set c s 1420\r", "AOK"))
00106             continue;
00107 
00108         // set comm idle time to auto-close (sec)
00109         //if (!sendCommand("set c i 5\r", "AOK"))
00110         //    continue;
00111 
00112         // red led on when tcp connection active
00113         if (!sendCommand("set s i 0x40\r", "AOK"))
00114             continue;
00115 
00116         // no hello string sent to the tcp client
00117         if (!sendCommand("set c r 0\r", "AOK"))
00118             continue;
00119 
00120         // tcp protocol
00121         if (!sendCommand("set i p 2\r", "AOK"))
00122             continue;
00123 
00124         // tcp retry (retry enabled, Nagle alg, retain link)
00125         if (!sendCommand("set i f 0x7\r", "AOK"))
00126             continue;
00127 
00128 #ifdef INCREASE_SECURITY
00129         // tcp-mode 0x10 = disable remote configuration
00130         // only in SW 2.27 and higher (see 2.3.39)
00131         if ((swVersion >= 2.27) && (!sendCommand("set i t 0x10\r", "AOK")))
00132             continue;
00133 #endif
00134 
00135         // set dns server
00136         if (!sendCommand("set d n rn.microchip.com\r", "AOK"))
00137             continue;
00138 
00139         //dhcp
00140         sprintf(cmd, "set i d %d\r", (state.dhcp) ? 1 : 0);
00141         if (!sendCommand(cmd, "AOK"))
00142             continue;
00143 
00144         // ssid
00145         sprintf(cmd, "set w s %s\r", ssid);
00146         if (!sendCommand(cmd, "AOK"))
00147             continue;
00148 
00149         //auth
00150         sprintf(cmd, "set w a %d\r", state.sec);
00151         if (!sendCommand(cmd, "AOK"))
00152             continue;
00153 
00154         // if no dhcp, set ip, netmask and gateway
00155         if (!state.dhcp) {
00156             INFO("not dhcp");
00157             sprintf(cmd, "set i a %s\r", ip);
00158             if (!sendCommand(cmd, "AOK"))
00159                 continue;
00160 
00161             sprintf(cmd, "set i n %s\r", netmask);
00162             if (!sendCommand(cmd, "AOK"))
00163                 continue;
00164 
00165             sprintf(cmd, "set i g %s\r", gateway);
00166             if (!sendCommand(cmd, "AOK"))
00167                 continue;
00168         }
00169 
00170         //key step
00171         cmd[0] = '\0';
00172         switch (state.sec) {
00173             case WPE_64:        // google searching suggests this is a typo and should be WEP_64
00174             case WEP_128:
00175                 sprintf(cmd, "set w k %s\r", phrase);
00176                 break;
00177             case WPA1:
00178             case WPA_MIXED: // alias WPA
00179             case WPA2_PSK:
00180                 sprintf(cmd, "set w p %s\r", phrase);
00181                 break;
00182             case ADHOC:
00183             case NONE:
00184             default:
00185                 break;
00186         }
00187         if (cmd[0] && !sendCommand(cmd, "AOK"))
00188             continue;
00189 
00190         if (!sendCommand("save\r", "Stor", NULL, 5000))
00191             continue;
00192 
00193         exit();
00194         return true;
00195     }
00196     return false;
00197 }
00198 
00199 
00200 bool Wifly::join()
00201 {
00202     INFO("join");
00203     //join the network (10s timeout)
00204     if (state.dhcp && swVersion < 4.75) {
00205         if (!sendCommand("join\r", "DHCP=ON", NULL, 10000))     // possibly older SW did this
00206             return false;
00207     } else {
00208         if (!sendCommand("join\r", "Associated!", NULL, 10000))  // This for most uses
00209             return false;
00210     }
00211     INFO("  join exit");
00212     exit();
00213     INFO("  join end.");
00214     state.associated = true;
00215     return true;
00216 }
00217 
00218 
00219 bool Wifly::setProtocol(Protocol p)
00220 {
00221     // use udp auto pairing
00222     char cmd[20];
00223     sprintf(cmd, "set i p %d\r", p);
00224     if (!sendCommand(cmd, "AOK"))
00225         return false;
00226 
00227     switch(p) {
00228         case TCP:
00229             // set ip flags: tcp retry enabled
00230             if (!sendCommand("set i f 0x07\r", "AOK"))
00231                 return false;
00232             break;
00233         case UDP:
00234             // set ip flags: udp auto pairing enabled
00235             if (!sendCommand("set i h 0.0.0.0\r", "AOK"))
00236                 return false;
00237             if (!sendCommand("set i f 0x40\r", "AOK"))
00238                 return false;
00239             break;
00240     }
00241     state.proto = p;
00242     return true;
00243 }
00244 
00245 
00246 char * Wifly::getStringSecurity()
00247 {
00248     switch(state.sec) {
00249         case NONE:              // 0
00250             return "NONE";
00251         case WEP_128:           // 1
00252             return "WEP_128";
00253         case WPA1:              // 2
00254             return "WPA1";
00255         case WPA:               // 3
00256             return "WPA";
00257         case WPA2_PSK:          // 4
00258             return "WPA2_PSK";
00259         case ADHOC:             // 6
00260             return "ADHOC";
00261         case WPE_64:            // 8
00262             return "WPE_64";
00263         default:                // ?
00264             return "UNKNOWN";
00265     }
00266 }
00267 
00268 
00269 bool Wifly::connect(const char * host, int port)
00270 {
00271     char rcv[20];
00272     char cmd[20];
00273 
00274     // try to open
00275     sprintf(cmd, "open %s %d\r", host, port);
00276     if (sendCommand(cmd, "OPEN", NULL, 10000)) {
00277         setConnectionState(true);
00278         exit();
00279         return true;
00280     }
00281 
00282     // if failed, retry and parse the response
00283     if (sendCommand(cmd, NULL, rcv, 5000)) {
00284         if (strstr(rcv, "OPEN") == NULL) {
00285             if (strstr(rcv, "Connected") != NULL) {
00286                 if (!sendCommand("close\r", "CLOS"))
00287                     return false;
00288                 if (!sendCommand(cmd, "OPEN", NULL, 10000))
00289                     return false;
00290             } else {
00291                 return false;
00292             }
00293         }
00294     } else {
00295         return false;
00296     }
00297 
00298     setConnectionState(true);
00299     exit();
00300     return true;
00301 }
00302 
00303 
00304 bool Wifly::gethostbyname(const char * host, char * ip)
00305 {
00306     string h = host;
00307     char cmd[30], rcv[100];
00308     int l = 0;
00309     char * point;
00310     int nb_digits = 0;
00311 
00312     // no dns needed
00313     int pos = h.find(".");
00314     if (pos != string::npos) {
00315         string sub = h.substr(0, h.find("."));
00316         nb_digits = atoi(sub.c_str());
00317     }
00318     //printf("substrL %s\r\n", sub.c_str());
00319     if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) {
00320         strcpy(ip, host);
00321     }
00322     // dns needed
00323     else {
00324         nb_digits = 0;
00325         sprintf(cmd, "lookup %s\r", host);
00326         if (!sendCommand(cmd, NULL, rcv))
00327             return false;
00328 
00329         // look for the ip address
00330         char * begin = strstr(rcv, "=") + 1;
00331         for (int i = 0; i < 3; i++) {
00332             point = strstr(begin + l, ".");
00333             INFO("str: %s", begin + l);
00334             l += point - (begin + l) + 1;
00335         }
00336         INFO("str: %s", begin + l);
00337         while(*(begin + l + nb_digits) >= '0' && *(begin + l + nb_digits) <= '9') {
00338             INFO("digit: %c", *(begin + l + nb_digits));
00339             nb_digits++;
00340         }
00341         memcpy(ip, begin, l + nb_digits);
00342         ip[l+nb_digits] = 0;
00343         INFO("ip from dns: %s", ip);
00344     }
00345     return true;
00346 }
00347 
00348 
00349 void Wifly::flush()
00350 {
00351 #if 0 and defined(DEBUG)
00352     char chatter[500];
00353     int count = 0;
00354     char c;
00355 
00356     while (buf_wifly.available()) {
00357         buf_wifly.dequeue(&c);
00358         chatter[count++] = c;
00359     }
00360     chatter[count] = '\0';
00361     if (count)
00362         DBG("Wifly::flush {%s}", chatter);
00363 #endif
00364     buf_wifly.flush();
00365 }
00366 
00367 
00368 bool Wifly::sendCommand(const char * cmd, const char * ack, char * res, int timeout)
00369 {
00370     int tries = 1;
00371     Timer t;
00372     
00373     INFO("sendCommand");
00374     t.start();
00375     while (tries <= 3) {
00376         if (cmdMode()) {      // some influences to the wifi module sometimes kick it out
00377             if (send(cmd, strlen(cmd), ack, res, timeout) >= 0) {
00378                 INFO("  sendCommand - success");
00379                 t.stop();
00380                 INFO("  sendCommand - success in %f", t.read());
00381                 return true;
00382             }
00383         }
00384         state.cmd_mode = false;     // must not really be in cmd mode
00385         ERR("sendCommand: failure %d when sending: %s", tries, cmd);
00386         tries++;
00387     }
00388     INFO("  sendCommand - failure in %f", t.read());
00389     send("exit\r", 5, "EXIT");
00390     return false;
00391 }
00392 
00393 
00394 bool Wifly::cmdMode()
00395 {
00396     char buf[200];
00397     // if already in cmd mode, return
00398     if (state.cmd_mode) {
00399         INFO("  is cmdMode");
00400         #if 0
00401         return true;
00402         #else  // for deeper debugging
00403         // Quick verify to ensure we really are in cmd mode
00404         //flushIn(0);
00405         //INFO("  send \\r to test for cmdMode");
00406         if (send("\r", 1, ">") == 1) {
00407             //INFO("  is cmdMode");
00408             return true;
00409         } else {
00410             ERR(" failed to detect command mode");
00411             state.cmd_mode = false;
00412         }
00413         #endif
00414     } else {
00415         wait_ms(460);   // manual 1.2.1 (250 msec before and after)
00416         #if 1
00417         if (send("$$$", 3, NULL, buf, 1500)) {
00418             INFO("Resp: [%s]", buf);
00419             if ( ! strstr(buf, "CMD")) {
00420                 WARN("cannot enter cmd mode");
00421                 send("exit\r", 5, "EXIT", NULL, 100);
00422                 return false;
00423             }
00424         }
00425         #else
00426         if (send("$$$", 3, "CMD") == -1) {  // the module controls the 'after' delay
00427             ERR("cannot enter in cmd mode");
00428 
00429             return false;
00430         }
00431         #endif
00432         state.cmd_mode = true;
00433     }
00434     return true;
00435 }
00436 
00437 
00438 bool Wifly::disconnect()
00439 {
00440     // if already disconnected, return
00441     if (!state.associated)
00442         return true;
00443 
00444     if (!sendCommand("leave\r", "DeAuth"))
00445         return false;
00446     exit();
00447 
00448     state.associated = false;
00449     return true;
00450 }
00451 
00452 
00453 uint16_t Wifly::hextoi(char *p)
00454 {
00455     uint16_t res = 0;
00456     
00457     while ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')) {
00458         if (*p >= '0' && *p <= '9')
00459             res = (res * 16) + (*p - '0');
00460         else if (*p >= 'a' && *p <= 'f')
00461             res = (res * 16) + (*p - 'a' + 10);
00462         else if (*p >= 'A' && *p <= 'F')
00463             res = (res * 16) + (*p - 'A' + 10);
00464         p++;
00465     }
00466     return res;
00467 }
00468 
00469 
00470 bool Wifly::is_connected()
00471 {
00472     char buf[30];
00473     uint16_t connectionStatus = 0;
00474     bool cnxStatus = false;
00475     
00476     if (sendCommand("show connection\r", NULL, buf)) {
00477         connectionStatus = hextoi(buf);
00478         exit();
00479     }
00480     //return (tcp_status.read() ==  1) ? true : false;  // hw pin
00481     if (connectionStatus & 0x0010) { // associated
00482         cnxStatus = true;
00483     } else {
00484         state.associated = false;
00485         cnxStatus = false;
00486     }
00487     return cnxStatus;
00488 }
00489 
00490 
00491 void Wifly::reset()
00492 {
00493     reset_pin = 0;
00494     INFO("RESET ACTIVATED");
00495     wifi.baud(9600);
00496     wait_ms(400);
00497     reset_pin = 1;
00498     GatherLogonInfo();
00499     INFO("swver %3.2f, {%s}", getWiflyVersion(), getWiflyVersionString());
00500 }
00501 
00502 
00503 bool Wifly::reboot()
00504 {
00505     if (sendCommand("reboot\r", "Reboot")) {
00506         state.cmd_mode = false;
00507         wait_ms(500);
00508         wifi.baud(9600);
00509         baud(baudrate);
00510         exit();
00511         return true;
00512     } else {
00513         return false;
00514     }
00515 }
00516 
00517 
00518 bool Wifly::close()
00519 {
00520     if (!state.tcp) {
00521         return true;    // already closed
00522     }
00523     if (!sendCommand("close\r", "*CLOS*")) {
00524         return false;   // failed to close
00525     }
00526 #if 1
00527     // It appears that the close exits cmd mode
00528     // so we won't bother trying to close which
00529     // could cause it to open command mode to
00530     // send the close (which add more 0.5s delays).
00531     state.cmd_mode = false;
00532 #else
00533     flushIn();
00534     exit();
00535 #endif
00536     setConnectionState(false);
00537     return true;        // succeeded to close
00538 }
00539 
00540 
00541 int Wifly::putc(char c)
00542 {
00543     while (!wifi.writeable())
00544         ;
00545     return wifi.putc(c);
00546 }
00547 
00548 
00549 bool Wifly::exit()
00550 {
00551     INFO("exit()");
00552     if (!sendCommand("exit\r", "EXIT")) {
00553         ERR("  failed to exit.");
00554         return false;
00555     }
00556     state.cmd_mode = false;
00557     return true;
00558 }
00559 
00560 
00561 int Wifly::readable()
00562 {
00563     return buf_wifly.available();
00564 }
00565 
00566 
00567 int Wifly::writeable()
00568 {
00569     return wifi.writeable();
00570 }
00571 
00572 
00573 char Wifly::getc()
00574 {
00575     char c = 0xCC;  // avoid compiler warning of uninitialized var.
00576 
00577     while (!buf_wifly.available())
00578         ;
00579     buf_wifly.dequeue(&c);
00580     return c;
00581 }
00582 
00583 
00584 void Wifly::handler_rx(void)
00585 {
00586     //read characters
00587     while (wifi.readable())
00588         buf_wifly.queue(wifi.getc());
00589 }
00590 
00591 
00592 void Wifly::attach_rx(bool callback)
00593 {
00594     if (!callback)
00595         wifi.attach(NULL);
00596     else
00597         wifi.attach(this, &Wifly::handler_rx);
00598 }
00599 
00600 int Wifly::send(const char * str, int len, const char * ACK, char * res, int timeout)
00601 {
00602     char read;
00603     int ackIndex = 0;
00604     Timer tmr;
00605     int result = 0;
00606 
00607     INFO("will send: %s",str);
00608     attach_rx(false);
00609     flushIn();
00610 
00611     for (int i = 0; i < len; i++)
00612         result = (putc(str[i]) == str[i]) ? result + 1 : result;
00613     INFO("  data sent.");
00614     tmr.start();
00615     if (ACK) {
00616         while (1) {
00617             if (tmr.read_ms() > timeout) {
00618                 //flushIn();
00619                 WARN("timeout awaiting '%s' in (%f)", ACK, tmr.read());
00620                 attach_rx(true);
00621                 return -1;
00622             } else if (wifi.readable()) {
00623                 read = wifi.getc();
00624                 if (tolower(read) != tolower(ACK[ackIndex]))
00625                     ackIndex = 0;
00626                 if (tolower(read) == tolower(ACK[ackIndex])) {
00627                     ackIndex++;
00628                     if (ackIndex == strlen(ACK)) {
00629                         //flushIn();
00630                         break;
00631                     }
00632                 }
00633             }
00634         }
00635         INFO("check: ACK '%s' received in (%f)", ACK, tmr.read());
00636         if (strcmp(str,"exit") != 0)
00637             flushIn();
00638         attach_rx(true);
00639         return result;
00640     }
00641 
00642     // the user wants the result from the command (ACK == NULL, res != NULL)
00643     if ( res != NULL) {
00644         int i = 0;
00645         int lastStamp = tmr.read_ms();
00646         //Timer timeout;
00647         //timeout.start();
00648         //tmr.reset();
00649         while (1) {
00650             if (tmr.read_ms() > timeout) {      // crash and burn timeout...
00651                 if (i == 0) {
00652                     res = NULL;
00653                     break;
00654                 }
00655                 res[i] = '\0';
00656                 WARN(" hit user %d msec timeout: %s", timeout, res);
00657                 break;
00658             } else {
00659                 if ((tmr.read_ms() - lastStamp) > 300) { // timeout since last char suggests done...
00660                     res[i] = '\0';
00661                     //WARN("user str: %s", res);
00662                     break;
00663                 }
00664                 while (wifi.readable()) {
00665                     lastStamp = tmr.read_ms();
00666                     read = wifi.getc();
00667                     res[i++] = read;
00668                 }
00669             }
00670         }
00671         INFO("user str: %s", res);
00672     }
00673     flushIn();
00674     attach_rx(true);
00675     INFO("result: %d in (%f)", result, tmr.read())
00676     return result;
00677 }
00678 
00679 void Wifly::flushIn(int timeout_ms)
00680 {
00681     Timer tmr;
00682     int lastStamp;
00683 #if 1 and defined(DEBUG)
00684     char chatter[500];
00685     int count = 0;
00686     int c;
00687 #endif
00688 
00689     if (timeout_ms <= 0) {
00690         timeout_ms = 30; // 2 * 10000 / baudrate;  // compute minimal timeout
00691     }
00692     tmr.start();
00693     lastStamp = tmr.read_ms();
00694     while (wifi.readable() || ((tmr.read_ms() - lastStamp) < timeout_ms)) {
00695         if (wifi.readable()) {
00696 #if 1 and defined(DEBUG)
00697             c = wifi.getc();
00698             //printf("%02X ", c);
00699             if (count < sizeof(chatter)-1)  // guard overflow
00700                 chatter[count++] = c;
00701 #else
00702             wifi.getc();
00703 #endif
00704             lastStamp = tmr.read_ms();
00705         }
00706     }
00707 #if 1 and defined(DEBUG)
00708     chatter[count] = '\0';
00709     if (count && (count > 2 || chatter[0] != '\r' || chatter[1] != '\n')) {
00710         INFO("Wifly::flushIn(%d) {%s} in (%f)", count, chatter, tmr.read());
00711     } else {
00712         INFO("Wifly::flushIn() empty in [%d] (%f)", lastStamp, tmr.read());
00713     }
00714 #endif
00715 }
00716 
00717 
00718 // The ARM uart and the Wifly uart have to be in sync or we get
00719 // no meaningful response, so then have to try the possibilities.
00720 //
00721 // First try is at the currently configured ARM uart baud, if
00722 // that fails then it shifts the ARM uart baud through the probable
00723 // speeds, trying to establish contact with the Wifly module.
00724 // Once contact is demonstrated (by response to the 'ver' command),
00725 // then it sets the Wifly module and then the ARM uart.
00726 bool Wifly::baud(int _targetBaud)
00727 {
00728     // in testing, 460800 and 921600 may change the Wifly module where you can't
00729     // change it back w/o a reset. So, we won't even permit those speeds.
00730     const int baudrates[] = {2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}; //, 460800, 921600};
00731 #define BRCOUNT (sizeof(baudrates)/sizeof(baudrates[0]))
00732     char cmd[26];       // sized for "set u i 460800\r" [15+1], plus margin [4]
00733     int tryIndex = 0;
00734     bool res = false;
00735     int userIndex;
00736 
00737     sprintf(cmd, "set uart instant %d\r", _targetBaud);
00738     // set u i # should cause it to exit command mode (manual 2.3.64),
00739     // but testing indicates that it does not.
00740     for (userIndex=0; userIndex < BRCOUNT; userIndex++) {
00741         if (_targetBaud == baudrates[userIndex]) {
00742             while (tryIndex <= BRCOUNT) {
00743                 //INFO("baud() try: %d: %d", tryIndex, _targetBaud);
00744                 sendCommand(cmd); // shift Wifly to desired speed [it may not respond (see 2.3.64)]
00745                 flushIn(10);
00746                 //state.cmd_mode = false;  // see note above why this is disabled
00747                 wifi.baud(_targetBaud);     // shift the ARM uart to match
00748                 if (sendCommand("ver\r", "wifly", NULL, 125)) {  // use this to verify communications
00749                     baudrate = _targetBaud;
00750                     res = true;
00751                     break;              // success
00752                 }
00753                 // keep trying baudrates between ARM and WiFly
00754                 if (tryIndex < BRCOUNT) {
00755                     //INFO(" baud() set to %d", baudrates[tryIndex]);
00756                     wifi.baud(baudrates[tryIndex]);
00757                 }
00758                 tryIndex++;
00759             }
00760             break;  // if they selected a legitimate baud, try no others
00761         }
00762     }
00763     //INFO(" baud() result: %d", res);
00764     return res;
00765 }
00766 
00767 
00768 bool Wifly::FixPhrase(char * dst, size_t dstLen, const char * src)
00769 {
00770     if (strlen(src) < dstLen) {
00771         strcpy(dst, src);
00772         // change all ' ' to '$' in ssid or passphrase
00773         for (int i = 0; i < strlen(dst); i++) {
00774             if ((dst)[i] == ' ')
00775                 (dst)[i] = '$';
00776         }
00777         INFO("phrase: {%s} fr {%s}", dst, src);
00778         return true;
00779     } else {
00780         ERR("Source {%s} is too long for destination buffer of %d bytes", src, dstLen);
00781         return false;
00782     }
00783 }
00784 
00785 
00786 void Wifly::GatherLogonInfo()
00787 {
00788     Timer timer;
00789     char logonText[200];
00790     int i = 0;
00791     char *p;
00792 
00793     timer.start();
00794     if (wiflyVersionString) {
00795         free(wiflyVersionString);
00796         wiflyVersionString = NULL;
00797     }
00798     logonText[i] = '\0';
00799     while (timer.read_ms() < 500) {
00800         while (wifi.readable() && (i <sizeof(logonText)-1)) {
00801             logonText[i++] = wifi.getc();
00802         }
00803     }
00804     logonText[i] = '\0';
00805     p = strchr(logonText, '\r');
00806     if (p)
00807         *p = '\0';
00808     wiflyVersionString = (char *)malloc(strlen(logonText)+1);
00809     if (wiflyVersionString) {
00810         strcpy(wiflyVersionString, logonText);
00811     }
00812     p = strstr(logonText, "Ver ");          // "Ver 4.00" for ver <= 4.00
00813     if (!p) p = strstr(logonText, "Ver: "); // "Ver: 4.40" new in ver 4.40
00814     if (p) {
00815         while (*p && (*p < '0' || *p > '9'))
00816             p++;
00817         swVersion = atof(p);
00818     }
00819     WARN("swVersion: %3.2f,\r\nverString: {%s}", swVersion, wiflyVersionString);
00820 }
00821 
00822 
00823 float Wifly::getWiflyVersion()
00824 {
00825     INFO("swVersion: %3.2f", swVersion);
00826     return swVersion;
00827 }
00828 
00829 
00830 char * Wifly::getWiflyVersionString()
00831 {
00832     INFO("version string: %s", wiflyVersionString);
00833     return wiflyVersionString;
00834 }
00835 
00836 bool Wifly::SWUpdateWifly(const char * file)
00837 {
00838     bool success = false;
00839     char buf[80];
00840     
00841     INFO("\r\n\r\n\r\n");
00842     INFO("SWUpdateWifly %s", file);
00843     if (strlen(file) < (80 - 13)) {
00844         sprintf(buf, "ftp update %s\r", file);
00845         if (is_connected()) {
00846             // once connected, send command to update firmware
00847             if (sendCommand("set ftp address 0\r", "AOK")) {
00848                 if (sendCommand("set dns name rn.microchip.com\r", "AOK")) {
00849                     if (sendCommand("save\r", "Stor", NULL, 5000)) {
00850                         if (sendCommand(buf, "UPDATE OK", NULL, 50000)) {
00851                             if (sendCommand("factory RESET\r")) {
00852                                 if (reboot()) {
00853                                     success = true;
00854                                 }
00855                             }
00856                         }
00857                     }
00858                 }
00859             }
00860         }
00861     }
00862     return success;
00863 }
00864 
00865 
00866 void Wifly::setConnectionState(bool value)
00867 {
00868     state.tcp = value;
00869 }