GSwifiInterface library (interface for GainSpan Wi-Fi GS1011 modules) Please see https://mbed.org/users/gsfan/notebook/GSwifiInterface/

Dependents:   GSwifiInterface_HelloWorld GSwifiInterface_HelloServo GSwifiInterface_UDPEchoServer GSwifiInterface_UDPEchoClient ... more

Fork of WiflyInterface by mbed official

GainSpan Wi-Fi library

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

mbed RTOS supported.

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

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

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

mbed RTOS に対応しています。(mbed2.0)

GSwifi/GSwifi.cpp

Committer:
gsfan
Date:
2013-01-27
Revision:
5:78943b3945b5
Parent:
Wifly/Wifly.cpp@ 4:0bcec6272784
Child:
7:f94c59d0c735
Child:
8:64184a968e3b

File content as of revision 5:78943b3945b5:

/* 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;
}