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_msg.cpp

Committer:
gsfan
Date:
2013-10-31
Revision:
8:64184a968e3b
Child:
11:71d67fea5ace

File content as of revision 8:64184a968e3b:

/* Copyright (C) 2013 gsfan, 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.
 */

#include "GSwifi.h"

#ifdef RTOS_H
#undef DBG
#define DBG(x, ...)
#endif

void GSwifi::recvData (char c) {
    static int sub, len, count;

#ifdef DEBUG_DUMP
    if (c < 0x20) {
        DBG("%02x_", c);
    } else {
        DBG("%c_", c);
    }
#endif
    switch (_state.mode) {
    case MODE_COMMAND:
        switch (c) {
        case 0:
        case 0x0a: // LF
        case 0x0d: // CR
            break;
        case 0x1b: // ESC
            _state.buf->flush();
            _state.mode = MODE_ESCAPE;
            break;
        default:
            _state.buf->flush();
            _state.buf->queue(c);
            _state.mode = MODE_CMDRESP;
            break;
        }
        break;
    
    case MODE_CMDRESP:
        switch (c) {
        case 0:
            break;
        case 0x0a: // LF
        case 0x0d: // CR
//            _state.buf->queue(c);
            parseMessage();
            _state.mode = MODE_COMMAND;
            break;
        case 0x1b: // ESC
            _state.mode = MODE_ESCAPE;
            break;
        default:
            _state.buf->queue(c);
            break;
        }
        break;

    case MODE_ESCAPE:
        sub = 0;
        switch (c) {
        case 'H':
            _state.mode = MODE_DATA_RXHTTP;
            break;
        case 'u':
            _state.mode = MODE_DATA_RXUDP;
            break;
        case 'y':
            _state.mode = MODE_DATA_RXUDP_BULK;
            break;
        case 'Z':
            _state.mode = MODE_DATA_RX_BULK;
            break;
        case 'S':
            _state.mode = MODE_DATA_RX;
            break;
        case ':':
            _state.mode = MODE_DATA_RAW;
            break;
        case 'O':
            _state.mode = MODE_COMMAND;
            _state.ok = true;
            return;
        case 'F':
            _state.mode = MODE_COMMAND;
            _state.failure = true;
            return;
        default:
            _state.mode = MODE_COMMAND;
            return;
        }
        break;
    
    case MODE_DATA_RX:
    case MODE_DATA_RXUDP:
        switch (sub) {
        case 0:
            // cid
            _state.cid = x2i(c);
            sub ++;
            count = 0;
            if (_state.mode == MODE_DATA_RX) {
                sub = 3;
            }
            break;
        case 1:
            // ip
            if ((c >= '0' && c <= '9') || c == '.') {
                _con[_state.cid].ip[count] = c;
                count ++;
            } else {
                _con[_state.cid].ip[count] = 0;
                _con[_state.cid].port = 0;
                sub ++;
            }
            break;
        case 2:
            // port
            if (c >= '0' && c <= '9') {
                _con[_state.cid].port = (_con[_state.cid].port * 10) + (c - '0'); 
            } else {
                sub ++;
                count = 0;
            }
            break;            
        default:
            // data
            if (_state.escape) {
                if (c == 'E') {
                    DBG("recv ascii %d %d/a\r\n", _state.cid, count);
                    _con[_state.cid].received = true;
                    _state.mode = MODE_COMMAND;
                } else {
                    if (_con[_state.cid].buf != NULL) {
                        _con[_state.cid].buf->queue(0x1b);
                        _con[_state.cid].buf->queue(c);
                    }
                    count += 2;
                }
                _state.escape = false;
            } else
            if (c == 0x1b) {
                _state.escape = true;
            } else {
                if (_con[_state.cid].buf != NULL) {
                    _con[_state.cid].buf->queue(c);
                    if (_con[_state.cid].buf->available() > CFG_DATA_SIZE - 16) {
                        setRts(false);
                        _con[_state.cid].received = true;
                    }
                }
                count ++;
            }
            break;
        }
        break;
    
    case MODE_DATA_RX_BULK:
    case MODE_DATA_RXUDP_BULK:
    case MODE_DATA_RXHTTP:
        switch (sub) {
        case 0:
            // cid
            _state.cid = x2i(c);
            sub ++;
            len = 0;
            count = 0;
            if (_state.mode == MODE_DATA_RX_BULK) {
                sub = 3;
            }
            break;
        case 1:
            // ip
            if ((c >= '0' && c <= '9') || c == '.') {
                _con[_state.cid].ip[count] = c;
                count ++;
            } else {
                _con[_state.cid].ip[count] = 0;
                _con[_state.cid].port = 0;
                sub ++;
            }
            break;
        case 2:
            // port
            if (c >= '0' && c <= '9') {
                _con[_state.cid].port = (_con[_state.cid].port * 10) + (c - '0'); 
            } else {
                sub ++;
                count = 0;
            }
            break;
        case 3:
            // length
            len = (len * 10) + (c - '0');
            count ++;
            if (count >= 4) {
                sub ++;
                count = 0;
            }
            break;
        default:
            // data
            if (_con[_state.cid].buf != NULL) {
                _con[_state.cid].buf->queue(c);
                if (_con[_state.cid].buf->available() > CFG_DATA_SIZE - 16) {
                    setRts(false);
                    _con[_state.cid].received = true;
                }
            }
            count ++;
            if (count >= len) {
                DBG("recv bulk %d %d/%d\r\n", _state.cid, count, len);
                _con[_state.cid].received = true;
                _state.mode = MODE_COMMAND;
            }
            break;
        }
        break;
    }
}

int GSwifi::parseMessage () {
    int i;
    char buf[256];
    static const struct MSG_TABLE {
        const char msg[24];
        void (GSwifi::*func)(const char*);
    } msg_table[MSG_TABLE_NUM] = {
      {"OK",                      &GSwifi::msgOk},
      {"ERROR",                   &GSwifi::msgError},
      {"INVALID INPUT",           &GSwifi::msgError},
      {"CONNECT ",                &GSwifi::msgConnect},
      {"DISCONNECT ",             &GSwifi::msgDisconnect},
      {"DISASSOCIATED",           &GSwifi::msgDisassociated},
      {"Disassociated",           &GSwifi::msgDisassociated},
      {"Disassociation Event",    &GSwifi::msgDisassociated},
      {"Serial2WiFi APP",         &GSwifi::msgReset},
      {"UnExpected Warm Boot",    &GSwifi::msgReset},
      {"APP Reset-APP SW Reset",  &GSwifi::msgReset},
      {"APP Reset-Wlan Except",   &GSwifi::msgReset},
      {"Out of StandBy-Timer",    &GSwifi::msgOutofStandby},
      {"Out of StandBy-Alarm",    &GSwifi::msgOutofStandby},
      {"Out of Deep Sleep",       &GSwifi::msgOutofDeepsleep},
    };
    static const struct RES_TABLE {
        const Response res;
        void (GSwifi::*func)(const char*);
    } res_table[RES_TABLE_NUM] = {
      {RES_NULL,        NULL},
      {RES_CONNECT,     &GSwifi::resConnect},
      {RES_WPS,         &GSwifi::resWps},
      {RES_MACADDRESS,  &GSwifi::resMacAddress},
      {RES_DHCP,        &GSwifi::resIp},
      {RES_DNSLOOKUP,   &GSwifi::resLookup},
      {RES_HTTP,        &GSwifi::resConnect},
      {RES_RSSI,        &GSwifi::resRssi},
      {RES_TIME,        &GSwifi::resTime},
      {RES_STATUS,      &GSwifi::resStatus},
    };

    for (i = 0; i < sizeof(buf); i++) {
        if (_state.buf->dequeue(&buf[i]) == false) break;
    }
    buf[i] = 0;

    if (_state.res != RES_NULL) {
      for (i = 0; i < RES_TABLE_NUM; i ++) {
        if (res_table[i].res == _state.res) {
            DBG("parse res %d '%s'\r\n", i, buf);
            if (res_table[i].func != NULL) {
                (this->*(res_table[i].func))(buf);
            }
        }
      }
    }

    for (i = 0; i < MSG_TABLE_NUM; i ++) {
        if (strncmp(buf, msg_table[i].msg, strlen(msg_table[i].msg)) == 0) {
            DBG("parse msg %d '%s'\r\n", i, buf);
            if (msg_table[i].func != NULL) {
                (this->*(msg_table[i].func))(buf);
            }
            return 0;
        }
    }

    return -1;
}

void GSwifi::msgOk (const char *buf) {
    _state.ok = true;
}

void GSwifi::msgError (const char *buf) {
    _state.failure = true;
}

void GSwifi::msgConnect (const char *buf) {
    int i, count;

    if (buf[8] < '0' || buf[8] > 'F' || buf[9] != ' ') return;

    _state.cid = x2i(buf[8]);
    _state.acid = x2i(buf[10]);
    DBG("connect %d -> %d\r\n", _state.cid, _state.acid);
    // ip
    count = 0;
    for (i = 12; i < strlen(buf); i ++) {
        if ((buf[i] >= '0' && buf[i] <= '9') || buf[i] == '.') {
            _con[_state.acid].ip[count] = buf[i];
            count ++;
        } else {
            _con[_state.acid].ip[count] = 0;
            break;
        }
    }
    // port
    _con[_state.acid].port = 0;
    count = 0;
    for (; i < strlen(buf); i ++) {
        if (buf[i] >= '0' && buf[i] <= '9') {
            _con[_state.acid].port = (_con[_state.acid].port * 10) + (buf[i] - '0'); 
        } else {
            break;
        }
    }

    _con[_state.acid].protocol = _con[_state.cid].protocol;
    _con[_state.acid].type = _con[_state.cid].type;
    _con[_state.acid].parent = _state.cid;
    _con[_state.acid].accept = true;
    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;
}

void GSwifi::msgDisconnect (const char *buf) {
    int cid;

    if (buf[11] < '0' || buf[11] > 'F') return;

    cid = x2i(buf[11]);
    DBG("disconnect %d\r\n", cid);
    _con[cid].connected = false;
}

void GSwifi::msgDisassociated (const char *buf) {
    int i;
    DBG("disassociate\r\n");
    _state.associated = false;
    for (i = 0; i < 16; i ++) {
        _con[i].connected = false;
    }
#ifdef RTOS_H
    if (_threadPoll)
        _threadPoll->signal_set(1);
#endif
}

void GSwifi::msgReset (const char *buf) {
    _state.mode = MODE_COMMAND;
    _state.status = STAT_READY;
    msgDisassociated(NULL);
}

void GSwifi::msgOutofStandby (const char *buf) {
    _state.status = STAT_WAKEUP;
}

void GSwifi::msgOutofDeepsleep (const char *buf) {
    _state.status = STAT_READY;
}

void GSwifi::resConnect (const char *buf) {
    if (strncmp(buf, "CONNECT ", 8) == 0 && buf[9] == 0) {
        _state.cid = x2i(buf[8]);
        DBG("connect %d\r\n", _state.cid);
        _con[_state.cid].parent = -1;
        _con[_state.cid].accept = false;
        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;
        _state.res = RES_NULL;
        return;
    }
}

void GSwifi::resWps (const char *buf) {
    if (_state.n == 0 && strncmp(buf, "SSID", 4) == 0) {
        strncpy(_state.ssid, &buf[5], sizeof(_state.ssid));
        _state.n ++;
    } else
    if (_state.n == 1 && strncmp(buf, "CHANNEL", 7) == 0) {
        _state.n ++;
    } else
    if (_state.n == 2 && strncmp(buf, "PASSPHRASE", 10) == 0) {
        strncpy(_state.pass, &buf[11], sizeof(_state.pass));
        _state.n ++;
        _state.res = RES_NULL;
    }
}

void GSwifi::resMacAddress (const char *buf) {
    if (buf[2] == ':' && buf[5] == ':') {
        strncpy(_state.mac, buf, sizeof(_state.mac));
        _state.mac[17] = 0;
        _state.res = RES_NULL;
        DBG("mac: %s", _state.mac);
    }
}

void GSwifi::resIp (const char *buf) {
    const char *tmp, *tmp2;

    if (_state.n == 0 && strstr(buf, "SubNet") && strstr(buf, "Gateway")) {
        _state.n ++;
    } else
    if (_state.n == 1) {
        tmp = buf + 1;
        tmp2 = strstr(tmp, ":");
        strncpy(_state.ip, tmp, tmp2 - tmp);
        tmp = tmp2 + 2;
        tmp2 = strstr(tmp, ":");
        strncpy(_state.netmask, tmp, tmp2 - tmp);
        tmp = tmp2 + 2;
        strncpy(_state.gateway, tmp, sizeof(_state.gateway));
        _state.n ++;
        _state.res = RES_NULL;
        DBG("ip: %s\r\nnetmask: %s\r\ngateway: %s", _state.ip, _state.netmask, _state.gateway);
    }
}

void GSwifi::resLookup (const char *buf) {
    if (strncmp(buf, "IP:", 3) == 0) {
        strncpy(_state.resolv, &buf[3], sizeof(_state.resolv));
        _state.res = RES_NULL;
        DBG("resolv: %s", _state.resolv);
    }
}

void GSwifi::resRssi (const char *buf) {
    if (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9')) {
        _state.rssi = atoi(buf);
        _state.res = RES_NULL;
        DBG("rssi: %d", _state.rssi);
    }
}

void GSwifi::resTime (const char *buf) {
    int year, month, day, hour, min, sec;
    struct tm t;
    if (buf[0] >= '0' && buf[0] <= '9') {
        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;   
        _state.time = mktime(&t);            
        _state.res = RES_NULL;
    }
}

void GSwifi::resChannel (const char *buf) {
}

void GSwifi::resStatus (const char *buf) {
    if (_state.n == 0 && strncmp(buf, "NOT ASSOCIATED", 14) == 0) {
        msgDisassociated(NULL);
        _state.res = RES_NULL;
    }

    if (_state.n == 0 && strncmp(buf, "MODE:", 5) == 0) {
        _state.n ++;
    } else
    if (_state.n == 1 && strncmp(buf, "BSSID:", 6) == 0) {
        const char *tmp = strstr(buf, "SECURITY:") + 2;
        if (strncmp(tmp, "WEP (OPEN)", 10) == NULL) {
            _state.sec = SEC_OPEN;
        } else
        if (strncmp(tmp, "WEP (SHARED)", 12) == NULL) {
            _state.sec = SEC_WEP;
        } else
        if (strncmp(tmp, "WPA-PERSONAL", 12) == NULL) {
            _state.sec = SEC_WPA_PSK;
        } else
        if (strncmp(tmp, "WPA2-PERSONAL", 13) == NULL) {
            _state.sec = SEC_WPA2_PSK;
        }
        _state.res = RES_NULL;
    }
}