Host library for controlling a WiConnect enabled Wi-Fi module.
Dependents: wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more
Diff: NetworkInterface.cpp
- Revision:
- 29:b6af04b77a56
- Child:
- 31:59fac148a8d5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NetworkInterface.cpp Mon Oct 27 13:42:26 2014 -0700 @@ -0,0 +1,659 @@ +/** + * ACKme WiConnect Host Library is licensed under the BSD licence: + * + * Copyright (c)2014 ACKme Networks. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ + +#include "Wiconnect.h" +#include "internal/common.h" +#include "api/StringUtil.h" + + +#define IPV4_FORMAT "%u.%u.%u.%u" +#define IPV4_ARGS(ip) \ + (int)(((ip) >> 0) & 0xff), \ + (int)(((ip) >> 8) & 0xff), \ + (int)(((ip) >> 16) & 0xff), \ + (int)(((ip) >> 24) & 0xff) + + + +/*************************************************************************************************/ +NetworkInterface::NetworkInterface(Wiconnect *wiconnect_) +{ + wiconnect = wiconnect_; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::ping(const char *domain, uint32_t *timeMsPtr) +{ + WiconnectResult result; + + CHECK_OTHER_COMMAND_EXECUTING(); + + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("ping %s", (domain == NULL) ? "-g" : domain)) && + timeMsPtr != NULL) + { + if(sscanf(wiconnect->internalBuffer, "Ping reply in %ums", (unsigned int*)timeMsPtr) != 1) + { + result = WICONNECT_RESPONSE_PARSE_ERROR; + } + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::lookup(const char *domain, uint32_t *ipAddressPtr) +{ + WiconnectResult result; + + CHECK_OTHER_COMMAND_EXECUTING(); + + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("nlo %s", domain))) + { + if(!NetworkInterface::strToIp(wiconnect->internalBuffer, ipAddressPtr)) + { + result = WICONNECT_RESPONSE_PARSE_ERROR; + } + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::setDhcpEnabled(bool enabled) +{ + WiconnectResult result; + + CHECK_OTHER_COMMAND_EXECUTING(); + + result = wiconnect->sendCommand(CMD_SET_NETWORK_DHCP, enabled); + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::getDhcpEnabled(bool *enabledPtr) +{ + WiconnectResult result; + + CHECK_OTHER_COMMAND_EXECUTING(); + + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.dhcp.enabled"))) + { + int32_t enabled; + if(WICONNECT_SUCCEEDED(result, wiconnect->responseToInt32(&enabled))) + { + *enabledPtr = (bool)enabled; + } + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::setIpSettings(uint32_t ip, uint32_t netmask, uint32_t gateway) +{ + WiconnectResult result = WICONNECT_ERROR; + + enum + { + FS_SET_IP, + FS_SET_NETMASK, + FS_SET_GATEWAY + }; + + CHECK_OTHER_COMMAND_EXECUTING(); + + if(wiconnect->internalProcessingState == FS_SET_IP) + { + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_IP, IPV4_ARGS(ip)))) + { + wiconnect->internalProcessingState = FS_SET_NETMASK; + } + } + + if(wiconnect->internalProcessingState == FS_SET_NETMASK) + { + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_NETMASK, IPV4_ARGS(netmask)))) + { + wiconnect->internalProcessingState = FS_SET_GATEWAY; + } + } + + if(wiconnect->internalProcessingState == FS_SET_GATEWAY) + { + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(CMD_SET_STATIC_GATEWAY, IPV4_ARGS(gateway)))) + { + } + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::setIpSettings(const char* ipStr, const char* netmaskStr, const char* gatewayStr) +{ + uint32_t ip, nm, gw; + + if( !NetworkInterface::strToIp(ipStr, &ip) || + !NetworkInterface::strToIp(netmaskStr, &nm) || + !NetworkInterface::strToIp(gatewayStr, &gw)) + { + return WICONNECT_ERROR; + } + return setIpSettings(ip, nm, gw); +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::getIpSettings(uint32_t *ip, uint32_t *netmask, uint32_t *gateway) +{ + WiconnectResult result = WICONNECT_ERROR; + + enum + { + FS_GET_IP, + FS_GET_NETMASK, + FS_GET_GATEWAY + }; + + CHECK_OTHER_COMMAND_EXECUTING(); + + if(wiconnect->internalProcessingState == FS_GET_IP) + { + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.ip"))) + { + if(!NetworkInterface::strToIp(wiconnect->internalBuffer, ip)) + { + result = WICONNECT_RESPONSE_PARSE_ERROR; + } + else + { + wiconnect->internalProcessingState = FS_GET_NETMASK; + } + } + } + + if(wiconnect->internalProcessingState == FS_GET_NETMASK) + { + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.netmask"))) + { + if(!NetworkInterface::strToIp(wiconnect->internalBuffer, netmask)) + { + result = WICONNECT_RESPONSE_PARSE_ERROR; + } + else + { + wiconnect->internalProcessingState = FS_GET_GATEWAY; + } + } + } + + if(wiconnect->internalProcessingState == FS_GET_GATEWAY) + { + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.gateway"))) + { + if(!NetworkInterface::strToIp(wiconnect->internalBuffer, gateway)) + { + result = WICONNECT_RESPONSE_PARSE_ERROR; + } + } + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::setDnsAddress(uint32_t dnsAddress) +{ + WiconnectResult result; + + CHECK_OTHER_COMMAND_EXECUTING(); + + result = wiconnect->sendCommand("set static.dns %d.%d.%d.%d", IPV4_ARGS(dnsAddress)); + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::getDnsAddress(uint32_t *dnsAddress) +{ + WiconnectResult result; + + CHECK_OTHER_COMMAND_EXECUTING(); + + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get static.dns"))) + { + if(!NetworkInterface::strToIp(wiconnect->internalBuffer, dnsAddress)) + { + result = WICONNECT_RESPONSE_PARSE_ERROR; + } + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::getRssi(int32_t *rssiPtr) +{ + WiconnectResult result; + + CHECK_OTHER_COMMAND_EXECUTING(); + + *rssiPtr = -999; + + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("rssi"))) + { + result = wiconnect->responseToInt32(rssiPtr); + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::getSignalStrength(NetworkSignalStrength *signalStrengthPtr) +{ + WiconnectResult result; + int32_t rssiDbm; + + if(WICONNECT_SUCCEEDED(result, getRssi(&rssiDbm))) + { + *signalStrengthPtr = NetworkInterface::rssiToSignalStrength(rssiDbm); + } + else if(result == WICONNECT_CMD_RESPONSE_ERROR) + { + *signalStrengthPtr = NETWORK_RSSI_UNKNOWN; + result = WICONNECT_SUCCESS; + } + + return result; +} + +/*************************************************************************************************/ +WiconnectResult NetworkInterface::getMacAddress(MacAddress *macAddress) +{ + WiconnectResult result; + + CHECK_OTHER_COMMAND_EXECUTING(); + + if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get wlan.mac"))) + { + if(!Wiconnect::strToMacAddress(wiconnect->internalBuffer, macAddress)) + { + result = WICONNECT_RESPONSE_PARSE_ERROR; + } + } + + CHECK_CLEANUP_COMMAND(); + + return result; +} + + +/*************************************************************************************************/ +const char* NetworkInterface::getIpAddress(char *ipStrBuffer) +{ + SET_STR_BUFFER(ipStrBuffer, 17); + + if(wiconnect->nonBlocking) + { + return "Err"; + } + + if(wiconnect->sendCommand(ptr, 17, "get network.ip") != WICONNECT_SUCCESS) + { + strcpy(ptr, "0.0.0.0"); + } + + return ptr; +} + + +//----------------------------------------------------------------------------------------------- + + +/*************************************************************************************************/ +bool NetworkInterface::strToIp(const char *str, uint32_t *intPtr) +{ + if (!intPtr) + { + return false; + } + uint32_t ip = 0; + int i; + char *tok; + + for(i = 0; i < 4; ++i, str = tok) + { + uint8_t nibble; + + tok = strchr(str, '.'); + if(tok == NULL) + { + if(i < 3) + { + return false; + } + } + else + { + *tok++ = 0; + } + + if(!StringUtil::strToUint8(str, &nibble)) + { + return false; + } + ip |= (((uint32_t)nibble) << 24); + if(i < 3) + { + ip = (ip >> 8UL); + } + } + + if(i != 4) + { + return false; + } + + *intPtr = ip; + + return true; +} + +/*************************************************************************************************/ +const char* NetworkInterface::ipToStr(uint32_t ip, char *ipStrBuffer) +{ + SET_STR_BUFFER(ipStrBuffer, 17); + + sprintf(ptr, IPV4_FORMAT, IPV4_ARGS(ip)); + return ptr; +} + +/*************************************************************************************************/ +const char* NetworkInterface::networkStatusToStr(NetworkStatus status) +{ + switch(status) + { + case NETWORK_STATUS_DOWN: + return "Down"; + case NETWORK_STATUS_WIFI_ONLY: + return "WiFi Only"; + case NETWORK_STATUS_UP: + return "Up"; + default: + return "Unknown"; + } +} + +/*************************************************************************************************/ +const char* NetworkInterface::networkJoinResultToStr(NetworkJoinResult joinResult) +{ + switch(joinResult) + { + case NETWORK_JOIN_RESULT_NONE: + return "None"; + case NETWORK_JOIN_RESULT_SUCCESS: + return "Success"; + case NETWORK_JOIN_RESULT_JOINING: + return "Joining"; + case NETWORK_JOIN_RESULT_NO_SSID: + return "No SSID"; + case NETWORK_JOIN_RESULT_NO_PASSWORD: + return "No Password"; + case NETWORK_JOIN_RESULT_BAD_SECURITY: + return "Bad Security Setting"; + case NETWORK_JOIN_RESULT_NOT_FOUND: + return "Network Not Found"; + case NETWORK_JOIN_RESULT_FAILED: + return "Failed"; + case NETWORK_JOIN_RESULT_ABORTED: + return "Aborted"; + default: + return "Unknown"; + } +} + + +/*************************************************************************************************/ +const char* NetworkInterface::signalStrengthToStr(NetworkSignalStrength signalStrenth) +{ + switch(signalStrenth) + { + case NETWORK_RSSI_EXCELLENT: + return "Excellent"; + case NETWORK_RSSI_VERY_GOOD: + return "Very Good"; + case NETWORK_RSSI_GOOD: + return "Good"; + case NETWORK_RSSI_POOR: + return "Poor"; + case NETWORK_RSSI_VERY_POOR: + return "Very Poor"; + case NETWORK_RSSI_UNKNOWN: + default: + return "Unknown"; + } +} + +/*************************************************************************************************/ +NetworkSignalStrength NetworkInterface::rssiToSignalStrength(int rssi_dbm) +{ + if(rssi_dbm > -20) + { + return NETWORK_RSSI_EXCELLENT; + } + else if(rssi_dbm > -35) + { + return NETWORK_RSSI_VERY_GOOD; + } + else if(rssi_dbm > -50) + { + return NETWORK_RSSI_GOOD; + } + else if(rssi_dbm > -70) + { + return NETWORK_RSSI_POOR; + } + else + { + return NETWORK_RSSI_VERY_POOR; + } +} + + +typedef struct +{ + const char* key; + NetworkSecurity value; +} NetworkSecurityTableEntry; + +static const NetworkSecurityTableEntry networkSecurityTable[] = { + {"Auto", NETWORK_SECURITY_UNKNOWN}, + {"Open", NETWORK_SECURITY_OPEN}, + {"Unknown", NETWORK_SECURITY_UNKNOWN}, + {"WEP", NETWORK_SECURITY_WEP_PSK}, + {"WPA-AES", NETWORK_SECURITY_WPA_AES_PSK}, + {"WPA-TKIP", NETWORK_SECURITY_WPA_TKIP_PSK}, + {"WPA2-AES", NETWORK_SECURITY_WPA2_AES_PSK}, + {"WPA2-Mixed", NETWORK_SECURITY_WPA2_MIXED_PSK}, + {"WPA2-TKIP", NETWORK_SECURITY_WPA2_TKIP_PSK}, +}; + + +/*************************************************************************************************/ +NetworkSecurity NetworkInterface::strToNetworkSecurity(const char *str) +{ + const NetworkSecurityTableEntry *end = &networkSecurityTable[ARRAY_COUNT(networkSecurityTable)]; + + for(const NetworkSecurityTableEntry *e = networkSecurityTable; e < end; ++e) + { + if(StringUtil::strcasecmp(e->key, str) == 0) + { + return e->value; + } + } + return NETWORK_SECURITY_UNKNOWN; +} + +/*************************************************************************************************/ +const char* NetworkInterface::networkSecurityToStr(NetworkSecurity security) +{ + const NetworkSecurityTableEntry *end = &networkSecurityTable[ARRAY_COUNT(networkSecurityTable)]; + + for(const NetworkSecurityTableEntry *e = networkSecurityTable; e < end; ++e) + { + if(e->value == security) + { + return e->key; + } + } + return "Unknown"; +} + +/*************************************************************************************************/ +bool NetworkInterface::strToSsid(const char *str, Ssid *ssid) +{ +#define ESCAPE_CHARACTER_DELIMITER '\\' +#define HEX_ESCAPE_CHARACTER 'x' + int c; + uint8_t *ssidPtr = ssid->val; + uint32_t ssidLen = 0; + + while((c = (int)(*str++)) != 0) + { + if(c == ESCAPE_CHARACTER_DELIMITER) + { + if(*str == HEX_ESCAPE_CHARACTER) + { + c = StringUtil::hexToInt(str+1); + if(c == -1) + return false; + str += 3; + } + else + { + return false; + } + } + if(ssidLen >= sizeof(ssid->val)) + return false; + ++ssidLen; + *ssidPtr++ = (uint8_t)c; + } + + ssid->len = ssidLen; + + return true; +} + +/*************************************************************************************************/ +const char* NetworkInterface::ssidToStr(const Ssid *ssid, char *ssidStrBuffer) +{ + SET_STR_BUFFER(ssidStrBuffer, sizeof(SsidStrBuffer)); + const char *src = (const char*)ssid->val; + int len = ssid->len; + char *buf = ptr; + + while(len--) + { + if(*src >= 0x20 && *src <= 0x7E) + { + *ptr++ = *src; + } + else + { + ptr += sprintf(ptr, "\\x%02X", (*src) & 0xff); + } + ++src; + } + *ptr = 0; + return buf; +} + +/*************************************************************************************************/ +bool NetworkInterface::strToMacAddress(const char *str, MacAddress *macAddress) +{ + const char* strPtr = str; + uint8_t *macPtr = (uint8_t*)macAddress->octet; + + for(int count = 0; count < 6; ++count) + { + if(count < 5) + { + const char *idx = strchr(strPtr, ':'); + if(idx == NULL) + { + return false; + } + } + int num = StringUtil::hexToInt(strPtr); + if(num == -1) + { + return false; + } + *macPtr++ = (uint8_t)num; + strPtr += 3; + } + + return true; +} + +/*************************************************************************************************/ +const char* NetworkInterface::macAddressToStr(const MacAddress *macAddress, char *macStrBuffer) +{ + SET_STR_BUFFER(macStrBuffer, sizeof(MacAddressStrBuffer)); + const uint8_t *mac = macAddress->octet; + + sprintf(ptr, "%02X:%02X:%02X:%02X:%02X:%02X", + (unsigned int)mac[0], + (unsigned int)mac[1], + (unsigned int)mac[2], + (unsigned int)mac[3], + (unsigned int)mac[4], + (unsigned int)mac[5]); + + return ptr; +}