David Smart / WiflyInterface Featured

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 }