OLD
OLD
Diff: GSwifi.cpp
- 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()); +}