GainSpan Wi-Fi library see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/

Dependents:   GSwifi_httpd GSwifi_websocket GSwifi_tcpclient GSwifi_tcpserver ... more

Fork of GSwifi by gs fan

GainSpan Wi-Fi library

The GS1011 is an ultra low power 802.11b wireless module from GainSpan.

see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/

/media/uploads/gsfan/gs_im_002.jpg /media/uploads/gsfan/gs1011m_2.jpg

ゲインスパン Wi-Fi モジュール ライブラリ

ゲインスパン社の低電力 Wi-Fiモジュール(無線LAN) GS1011 シリーズ用のライブラリです。

解説: http://mbed.org/users/gsfan/notebook/gainspan_wifi/

Revision:
0:2f6062c6d018
Child:
1:b127c6c5241d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GSwifi.cpp	Mon Jul 09 14:36:06 2012 +0000
@@ -0,0 +1,1101 @@
+/**
+ * Gainspan wi-fi module library for mbed
+ * Copyright (c) 2012 gsfan
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+/** @file
+ * @brief Gainspan wi-fi module library for mbed
+ * GS1011MIC, GS1011MIP, GainSpan WiFi Breakout, etc.
+ * module configuration: ATB=115200
+ */
+
+#include "dbg.h"
+#include "mbed.h"
+#include "GSwifi.h"
+
+
+GSwifi::GSwifi (PinName p_tx, PinName p_rx) : _gs(p_tx, p_rx), _buf_cmd(GS_CMD_SIZE) {
+    _connect = false;
+    _status = GSSTAT_READY;
+    _escape = 0;
+    _gs_mode = GSMODE_COMMAND;
+
+    _gs.baud(GS_BAUD);
+    _gs.attach(this, &GSwifi::isr_recv, Serial::RxIrq);
+    _rts = false;
+}
+
+GSwifi::GSwifi (PinName p_tx, PinName p_rx, PinName p_cts, PinName p_rts) : _gs(p_tx, p_rx), _buf_cmd(GS_CMD_SIZE) {
+    _connect = false;
+    _status = GSSTAT_READY;
+    _escape = 0;
+    _gs_mode = GSMODE_COMMAND;
+
+    _gs.baud(GS_BAUD);
+    _gs.attach(this, &GSwifi::isr_recv, Serial::RxIrq);
+
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+    if (p_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 (p_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 (p_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 (p_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 interrupt
+void GSwifi::isr_recv () {
+    static int len, mode;
+    static char tmp[20];
+    char flg, dat;
+    
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+    flg = LPC_UART1->LSR;
+#elif defined(TARGET_LPC11U24)
+    flg = LPC_USART->LSR;
+#endif
+    dat = _gs.getc();
+    
+    if (flg & ((1 << 7)|(1 << 3)|(1 << 4))) return;
+//    DBG("%02x ", dat);
+
+    switch (_gs_mode) {
+    case GSMODE_COMMAND: // command responce
+        if (_escape) {
+            // esc
+            switch (dat) {
+            case 'O':
+                DBG("ok\r\n");
+                _gs_ok = 1;
+                break;
+            case 'F':
+                DBG("failure\r\n");
+                _gs_failure = 1;
+                break;
+            case 'S':
+                DBG("GSMODE_DATA_RX\r\n");
+                _gs_mode = GSMODE_DATA_RX;
+                mode = 0;
+                break;
+            case 'u':
+                DBG("GSMODE_DATA_RXUDP\r\n");
+                _gs_mode = GSMODE_DATA_RXUDP;
+                mode = 0;
+                break;
+            case 'Z':
+            case 'H':
+                DBG("GSMODE_DATA_RX_BULK\r\n");
+                _gs_mode = GSMODE_DATA_RX_BULK;
+                mode = 0;
+                break;
+            case 'y':
+                DBG("GSMODE_DATA_RXUDP_BULK\r\n");
+                _gs_mode = GSMODE_DATA_RXUDP_BULK;
+                mode = 0;
+                break;
+            default:
+                DBG("unknown [ESC] %02x\r\n", dat);
+                break;
+            }
+            _escape = 0;
+        } else {
+            if (dat == 0x1b) {
+                _escape = 1;
+            } else
+            if (dat != '\r') {
+                // command
+                _buf_cmd.put(dat);
+                if (dat == '\n') _gs_enter ++;
+            }
+        }
+        break;
+
+    case GSMODE_DATA_RX:
+    case GSMODE_DATA_RXUDP:
+        if (mode == 0) {
+            // cid
+            _cid = x2i(dat);
+            _gs_sock[_cid].received = 0;
+            mode ++;
+            if (_gs_mode == GSMODE_DATA_RX) {
+                mode = 3;
+            }
+            len = 0;
+        } else
+        if (mode == 1) {
+            // ip
+            if ((dat < '0' || dat > '9') && dat != '.') {
+                int ip1, ip2, ip3, ip4;
+                tmp[len] = 0;
+                sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+                _from.setIp(IpAddr(ip1, ip2, ip3, ip4));
+                mode ++;
+                len = 0;
+                break;
+            }
+            tmp[len] = dat;    
+            len ++;        
+        } else
+        if (mode == 2) {
+            // port
+            if (dat < '0' || dat > '9') {
+                tmp[len] = 0;
+                _from.setPort(atoi(tmp));
+                mode ++;
+                len = 0;
+                break;
+            }
+            tmp[len] = dat;            
+            len ++;        
+        } else
+        if (_escape) {
+            // esc
+            switch (dat) {
+            case 'E':
+                DBG("recv ascii %d\r\n", _cid);
+                _gs_sock[_cid].received = 1;
+                _gs_mode = GSMODE_COMMAND;
+                // recv interrupt
+                if (_gs_sock[_cid].protocol == GSPROT_HTTPGET && _gs_sock[_cid].onGsReceive != NULL) {
+                    _gs_sock[_cid].onGsReceive(_cid, 0, _gs_sock[_cid].data->use());
+                    _gs_sock[_cid].received = 0;
+                }
+                break;
+            default:
+                DBG("unknown <ESC> %02x\r\n", dat);
+                break;
+            }
+            _escape = 0;
+        } else {
+            if (dat == 0x1b) {
+                _escape = 1;
+            } else {
+                // data
+                _gs_sock[_cid].data->put(dat);
+                len ++;
+            }
+        }
+        break;
+
+    case GSMODE_DATA_RX_BULK:
+    case GSMODE_DATA_RXUDP_BULK:
+        if (mode == 0) {
+            // cid
+            _cid = x2i(dat);
+            _gs_sock[_cid].received = 0;
+            mode ++;
+            if (_gs_mode == GSMODE_DATA_RX_BULK) {
+                mode = 3;
+            }
+            len = 0;
+        } else
+        if (mode == 1) {
+            // ip
+            if ((dat < '0' || dat > '9') && dat != '.') {
+                int ip1, ip2, ip3, ip4;
+                tmp[len] = 0;
+                sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+                _from.setIp(IpAddr(ip1, ip2, ip3, ip4));
+                mode ++;
+                len = 0;
+                break;
+            }
+            tmp[len] = dat;    
+            len ++;        
+        } else
+        if (mode == 2) {
+            // port
+            if (dat < '0' || dat > '9') {
+                tmp[len] = 0;
+                _from.setPort(atoi(tmp));
+                mode ++;
+                len = 0;
+                break;
+            }
+            tmp[len] = dat;            
+            len ++;        
+        } else
+        if (mode == 3) {
+            // length
+            tmp[len] = dat;            
+            len ++;        
+            if (len >= 4) {
+                tmp[len] = 0;
+                len = atoi(tmp);
+                mode ++;
+                break;
+            }
+        } else
+        if (mode == 4) {
+            // data
+            _gs_sock[_cid].data->put(dat);
+            len  --;
+            if (len == 0) {
+                DBG("recv binary %d\r\n", _cid);
+                _gs_sock[_cid].received = 1;
+                _escape = 0;
+                _gs_mode = GSMODE_COMMAND;
+                // recv interrupt
+                if (_gs_sock[_cid].protocol == GSPROT_HTTPGET && _gs_sock[_cid].onGsReceive != NULL) {
+                    _gs_sock[_cid].onGsReceive(_cid, 0, _gs_sock[_cid].data->use());
+                    _gs_sock[_cid].received = 0;
+                }
+            }
+        }
+        break;
+
+    }
+}
+
+int GSwifi::command (char *cmd, GSRESPONCE res, int timeout) {
+    int i;
+
+    if (! cmd) {
+        // dummy CR+LF
+        _gs.printf("\r\n");
+        wait_ms(100);
+        while (_gs.readable()) _gs.getc(); // dummy read
+        return 0;
+    }
+
+    _buf_cmd.clear();
+    _gs_ok = 0;
+    _gs_failure = 0;
+    _gs_enter = 0;
+    for (i = 0; i < strlen(cmd); i ++) {
+        _gs.putc(cmd[i]);
+    }
+    _gs.putc('\r');
+    _gs.putc('\n');
+    DBG("command: %s\r\n", cmd);
+    if (strlen(cmd) == 0) return 0;
+    wait_ms(50);
+    if (timeout) {
+        return cmdResponse(res, timeout);
+    } else {
+        return 0;
+    }
+}
+
+int GSwifi::cmdResponse (GSRESPONCE res, int ms) {
+    int i, n = 0, flg = 0;
+    char buf[GS_CMD_SIZE];
+    Timer timeout;
+
+    timeout.start();
+    for (;;) {
+        // recv response
+        i = 0;
+        while (i < sizeof(buf)) {
+            if (_buf_cmd.use()) {
+                _buf_cmd.get(&buf[i]);
+                if (buf[i] == '\n') {
+                    break;
+                }
+                i ++;
+            }
+            if (timeout.read_ms() > ms) {
+                timeout.stop();
+                DBG("timeout\r\n");
+                return -1;
+            }
+        }
+        _gs_enter = 0;
+        if (i == 0) continue;
+        buf[i] = 0;
+        DBG("response: %s\r\n", buf);
+        timeout.stop();
+
+        if (strcmp(buf, "OK") == 0) {
+            _gs_ok = 1;
+        } else
+        if (strncmp(buf, "ERROR", 5) == 0) {
+            _gs_failure = 1;
+        }
+
+        switch(res) {
+        case GSRES_NORMAL:
+            flg = 1;
+            break;
+        case GSRES_WPS:
+            if (n == 0 && strncmp(buf, "SSID", 4) == 0) {
+                n ++;
+            } else
+            if (n == 1 && strncmp(buf, "CHANNEL", 7) == 0) {
+                n ++;
+            } else
+            if (n == 2 && strncmp(buf, "PASSPHRASE", 10) == 0) {
+                n ++;
+                flg = 1;
+            }
+            break;
+        case GSRES_CONNECT:
+            if (strncmp(buf, "CONNECT", 7) == 0) {
+                _cid = x2i(buf[8]);
+                flg = 1;
+            }
+            break;
+        case GSRES_DHCP:
+            if (n == 0 && strstr(buf, "SubNet") && strstr(buf, "Gateway")) {
+                n ++;
+            } else
+            if (n == 1) {
+                int ip1, ip2, ip3, ip4;
+                char *tmp = buf + 1;
+                sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+                _ipaddr = IpAddr(ip1, ip2, ip3, ip4);
+                tmp = strstr(tmp, ":") + 2;
+                sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+                _netmask = IpAddr(ip1, ip2, ip3, ip4);
+                tmp = strstr(tmp, ":") + 2;
+                sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+                _gateway = IpAddr(ip1, ip2, ip3, ip4);
+                n ++;
+                flg = 1;
+            }
+            break;
+        case GSRES_MACADDRESS:
+            if (strncmp(buf, "00:", 3) == 0) {
+                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;
+                flg = 1;
+            }
+            break;
+        case GSRES_DNSLOOKUP:
+            if (strncmp(buf, "IP:", 3) == 0) {
+                int ip1, ip2, ip3, ip4;
+                sscanf(&buf[3], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+                _resolv = IpAddr(ip1, ip2, ip3, ip4);
+                flg = 1;
+            }
+            break;
+        case GSRES_HTTP:
+            if (i == 1 && buf[0] >= '0' && buf[0] <= 'F') {
+                _cid = x2i(buf[8]);
+                flg = 1;
+            }
+            break;
+        }
+        
+        if ((flg && _gs_ok) || _gs_failure) break;
+        timeout.reset();
+        timeout.start();
+    }
+
+    if (_gs_failure || flg == 0) {
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
+int GSwifi::connect (GSSECURITY sec, char *ssid, char *pass, int dhcp) {
+    int r;
+    char cmd[GS_CMD_SIZE];
+    
+    if (_connect || _status != GSSTAT_READY) return -1;
+
+    command(NULL, GSRES_NORMAL);
+    if (command("ATE0", GSRES_NORMAL)) return -1;
+    if (_rts) {
+        command("AT&K0", GSRES_NORMAL);
+        command("AT&R1", GSRES_NORMAL);
+    }
+    command("AT+NMAC=?", GSRES_MACADDRESS);
+#ifdef GS_BULK
+    command("AT+BDATA=1", GSRES_NORMAL);
+#endif
+
+    disconnect();
+    command("AT+WM=0", GSRES_NORMAL); // infrastructure
+    wait_ms(100);
+    if (dhcp) {
+        command("AT+NDHCP=1", GSRES_NORMAL);
+    } else {
+        command("AT+NDHCP=0", GSRES_NORMAL);
+    }
+
+    switch (sec) {
+    case GSSEC_NONE:
+        command("AT+WAUTH=0", GSRES_NORMAL);
+        sprintf(cmd, "AT+WA=%s", ssid);
+        r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2);
+        break;
+    case GSSEC_OPEN:
+    case GSSEC_WEP:
+        sprintf(cmd, "AT+WAUTH=%d", sec);
+        command(cmd, GSRES_NORMAL);
+        sprintf(cmd, "AT+WWEP1=%s", pass);
+        command(cmd, GSRES_NORMAL);
+        wait_ms(100);
+        sprintf(cmd, "AT+WA=%s", ssid);
+        r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2);
+        break;
+    case GSSEC_WPA_PSK:
+    case GSSEC_WPA2_PSK:
+        command("AT+WAUTH=0", GSRES_NORMAL);
+//        sprintf(cmd, "AT+WWPA=%s", pass);
+//        command(cmd, GSRES_NORMAL);
+        sprintf(cmd, "AT+WPAPSK=%s,%s", ssid, pass);
+        command(cmd, GSRES_NORMAL, GS_TIMEOUT2);
+        wait_ms(100);
+        sprintf(cmd, "AT+WA=%s", ssid);
+        r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2);
+        break;
+    case GSSEC_WPS_BUTTON:
+        command("AT+WAUTH=0", GSRES_NORMAL);
+        r = command("AT+WWPS=1", GSRES_WPS, GS_TIMEOUT2);
+        if (r) break;
+        if (dhcp) {
+            r = command("AT+NDHCP=1", GSRES_DHCP, GS_TIMEOUT2);
+        }
+        break;
+    }
+
+    if (r == 0) _connect = true;
+    return r;
+}
+
+int GSwifi::adhock (GSSECURITY sec, char *ssid, char *pass, IpAddr ipaddr, IpAddr netmask) {
+    int r;
+    char cmd[GS_CMD_SIZE];
+
+    if (_connect || _status != GSSTAT_READY) return -1;
+
+    command(NULL, GSRES_NORMAL);
+    if (command("ATE0", GSRES_NORMAL)) return -1;
+    if (_rts) {
+        command("AT&K0", GSRES_NORMAL);
+        command("AT&R1", GSRES_NORMAL);
+    }
+    disconnect();
+    command("AT+NMAC=?", GSRES_MACADDRESS);
+#ifdef GS_BULK
+    command("AT+BDATA=1", GSRES_NORMAL);
+#endif
+
+    command("AT+WM=1", GSRES_NORMAL); // adhock
+    wait_ms(100);
+    command("AT+NDHCP=0", GSRES_NORMAL);
+    setAddress(ipaddr, netmask, ipaddr, ipaddr);
+
+    switch (sec) {
+    case GSSEC_NONE:
+        command("AT+WAUTH=0", GSRES_NORMAL);
+        sprintf(cmd, "AT+WA=%s", ssid);
+        r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2);
+        break;
+    case GSSEC_OPEN:
+    case GSSEC_WEP:
+        sprintf(cmd, "AT+WAUTH=%d", sec);
+        command(cmd, GSRES_NORMAL);
+        sprintf(cmd, "AT+WWEP1=%s", pass);
+        command(cmd, GSRES_NORMAL);
+        wait_ms(100);
+        sprintf(cmd, "AT+WA=%s", ssid);
+        r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2);
+        break;
+    default:
+        DBG("Can't use security\r\n");
+        r = -1;
+        break;
+    }
+
+    if (r == 0) _connect = true;
+    return r;
+}
+
+int GSwifi::limitedap (GSSECURITY sec, char *ssid, char *pass, IpAddr ipaddr, IpAddr netmask) {
+    int r;
+    char cmd[GS_CMD_SIZE];
+    
+    if (_connect || _status != GSSTAT_READY) return -1;
+
+    command(NULL, GSRES_NORMAL);
+    if (command("ATE0", GSRES_NORMAL)) return -1;
+    if (_rts) {
+        command("AT&K0", GSRES_NORMAL);
+        command("AT&R1", GSRES_NORMAL);
+    }
+    disconnect();
+    command("AT+NMAC=?", GSRES_MACADDRESS);
+#ifdef GS_BULK
+    command("AT+BDATA=1", GSRES_NORMAL);
+#endif
+
+    command("AT+WM=2", GSRES_NORMAL); // limited ap
+    wait_ms(1000);
+    command("AT+NDHCP=0", GSRES_NORMAL);
+    setAddress(ipaddr, netmask, ipaddr, ipaddr);
+    command("AT+DHCPSRVR=1", GSRES_NORMAL);
+    command("AT+DNS=1,gainspan", GSRES_NORMAL);
+
+    switch (sec) {
+    case GSSEC_NONE:
+        command("AT+WAUTH=0", GSRES_NORMAL);
+        sprintf(cmd, "AT+WA=%s", ssid);
+        r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2);
+        break;
+    case GSSEC_OPEN:
+    case GSSEC_WEP:
+        sprintf(cmd, "AT+WAUTH=%d", sec);
+        command(cmd, GSRES_NORMAL);
+        sprintf(cmd, "AT+WWEP1=%s", pass);
+        command(cmd, GSRES_NORMAL);
+        wait_ms(100);
+        sprintf(cmd, "AT+WA=%s", ssid);
+        r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2);
+        break;
+    default:
+        DBG("Can't use security\r\n");
+        r = -1;
+        break;
+    }
+
+    if (r == 0) _connect = true;
+    return r;
+}
+
+int GSwifi::disconnect () {
+    int i;
+
+    _connect = false;
+    for (i = 0; i < 16; i ++) {
+        _gs_sock[i].connect = false;
+    }
+    command("AT+NCLOSEALL", GSRES_NORMAL);
+    command("AT+WD", GSRES_NORMAL);
+    command("AT+NDHCP=0", GSRES_NORMAL);
+    wait_ms(100);
+    return 0;
+}
+
+int GSwifi::setAddress () {
+
+    if (command("AT+NDHCP=1", GSRES_DHCP), GS_TIMEOUT2) return -1;
+    if (_ipaddr.isNull()) return -1;
+    return 0;
+}
+
+int GSwifi::setAddress (IpAddr ipaddr, IpAddr netmask, IpAddr gateway, IpAddr nameserver) {
+    int r;
+    char cmd[GS_CMD_SIZE];
+
+    command("AT+NDHCP=0", GSRES_NORMAL);
+    wait_ms(100);
+
+    sprintf(cmd, "AT+NSET=%d.%d.%d.%d,%d.%d.%d.%d,%d.%d.%d.%d",
+        ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3],
+        netmask[0], netmask[1], netmask[2], netmask[3],
+        gateway[0], gateway[1], gateway[2], gateway[3]);
+    r = command(cmd, GSRES_NORMAL);
+    if (r) return -1;
+    _ipaddr = ipaddr;
+    _netmask = netmask;
+    _gateway = gateway;
+
+    if (ipaddr != nameserver) {
+        sprintf(cmd, "AT+DNSSET=%d.%d.%d.%d",
+            nameserver[0], nameserver[1], nameserver[2], nameserver[3]);
+        r = command(cmd, GSRES_NORMAL);
+    }
+    return r;
+}
+
+int GSwifi::getHostByName (const char* name, IpAddr &addr) {
+    char cmd[GS_CMD_SIZE];
+
+    if (! _connect || _status != GSSTAT_READY) return -1;
+
+    sprintf(cmd, "AT+DNSLOOKUP=%s", name);
+    if (command(cmd, GSRES_DNSLOOKUP)) return -1;
+
+    addr = _resolv;
+    return 0;
+}
+
+int GSwifi::getHostByName (Host &host) {
+    char cmd[GS_CMD_SIZE];
+
+    if (! _connect || _status != GSSTAT_READY) return -1;
+
+    sprintf(cmd, "AT+DNSLOOKUP=%s", host.getName());
+    if (command(cmd, GSRES_DNSLOOKUP)) return -1;
+
+    host.setIp(_resolv);
+    return 0;
+}
+
+int GSwifi::setRFPower (int power) {
+    char cmd[GS_CMD_SIZE];
+
+    if (power < 0 || power > 7) return -1;
+
+    sprintf(cmd, "AT+WP=%d", power);
+    return command(cmd, GSRES_NORMAL);
+}
+
+int GSwifi::powerSave (int beacon, int association) {
+    char cmd[GS_CMD_SIZE];
+
+    if (_status != GSSTAT_READY) return -1;
+
+    sprintf(cmd, "AT+WAPSM=%d", association);
+    command(cmd, GSRES_NORMAL);
+    if (beacon) {
+        sprintf(cmd, "AT+WRXPS=1,%d", beacon);
+    } else {
+        strcpy(cmd, "AT+WRXPS=0");
+    }
+    return command(cmd, GSRES_NORMAL);
+}
+
+int GSwifi::standby (int msec) {
+    char cmd[GS_CMD_SIZE];
+
+    if (_status != GSSTAT_READY && _status != GSSTAT_WAKEUP) return -1;
+
+    if (_status != GSSTAT_WAKEUP) {
+        command("AT+WRXACTIVE=0", GSRES_NORMAL);
+        command("AT+STORENWCONN", GSRES_NORMAL);
+    } else {
+        command("ATE0", GSRES_NORMAL);
+        if (_rts) {
+            command("AT&K0", GSRES_NORMAL);
+            command("AT&R1", GSRES_NORMAL);
+        }
+    }
+    _status = GSSTAT_STANDBY;
+    sprintf(cmd, "AT+PSSTBY=%d,0,0,0", msec); // go standby
+    return command(cmd, GSRES_NORMAL, 0);
+}
+
+int GSwifi::wakeup () {
+
+    if (_status == GSSTAT_WAKEUP) {
+        _status = GSSTAT_READY;
+        command("ATE0", GSRES_NORMAL);
+        if (_rts) {
+            command("AT&K0", GSRES_NORMAL);
+            command("AT&R1", GSRES_NORMAL);
+        }
+#ifdef GS_BULK
+        command("AT+BDATA=1", GSRES_NORMAL);
+#endif
+        command("AT+RESTORENWCONN", GSRES_NORMAL);
+        wait_ms(100);
+        return command("AT+WRXACTIVE=1", GSRES_NORMAL);
+    } else
+    if (_status == GSSTAT_DEEPSLEEP) {
+        _status = GSSTAT_READY;
+        return command("AT", GSRES_NORMAL);
+    }
+    return -1;
+}
+
+int GSwifi::deepSleep () {
+
+    if (_status != GSSTAT_READY) return -1;
+
+    _status = GSSTAT_DEEPSLEEP;
+    return command("AT+PSDPSLEEP", GSRES_NORMAL, 0); // go deep sleep
+}
+
+bool GSwifi::isConnected () {
+    return _connect;
+}
+
+GSSTATUS GSwifi::getStatus () {
+    return _status;
+}
+
+void GSwifi::poll() {
+    int i;
+
+    if (_gs_enter) {
+        // received "\n"
+        int i;
+        char buf[GS_CMD_SIZE];
+
+        wait_ms(10);
+        _gs_enter --;
+        i = 0;
+        while (_buf_cmd.use() && i < sizeof(buf)) {
+            _buf_cmd.get(&buf[i]);
+            if (buf[i] == '\n') {
+                if (i == 0) continue;
+                break;
+            }
+            i ++;
+        }
+        buf[i] = 0;
+        DBG("poll: %s\r\n", buf);
+
+        if (strncmp(buf, "CONNECT", 7) == 0 && buf[9] >= '0' && buf[9] <= 'F' &&
+          _gs_sock[x2i(buf[8])].type == GSTYPE_SERVER) {
+            i = x2i(buf[8]);
+            _gs_sock[i].acid = x2i(buf[9]);
+            // ip, port
+        } else
+        if (strncmp(buf, "DISCONNECT", 10) == 0) {
+            _gs_sock[x2i(buf[11])].connect = false;
+        } else
+        if (strncmp(buf, "DISASSOCIATED", 13) == 0 ||
+          strncmp(buf, "Disassociated", 13) == 0 ||
+          strncmp(buf, "UnExpected", 10) == 0) {
+            _connect = false;
+            for (i = 0; i < 16; i ++) {
+                _gs_sock[i].connect = false;
+            }
+        } else
+        if (strncmp(buf, "Out of StandBy-Timer", 20) == 0 ||
+          strncmp(buf, "Out of StandBy-Alarm", 20) == 0) {
+            if (_status == GSSTAT_STANDBY) {
+                _status = GSSTAT_WAKEUP;
+            }
+        } else 
+        if (strncmp(buf, "Out of Deep Sleep", 17) == 0 ) {
+            if (_status == GSSTAT_DEEPSLEEP) {
+                _status = GSSTAT_READY;
+            }
+        } else 
+        if (strncmp(buf, "Out of", 6) == 0) {
+        }
+        DBG("status: %d\r\n", _status);
+    }
+    
+    for (i = 0; i < 16; i ++) {
+//        if (_gs_sock[i].connect && _gs_sock[i].received) {
+        if (_gs_sock[i].received && _gs_sock[i].data->use()) {
+            // recv interrupt
+            _gs_sock[i].received = 0;
+            if (_gs_sock[i].onGsReceive != NULL)
+                _gs_sock[i].onGsReceive(i, _gs_sock[i].acid, _gs_sock[i].data->use());
+        }
+    }
+}
+
+int GSwifi::open (Host &host, GSPROTOCOL pro, onGsReceiveFunc ponGsReceive) {
+    char cmd[GS_CMD_SIZE];
+
+    if (! _connect || _status != GSSTAT_READY) return -1;
+    if (host.getIp().isNull() || host.getPort() == 0) {
+        return -1;
+    }
+
+    if (pro == GSPROT_UDP) {
+        sprintf(cmd, "AT+NCUDP=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
+    } else {
+        sprintf(cmd, "AT+NCTCP=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
+    }
+    if (command(cmd, GSRES_CONNECT)) return -1;
+
+    _gs_sock[_cid].type = GSTYPE_CLIENT;
+    _gs_sock[_cid].protocol = pro;
+    _gs_sock[_cid].connect = true;
+    if (_gs_sock[_cid].data == NULL) {
+        _gs_sock[_cid].data = new RingBuffer(GS_DATA_SIZE);
+    } else {
+        _gs_sock[_cid].data->clear();
+    }
+    _gs_sock[_cid].acid = 0;
+    _gs_sock[_cid].received = 0;
+    _gs_sock[_cid].onGsReceive = ponGsReceive;
+    return _cid;
+}
+
+int GSwifi::listen (int port, GSPROTOCOL pro, onGsReceiveFunc ponGsReceive) {
+    char cmd[GS_CMD_SIZE];
+
+    if (! _connect || _status != GSSTAT_READY) return -1;
+    if (port == 0) {
+        return -1;
+    }
+
+    if (pro == GSPROT_UDP) {
+        sprintf(cmd, "AT+NSUDP=%d", port);
+    } else {
+        sprintf(cmd, "AT+NSTCP=%d", port);
+    }
+    if (command(cmd, GSRES_CONNECT)) return -1;
+
+    _gs_sock[_cid].type = GSTYPE_SERVER;
+    _gs_sock[_cid].protocol = pro;
+    _gs_sock[_cid].connect = true;
+    if (_gs_sock[_cid].data == NULL) {
+        _gs_sock[_cid].data = new RingBuffer(GS_DATA_SIZE);
+    } else {
+        _gs_sock[_cid].data->clear();
+    }
+    _gs_sock[_cid].acid = 0;
+    _gs_sock[_cid].received = 0;
+    _gs_sock[_cid].onGsReceive = ponGsReceive;
+    return _cid;
+}
+
+int GSwifi::close (int cid) {
+    char cmd[GS_CMD_SIZE];
+
+    if (! _gs_sock[cid].connect) return -1;
+
+    _gs_sock[cid].connect = false;
+    delete _gs_sock[cid].data;
+    _gs_sock[cid].data = NULL;
+    sprintf(cmd, "AT+NCLOSE=%X", cid);
+    return command(cmd, GSRES_NORMAL);    
+}
+
+int GSwifi::send (int cid, char *buf, int len) {
+    int i;
+
+    if (! _gs_sock[cid].connect) return -1;
+
+    if ((_gs_sock[cid].protocol == GSPROT_TCP) ||
+      (_gs_sock[cid].protocol == GSPROT_UDP && _gs_sock[cid].type == GSTYPE_CLIENT)) {
+        // TCP Client, TCP Server, UDP Client
+        _gs_ok = 0;
+        _gs_failure = 0;
+#ifdef GS_BULK
+        _gs.printf("\x1bZ%X%04d", cid, len);
+        for (i = 0; i < len; i ++) {
+            _gs.putc(buf[i]);
+            DBG("%c", buf[i]);
+        }
+#else
+        _gs.printf("\x1bS%X", cid);
+        for (i = 0; i < len; i ++) {
+            if (buf[i] >= 0x20 && buf[i] < 0x7f) {
+                _gs.putc(buf[i]);
+                DBG("%c", buf[i]);
+            }
+        }
+        _gs.putc(0x1b);
+        _gs.putc('E');
+#endif
+    } else {
+        return -1;
+    }
+    while (!_gs_ok && !_gs_failure);
+    return _gs_ok == 1 ? 0 : -1;
+}
+
+int GSwifi::send (int cid, char *buf, int len, Host &host) {
+    int i;
+
+    if (! _gs_sock[cid].connect) return -1;
+
+    if ((_gs_sock[cid].protocol == GSPROT_UDP && _gs_sock[cid].type == GSTYPE_SERVER)) {
+        // UDP Server
+        _gs_ok = 0;
+        _gs_failure = 0;
+        _gs.putc(0x1b);
+#ifdef GS_BULK
+        _gs.printf("\x1bY%X", cid);
+        _gs.printf("%d.%d.%d.%d %d:", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
+        _gs.printf("%04d", len);
+        for (i = 0; i < len; i ++) {
+            _gs.putc(buf[i]);
+            DBG("%c", buf[i]);
+        }
+#else
+        _gs.printf("\x1bU%X", cid);
+        _gs.printf("%d.%d.%d.%d %d:", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
+        for (i = 0; i < len; i ++) {
+            if (buf[i] >= 0x20 && buf[i] < 0x7f) {
+                _gs.putc(buf[i]);
+                DBG("%c", buf[i]);
+            }
+        }
+        _gs.putc(0x1b);
+        _gs.putc('E');
+#endif
+    } else {
+        return -1;
+    }
+    while (!_gs_ok && !_gs_failure);
+    return _gs_ok == 1 ? 0 : -1;
+}
+
+int GSwifi::recv (int cid, char *buf, int len) {
+    int r;
+    Timer timeout;
+    
+    if (_gs_sock[cid].data == NULL) return 0;
+
+    timeout.start();
+    while (_gs_sock[cid].data->use() == 0) {
+        if (timeout.read_ms() > GS_TIMEOUT) return 0;
+    }
+    timeout.stop();
+
+    r = _gs_sock[cid].data->get(buf, len);
+    return r;
+}
+
+int GSwifi::recv (int cid, char *buf, int len, Host &host) {
+    int r;
+    Timer timeout;
+    
+    if (_gs_sock[cid].data == NULL) return 0;
+
+    timeout.start();
+    while (_gs_sock[cid].data->use() == 0) {
+        if (timeout.read_ms() > GS_TIMEOUT) return 0;
+    }
+    timeout.stop();
+
+    r = _gs_sock[cid].data->get(buf, len);
+    host = _from;
+    return r;
+}
+
+bool GSwifi::isConnected (int cid) {
+    return _gs_sock[cid].connect;
+}
+
+int GSwifi::httpGet (Host &host, char *uri, int ssl, onGsReceiveFunc ponGsReceive) {
+    char cmd[GS_CMD_SIZE];
+
+    if (! _connect || _status != GSSTAT_READY) return -1;
+
+    if (host.getIp().isNull()) {
+        if (getHostByName(host)) {
+            if (getHostByName(host)) return -1;
+        }
+    }
+    if (host.getPort() == 0) {
+        if (ssl) {
+            host.setPort(443);
+        } else {
+            host.setPort(80);
+        }
+    }
+
+    command("AT+HTTPCONF=3,close", GSRES_NORMAL); // Connection:
+    sprintf(cmd, "AT+HTTPCONF=11,%s", host.getName());  // Host:
+    command(cmd, GSRES_NORMAL);
+    sprintf(cmd, "AT+HTTPOPEN=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
+    if (ssl) {
+        strcat(cmd, ",1");
+    }
+    if (command(cmd, GSRES_HTTP)) return -1;
+
+    _gs_sock[_cid].type = GSTYPE_CLIENT;
+    _gs_sock[_cid].protocol = GSPROT_HTTPGET;
+    _gs_sock[_cid].connect = true;
+    if (_gs_sock[_cid].data == NULL) {
+        _gs_sock[_cid].data = new RingBuffer(GS_DATA_SIZE);
+    } else {
+        _gs_sock[_cid].data->clear();
+    }
+    _gs_sock[_cid].acid = 0;
+    _gs_sock[_cid].received = 0;
+    _gs_sock[_cid].onGsReceive = ponGsReceive;
+
+    sprintf(cmd, "AT+HTTPSEND=%d,1,%d,%s", _cid, GS_TIMEOUT / 1000, uri);  // Get:
+    command(cmd, GSRES_NORMAL);
+
+    return _cid;
+}
+
+int GSwifi::certAdd (char *name, char *cert, int len) {
+    int i;
+    char cmd[GS_CMD_SIZE];
+
+    if (! _connect || _status != GSSTAT_READY) return -1;
+
+    sprintf(cmd, "AT+TCERTADD=%s,1,%d,1", name, len);  // Hex, ram
+    command(cmd, GSRES_NORMAL);
+    
+    _gs.putc(0x1b);
+    _gs.putc('W');
+    for (i = 0; i < len; i ++) {
+        _gs.putc(cert[i]);
+    }
+    return cmdResponse(GSRES_NORMAL, GS_TIMEOUT);
+}
+
+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;
+}
+
+
+// for test
+
+void GSwifi::test () {
+    command(NULL, GSRES_NORMAL);
+    wait_ms(100);
+    command("AT+NCLOSEALL", GSRES_NORMAL);
+    _connect = true;
+}
+
+int GSwifi::getc() {
+    char c;
+    if (_buf_cmd.use()) {
+        _buf_cmd.get(&c);
+    }
+/*
+    } else
+    if (_gs_sock[0].data != NULL) {
+        _gs_sock[0].data->get(&c);
+    }
+*/
+    return c;
+}
+
+void GSwifi::putc(char c) {
+    _gs.putc(c);
+}
+
+int GSwifi::readable() {
+    return _buf_cmd.use();
+//    return _buf_cmd.use() || (_gs_sock[0].data != NULL && _gs_sock[0].data->use());
+}