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
GainSpan Wi-Fi library
The GS1011/GS2100 is an ultra low power 802.11b wireless module from GainSpan.
mbed RTOS supported.
- about this library: http://mbed.org/users/gsfan/notebook/GSwifiInterface/
- about Wi-Fi module: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
ゲインスパン Wi-Fi モジュール ライブラリ
ゲインスパン社の低電力 Wi-Fiモジュール(無線LAN) GS1011/GS2100 シリーズ用のライブラリです。
mbed RTOS に対応しています。(mbed2.0)
- このライブラリについて: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
- Wi-FIモジュールについて: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
- UARTコマンド、SPIデータインターフェースに対応しました。(2019/09)
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; }