private fork

Fork of GSwifiInterface by gs fan

Revision:
5:78943b3945b5
Parent:
4:0bcec6272784
Child:
7:f94c59d0c735
Child:
8:64184a968e3b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi/GSwifi.cpp	Sun Jan 27 14:31:19 2013 +0000
@@ -0,0 +1,669 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/* Copyright (C) 2013 gsfan, MIT License
+ *  port to the GainSpan Wi-FI module GS1011
+ */
+
+#include "mbed.h"
+#include "GSwifi.h"
+#include <string>
+#include <algorithm>
+
+GSwifi * GSwifi::_inst;
+
+GSwifi::GSwifi(   PinName tx, PinName rx, PinName cts, PinName rts, PinName reset, const char * ssid, const char * phrase, Security sec):
+    _uart(tx, rx), _reset(reset), _buf_gswifi(CFG_CMD_SIZE)
+{
+    memset(&_state, 0, sizeof(_state));
+    memset(&_con, 0, sizeof(_con));
+    _state.sec = sec;
+    _state.acid = -1;
+
+    // change all ' ' in '$' in the ssid and the passphrase
+    strncpy(_ssid, ssid, sizeof(_ssid));
+    for (int i = 0; i < strlen(ssid); i++) {
+        if (_ssid[i] == ' ')
+            _ssid[i] = '$';
+    }
+    strncpy(_phrase, phrase, sizeof(_phrase));
+    for (int i = 0; i < strlen(phrase); i++) {
+        if (_phrase[i] == ' ')
+            _phrase[i] = '$';
+    }
+
+    _inst = this;
+    _state.mode = MODE_COMMAND;
+
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+    if (cts == p12) { // CTS input (P0_17)
+        LPC_UART1->MCR |= (1<<7); // CTSEN
+        LPC_PINCON->PINSEL1 &= ~(3 << 2);
+        LPC_PINCON->PINSEL1 |= (1 << 2); // UART CTS
+    }
+    if (rts == P0_22) { // RTS output (P0_22)
+        LPC_UART1->MCR |= (1<<6); // RTSEN
+        LPC_PINCON->PINSEL1 &= ~(3 << 12);
+        LPC_PINCON->PINSEL1 |= (1 << 12); // UART RTS
+        _rts = true;
+    } else {
+        _rts = false;
+    }
+#elif defined(TARGET_LPC11U24)
+    if (cts == p21) { // CTS input (P0_7)
+        LPC_USART->MCR |= (1<<7); // CTSEN
+        LPC_IOCON->PIO0_7 &= ~0x07;
+        LPC_IOCON->PIO0_7 |= 0x01; // UART CTS
+    }
+    if (rts == p22) { // RTS output (P0_17)
+        LPC_USART->MCR |= (1<<6); // RTSEN
+        LPC_IOCON->PIO0_17 &= ~0x07;
+        LPC_IOCON->PIO0_17 |= 0x01; // UART RTS
+        _rts = true;
+    } else {
+        _rts = false;
+    }
+#endif
+    _uart.baud(CFG_UART_BAUD);
+    _uart.attach(this, &GSwifi::handler_rx);
+    this->reset();
+}
+
+bool GSwifi::join()
+{
+    bool r;
+    char cmd[CFG_CMD_SIZE];
+
+    send("\r\n", 2);
+    if (sendCommand("ATE0") == false) return -1;
+    if (_rts) {
+        sendCommand("AT&K0");
+        sendCommand("AT&R1");
+    }
+
+    disconnect();
+    sendCommand("AT+WREGDOMAIN=" CFG_WREGDOMAIN);
+    sendCommand("AT+BDATA=1");
+    sendCommand("AT+WM=0"); // infrastructure
+    wait_ms(100);
+    if (_state.dhcp && _state.sec != SEC_WPS_BUTTON) {
+        sendCommand("AT+NDHCP=1");
+    } else {
+        sendCommand("AT+NDHCP=0");
+    }
+
+    switch (_state.sec) {
+    case SEC_NONE:
+    case SEC_OPEN:
+    case SEC_WEP:
+        sprintf(cmd, "AT+WAUTH=%d", _ssid);
+        sendCommand(cmd);
+        if (_state.sec != SEC_NONE) {
+            sprintf(cmd, "AT+WWEP1=%s", _phrase);
+            sendCommand(cmd);
+            wait_ms(100);
+        }
+        sprintf(cmd, "AT+WA=%s", _ssid);
+        for (int i= 0; i < MAX_TRY_JOIN; i++) {
+            r = sendCommand(cmd, RES_DHCP, CFG_TIMEOUT2);
+            if (r) break;
+        }
+        break;
+    case SEC_WPA_PSK:
+    case SEC_WPA2_PSK:
+        sendCommand("AT+WAUTH=0");
+        sprintf(cmd, "AT+WPAPSK=%s,%s", _ssid, _phrase);
+        sendCommand(cmd, RES_NORMAL, CFG_TIMEOUT2);
+        wait_ms(100);
+        sprintf(cmd, "AT+WA=%s", _ssid);
+        for (int i= 0; i < MAX_TRY_JOIN; i++) {
+            r = sendCommand(cmd, RES_DHCP, CFG_TIMEOUT2);
+            if (r) break;
+        }
+        break;
+    case SEC_WPS_BUTTON:
+        sendCommand("AT+WAUTH=0");
+        for (int i= 0; i < MAX_TRY_JOIN; i++) {
+            r = sendCommand("AT+WWPS=1", RES_WPS, CFG_TIMEOUT2);
+            if (r) break;
+        }
+        if (r && _state.dhcp) {
+            r = sendCommand("AT+NDHCP=1", RES_DHCP, CFG_TIMEOUT2);
+        }
+        break;
+    default:
+        DBG("Can't use security\r\n");
+        r = false;
+        break;
+    }
+
+    if (r) {
+        if (!_state.dhcp) {
+            sprintf(cmd, "AT+NSET=%s,%s,%s", _ip, _netmask, _gateway);
+            sendCommand(cmd);
+            sprintf(cmd, "AT+DNSSET=%s", _nameserver);
+            sendCommand(cmd);
+        }
+
+        _state.associated = true;
+        INFO("ssid: %s\r\nphrase: %s\r\nsecurity: %d", _ssid, _phrase, _state.sec);
+    }
+
+    return r;
+}
+
+
+bool GSwifi::gethostbyname(const char * host, char * ip)
+{
+    int i, flg = 0;
+    char cmd[CFG_CMD_SIZE];
+
+    for (i = 0; i < strlen(host); i ++) {
+        if ((host[i] < '0' || host[i] > '9') && host[i] != '.') {
+            flg = 1;
+            break;
+        }
+    }
+    if (!flg) {
+        strncpy(ip, host, 16);
+        return true;
+    }
+
+    sprintf(cmd, "AT+DNSLOOKUP=%s", host);
+    if (sendCommand(cmd, RES_DNSLOOKUP)) {
+        strncpy(ip, _resolv, 16);
+        return true;
+    }
+
+    return false; 
+}
+
+
+void GSwifi::flush(int cid)
+{
+    if (cid < 0) {
+        return _buf_gswifi.flush();
+    } else {
+        if (_con[cid].buf == NULL)
+            _con[cid].buf = new CircBuffer<char>(CFG_DATA_SIZE);
+        return _con[cid].buf->flush();
+    }
+}
+
+bool GSwifi::sendCommand(const char * cmd, Response res, int timeout)
+{
+    DBG("command: %s",cmd);
+
+    send(cmd, strlen(cmd));
+    if (send("\r\n", 2, res, timeout) == -1) {
+        ERR("sendCommand: cannot %s", cmd);
+        return false;
+    }
+    return true;
+}
+
+
+bool GSwifi::disconnect()
+{
+    // if already disconnected, return
+    if (!_state.associated)
+        return true;
+
+    for (int i = 0; i < 16; i ++) {
+        if (_con[i].buf)
+            _con[i].buf->flush();
+    }
+    sendCommand("AT+NCLOSEALL");
+    sendCommand("AT+WD");
+    sendCommand("AT+NDHCP=0");
+    wait_ms(100);
+
+    _state.associated = false;
+    return true;
+
+}
+
+bool GSwifi::is_connected(int cid)
+{
+    return _con[cid].connected;
+}
+
+
+void GSwifi::reset()
+{
+    _reset = 0;
+    wait_ms(100);
+    _reset = 1;
+    wait_ms(500);
+}
+
+
+int GSwifi::putc(char c)
+{
+    while (!_uart.writeable());
+    return _uart.putc(c);
+}
+
+
+int GSwifi::readable(int cid)
+{
+    if (cid < 0) {
+        return _buf_gswifi.available();
+    } else {
+        return _con[cid].buf->available();
+    }
+}
+
+int GSwifi::writeable()
+{
+    return _uart.writeable();
+}
+
+char GSwifi::getc(int cid)
+{
+    char c;
+    if (cid < 0) {
+        while (!_buf_gswifi.available());
+        _buf_gswifi.dequeue(&c);
+    } else {
+        while (!_con[cid].buf->available());
+        _con[cid].buf->dequeue(&c);
+    }
+    return c;
+}
+
+void GSwifi::handler_rx(void)
+{
+    static int len, flg;
+    static char tmp[20];
+    char dat;
+
+    while (_uart.readable()) {
+
+    dat = _uart.getc();
+
+    switch (_state.mode) {
+    case MODE_COMMAND: // command responce
+        if (_state.escape) {
+            // esc
+            switch (dat) {
+            case 'O':
+                DBG("ok");
+                _state.retres = RES_OK;
+                _state.cmdres = RES_OK;
+                break;
+            case 'F':
+                DBG("failure");
+                _state.retres = RES_FAILURE;
+                _state.cmdres = RES_FAILURE;
+                break;
+            case 'Z':
+            case 'H':
+                DBG("GSMODE_DATA_RX");
+                _state.mode = MODE_DATA_RX;
+                flg = 0;
+                break;
+            case 'y':
+                DBG("GSMODE_DATA_RXUDP");
+                _state.mode = MODE_DATA_RXUDP;
+                flg = 0;
+                break;
+            case 'S':
+            case 'u':
+            default:
+                WARN("unknown [ESC] %02x", dat);
+                break;
+            }
+            _state.escape = 0;
+        } else {
+            if (dat == 0x1b) {
+                _state.escape = 1;
+            } else
+            if (dat == '\n') {
+                parseResponse();
+            } else
+            if (dat != '\r') {
+                // command
+                _buf_gswifi.queue(dat);
+            }
+        }
+        break;
+
+    case MODE_DATA_RX:
+    case MODE_DATA_RXUDP:
+        switch (flg) {
+        case 0:
+            // CID
+            _state.cid = x2i(dat);
+            flg ++;
+            if (_state.mode == MODE_DATA_RX) {
+                flg = 3;
+            }
+            len = 0;
+            break;
+        case 1:
+            // IP (UDP)
+            if ((dat >= '0' && dat <= '9') || dat == '.') {
+                tmp[len] = dat;    
+                len ++;
+            } else
+            if (len < sizeof(tmp) - 1) {
+                tmp[len] = 0;
+                strncpy(_con[_state.cid].ip, tmp, sizeof(_con[_state.cid].ip));
+                flg ++;
+                len = 0;
+            }
+            break;
+        case 2:
+            // port
+            if (dat >= '0' && dat <= '9') {
+                tmp[len] = dat;            
+                len ++;        
+            } else {
+                tmp[len] = 0;
+                _con[_state.cid].port = atoi(tmp);
+                flg ++;
+                len = 0;
+            }
+            break;
+        case 3:
+            // length
+            tmp[len] = dat;            
+            len ++;        
+            if (len >= 4) {
+                tmp[len] = 0;
+                len = atoi(tmp);
+                flg ++;
+            }
+            break;
+        case 4:
+            // data
+            if (_con[_state.cid].buf != NULL) {
+                _con[_state.cid].buf->queue(dat);
+            }
+            len --;
+
+            if (len == 0 || _con[_state.cid].buf->isFull()) {
+                DBG("recv binary %d", _state.cid);
+                _state.escape = 0;
+                _state.mode = MODE_COMMAND;
+                // recv interrupt
+/*
+                if (_gs_sock[_cid].protocol == GSPROT_HTTPGET && _gs_sock[_cid].onGsReceive != NULL) {
+                    _gs_sock[_cid].onGsReceive(_cid, _gs_sock[_cid].data->use());
+                    _gs_sock[_cid].received = 0;
+                }
+*/
+            }
+            break;
+        }
+        
+        break;
+    }
+
+    } // while
+}
+
+void GSwifi::parseResponse () {
+    int i;
+    char buf[CFG_CMD_SIZE];
+
+    while (_buf_gswifi.available()) {
+        i = 0;
+        while (_buf_gswifi.available() && i < sizeof(buf)) {
+            _buf_gswifi.dequeue(&buf[i]);
+            if (buf[i] == '\n') {
+                break;
+            }
+            i ++;
+        }
+        if (i == 0) continue;
+        buf[i] = 0;
+        DBG("parseResponse: %s", buf);
+
+        if (_state.cmdres != RES_NULL) {
+            parseCmdResponse(buf);
+            DBG("parseCmdResponse %d %d", _state.cmdres, _state.retres);
+        }
+
+        if (strncmp(buf, "CONNECT ", 8) == 0 && buf[8] >= '0' && buf[8] <= 'F' && buf[9] != 0) {
+            int cid;
+            char *tmp, *tmp2;
+            cid = x2i(buf[8]);
+            _state.acid = x2i(buf[10]);
+            tmp = buf + 12;
+            tmp2 = strstr(tmp, " ");
+            tmp2[0] = 0;
+            strncpy(_con[_state.acid].ip, tmp, sizeof(_con[_state.acid].ip));
+            tmp = tmp2 + 1;
+            _con[_state.acid].port = atoi(tmp);
+            _con[_state.acid].parent = cid;
+            if (_con[_state.acid].buf == NULL)
+                _con[_state.acid].buf = new CircBuffer<char>(CFG_DATA_SIZE);
+            _con[_state.acid].buf->flush();
+            _con[_state.acid].connected = true;
+            DBG("connect %d -> %d", cid, _state.acid);
+        } else
+        if (strncmp(buf, "DISCONNECT ", 11) == 0) {
+            int cid;
+            cid = x2i(buf[11]);
+            DBG("disconnect %d", cid);
+            _con[cid].connected = false;
+        } else
+        if (strncmp(buf, "DISASSOCIATED", 13) == 0 ||
+          strncmp(buf, "Disassociated", 13) == 0 ||
+          strncmp(buf, "Disassociation Event", 20) == 0 ||
+          strncmp(buf, "UnExpected Warm Boot", 20) == 0) {
+            _state.associated = false;
+            for (i = 0; i < 16; i ++) {
+                _con[i].connected = false;
+            }
+        } else
+        if (strncmp(buf, "Out of StandBy-Timer", 20) == 0 ||
+          strncmp(buf, "Out of StandBy-Alarm", 20) == 0) {
+            _state.status = STAT_WAKEUP;
+        } else 
+        if (strncmp(buf, "Out of Deep Sleep", 17) == 0 ) {
+            _state.status = STAT_READY;
+        } else 
+        if (strncmp(buf, "Out of", 6) == 0) {
+        }
+    }
+}
+
+void GSwifi::parseCmdResponse (char *buf) {
+
+        if (strcmp(buf, "OK") == 0) {
+            _state.retres = RES_OK;
+        } else
+        if (strncmp(buf, "ERROR", 5) == 0) {
+            _state.retres = RES_FAILURE;
+        }
+
+        switch(_state.cmdres) {
+        case RES_NORMAL:
+            _state.cmdres = RES_OK;
+            break;
+        case RES_WPS:
+            if (_state.n == 0 && strncmp(buf, "SSID", 4) == 0) {
+                _state.n ++;
+            } else
+            if (_state.n == 1 && strncmp(buf, "CHANNEL", 7) == 0) {
+                _state.n ++;
+            } else
+            if (_state.n == 2 && strncmp(buf, "PASSPHRASE", 10) == 0) {
+                _state.n ++;
+                _state.cmdres = RES_OK;
+            }
+            break;
+        case RES_CONNECT:
+            if (strncmp(buf, "CONNECT ", 8) == 0 && buf[9] == 0) {
+                _state.cid = x2i(buf[8]);
+                _state.cmdres = RES_OK;
+                if (_con[_state.cid].buf == NULL)
+                    _con[_state.cid].buf = new CircBuffer<char>(CFG_DATA_SIZE);
+                _con[_state.cid].buf->flush();
+                _con[_state.cid].connected = true;
+                INFO("connect: %d", _state.cid);
+            }
+            break;
+        case RES_DHCP:
+            if (_state.n == 0 && strstr(buf, "SubNet") && strstr(buf, "Gateway")) {
+                _state.n ++;
+            } else
+            if (_state.n == 1) {
+                char *tmp, *tmp2;
+                tmp = buf + 1;
+                tmp2 = strstr(tmp, ":");
+                tmp2[0] = 0;
+                strncpy(_ip, tmp, sizeof(_ip));
+                tmp = tmp2 + 2;
+                tmp2 = strstr(tmp, ":");
+                tmp2[0] = 0;
+                strncpy(_netmask, tmp, sizeof(_netmask));
+                tmp = tmp2 + 2;
+                strncpy(_gateway, tmp, sizeof(_gateway));
+                _state.n ++;
+                _state.cmdres = RES_OK;
+                INFO("ip: %s\r\nnetmask: %s\r\ngateway: %s", _ip, _netmask, _gateway);
+            }
+            break;
+        case RES_MACADDRESS:
+            if (buf[2] == ':' && buf[5] == ':') {
+/*
+                int mac1, mac2, mac3, mac4, mac5, mac6;
+                sscanf(buf, "%x:%x:%x:%x:%x:%x", &mac1, &mac2, &mac3, &mac4, &mac5, &mac6);
+                _mac[0] = mac1;
+                _mac[1] = mac2;
+                _mac[2] = mac3;
+                _mac[3] = mac4;
+                _mac[4] = mac5;
+                _mac[5] = mac6;
+*/
+                _state.cmdres = RES_OK;
+            }
+            break;
+        case RES_DNSLOOKUP:
+            if (strncmp(buf, "IP:", 3) == 0) {
+                strncpy(_resolv, &buf[3], sizeof(_resolv));
+                _state.cmdres = RES_OK;
+                INFO("resolv: %s", _resolv);
+            }
+            break;
+        case RES_HTTP:
+            if (buf[0] >= '0' && buf[0] <= 'F') {
+                _state.cid = x2i(buf[0]);
+                _state.cmdres = RES_OK;
+                INFO("http: %d", _state.cid);
+            }
+            break;
+        case RES_RSSI:
+            if (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9')) {
+                _rssi = atoi(buf);
+                _state.cmdres = RES_OK;
+                INFO("rssi: %d", _rssi);
+            }
+            break;
+        case RES_TIME:
+            if (buf[0] >= '0' && buf[0] <= '9') {
+                int year, month, day, hour, min, sec;
+                struct tm t;
+                sscanf(buf, "%d/%d/%d,%d:%d:%d", &day, &month, &year, &hour, &min, &sec);
+                t.tm_sec = sec;
+                t.tm_min = min;
+                t.tm_hour = hour;
+                t.tm_mday = day;
+                t.tm_mon = month - 1;
+                t.tm_year = year - 1900;   
+                _time = mktime(&t);            
+                _state.cmdres = RES_OK;
+            }
+            break;
+        }
+}
+
+int GSwifi::send(const char * str, int len, Response res, int timeout)
+{
+    Timer tmr;
+    int result = 0;
+
+    if (res == RES_NULL) {
+        for (int i = 0; i < len; i++)
+            result = (putc(str[i]) == str[i]) ? result + 1 : result;
+    } else {
+        _state.cmdres = res;
+        _state.retres = RES_NULL;
+
+        tmr.start();
+        for (int i = 0; i < len; i++)
+            result = (putc(str[i]) == str[i]) ? result + 1 : result;
+
+        while (1) {
+            if (tmr.read_ms() > timeout || _state.retres == RES_FAILURE) {
+                result = -1;
+                break;
+            }
+            if (_state.retres == RES_OK && _state.cmdres != res) break;
+        }
+    }
+
+    _state.cmdres = RES_NULL;
+    _state.retres = RES_NULL;
+    return result;
+}
+
+bool GSwifi::readRemote(int cid, char **ip, int *port) {
+    *ip = _con[cid].ip;
+    *port = _con[cid].port;
+    return true;
+}
+
+int GSwifi::readCID () {
+    return _state.cid;
+}
+
+int GSwifi::readACID () {
+    int r = -1;
+    if (_state.acid >= 0 && _con[_state.acid].connected == true) {
+        r = _state.acid;
+        _state.acid = -1;
+    }
+    return r;
+}
+
+int GSwifi::x2i (char c) {
+    if (c >= '0' && c <= '9') {
+        return c - '0';
+    } else
+    if (c >= 'A' && c <= 'F') {
+        return c - 'A' + 10;
+    } else
+    if (c >= 'a' && c <= 'f') {
+        return c - 'a' + 10;
+    }
+    return 0;
+}
+
+char GSwifi::i2x (int i) {
+    if (i >= 0 && i <= 9) {
+        return i + '0';
+    } else
+    if (i >= 10 && i <= 15) {
+        return i - 10 + 'A';
+    }
+    return 0;
+}