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

Files at this revision

API Documentation at this revision

Comitter:
dan_ackme
Date:
Mon Aug 11 09:58:24 2014 +0000
Child:
1:6ec9998427ad
Commit message:
initial check-in

Changed in this revision

FileInterface.h Show annotated file Show diff for this revision Revisions of this file
NetworkInterface.h Show annotated file Show diff for this revision Revisions of this file
SocketInterface.h Show annotated file Show diff for this revision Revisions of this file
StringUtil.h Show annotated file Show diff for this revision Revisions of this file
Wiconnect.h Show annotated file Show diff for this revision Revisions of this file
WiconnectInterface.h Show annotated file Show diff for this revision Revisions of this file
WiconnectTypes.h Show annotated file Show diff for this revision Revisions of this file
internal/WiconnectCommands.h Show annotated file Show diff for this revision Revisions of this file
internal/common.h Show annotated file Show diff for this revision Revisions of this file
internal/file/FileInterface.cpp Show annotated file Show diff for this revision Revisions of this file
internal/file/FileList.cpp Show annotated file Show diff for this revision Revisions of this file
internal/network/NetworkInterface.cpp Show annotated file Show diff for this revision Revisions of this file
internal/network/NetworkJoin.cpp Show annotated file Show diff for this revision Revisions of this file
internal/network/NetworkScan.cpp Show annotated file Show diff for this revision Revisions of this file
internal/network/NetworkSoftAp.cpp Show annotated file Show diff for this revision Revisions of this file
internal/network/NetworkWebSetup.cpp Show annotated file Show diff for this revision Revisions of this file
internal/socket/SocketInterface.cpp Show annotated file Show diff for this revision Revisions of this file
internal/types/File.cpp Show annotated file Show diff for this revision Revisions of this file
internal/types/FileList.cpp Show annotated file Show diff for this revision Revisions of this file
internal/types/QueuedCommand.cpp Show annotated file Show diff for this revision Revisions of this file
internal/types/ScanResult.cpp Show annotated file Show diff for this revision Revisions of this file
internal/types/ScanResultList.cpp Show annotated file Show diff for this revision Revisions of this file
internal/types/Socket.cpp Show annotated file Show diff for this revision Revisions of this file
internal/wiconnect/AsyncCommand.cpp Show annotated file Show diff for this revision Revisions of this file
internal/wiconnect/CommandCommon.h Show annotated file Show diff for this revision Revisions of this file
internal/wiconnect/ProcessCommand.cpp Show annotated file Show diff for this revision Revisions of this file
internal/wiconnect/SendCommand.cpp Show annotated file Show diff for this revision Revisions of this file
internal/wiconnect/Wiconnect.cpp Show annotated file Show diff for this revision Revisions of this file
internal/wiconnect/WiconnectCommand.cpp Show annotated file Show diff for this revision Revisions of this file
sdk/mbed/Gpio.cpp Show annotated file Show diff for this revision Revisions of this file
sdk/mbed/PeriodicTimer.cpp Show annotated file Show diff for this revision Revisions of this file
sdk/mbed/PinIrqHandler.cpp Show annotated file Show diff for this revision Revisions of this file
sdk/mbed/TimeoutTimer.cpp Show annotated file Show diff for this revision Revisions of this file
sdk/mbed/WiconnectSerial.cpp Show annotated file Show diff for this revision Revisions of this file
sdk/mbed/sdk.h Show annotated file Show diff for this revision Revisions of this file
types/Callback.h Show annotated file Show diff for this revision Revisions of this file
types/CommandQueue.h Show annotated file Show diff for this revision Revisions of this file
types/File.h Show annotated file Show diff for this revision Revisions of this file
types/FileList.h Show annotated file Show diff for this revision Revisions of this file
types/FunctionPointer.h Show annotated file Show diff for this revision Revisions of this file
types/Gpio.h Show annotated file Show diff for this revision Revisions of this file
types/LogFunc.h Show annotated file Show diff for this revision Revisions of this file
types/PeriodicTimer.h Show annotated file Show diff for this revision Revisions of this file
types/PinIrqHandler.h Show annotated file Show diff for this revision Revisions of this file
types/QueuedCommand.h Show annotated file Show diff for this revision Revisions of this file
types/ReaderFunc.h Show annotated file Show diff for this revision Revisions of this file
types/ScanResult.h Show annotated file Show diff for this revision Revisions of this file
types/ScanResultList.h Show annotated file Show diff for this revision Revisions of this file
types/Socket.h Show annotated file Show diff for this revision Revisions of this file
types/SocketIrqHandlerMap.h Show annotated file Show diff for this revision Revisions of this file
types/TimeoutTimer.h Show annotated file Show diff for this revision Revisions of this file
types/WiconnectSerial.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileInterface.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "mbed.h"
+
+#include "WiconnectTypes.h"
+#include "types/FileList.h"
+
+
+#define FILE_NAME_MAX_SIZE 96
+#define FILE_MAKE_VERSION(major, minor, patch, rc) ((unsigned int)((major) << 27)|(unsigned int)((minor) << 21)|(unsigned int)((patch) << 8)|(unsigned int)((rc) << 0))
+#define FILE_VERSION_ARGS(version) (unsigned int)((version >> 27) & 0x1F),(unsigned int)((version >> 21) & 0x3F),(unsigned int)((version >> 8) & 0x1FFF),(unsigned int)(version & 0xFF)
+
+
+namespace wiconnect {
+
+
+class FileInterface
+{
+public:
+    FileInterface(Wiconnect *wiconnect);
+
+    WiconnectResult createFile(const ReaderFunc &reader, void *user, const char *name, uint32_t size, uint32_t version = 0, FileType type = FILE_TYPE_ANY, bool isEssential = false, int32_t checksum = -1);
+    WiconnectResult openFile(File &file, const char *name);
+    WiconnectResult deleteFile(const char *name);
+    WiconnectResult deleteFile(const File &file);
+    WiconnectResult listFiles(FileList &list, const char *name = NULL, FileType type = FILE_TYPE_ANY, uint32_t version = 0);
+
+    static const char* fileVersionIntToStr(uint32_t version, bool verbose = true, char *buffer = NULL);
+    static bool fileVersionStrToInt(const char *versionStr, uint32_t *versionIntPtr);
+    static const char* fileTypeToStr(FileType type);
+    static const char* fileFlagsToStr(FileFlags flags, char *buffer = NULL);
+
+protected:
+    WiconnectResult processFileList(char *responseStr, FileList &list, const char *name, FileType type, uint32_t version);
+private:
+    Wiconnect *wiconnect;
+};
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkInterface.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include "WiconnectTypes.h"
+#include "types/ScanResultList.h"
+
+
+namespace wiconnect {
+
+
+class NetworkInterface
+{
+public:
+    WiconnectResult startWebSetup(const char *ssid = NULL, const char *password = NULL, const Callback &completeHandler = Callback());
+    WiconnectResult stopWebSetup();
+    WiconnectResult isWebSetupRunning(bool *isRunningPtr);
+
+    WiconnectResult join(const char* ssid = NULL, const char *password = NULL, const Callback &completeHandler = Callback());
+    WiconnectResult leave();
+    WiconnectResult getNetworkStatus(NetworkStatus *statusPtr);
+
+//    WiconnectResult startSoftAp(const char* ssid = NULL, const char *password = NULL, const Callback &clientConnectedCallback = Callback());
+//    WiconnectResult stopSoftAp();
+//    WiconnectResult getSoftApClientList();
+
+    WiconnectResult scan(ScanResultList &resultList, const uint8_t *channelList = NULL, const char* ssid = NULL);
+    WiconnectResult ping(const char *domain = NULL, uint32_t *timeMsPtr = NULL);
+    WiconnectResult lookup(const char *domain, uint32_t *ipAddressPtr);
+
+    WiconnectResult setDhcpEnabled(bool enabled);
+    WiconnectResult getDhcpEnabled(bool *enabledPtr);
+    WiconnectResult setIpSettings(uint32_t ip, uint32_t netmask, uint32_t gateway);
+    WiconnectResult setIpSettings(const char* ip, const char* netmask, const char* gateway);
+    WiconnectResult getIpSettings(uint32_t *ip, uint32_t *netmask, uint32_t *gateway);
+    WiconnectResult getSignalStrength(NetworkSignalStrength *signalStrengthPtr);
+
+    static bool strToIp(const char *str, uint32_t *intPtr);
+    static const char* ipToStr(uint32_t ip, char *ipStrBuffer = NULL);
+    static const char* networkStatusToStr(NetworkStatus status);
+    static const char* signalStrengthToStr(NetworkSignalStrength signalStrenth);
+    static NetworkSignalStrength rssiToSignalStrength(int rssi);
+    static NetworkSecurity strToNetworkSecurity(const char *str);
+    static const char* networkSecurityToStr(NetworkSecurity security);
+    static bool strToSsid(const char *str, Ssid *ssid);
+    static const char* ssidToStr(const Ssid *ssid, char *ssidStrBuffer = NULL);
+    static bool strToMacAddress(const char *str, MacAddress *macAddress);
+    static const char* macAddressToStr(const MacAddress *macAddress, char *macStrBuffer = NULL);
+
+protected:
+    NetworkInterface(Wiconnect *wiconnect);
+
+    WiconnectResult processScanResults(char *resultStr, ScanResultList &resultList);
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+    Callback completeHandler;
+    PeriodicTimer monitorTimer;
+
+    void webSetupStatusMonitor();
+    void webSetupStatusCheckCallback(WiconnectResult result, void *arg1, void *arg2);
+
+    void joinStatusMonitor();
+    void joinStatusCheckCallback(WiconnectResult result, void *arg1, void *arg2);
+
+    //void scanCompleteCallback(WiconnectResult result, void *arg1, void *arg2);
+#endif
+
+private:
+    Wiconnect *wiconnect;
+};
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SocketInterface.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "Wiconnect.h"
+#include "types/Socket.h"
+#include "types/SocketIrqHandlerMap.h"
+
+
+namespace wiconnect {
+
+
+#define SOCKET_ANY_PORT (uint16_t)0
+
+
+
+class SocketInterface
+{
+public:
+    SocketInterface(Wiconnect *wiconnect);
+    ~SocketInterface();
+
+    WiconnectResult closeAllSockets();
+    WiconnectResult registerSocketIrqHandler(Pin irqPin, const Callback &handler);
+    WiconnectResult unregisterSocketIrqHandler(Pin irqPin);
+
+    WiconnectResult connect(Socket &socket, SocketType type, const char *host, uint16_t remortPort, uint16_t localPort, const void *args, Pin irqPin);
+    WiconnectResult tcpConnect(Socket &socket, const char *host, uint16_t remortPort, Pin irqPin = NC);
+    WiconnectResult tlsConnect(Socket &socket, const char *host, uint16_t remortPort, const char *certFilename = NULL, Pin irqPin = NC);
+    WiconnectResult udpConnect(Socket &socket, const char *host, uint16_t remortPort, uint16_t localPort = SOCKET_ANY_PORT, Pin irqPin = NC);
+    WiconnectResult httpConnect(Socket &socket, const char *url, const HttpSocketArgs *args);
+    WiconnectResult httpGet(Socket &socket, const char *url, bool openOnly = false, const char *certFilename = NULL);
+    WiconnectResult httpPost(Socket &socket, const char *url, const char *contextType, bool openOnly = true, const char *certFilename = NULL);
+    WiconnectResult httpHead(Socket &socket, const char *url, const char *certFilename = NULL);
+    WiconnectResult httpAddHeader(Socket &socket, const char *key, const char *value);
+    WiconnectResult httpGetStatus(Socket &socket, uint32_t *statusCodePtr);
+
+protected:
+    SocketIrqHandlerMap irqHandlers;
+
+private:
+    Wiconnect *wiconnect;
+};
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StringUtil.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <limits.h>
+
+
+#ifdef WICONNECT_USE_STRTOLL
+// Necessary to get strtoll in C99 mode.
+// http://sourceware.org/ml/newlib/2012/msg00425.html
+extern long long strtoll(const char *__n, char **__end_PTR, int __base);
+#endif
+
+
+class StringUtil
+{
+
+public:
+    /*************************************************************************************************/
+    // Helper to find an occurrence of a delimiter string,
+    // insert '\0' in its place and return string after
+    // the delimiter e.g.
+    //     if char s[] = "foo://bar";
+    //     - strchop(s, "://") returns "bar"
+    //     - s becomes "foo"
+    static char *chop(char *haystack, const char *needle)
+    {
+        if (!haystack)
+        {
+            return NULL;
+        }
+        char *end = strstr(haystack, needle);
+        if (end)
+        {
+            *end = '\0';
+            return end + strlen(needle);
+        }
+        return NULL;
+    }
+
+    /*************************************************************************************************/
+    // Check if string is non-null and non-empty.
+    static bool empty(const char *s)
+    {
+        return !(s && *s);
+    }
+
+    /*************************************************************************************************/
+    static bool isSpace(const char *s)
+    {
+        while(*s != 0)
+        {
+            if(!isspace((uint8_t)*s++))
+                return false;
+        }
+        return true;
+    }
+
+    /*************************************************************************************************/
+    // Convert null-terminated string to lower case.
+    // ASCII charset only.
+    static void toLower(char *s)
+    {
+        for (; *s; ++s)
+        {
+            *s = tolower((int) * s);
+        }
+    }
+
+    /*************************************************************************************************/
+    // Combination of strip left + right.
+    static char *strip(char *s, const char *chars)
+    {
+        return rightStrip(leftStrip(s, chars), chars);
+    }
+
+    /*************************************************************************************************/
+    // Strip string from the left.
+    // Returns pointer into the input string.
+    static char *leftStrip(char *s, const char *chars)
+    {
+        return s + strspn(s, chars);
+    }
+
+    /*************************************************************************************************/
+    // Strip string from the right.
+    // Modified in place.
+    static char *rightStrip(char *s, const char *chars)
+    {
+        char *end = s + strlen(s) - 1;
+        while (end > s && strstr(chars, end))
+        {
+            *end-- = '\0';
+        }
+        return s;
+    }
+
+    /*************************************************************************************************/
+    // Parse decimal integer and check if it's in bounds [min, max].
+    static bool parseInt(const char *s, intmax_t *result, intmax_t min, intmax_t max)
+    {
+        return parseBase(s, result, min, max, 10);
+    }
+
+    // Parse hexadecimal integer and check if it's in bounds [min, max].
+    static bool parseHex(const char *s, intmax_t *result, intmax_t min, intmax_t max)
+    {
+        return parseBase(s, result, min, max, 16);
+    }
+
+    /*************************************************************************************************/
+    static bool parseBase(const char *s, intmax_t *result, intmax_t min, intmax_t max, int base)
+    {
+        if (!s)
+        {
+            return false;
+        }
+        char *end;
+#ifdef WICONNECT_USE_STRTOLL
+        intmax_t value = strtoll(s, &end, base);
+#else
+        intmax_t value = strtol(s, &end, base);
+#endif
+        if (*end || value < min || value > max)
+        {
+            return false;
+        }
+        *result = value;
+        return true;
+    }
+
+    /*************************************************************************************************/
+    // Parse an long long integer.
+    static bool parseBool(const char *onoff, bool *var)
+    {
+        const char* const on_vals[] =
+        {
+                "1",
+                "on",
+                "true",
+                "yes",
+        };
+
+        for(uint8_t i = 0; i < ARRAY_COUNT(on_vals); ++i)
+        {
+            if(strcasecmp(on_vals[i], onoff) == 0)
+            {
+                *var = true;
+                return true;
+            }
+        }
+
+        const char* const off_vals[] =
+        {
+                "0",
+                "false",
+                "no",
+                "off",
+                NULL
+        };
+        for(uint8_t i = 0; i < ARRAY_COUNT(off_vals); ++i)
+        {
+            if(strcasecmp(off_vals[i], onoff) == 0)
+            {
+                *var = false;
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /*************************************************************************************************/
+    // convert binary data to hex string
+    static void binToHex(char *dst, int max_dst, const void *data, int data_len)
+    {
+        char *end = dst + max_dst - 1;
+        for (int i = 0; i < data_len; ++i)
+        {
+            if (dst < end)
+            {
+                dst += sprintf(dst, "%2.2x", ((uint8_t *)data)[i]);
+            }
+        }
+    }
+
+
+    /*************************************************************************************************/
+    // Parse binary data into hex string
+    // the input buffer MUST be len*2  long
+    // as the parsing is destructive and done in-place
+    static void binToHex(void *h, int len)
+    {
+        char *dst = (char*)h;
+        char *src= (char*)h+len;
+
+        memmove(src, dst, len);
+
+        while(len--)
+        {
+            sprintf(dst, "%2.2X", (unsigned int)(*src & 0xff));
+            dst += 2;
+            ++src;
+        }
+    }
+
+
+    /*************************************************************************************************/
+    // Parses hex representation of binary data destructively.
+    // Returns number of bytes parsed or -1 on error.
+    static int hexToBin(char *s)
+    {
+        int len, i, j;
+        len = strlen(s);
+        if (len % 2)
+        {
+            return -1;
+        }
+        for (i = j = 0; i < len; i += 2, j++)
+        {
+            const int num = hexToInt(&s[i]);
+            if(num == -1)
+                return -1;
+            s[j] = (char)num;
+        }
+        return j;
+    }
+
+    /*************************************************************************************************/
+    // hex string to integer, returns -1 on error
+    static int hexToInt(const char *hex_str)
+    {
+        int hi = hexToNibble(*hex_str);
+        int lo = hexToNibble(*(hex_str+1));
+        if (hi == -1 || lo == -1)
+        {
+            return -1;
+        }
+        return (hi << 4) | lo;
+    }
+
+    /*************************************************************************************************/
+    static int hexToNibble(char c)
+    {
+        if (c >= '0' && c <= '9')
+        {
+            return c - '0';
+        }
+        if (c >= 'a' && c <= 'f')
+        {
+            return 10 + (c - 'a');
+        }
+        if (c >= 'A' && c <= 'F')
+        {
+            return 10 + (c - 'A');
+        }
+        return -1;
+    }
+
+    /*************************************************************************************************/
+    static const char* uint32ToStr(char* intStrBuffer, int integer)
+    {
+        sprintf(intStrBuffer, "%u", integer);
+        return intStrBuffer;
+    }
+
+    /*************************************************************************************************/
+    static bool strToUint32(const char *str, uint32_t *uint32Ptr)
+    {
+        intmax_t r;
+        bool result = StringUtil::parseInt(str, &r, 0, UINT_MAX);
+        *uint32Ptr = (uint32_t)r;
+        return result;
+    }
+
+    /*************************************************************************************************/
+    static bool strToInt32(const char *str, int32_t *int32Ptr)
+    {
+        intmax_t r;
+        bool result = StringUtil::parseInt(str, &r, INT_MIN, INT_MAX);
+        *int32Ptr = (int32_t)r;
+        return result;
+    }
+
+    /*************************************************************************************************/
+    // uint32 hex string to uint32
+    static bool strHexToUint32(const char *strHex, uint32_t *uint32Ptr)
+    {
+        intmax_t r;
+        bool result = StringUtil::parseHex(strHex, &r, 0, UINT_MAX);
+        *uint32Ptr = (uint32_t)r;
+        return result;
+    }
+
+    /*************************************************************************************************/
+    static char *strtok_r(char *str, const char *delim, char **nextp)
+    {
+        char *ret;
+
+        if (str == NULL)
+        {
+            str = *nextp;
+        }
+
+        str += strspn(str, delim);
+
+        if (*str == '\0')
+        {
+            return NULL;
+        }
+
+        ret = str;
+
+        str += strcspn(str, delim);
+
+        if (*str)
+        {
+            *str++ = '\0';
+        }
+
+        *nextp = str;
+
+        return ret;
+    }
+
+    /*************************************************************************************************/
+    static int strncasecmp(const char *s1, const char *s2, int n)
+    {
+        if (n == 0)
+            return 0;
+
+        while (n-- != 0 && tolower(*s1) == tolower(*s2))
+        {
+            if (n == 0 || *s1 == '\0' || *s2 == '\0')
+                break;
+            s1++;
+            s2++;
+        }
+
+        return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
+    }
+
+    /*************************************************************************************************/
+    static int strcasecmp(const char *s1, const char *s2)
+    {
+        register const unsigned char *p1 = (const unsigned char *) s1;
+        register const unsigned char *p2 = (const unsigned char *) s2;
+        unsigned char c1, c2;
+
+        if (p1 == p2)
+            return 0;
+
+        do
+        {
+            c1 = tolower (*p1);
+            c2 = tolower (*p2);
+
+            if (c1 == '\0')
+                break;
+
+            ++p1;
+            ++p2;
+        }
+        while (c1 == c2);
+
+        if (UCHAR_MAX <= INT_MAX)
+            return c1 - c2;
+        else
+            /* On machines where 'char' and 'int' are types of the same size, the
+               difference of two 'unsigned char' values - including the sign bit -
+               doesn't fit in an 'int'.  */
+            return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+    }
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wiconnect.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+
+#include "WiconnectInterface.h"
+
+
+using namespace wiconnect;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WiconnectInterface.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "WiconnectTypes.h"
+
+
+#include "types/LogFunc.h"
+#include "types/ReaderFunc.h"
+#include "types/Callback.h"
+#include "types/QueuedCommand.h"
+#include "types/CommandQueue.h"
+#include "types/TimeoutTimer.h"
+#include "types/PeriodicTimer.h"
+#include "types/Gpio.h"
+#include "types/WiconnectSerial.h"
+
+#include "NetworkInterface.h"
+#include "SocketInterface.h"
+#include "FileInterface.h"
+
+
+#ifdef WICONNECT_ENABLE_MALLOC
+#define WICONNECT_MALLOC_ARGS , void* (*malloc_)(size_t) = WICONNECT_DEFAULT_MALLOC, void (*free_)(void*) = WICONNECT_DEFAULT_FREE
+#else
+#define WICONNECT_MALLOC_ARGS
+#endif
+
+
+namespace wiconnect {
+
+
+class Wiconnect : public NetworkInterface,
+                  public SocketInterface,
+                  public FileInterface
+{
+public:
+    Wiconnect(const SerialConfig &serialConfig, Pin reset = PIN_NC, Pin wake = PIN_NC, bool nonBlocking = WICONNECT_DEFAULT_NONBLOCKING WICONNECT_MALLOC_ARGS);
+    Wiconnect(const SerialConfig &serialConfig, void *internalBuffer, int internalBufferSize, Pin reset = PIN_NC, Pin wake = PIN_NC, bool nonBlocking = WICONNECT_DEFAULT_NONBLOCKING WICONNECT_MALLOC_ARGS);
+    ~Wiconnect();
+
+    static Wiconnect* getInstance();
+
+    WiconnectResult init(bool bringNetworkUp);
+    void deinit();
+    bool isInitialized();
+    WiconnectResult reset();
+    WiconnectResult wakeup();
+    void flush(int delayMs = 500);
+
+    WiconnectResult getVersion(char *versionBuffer = NULL, int versionBufferSize = 0, const Callback &completeCallback = Callback());
+
+    WiconnectResult sendCommand(const Callback &completeCallback, char *responseBuffer, int responseBufferLen,
+                                int timeoutMs, const ReaderFunc &reader, void *user, const char *cmd, va_list vaList);
+    WiconnectResult sendCommand(char *responseBuffer, int responseBufferLen, int timeoutMs, const ReaderFunc &reader,
+                                void *user, const char *cmd, va_list vaList);
+    WiconnectResult sendCommand(char *responseBuffer, int responseBufferLen, int timeoutMs, const ReaderFunc &reader,
+                                void *user, const char *cmd, ...);
+    WiconnectResult sendCommand( int timeoutMs, const ReaderFunc &reader, void *user, const char *cmd, ...);
+    WiconnectResult sendCommand(const ReaderFunc &reader, void *user, const char *cmd, ...);
+    WiconnectResult sendCommand(char *responseBuffer, int responseBufferLen,  int timeoutMs, const char *cmd, ...);
+    WiconnectResult sendCommand(const Callback &completeCallback, char *responseBuffer, int responseBufferLen, const char *cmd, ...);
+    WiconnectResult sendCommand(char *responseBuffer, int responseBufferLen, const char *cmd, ...);
+    WiconnectResult sendCommand(const Callback &completeCallback, const char *cmd, ...);
+    WiconnectResult sendCommand(const char *cmd, ...);
+    WiconnectResult sendCommand(const Callback &completeCallback, int timeoutMs, const char *cmd, ...);
+    WiconnectResult sendCommand(int timeoutMs, const char *cmd, ...);
+    WiconnectResult sendCommand(const char *cmd, va_list vaList);
+
+    const char* getLastCommandResponseCodeStr();
+    uint16_t getLastCommandResponseLength();
+    char* getResponseBuffer();
+    WiconnectResult responseToUint32(uint32_t *uint32Ptr);
+    WiconnectResult responseToInt32(int32_t *int32Ptr);
+
+    WiconnectResult checkCurrentCommand();
+    void stopCurrentCommand();
+    void setCommandDefaultTimeout(int timeoutMs);
+    int getCommandDefaultTimeout();
+
+    void setPinToGpioMapper(PinToGpioMapper mapper);
+
+    static const char* getWiconnectResultStr(WiconnectResult wiconnectResult);
+    void setDebugLogger(LogFunc logFunc);
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+    WiconnectResult enqueueCommand(QueuedCommand *command, const Callback &commandCompleteHandler = Callback());
+    void setCommandProcessingPeriod(uint32_t periodMs);
+#endif
+
+protected:
+
+#ifdef WICONNECT_ENABLE_MALLOC
+    void* (*_malloc)(size_t);
+    void (*_free)(void *);
+    friend class QueuedCommand;
+    friend class WiconnectSerial;
+    friend class ScanResult;
+    friend class Socket;
+    friend class File;
+#endif
+
+    wiconnect::WiconnectSerial serial;
+    wiconnect::Gpio resetGpio;
+    wiconnect::Gpio wakeGpio;
+
+    volatile bool commandExecuting;
+    bool initialized;
+    bool nonBlocking;
+
+    PinToGpioMapper pinToGpioMapper;
+
+    char *internalBuffer;
+    int internalBufferSize;
+    bool internalBufferAlloc;
+    uint8_t internalProcessingState;
+    void *currentCommandId;
+
+    wiconnect::TimeoutTimer timeoutTimer;
+    int defaultTimeoutMs;
+
+    uint8_t commandHeaderBuffer[32];
+    char commandFormatBuffer[WICONNECT_MAX_CMD_SIZE];
+    uint8_t commandContext[96];
+
+    void prepare(void *internalBuffer, int internalBufferSize, bool nonBlocking);
+    WiconnectResult inline receiveResponse();
+    WiconnectResult inline receivePacket();
+    void issueCommandCallback(WiconnectResult result);
+
+    wiconnect::LogFunc debugLogger;
+    void debugLog(const char *msg, ...);
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+    wiconnect::PeriodicTimer commandProcessorTimer;
+    uint32_t commandProcessingPeriod;
+    CommandQueue commandQueue;
+    wiconnect::QueuedCommand *currentQueuedCommand;
+
+    void commandProcessingTimerHandler(void);
+    void processNextQueuedCommand();
+    void checkQueuedCommandTimeout();
+#endif
+
+    friend class NetworkInterface;
+    friend class SocketInterface;
+    friend class FileInterface;
+};
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WiconnectTypes.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdarg.h>
+
+#include "sdk.h"
+
+namespace wiconnect {
+
+
+#ifndef MIN
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#endif
+#ifndef MAX
+#define MAX(x,y)  ((x) > (y) ? (x) : (y))
+#endif
+#define ALIGN_n(x, n) ((((uint32_t)x) + ((n)-1)) & ~((n)-1))
+#define ALIGN_8(x) ALIGN_n(x, 8)
+#define ALIGN_4(x) ALIGN_n(x, 4)
+
+#ifndef OFFSETOF
+#define    OFFSETOF(type, member)    ((uintptr_t)&((type *)0)->member)
+#endif
+
+#define ARRAY_COUNT(x) (sizeof (x) / sizeof *(x))
+
+
+#define WICONNECT_FAILED(result, func) ((int)(result = (func)) < (int)wiconnect::WICONNECT_SUCCESS)
+#define WICONNECT_SUCCEEDED(result, func) ((result = (func)) == wiconnect::WICONNECT_SUCCESS)
+
+#define WICONNECT_NULL_RESPONSE_HANDLER WiconnectAsyncCallback()
+
+
+#define WICONNECT_MAX_CMD_SIZE 128
+#define WICONNECT_MAX_VERSION_SIZE 96
+#define WICONNECT_MAX_SOCKETS 8
+
+
+#define SOCKET_INVALID_HANDLE ((uint8_t)0xFF)
+
+
+typedef enum
+{
+    WICONNECT_ABORTED               = 3,
+    WICONNECT_IDLE                  = 2,
+    WICONNECT_PROCESSING            = 1,
+    WICONNECT_SUCCESS               = 0,
+    WICONNECT_ERROR                 = -1,
+    WICONNECT_CMD_RESPONSE_ERROR    = -2,
+    WICONNECT_NULL_BUFFER           = -3,
+    WICONNECT_NOT_INITIALIZED       = -4,
+    WICONNECT_OVERFLOW              = -5,
+    WICONNECT_TIMEOUT               = -6,
+    WICONNECT_RESPONSE_HANDLER_NULL = -7,
+    WICONNECT_RESPONSE_PARSE_ERROR  = -8,
+    WICONNECT_ANOTHER_CMD_EXECUTING = -9,
+    WICONNECT_BAD_ARG               = -10,
+    WICONNECT_UNSUPPORTED           = -11,
+    WICONNECT_PINNAME_TO_GPIO_MAPPER_NULL = -12,
+    WICONNECT_DUPLICATE             = -13,
+    WICONNECT_NOT_FOUND             = -14,
+    WICONNECT_PINNAME_TO_GPIO_NO_MAPPING = -15,
+    WICONNECT_NOT_CONNECTED         = -16,
+    WICONNECT_UNDERFLOW             = -17,
+    WICONNECT_MONITOR_NOT_AVAILABLE = -18,
+    WICONNECT_NOT_OPENED_FOR_READING = -19,
+} WiconnectResult;
+
+
+typedef enum
+{
+    NETWORK_STATUS_DOWN,
+    NETWORK_STATUS_WIFI_ONLY,
+    NETWORK_STATUS_UP
+} NetworkStatus;
+
+typedef enum
+{
+    NETWORK_RSSI_EXCELLENT              = 0,    ///< > -20 dBm
+    NETWORK_RSSI_VERY_GOOD              = 1,    ///< > -35 dBm
+    NETWORK_RSSI_GOOD                   = 2,    ///< > -50 dBm
+    NETWORK_RSSI_POOR                   = 3,    ///< > -70 dBm
+    NETWORK_RSSI_VERY_POOR              = 4,    ///< < -71 dBm
+    NETWORK_RSSI_UNKNOWN                = 5     ///< Not available
+} NetworkSignalStrength;
+
+typedef enum
+{
+    NETWORK_SECURITY_OPEN,
+    NETWORK_SECURITY_WEP_PSK,
+    NETWORK_SECURITY_WPA_AES_PSK,
+    NETWORK_SECURITY_WPA_TKIP_PSK,
+    NETWORK_SECURITY_WPA2_AES_PSK,
+    NETWORK_SECURITY_WPA2_MIXED_PSK,
+    NETWORK_SECURITY_WPA2_TKIP_PSK,
+    NETWORK_SECURITY_UNKNOWN
+} NetworkSecurity;
+
+typedef struct
+{
+    uint8_t val[32];
+    uint8_t len;
+} Ssid;
+
+typedef struct
+{
+    uint8_t octet[6];
+} MacAddress;
+typedef char MacAddressStrBuffer[18];
+typedef char SsidStrBuffer[129];
+typedef char IpStrBuffer[18];
+
+
+typedef enum
+{
+    SOCKET_TYPE_UNKNOWN,
+    SOCKET_TYPE_TCP,
+    SOCKET_TYPE_TLS,
+    SOCKET_TYPE_UDP,
+    SOCKET_TYPE_HTTP,
+} SocketType;
+
+typedef enum
+{
+    SOCKET_HTTP_GET,
+    SOCKET_HTTP_POST,
+    SOCKET_HTTP_HEAD,
+} HttpSocketType;
+
+typedef struct
+{
+    const char *contextType;
+    const char *certName;
+    bool openOnly;
+    HttpSocketType type;
+} HttpSocketArgs;
+
+typedef int8_t (*PinToGpioMapper)(Pin pin);
+
+
+typedef enum
+{
+    FILE_FLAG_NONE          = 0,
+
+    FILE_FLAG_VALID         = (1 << 0),
+    FILE_FLAG_EXECUTABLE    = (1 << 1),
+    FILE_FLAG_ENCRYPTED     = (1 << 2),
+    FILE_FLAG_INTERNAL      = (1 << 3),
+    FILE_FLAG_BOOTABLE      = (1 << 4),
+    FILE_FLAG_USER          = (1 << 5),
+    FILE_FLAG_ESSENTIAL     = (1 << 6),
+    FILE_FLAG_BACKUP        = (1 << 7),
+
+    FILE_FLAG_FORCE_COPY    = (1 << 15),
+
+    FILE_FLAG_INVALID       = 0xFFFF
+} FileFlags;
+
+typedef enum
+{
+    FILE_TYPE_UPGRADE_APP   = 0x00,
+    FILE_TYPE_WIFI_FW       = 0x01,
+    FILE_TYPE_SHARED_LIB    = 0x02,
+    FILE_TYPE_TLS_CERT      = 0x03,
+    FILE_TYPE_TXT_LOG       = 0x04,
+    FILE_TYPE_DCT           = 0x05,
+
+    FILE_TYPE_MISC_APP      = 0x80,
+    FILE_TYPE_REGULAR_APP   = 0x81,
+
+    FILE_TYPE_USER_RANGE_START = 150,
+    FILE_TYPE_USER_RANGE_END = 199,
+
+    FILE_TYPE_TEMPORY       = 0xF9,
+    FILE_TYPE_GPIO_CONFIG   = 0xFA,
+    FILE_TYPE_COMMAND_HELP  = 0xFB,
+    FILE_TYPE_SDC_CAPS      = 0xFC,
+    FILE_TYPE_SETUP_SCRIPT  = 0xFD,
+    FILE_TYPE_MISC_FIX_LEN  = 0xFE,
+    FILE_TYPE_UNKNOWN       = 0xFF,
+    FILE_TYPE_ANY           = FILE_TYPE_UNKNOWN
+} FileType;
+
+typedef struct
+{
+    int size;
+    uint8_t *buffer;
+    uint8_t *ptr;
+    int bytesPending;
+    bool allocated;
+} Buffer;
+
+
+class Wiconnect;
+class TimeoutTimer;
+class PeriodicTimer;
+class QueuedCommand;
+class CommandQueue;
+class LogFunc;
+class ReaderFunc;
+class Callback;
+class ScanResult;
+class ScanResultList;
+class Socket;
+class WiconnectSerial;
+class File;
+class FileList;
+class Gpio;
+class SocketIrqHandlerMap;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/WiconnectCommands.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+
+
+#define CMD_SAVE                            "save"
+#define CMD_GET_VERSION                     "ver"
+
+
+#define CMD_SET_SYSTEM_COMMAND_MODE         "set system.cmd.mode %s"
+#define CMD_SET_NETWORK_DHCP                "set network.dhcp %d"
+#define CMD_SET_STATIC_IP                   "set static.ip %d.%d.%d.%d"
+#define CMD_SET_STATIC_GATEWAY              "set static.netmask %d.%d.%d.%d"
+#define CMD_SET_STATIC_NETMASK              "set static.gatewat %d.%d.%d.%d"
+
+
+#define CMD_GET_NETWORK_STATUS              "get network.status"
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/common.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+
+#include "WiconnectCommands.h"
+
+/* Note we need the 2 concats below because arguments to ##
+ * are not expanded, so we need to expand __LINE__ with one indirection
+ * before doing the actual concatenation. */
+#define ASSERT_CONCAT_(a, b) a##b
+#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
+#define ct_assert(e) enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
+
+
+#ifndef WICONNECT_ASYNC_TIMER_ENABLED
+#define CHECK_CALLBACK_AVAILABLE(cb) if(cb.isValid()) return WICONNECT_UNSUPPORTED
+#else
+#define CHECK_CALLBACK_AVAILABLE(cb)
+#endif
+
+#define CHECK_CLEANUP_COMMAND()                                     \
+    if(result != WICONNECT_PROCESSING)                              \
+    {                                                               \
+        wiconnect->internalProcessingState = 0;                     \
+        wiconnect->currentCommandId = NULL;                         \
+    }
+
+#define CHECK_OTHER_COMMAND_EXECUTING()                             \
+{                                                                   \
+    static const volatile uint8_t __funcId = 0;                     \
+    if(wiconnect->currentCommandId == NULL)                         \
+    {                                                               \
+        wiconnect->currentCommandId = (void*)&__funcId;             \
+    }                                                               \
+    else if(wiconnect->currentCommandId != (void*)&__funcId)        \
+    {                                                               \
+        return WICONNECT_ANOTHER_CMD_EXECUTING;                     \
+    }                                                               \
+}
+
+
+#define WICONNECT_IS_IDLE() (wiconnect->currentCommandId == NULL)
+
+
+
+
+#ifdef WICONNECT_USE_DEFAULT_STRING_BUFFERS
+#define SET_STR_BUFFER(_buffer, size)                               \
+    char *ptr, *buf;                                                \
+    (void)buf;                                                      \
+    static char defaultBuffer[size];                                \
+    ptr = buf = (_buffer == NULL) ? defaultBuffer : _buffer;
+#else
+#define SET_STR_BUFFER(_buffer, size)                               \
+    char *ptr, *buf;                                                \
+    (void)buf;                                                      \
+    if(_buffer == NULL)                                             \
+    {                                                               \
+        return "<null>";                                            \
+    }                                                               \
+    ptr = buf = _buffer;
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/file/FileInterface.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+#include "StringUtil.h"
+
+
+/*************************************************************************************************/
+FileInterface::FileInterface(Wiconnect *wiconnect_)
+{
+    wiconnect = wiconnect_;
+}
+
+/*************************************************************************************************/
+WiconnectResult FileInterface::openFile(File &file, const char *name)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("fop %s", name)))
+    {
+        int32_t handle;
+        if(!WICONNECT_FAILED(result, wiconnect->responseToInt32(&handle)))
+        {
+            file.openForRead(handle, name);
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult FileInterface::createFile(const ReaderFunc &reader, void *user, const char *name, uint32_t size, uint32_t version, FileType type, bool isEssential, int32_t checksum)
+{
+    WiconnectResult result;
+    char cmdBuffer[WICONNECT_MAX_CMD_SIZE];
+
+    if(WICONNECT_IS_IDLE())
+    {
+        char *ptr = cmdBuffer;
+
+        ptr += sprintf(cmdBuffer, "fcr %s%s %d", isEssential ? "-e " : "", name, size);
+
+        if(version != 0)
+        {
+            *ptr = ' ';
+            ++ptr;
+            FileInterface::fileVersionIntToStr(version, true, ptr);
+            ptr = ptr + strlen(ptr);
+        }
+        if(type != FILE_TYPE_ANY)
+        {
+            ptr += sprintf(ptr, " %X", type);
+        }
+        if(checksum != -1)
+        {
+            ptr += sprintf(ptr, " %X", checksum);
+        }
+    }
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    result = wiconnect->sendCommand(reader, user, (const char *)cmdBuffer);
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+/*************************************************************************************************/
+WiconnectResult FileInterface::deleteFile(const char *name)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    result = wiconnect->sendCommand("fde %s", name);
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult FileInterface::deleteFile(const File &file)
+{
+    return deleteFile(file.getName());
+}
+
+
+/*************************************************************************************************/
+const char* FileInterface::fileVersionIntToStr(uint32_t version, bool verbose, char *buffer)
+{
+    SET_STR_BUFFER(buffer, 32);
+    const char *fmt = verbose ? "%u.%u.%u.%u" : "%u.%u.%u";
+    sprintf(ptr, fmt, FILE_VERSION_ARGS(version));
+    return ptr;
+}
+
+/*************************************************************************************************/
+bool FileInterface::fileVersionStrToInt(const char *versionStr, uint32_t *versionIntPtr)
+{
+    const uint8_t offsets[] = {27, 21, 8, 0};
+    char buffer[18];
+    char *tok, *ptr = buffer;
+    uint32_t version = 0;
+
+    strcpy(buffer, versionStr);
+
+    for(int i = 0; i < 4 && (tok = strtok(ptr, ".")) != NULL; ++i)
+    {
+        char *end;
+        const uint32_t value = strtol(tok, &end, 10);
+        if(*end != 0)
+        {
+            return false;
+        }
+        version |= (value << offsets[i]);
+        ptr = NULL;
+    }
+
+    *versionIntPtr = version;
+
+    return true;
+}
+
+/*************************************************************************************************/
+const char* FileInterface::fileTypeToStr(FileType type)
+{
+    switch(type)
+    {
+    case FILE_TYPE_UPGRADE_APP:
+        return "Upgrade App";
+    case FILE_TYPE_WIFI_FW:
+        return "Wifi Firmware";
+    case FILE_TYPE_REGULAR_APP:
+        return "Regular App";
+    case FILE_TYPE_TEMPORY:
+        return "Temporary";
+    case FILE_TYPE_GPIO_CONFIG:
+        return "GPIO Default Configuration";
+    case FILE_TYPE_COMMAND_HELP:
+        return "Command Help";
+    case FILE_TYPE_SDC_CAPS:
+        return "goHACK.me Capabilities";
+    case FILE_TYPE_SETUP_SCRIPT:
+        return "Setup Dcript";
+    case FILE_TYPE_MISC_FIX_LEN:
+        return "Miscellaneous";
+    default:
+        if(type >= FILE_TYPE_USER_RANGE_START && type <= FILE_TYPE_USER_RANGE_END)
+            return "User";
+        else
+            return "Unknown";
+    }
+}
+
+/*************************************************************************************************/
+const char* FileInterface::fileFlagsToStr(FileFlags flags, char *buffer)
+{
+    SET_STR_BUFFER(buffer, 64);
+    static const char* const flag_strings[] = {
+            "Valid",
+            "Executable",
+            "Encrypted",
+            "Internal",
+            "Bootable",
+            "User",
+            "Essential",
+    };
+
+    int i = 0;
+    *ptr = 0;
+
+    for(uint16_t f = flags; f != 0 && i < 7; f >>= 1, ++i)
+    {
+        if(f & 0x0001)
+        {
+            ptr += sprintf(ptr, "%s,", flag_strings[i]);
+        }
+    }
+
+    if(ptr == buffer)
+    {
+        strcpy(buffer, "None");
+    }
+    else
+    {
+        *(ptr-1) = 0;
+    }
+
+    return buf;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/file/FileList.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+#include "StringUtil.h"
+
+
+static bool nameMatches(const char *needle, const char* haystack);
+
+
+
+/*************************************************************************************************/
+WiconnectResult FileInterface::listFiles(FileList &list, const char *name, FileType type, uint32_t version)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("ls -v")))
+    {
+        result = processFileList(wiconnect->internalBuffer, list, name, type, version);
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult FileInterface::processFileList(char *responseStr, FileList &list, const char *name, FileType type, uint32_t version)
+{
+    WiconnectResult result = WICONNECT_SUCCESS;
+    char *line, *savedLine;
+
+    for(savedLine = responseStr; (line = StringUtil::strtok_r(savedLine, "\r\n", &savedLine)) != NULL;)
+    {
+        uint32_t tmp;
+        char *toks[7], *savedTok;
+
+        if(*line != '#')
+        {
+            continue;
+        }
+        savedTok = line + 2;
+
+        for(int i = 0; i < 6 && (toks[i] = StringUtil::strtok_r(savedTok, " ", &savedTok)) != NULL; ++i)
+        {
+            if(toks[i] == NULL)
+            {
+                result = WICONNECT_RESPONSE_PARSE_ERROR;
+                goto exit;
+            }
+        }
+
+
+        if(name != NULL && !nameMatches(name, savedTok+1))
+        {
+            continue;
+        }
+        else if((type != FILE_TYPE_ANY) &&
+                StringUtil::strHexToUint32((const char*)&toks[1][2], &tmp) &&
+                (type != (FileType)tmp))
+        {
+            continue;
+        }
+        else if((version != 0) &&
+                FileInterface::fileVersionStrToInt(toks[5], &tmp) &&
+                (version != tmp))
+        {
+            continue;
+        }
+        else if(WICONNECT_FAILED(result, list.add(toks[1], toks[2], toks[4], toks[5], savedTok+1)))
+        {
+            goto exit;
+        }
+    }
+
+    exit:
+    return result;
+}
+
+
+/*************************************************************************************************/
+static bool nameMatches(const char *needle, const char* haystack)
+{
+    const int haystackLen = strlen(haystack);
+
+    if(*needle == '*')
+    {
+        const int n = strlen(needle + 1);
+
+        if(n > haystackLen)
+        {
+            return false;
+        }
+        return strcmp(needle+1, &haystack[haystackLen - n]) == 0;
+    }
+    else
+    {
+        return strcmp(needle, haystack) == 0;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/network/NetworkInterface.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+#include "StringUtil.h"
+
+
+#define IPV4_FORMAT "%d.%d.%d.%d"
+#define IPV4_ARGS(ip) \
+    (int)( (ip)        & 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(completeHandler, "ping %s",  (domain == NULL) ? "-g" : domain)) &&
+            timeMsPtr != NULL)
+    {
+        if(sscanf(wiconnect->internalBuffer, "Ping reply in %ums", 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")))
+    {
+        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;
+
+    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;
+
+    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;
+                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;
+                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::getSignalStrength(NetworkSignalStrength *signalStrengthPtr)
+{
+    WiconnectResult result;
+    int32_t rssi_dbm;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("rssi")))
+    {
+        if(!WICONNECT_FAILED(result, wiconnect->responseToInt32(&rssi_dbm)))
+        {
+            *signalStrengthPtr = NetworkInterface::rssiToSignalStrength(rssi_dbm);
+        }
+    }
+
+    if(result == WICONNECT_CMD_RESPONSE_ERROR)
+    {
+        *signalStrengthPtr = NETWORK_RSSI_UNKNOWN;
+        result = WICONNECT_SUCCESS;
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+//-----------------------------------------------------------------------------------------------
+
+
+/*************************************************************************************************/
+bool NetworkInterface::strToIp(const char *str, uint32_t *intPtr)
+{
+    if (!intPtr)
+    {
+        return false;
+    }
+    int temp[4];
+
+    if(sscanf(str, "%d.%d.%d.%d", &temp[0], &temp[1], &temp[2], &temp[3] ) != 4)
+    {
+        return false;
+    }
+    else if(temp[0] > 255 || temp[1] > 255 || temp[2] > 255 || temp[3] > 255)
+    {
+        return false;
+    }
+    *intPtr = (uint32_t)temp[3] << 24 | temp[2] << 16 | temp[1] << 8 | temp[0];
+
+    return true;
+}
+
+/*************************************************************************************************/
+const char* NetworkInterface::ipToStr(uint32_t ip, char *ipStrBuffer)
+{
+    SET_STR_BUFFER(ipStrBuffer, 16);
+    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::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;
+    int 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;
+
+    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;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/network/NetworkJoin.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::join(const char* ssid, const char *password, const Callback &completeHandler_)
+{
+    WiconnectResult result;
+
+    enum
+    {
+        FS_SET_SSID,
+        FS_SET_PASSWORD,
+        FS_NETWORK_UP
+    };
+
+    CHECK_CALLBACK_AVAILABLE(completeHandler_);
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(wiconnect->internalProcessingState == FS_SET_SSID)
+    {
+        if(ssid == NULL ||
+           WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("set wlan.ssid %s", ssid)))
+        {
+            wiconnect->internalProcessingState = FS_SET_PASSWORD;
+        }
+    }
+
+    if(wiconnect->internalProcessingState == FS_SET_PASSWORD)
+    {
+        if(password == NULL ||
+           WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("set wlan.passkey %s", password)))
+        {
+            wiconnect->internalProcessingState = FS_NETWORK_UP;
+        }
+    }
+
+    if(wiconnect->internalProcessingState == FS_NETWORK_UP)
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("network_up")))
+        {
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+            if(completeHandler_.isValid())
+            {
+                if(monitorTimer.isRunning())
+                {
+                    result = WICONNECT_MONITOR_NOT_AVAILABLE;
+                }
+                else
+                {
+                    completeHandler = completeHandler_;
+                    monitorTimer.start(this, &NetworkInterface::joinStatusMonitor, 1000);
+                }
+            }
+#endif
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::leave()
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+    monitorTimer.stop();
+#endif
+    result = wiconnect->sendCommand("network_down");
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::getNetworkStatus(NetworkStatus *statusPtr)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("get network.status")))
+    {
+        int32_t status;
+        if(!WICONNECT_FAILED(result, wiconnect->responseToInt32(&status)))
+        {
+            *statusPtr = (NetworkStatus)status;
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+
+/*************************************************************************************************/
+// this is called every 1s by the monitorTimer
+void NetworkInterface::joinStatusMonitor()
+{
+    monitorTimer.stop();
+    QueuedCommand *cmd = new QueuedCommand(32, NULL, "get network.status");
+    if(cmd == NULL)
+        return;
+    if(wiconnect->enqueueCommand(cmd, Callback(this, &NetworkInterface::joinStatusCheckCallback)) != WICONNECT_SUCCESS)
+    {
+        delete cmd;
+    }
+}
+
+/*************************************************************************************************/
+// this is called on the completion of the 'get'network.status' command above
+void NetworkInterface::joinStatusCheckCallback(WiconnectResult result, void *arg1, void *arg2)
+{
+    bool isComplete = true;
+
+    QueuedCommand *cmd = (QueuedCommand*)arg1;
+
+    if(result == WICONNECT_SUCCESS)
+    {
+        int32_t status;
+        if(!StringUtil::strToInt32(cmd->responseBuffer, &status))
+        {
+            result = WICONNECT_RESPONSE_PARSE_ERROR;
+        }
+        else if(status == 0)
+        {
+            isComplete = false;
+        }
+    }
+
+    delete cmd;
+
+    if(isComplete)
+    {
+        completeHandler.call(result, NULL, NULL);
+    }
+    else
+    {
+        monitorTimer.start(this, &NetworkInterface::joinStatusMonitor, 1000);
+    }
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/network/NetworkScan.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+
+
+#define SCAN_TIMEOUT 15000
+
+
+
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::scan(ScanResultList &resultList, const uint8_t *channelList, const char* ssid)
+{
+    WiconnectResult result;
+    char cmdBuffer[WICONNECT_MAX_CMD_SIZE];
+
+    CHECK_CALLBACK_AVAILABLE(completeHandler_);
+
+    if(WICONNECT_IS_IDLE())
+    {
+#define SCAN_CMD "scan -v "
+        char *cmdBufferPtr = cmdBuffer + sizeof(SCAN_CMD)-1;
+
+        strcpy(cmdBuffer, SCAN_CMD);
+
+        if(channelList != NULL)
+        {
+            for(const uint8_t *ch = (const uint8_t *)channelList; *ch != 0; ++ch)
+            {
+                cmdBufferPtr += sprintf(cmdBufferPtr, "%d,", *ch);
+            }
+            *(cmdBufferPtr-1) = ' ';
+        }
+        else
+        {
+            strcat(cmdBufferPtr, "all ");
+            cmdBufferPtr += 4;
+        }
+
+        if(ssid != NULL)
+        {
+            strcpy(cmdBufferPtr, ssid);
+        }
+    }
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    //if(!completeHandler_.isValid())
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(SCAN_TIMEOUT, cmdBuffer)))
+        {
+            result = processScanResults(wiconnect->internalBuffer, resultList);
+        }
+    }
+//#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+//    else
+//    {
+//        QueuedCommand *cmd = new QueuedCommand(NULL, 4096, SCAN_TIMEOUT, cmdBuffer);
+//        cmd->userData = (void*)resultList;
+//        completeHandler = completeHandler_;
+//        if(WICONNECT_FAILED(result, wiconnect->enqueueCommand(cmd, Callback(this, &NetworkInterface::scanCompleteCallback))))
+//        {
+//            delete cmd;
+//        }
+//        else
+//        {
+//            result = WICONNECT_PROCESSING;
+//        }
+//    }
+//#endif
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+
+
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::processScanResults(char *resultStr, ScanResultList &resultList)
+{
+    WiconnectResult result = WICONNECT_SUCCESS;
+    char *line, *savedLine;
+
+    for(savedLine = resultStr; (line = StringUtil::strtok_r(savedLine, "\r\n", &savedLine)) != NULL;)
+    {
+        char *toks[9], *savedTok;
+
+        if(*line != '#')
+        {
+            continue;
+        }
+        savedTok = line + 2;
+
+        for(int i = 0; i < 8 && (toks[i] = StringUtil::strtok_r(savedTok, " ", &savedTok)) != NULL; ++i)
+        {
+            if(toks[i] == NULL)
+            {
+                result = WICONNECT_RESPONSE_PARSE_ERROR;
+                goto exit;
+            }
+        }
+
+        if(WICONNECT_FAILED(result, resultList.add(toks[1], toks[2], toks[3], toks[4], toks[5], savedTok)))
+        {
+            goto exit;
+        }
+    }
+
+    exit:
+    return result;
+}
+
+//#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+//
+/*************************************************************************************************/
+//void NetworkInterface::scanCompleteCallback(WiconnectResult result, void *arg1, void *arg2)
+//{
+//    QueuedCommand *cmd = (QueuedCommand*)arg1;
+//    ScanResultList *listPtr = (ScanResultList*)cmd->userData;
+//
+//    if(result == WICONNECT_SUCCESS)
+//    {
+//        result = processScanResults(cmd->responseBuffer, listPtr);
+//    }
+//    delete cmd;
+//
+//    completeHandler.call(result, listPtr, NULL);
+//}
+//
+//#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/network/NetworkSoftAp.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include "Wiconnect.h"
+
+
+
+///*************************************************************************************************/
+//WiconnectResult NetworkInterface::startSoftAp(const char* ssid, const char *password, WiconnectAsyncCallback *clientConnected)
+//{
+//    return WICONNECT_UNSUPPORTED;
+//}
+//
+///*************************************************************************************************/
+//WiconnectResult NetworkInterface::stopSoftAp()
+//{
+//    return WICONNECT_UNSUPPORTED;
+//}
+//
+///*************************************************************************************************/
+//WiconnectResult NetworkInterface::getSoftApClientList()
+//{
+//    return WICONNECT_UNSUPPORTED;
+//}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/network/NetworkWebSetup.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+
+
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::startWebSetup(const char *ssid, const char *password, const Callback &completeHandler_)
+{
+    WiconnectResult result;
+
+    enum
+    {
+        FS_SET_SSID,
+        FS_SET_PASSWORD,
+        FS_NETWORK_UP
+    };
+
+    CHECK_CALLBACK_AVAILABLE(completeHandler_);
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(wiconnect->internalProcessingState == FS_SET_SSID)
+    {
+        if(ssid == NULL ||
+           WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("set setup.web.ssid %s", ssid)))
+        {
+            wiconnect->internalProcessingState = FS_SET_PASSWORD;
+        }
+    }
+
+    if(wiconnect->internalProcessingState == FS_SET_PASSWORD)
+    {
+        if(password == NULL ||
+           WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("set setup.web.passkey %s", password)))
+        {
+            wiconnect->internalProcessingState = FS_NETWORK_UP;
+        }
+    }
+
+    if(wiconnect->internalProcessingState == FS_NETWORK_UP)
+    {
+        if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("setup web")))
+        {
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+            if(completeHandler_.isValid())
+            {
+                if(monitorTimer.isRunning())
+                {
+                    result = WICONNECT_MONITOR_NOT_AVAILABLE;
+                }
+                else
+                {
+                    completeHandler = completeHandler_;
+                    monitorTimer.start(this, &NetworkInterface::webSetupStatusMonitor, 1000);
+                }
+            }
+#endif
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::stopWebSetup()
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    #ifdef WICONNECT_ASYNC_TIMER_ENABLED
+        monitorTimer.stop();
+    #endif
+    result = wiconnect->sendCommand("setup stop");
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+/*************************************************************************************************/
+WiconnectResult NetworkInterface::isWebSetupRunning(bool *isRunningPtr)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("setup status")))
+    {
+        int32_t status;
+        if(!WICONNECT_FAILED(result, wiconnect->responseToInt32(&status)))
+        {
+            *isRunningPtr = (bool)status;
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+
+/*************************************************************************************************/
+void NetworkInterface::webSetupStatusMonitor()
+{
+    monitorTimer.stop();
+    QueuedCommand *cmd = new QueuedCommand(32, NULL, "setup status");
+    if(cmd == NULL)
+        return;
+    if(wiconnect->enqueueCommand(cmd, Callback(this, &NetworkInterface::webSetupStatusCheckCallback)) != WICONNECT_SUCCESS)
+    {
+        delete cmd;
+    }
+}
+
+/*************************************************************************************************/
+void NetworkInterface::webSetupStatusCheckCallback(WiconnectResult result, void *arg1, void *arg2)
+{
+    bool isComplete = true;
+
+    QueuedCommand *cmd = (QueuedCommand*)arg1;
+
+    if(result == WICONNECT_SUCCESS)
+    {
+        int32_t status;
+        if(!StringUtil::strToInt32(cmd->responseBuffer, &status))
+        {
+            result = WICONNECT_RESPONSE_PARSE_ERROR;
+        }
+        else if(status > 0)
+        {
+            isComplete = false;
+        }
+    }
+
+    delete cmd;
+
+    if(isComplete)
+    {
+        completeHandler.call(result, NULL, NULL);
+    }
+    else
+    {
+        monitorTimer.start(this, &NetworkInterface::webSetupStatusMonitor, 1000);
+    }
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/socket/SocketInterface.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+#include "StringUtil.h"
+
+#include "types/SocketIrqHandlerMap.h"
+
+
+
+
+/*************************************************************************************************/
+SocketInterface::SocketInterface(Wiconnect *wiconnect_)
+{
+    wiconnect = wiconnect_;
+}
+
+/*************************************************************************************************/
+SocketInterface::~SocketInterface()
+{
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::connect(Socket &socket, SocketType type, const char *host, uint16_t remortPort, uint16_t localPort, const void *args, Pin irqPin)
+{
+    WiconnectResult result;
+    int32_t handle;
+    char cmdBuffer[WICONNECT_MAX_CMD_SIZE];
+
+    if(WICONNECT_IS_IDLE())
+    {
+        char gpioOption[8] = "";
+
+        if(irqPin != NC)
+        {
+            PinToGpioMapper mapper = wiconnect->pinToGpioMapper;
+            if(mapper == NULL)
+            {
+                return WICONNECT_PINNAME_TO_GPIO_MAPPER_NULL;
+            }
+            int8_t gpio = mapper(irqPin);
+            if(gpio == -1)
+            {
+                return WICONNECT_PINNAME_TO_GPIO_NO_MAPPING;
+            }
+            else if(!irqHandlers.pinIsRegistered(irqPin))
+            {
+                return WICONNECT_NOT_FOUND;
+            }
+
+            sprintf(gpioOption, "-g %d ", gpio);
+        }
+
+
+        switch(type)
+        {
+        case SOCKET_TYPE_TCP:
+            sprintf(cmdBuffer, "tcpc %s%s %d", gpioOption, host, remortPort);
+            break;
+
+        case SOCKET_TYPE_UDP: {
+            char tmp[16];
+            sprintf(cmdBuffer, "udpc %s%s %d %s", gpioOption, host, remortPort,
+                                                (localPort != SOCKET_ANY_PORT) ? StringUtil::uint32ToStr(tmp, localPort) : "");
+        } break;
+
+        case SOCKET_TYPE_TLS:
+            sprintf(cmdBuffer, "tlsc %s%s %d %s", gpioOption, host, remortPort,
+                                                (args != NULL) ? (char*)args : "");
+            break;
+
+        case SOCKET_TYPE_HTTP: {
+            const HttpSocketArgs *httpArgs = (const HttpSocketArgs*)args;
+            switch(httpArgs->type)
+            {
+            case SOCKET_HTTP_GET:
+                sprintf(cmdBuffer, "http_get %s%s %s", httpArgs->openOnly ? "-o " : "",
+                                            host,
+                                            (httpArgs->certName != NULL) ? httpArgs->certName : "");
+                break;
+
+            case SOCKET_HTTP_HEAD:
+                sprintf(cmdBuffer, "http_head %s%s %s", httpArgs->openOnly ? "-o " : "",
+                                            host,
+                                            (httpArgs->certName != NULL) ? httpArgs->certName : "");
+                break;
+
+            case SOCKET_HTTP_POST:
+                sprintf(cmdBuffer, "http_post %s%s %s %s", httpArgs->openOnly ? "-o " : "",
+                                               host,
+                                               httpArgs->contextType,
+                                              (httpArgs->certName != NULL) ? httpArgs->certName : "");
+                break;
+
+            default:
+                return WICONNECT_BAD_ARG;
+            }
+
+        } break;
+        default:
+            return WICONNECT_BAD_ARG;
+        }
+    }
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand(cmdBuffer)))
+    {
+        if(!WICONNECT_FAILED(result, wiconnect->responseToInt32(&handle)))
+        {
+            socket.init(handle, type, host, remortPort, localPort);
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::tcpConnect(Socket &socket, const char *host, uint16_t remortPort, Pin irqPin)
+{
+    return connect(socket, SOCKET_TYPE_TCP, host, remortPort, SOCKET_ANY_PORT, NULL, irqPin);
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::tlsConnect(Socket &socket, const char *host, uint16_t remortPort, const char *certFilename, Pin irqPin)
+{
+    return connect(socket, SOCKET_TYPE_TLS, host, remortPort, SOCKET_ANY_PORT, certFilename, irqPin);
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::udpConnect(Socket &socket, const char *host, uint16_t remortPort, uint16_t localPort, Pin irqPin)
+{
+    return connect(socket, SOCKET_TYPE_UDP, host, remortPort, localPort, NULL, irqPin);
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::httpConnect(Socket &socket, const char *url, const HttpSocketArgs *args)
+{
+    return connect(socket, SOCKET_TYPE_HTTP, url, SOCKET_ANY_PORT, SOCKET_ANY_PORT, args, NC);
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::httpGet(Socket &socket, const char *url, bool openOnly, const char *certFilename)
+{
+    const HttpSocketArgs args
+    {
+        NULL,
+        certFilename,
+        openOnly,
+        SOCKET_HTTP_GET
+    };
+    return httpConnect(socket, url, &args);
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::httpPost(Socket &socket, const char *url, const char *contextType, bool openOnly, const char *certFilename)
+{
+    const HttpSocketArgs args
+    {
+        contextType,
+        certFilename,
+        openOnly,
+        SOCKET_HTTP_POST
+    };
+    return httpConnect(socket, url, &args);
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::httpHead(Socket &socket, const char *url, const char *certFilename)
+{
+    const HttpSocketArgs args
+    {
+        NULL,
+        certFilename,
+        false,
+        SOCKET_HTTP_HEAD
+    };
+    return httpConnect(socket, url, &args);
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::httpAddHeader(Socket &socket, const char *key, const char *value)
+{
+    WiconnectResult result;
+    char cmdBuffer[WICONNECT_MAX_CMD_SIZE];
+
+    if(WICONNECT_IS_IDLE())
+    {
+        sprintf(cmdBuffer, "http_add_header %d %s %s", socket.getHandle(), key, value);
+    }
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    result = wiconnect->sendCommand(cmdBuffer);
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::httpGetStatus(Socket &socket, uint32_t *statusCodePtr)
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    result = wiconnect->sendCommand("http_read_status %d", socket.getHandle());
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::closeAllSockets()
+{
+    WiconnectResult result;
+
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    result = wiconnect->sendCommand("close all");
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::registerSocketIrqHandler(Pin irqPin, const Callback &handler)
+{
+    PinToGpioMapper mapper = wiconnect->pinToGpioMapper;
+    if(irqHandlers.pinIsRegistered(irqPin))
+    {
+        return WICONNECT_DUPLICATE;
+    }
+    else  if(mapper == NULL)
+    {
+        return WICONNECT_PINNAME_TO_GPIO_MAPPER_NULL;
+    }
+    int8_t gpio = mapper(irqPin);
+    if(gpio == -1)
+    {
+        return WICONNECT_PINNAME_TO_GPIO_NO_MAPPING;
+    }
+
+    return irqHandlers.registerHandler(irqPin, handler);
+}
+
+/*************************************************************************************************/
+WiconnectResult SocketInterface::unregisterSocketIrqHandler(Pin irqPin)
+{
+    return irqHandlers.unregisterHandler(irqPin);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/types/File.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include <assert.h>
+#include "Wiconnect.h"
+#include "internal/common.h"
+
+#define CHECK_OPENED_FOR_READING() if(!readEnabled) return WICONNECT_NOT_OPENED_FOR_READING
+
+
+
+
+/*************************************************************************************************/
+File::File(int rxBufferLen, void *rxBuffer_)
+{
+    wiconnect = Wiconnect::getInstance();
+
+    memset(&rxBuffer, 0, sizeof(Buffer));
+
+    rxBuffer.size = !wiconnect->nonBlocking ? rxBufferLen : 0;
+    rxBuffer.buffer = (uint8_t*)rxBuffer_;
+
+    if(rxBuffer.size > 0)
+    {
+        if(rxBuffer_ == NULL)
+        {
+#ifdef WICONNECT_ENABLE_MALLOC
+            assert(wiconnect->_malloc != NULL);
+            rxBuffer.buffer = (uint8_t*)wiconnect->_malloc(rxBufferLen);
+            assert(rxBuffer.buffer != NULL);
+            rxBuffer.allocated = true;
+#else
+            assert(0);
+#endif
+        }
+    }
+
+    previous = next = NULL;
+    handle = 0xff;
+    readEnabled = false;
+    *name = 0;
+    size = 0;
+    type = FILE_TYPE_UNKNOWN;
+    version = 0;
+    flags = FILE_FLAG_NONE;
+}
+
+/*************************************************************************************************/
+File::~File()
+{
+    while(close() == WICONNECT_PROCESSING)
+    {
+    }
+
+#ifdef WICONNECT_ENABLE_MALLOC
+    if(rxBuffer.allocated && rxBuffer.size > 0)
+    {
+        assert(wiconnect->_free != NULL);
+        wiconnect->_free(rxBuffer.buffer);
+    }
+#endif
+}
+
+/*************************************************************************************************/
+WiconnectResult File::openForRead(uint8_t handle_, const char *filename)
+{
+    handle = handle_;
+    readEnabled = true;
+    strcpy(name, filename);
+
+    return WICONNECT_SUCCESS;
+}
+
+/*************************************************************************************************/
+WiconnectResult File::initWithListing(const char *typeStr, const char *flagsStr, const char* sizeStr, const char *versionStr, const char *nameStr)
+{
+    uint32_t tmp;
+
+    if(!StringUtil::strHexToUint32(&typeStr[2], &tmp))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+    type = (FileType)tmp;
+
+    if(!StringUtil::strHexToUint32(flagsStr, &tmp))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+    flags = (FileFlags)tmp;
+
+    if(!StringUtil::strToUint32(sizeStr, &tmp))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+    size = (uint32_t)tmp;
+
+    if(!FileInterface::fileVersionStrToInt(versionStr, &version))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+
+    strcpy(name, nameStr);
+
+    return WICONNECT_SUCCESS;
+}
+
+/*************************************************************************************************/
+void* File::operator new(size_t size)
+{
+    assert(Wiconnect::getInstance()->_malloc != NULL);
+    return Wiconnect::getInstance()->_malloc(size);
+}
+
+/*************************************************************************************************/
+void File::operator delete(void* ptr)
+{
+    assert(Wiconnect::getInstance()->_free != NULL);
+    Wiconnect::getInstance()->_free(ptr);
+}
+
+
+/*************************************************************************************************/
+WiconnectResult File::close()
+{
+    WiconnectResult result;
+    CHECK_OPENED_FOR_READING();
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("close %d", handle)))
+    {
+        readEnabled = false;
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+const char* File::getName() const
+{
+    return name;
+}
+
+/*************************************************************************************************/
+uint32_t File::getSize() const
+{
+    return size;
+}
+
+/*************************************************************************************************/
+FileType File::getType() const
+{
+    return type;
+}
+
+/*************************************************************************************************/
+FileFlags File::getFlags() const
+{
+    return flags;
+}
+
+/*************************************************************************************************/
+uint32_t File::getVersion() const
+{
+    return version;
+}
+
+/*************************************************************************************************/
+const char* File::getVersionStr(char *buffer) const
+{
+    return FileInterface::fileVersionIntToStr(version, true, buffer);
+}
+
+/*************************************************************************************************/
+const File* File::getNext() const
+{
+    return next;
+}
+
+/*************************************************************************************************/
+const File* File::getPrevious() const
+{
+    return previous;
+}
+
+
+/*************************************************************************************************/
+WiconnectResult File::read(void* buffer, uint16_t maxLength, uint16_t *bytesRead)
+{
+    WiconnectResult result;
+
+    CHECK_OPENED_FOR_READING();
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand((char*)buffer, maxLength, "read %d %d", handle, maxLength-2)))
+    {
+        *bytesRead = wiconnect->getLastCommandResponseLength();
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult File::read(uint8_t **bufferPtr, uint16_t *bytesReadPtr)
+{
+    WiconnectResult result = WICONNECT_SUCCESS;
+
+    CHECK_OPENED_FOR_READING();
+
+    if(rxBuffer.size == 0)
+    {
+        return WICONNECT_UNSUPPORTED;
+    }
+    else if(bufferPtr != NULL && bytesReadPtr == NULL)
+    {
+        return WICONNECT_BAD_ARG;
+    }
+    else if(rxBuffer.bytesPending < rxBuffer.size - 2)
+    {
+        const int bytesToRead = rxBuffer.size - rxBuffer.bytesPending - 2;
+        char* ptr = (char*)&rxBuffer.buffer[rxBuffer.bytesPending];
+        if(!WICONNECT_FAILED(result, wiconnect->sendCommand(ptr, bytesToRead+2, "read %d %d", handle, bytesToRead)))
+        {
+            rxBuffer.bytesPending += wiconnect->getLastCommandResponseLength();
+        }
+    }
+
+    if(bufferPtr != NULL)
+    {
+        *bufferPtr = rxBuffer.buffer;
+        *bytesReadPtr = rxBuffer.bytesPending;
+        clearRxBuffer();
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult File::getc(uint8_t *c)
+{
+    WiconnectResult result;
+
+    if(rxBuffer.size == 0)
+    {
+        return WICONNECT_UNSUPPORTED;
+    }
+
+    read_data:
+    if(rxBuffer.bytesPending == 0 &&
+      WICONNECT_FAILED(result, read()))
+    {
+        return result;
+    }
+    else if(rxBuffer.ptr < &rxBuffer.buffer[rxBuffer.bytesPending])
+    {
+        *c = *rxBuffer.ptr;
+        ++rxBuffer.ptr;
+        return WICONNECT_SUCCESS;
+    }
+    else
+    {
+        clearRxBuffer();
+        goto read_data;
+    }
+}
+
+/*************************************************************************************************/
+void File::clearRxBuffer()
+{
+    rxBuffer.bytesPending = 0;
+    rxBuffer.ptr = rxBuffer.buffer;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/types/FileList.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+
+#include "Wiconnect.h"
+#include "types/FileList.h"
+
+
+
+/*************************************************************************************************/
+FileList::FileList(int bufferLen_, void *buffer_)
+{
+    count = 0;
+    listHead = listTail = NULL;
+    buffer = (uint8_t*)buffer_;
+    bufferPtr = buffer;
+    bufferLen = bufferLen_;
+}
+
+/*************************************************************************************************/
+FileList::~FileList()
+{
+    if(buffer == NULL)
+    {
+        File* result = listHead;
+        while(result != NULL)
+        {
+            File* tmp = result;
+            result = result->next;
+            delete tmp;
+        }
+    }
+}
+
+/*************************************************************************************************/
+WiconnectResult FileList::add(const char *typeStr, const char *flagsStr, const char* sizeStr, const char *versionStr, const char *nameStr)
+{
+    WiconnectResult result;
+    File *res;
+
+    if(buffer == NULL)
+    {
+        res = new File();
+        if(res == NULL)
+        {
+            return WICONNECT_NULL_BUFFER;
+        }
+    }
+    else
+    {
+        if(bufferLen < sizeof(File))
+        {
+            return WICONNECT_OVERFLOW;
+        }
+        res = (File*)bufferPtr;
+        memset(res, 0, sizeof(File));
+        bufferLen -= sizeof(File);
+        bufferPtr += sizeof(File);
+    }
+
+    if(WICONNECT_FAILED(result, res->initWithListing(typeStr, flagsStr, sizeStr, versionStr, nameStr)))
+    {
+        if(buffer == NULL)
+        {
+            delete res;
+        }
+    }
+    else
+    {
+        if(listHead == NULL)
+        {
+            listHead = listTail = res;
+        }
+        else
+        {
+            res->previous = listTail;
+            listTail->next = res;
+            listTail = res;
+        }
+        ++count;
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+const File* FileList::getListHead() const
+{
+    return listHead;
+}
+
+/*************************************************************************************************/
+int FileList::getCount() const
+{
+    return count;
+}
+
+/*************************************************************************************************/
+const File* FileList::getResult(int i) const
+{
+    if(i >= count)
+        return NULL;
+
+    File* result = listHead;
+    while(i-- != 0)
+        result = result->next;
+
+    return result;
+}
+
+/*************************************************************************************************/
+const File* FileList::operator [](int i) const
+{
+    return getResult(i);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/types/QueuedCommand.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include <assert.h>
+
+#include "Wiconnect.h"
+
+
+/*************************************************************************************************/
+QueuedCommand::QueuedCommand(int responseBufferLen_, char *responseBuffer_, int timeoutMs_, const ReaderFunc &reader_, void *user_, const char *cmd_, va_list vaList)
+{
+    initialize(responseBufferLen_, responseBuffer_, timeoutMs_, reader_, user_, cmd_, vaList);
+}
+
+/*************************************************************************************************/
+QueuedCommand::QueuedCommand(int responseBufferLen_, char* responseBuffer_, int timeoutMs_, const char *cmd_, ...)
+{
+    va_list args;
+    va_start(args, cmd_);
+    initialize(responseBufferLen_, responseBuffer_, timeoutMs_, NULL, NULL, cmd_, args);
+    va_end(args);
+}
+
+/*************************************************************************************************/
+QueuedCommand::QueuedCommand(int responseBufferLen_, char *responseBuffer_, const char *cmd_, ...)
+{
+    va_list args;
+    va_start(args, cmd_);
+    initialize(responseBufferLen_, responseBuffer_, WICONNECT_DEFAULT_TIMEOUT, NULL, NULL, cmd_, args);
+    va_end(args);
+}
+
+/*************************************************************************************************/
+QueuedCommand::QueuedCommand(int timeoutMs_, const char *cmd_, ...)
+{
+    va_list args;
+    va_start(args, cmd_);
+    initialize(0, NULL, timeoutMs_, NULL, NULL, cmd_, args);
+    va_end(args);
+}
+
+/*************************************************************************************************/
+QueuedCommand::QueuedCommand(const char *cmd_, ...)
+{
+    va_list args;
+    va_start(args, cmd_);
+    initialize(0, NULL, WICONNECT_DEFAULT_TIMEOUT, NULL, NULL, cmd_, args);
+    va_end(args);
+}
+
+/*************************************************************************************************/
+QueuedCommand::~QueuedCommand()
+{
+#ifdef WICONNECT_ENABLE_MALLOC
+    if(allocatedBuffer)
+    {
+        Wiconnect::getInstance()->_free(responseBuffer);
+    }
+#endif
+}
+
+/*************************************************************************************************/
+char *QueuedCommand::getResponseBuffer()
+{
+    return responseBuffer;
+}
+/*************************************************************************************************/
+int QueuedCommand::getResponseBufferLen()
+{
+    return responseBufferLen;
+}
+/*************************************************************************************************/
+int QueuedCommand::getTimeoutMs()
+{
+    return timeoutMs;
+}
+/*************************************************************************************************/
+ReaderFunc QueuedCommand::getReader()
+{
+    return reader;
+}
+/*************************************************************************************************/
+void * QueuedCommand::getReaderUserData()
+{
+    return user;
+}
+/*************************************************************************************************/
+char* QueuedCommand::getCommand()
+{
+    return command;
+}
+/*************************************************************************************************/
+Callback QueuedCommand::getCompletedCallback()
+{
+    return completeCallback;
+}
+/*************************************************************************************************/
+void QueuedCommand::setCompletedCallback(const Callback &cb)
+{
+    completeCallback = cb;
+}
+
+/*************************************************************************************************/
+QueuedCommand& QueuedCommand::operator=( const QueuedCommand& other )
+{
+    responseBuffer = other.responseBuffer;
+    responseBufferLen = other.responseBufferLen;
+    timeoutMs = other.timeoutMs;
+    reader = other.reader;
+    user = other.user;
+    completeCallback = other.completeCallback;
+    memcpy(command, other.command, sizeof(command));
+    return *this;
+}
+
+/*************************************************************************************************/
+void* QueuedCommand::operator new(size_t size)
+{
+    assert(Wiconnect::getInstance()->_malloc != NULL);
+    return Wiconnect::getInstance()->_malloc(size);
+}
+
+/*************************************************************************************************/
+void QueuedCommand::operator delete(void* ptr)
+{
+    assert(Wiconnect::getInstance()->_free != NULL);
+    Wiconnect::getInstance()->_free(ptr);
+}
+
+/*************************************************************************************************/
+void QueuedCommand::initialize(int responseBufferLen_, char *responseBuffer_, int timeoutMs_, const ReaderFunc &reader_, void *user_, const char *cmd_, va_list vaList)
+{
+    if(responseBufferLen_ > 0)
+    {
+#ifdef WICONNECT_ENABLE_MALLOC
+        allocatedBuffer = false;
+        if(responseBuffer_ == NULL)
+        {
+            assert(Wiconnect::getInstance()->_malloc != NULL);
+            responseBuffer = (char*)Wiconnect::getInstance()->_malloc(responseBufferLen_);
+            allocatedBuffer = true;
+        }
+        else
+#endif
+        {
+            assert(responseBuffer_ != NULL);
+            responseBuffer = responseBuffer_;
+        }
+    }
+    responseBufferLen = responseBufferLen_;
+    timeoutMs = timeoutMs_;
+    reader = reader_;
+    user = user_;
+    userData = NULL;
+
+    if(cmd_ != NULL)
+    {
+        int len = vsnprintf(command, sizeof(command)-3, cmd_, vaList);
+        command[len++] = '\r';
+        command[len++] = '\n';
+        command[len] = 0;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/types/ScanResult.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include <assert.h>
+
+#include "Wiconnect.h"
+#include "types/ScanResult.h"
+#include "NetworkInterface.h"
+#include "internal/common.h"
+
+
+static inline bool floatToFixedPointInt(const char *str, uint32_t *res);
+
+
+
+/*************************************************************************************************/
+ScanResult::ScanResult()
+{
+    next = NULL;
+    previous = NULL;
+    channel = 0xff;
+    rssi = -9999;
+    rate = 0;
+    security = NETWORK_SECURITY_UNKNOWN;
+    memset(&mac, 0, (uint32_t)sizeof(mac));
+    memset(&ssid, 0, (uint32_t)sizeof(ssid));
+}
+
+/*************************************************************************************************/
+WiconnectResult ScanResult::init(const char *channelStr, const char *rssiStr, const char* macStr, const char *rateStr, const char *secStr, const char *ssidStr)
+{
+    intmax_t r;
+    if(!StringUtil::parseInt(channelStr, &r, 0, 15))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+    channel = (int)r;
+    if(!StringUtil::parseInt(rssiStr, &r, -200, 100))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+    rssi = (int)r;
+
+    if(!Wiconnect::strToMacAddress(macStr, &mac))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+
+    if(!floatToFixedPointInt(rateStr, &rate))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+    security = Wiconnect::strToNetworkSecurity(secStr);
+
+    if(!Wiconnect::strToSsid(ssidStr, &ssid))
+    {
+        return WICONNECT_RESPONSE_PARSE_ERROR;
+    }
+
+    return WICONNECT_SUCCESS;
+}
+
+/*************************************************************************************************/
+void* ScanResult::operator new(size_t size)
+{
+    assert(Wiconnect::getInstance()->_malloc != NULL);
+    return Wiconnect::getInstance()->_malloc(size);
+}
+
+/*************************************************************************************************/
+void ScanResult::operator delete(void* ptr)
+{
+    assert(Wiconnect::getInstance()->_free != NULL);
+    Wiconnect::getInstance()->_free(ptr);
+}
+
+/*************************************************************************************************/
+uint8_t ScanResult::getChannel() const
+{
+    return channel;
+}
+/*************************************************************************************************/
+NetworkSignalStrength ScanResult::getSignalStrength() const
+{
+    return Wiconnect::rssiToSignalStrength(rssi);
+}
+/*************************************************************************************************/
+const MacAddress* ScanResult::getMacAddress() const
+{
+    return &mac;
+}
+/*************************************************************************************************/
+uint32_t ScanResult::getRate() const
+{
+    return rate;
+}
+/*************************************************************************************************/
+const char* ScanResult::getRateStr(char *buffer) const
+{
+    SET_STR_BUFFER(buffer, 16);
+    uint32_t i = rate / 10;
+    uint32_t f = rate % 10;
+    sprintf(ptr, "%u.%u", i, f);
+    return ptr;
+}
+/*************************************************************************************************/
+NetworkSecurity ScanResult::getSecurityType() const
+{
+    return security;
+}
+/*************************************************************************************************/
+const Ssid* ScanResult::getSsid() const
+{
+    return &ssid;
+}
+
+/*************************************************************************************************/
+const ScanResult* ScanResult::getNext() const
+{
+    return next;
+}
+
+/*************************************************************************************************/
+const ScanResult* ScanResult::getPrevious() const
+{
+    return previous;
+}
+
+
+/*************************************************************************************************/
+static inline bool floatToFixedPointInt(const char *str, uint32_t *res)
+{
+    intmax_t i;
+    intmax_t f = 0;
+    char buffer[32];
+
+    strcpy(buffer, str);
+
+    char* frac = strchr(buffer, '.');
+    if(frac != NULL)
+    {
+        *frac = 0;
+        ++frac;
+    }
+
+    if(!StringUtil::parseInt(buffer, &i, 0, 1000))
+    {
+        return false;
+    }
+    if(frac != NULL && !StringUtil::parseInt(frac, &f, 0, 9))
+    {
+        return false;
+    }
+
+    *res = (((uint32_t)i) * 10) + (uint32_t)f;
+
+    return true;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/types/ScanResultList.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include <assert.h>
+#include "Wiconnect.h"
+#include "types/ScanResult.h"
+
+
+
+/*************************************************************************************************/
+ScanResultList::ScanResultList(int bufferLen_, void *buffer_)
+{
+    assert((bufferLen_ == 0 && buffer_ == NULL) || (bufferLen_ != 0 && buffer_ != NULL));
+    count = 0;
+    listHead = listTail = NULL;
+    buffer = (uint8_t*)buffer_;
+    bufferPtr = buffer;
+    bufferLen = bufferLen_;
+}
+
+/*************************************************************************************************/
+ScanResultList::~ScanResultList()
+{
+    if(buffer == NULL)
+    {
+        ScanResult* result = listHead;
+        while(result != NULL)
+        {
+            ScanResult* tmp = result;
+            result = result->next;
+            delete tmp;
+        }
+    }
+}
+
+/*************************************************************************************************/
+WiconnectResult ScanResultList::add(const char *channelStr, const char *rssiStr, const char* macStr, const char *rateStr, const char *secStr, const char *ssidStr)
+{
+    WiconnectResult result;
+    ScanResult *res;
+
+    if(buffer == NULL)
+    {
+        res = new ScanResult();
+        if(res == NULL)
+        {
+            return WICONNECT_NULL_BUFFER;
+        }
+    }
+    else
+    {
+        if(bufferLen < sizeof(ScanResult))
+        {
+            return WICONNECT_OVERFLOW;
+        }
+        res = (ScanResult*)bufferPtr;
+        memset(res, 0, sizeof(ScanResult));
+        bufferLen -= sizeof(ScanResult);
+        bufferPtr += sizeof(ScanResult);
+    }
+
+    if(WICONNECT_FAILED(result, res->init(channelStr, rssiStr, macStr, rateStr, secStr, ssidStr)))
+    {
+        if(buffer == NULL)
+        {
+            delete res;
+        }
+    }
+    else
+    {
+        if(listHead == NULL)
+        {
+            listHead = listTail = res;
+        }
+        else
+        {
+            res->previous = listTail;
+            listTail->next = res;
+            listTail = res;
+        }
+        ++count;
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+const ScanResult* ScanResultList::getListHead() const
+{
+    return listHead;
+}
+
+/*************************************************************************************************/
+int ScanResultList::getCount() const
+{
+    return count;
+}
+
+/*************************************************************************************************/
+const ScanResult* ScanResultList::getResult(int i) const
+{
+    if(i >= count)
+        return NULL;
+
+    ScanResult* result = listHead;
+    while(i-- != 0)
+        result = result->next;
+
+    return result;
+}
+
+/*************************************************************************************************/
+const ScanResult* ScanResultList::operator [](int i) const
+{
+    return getResult(i);
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/types/Socket.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,490 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+#include "Wiconnect.h"
+#include "internal/common.h"
+#include "StringUtil.h"
+
+
+#define CHECK_CONNECTED() if(!isConnected()) return WICONNECT_NOT_CONNECTED
+
+
+/*************************************************************************************************/
+Socket::Socket(int rxBufferLen_, void *rxBuffer_, int txBufferLen_, void *txBuffer_)
+{
+    wiconnect = Wiconnect::getInstance();
+
+    memset(&txBuffer, 0, sizeof(Buffer));
+    memset(&rxBuffer, 0, sizeof(Buffer));
+
+    txBuffer.size = !wiconnect->nonBlocking ? txBufferLen_ : 0;
+    txBuffer.buffer = (uint8_t*)txBuffer_;
+
+    rxBuffer.size = !wiconnect->nonBlocking ? rxBufferLen_ : 0;
+    rxBuffer.buffer = (uint8_t*)rxBuffer_;
+
+    if(txBuffer.size > 0)
+    {
+        if(txBuffer_ == NULL)
+        {
+#ifdef WICONNECT_ENABLE_MALLOC
+            assert(wiconnect->_malloc != NULL);
+            txBuffer.buffer = (uint8_t*)wiconnect->_malloc(txBufferLen_);
+            assert(txBuffer.buffer != NULL);
+            txBuffer.allocated = true;
+#else
+            assert(0);
+#endif
+        }
+    }
+
+    if(rxBuffer.size > 0)
+    {
+        if(rxBuffer_ == NULL)
+        {
+#ifdef WICONNECT_ENABLE_MALLOC
+            assert(wiconnect->_malloc != NULL);
+            rxBuffer.buffer = (uint8_t*)wiconnect->_malloc(rxBufferLen_);
+            assert(rxBuffer.buffer != NULL);
+            rxBuffer.allocated = true;
+#else
+            assert(0);
+#endif
+        }
+    }
+
+    init(SOCKET_INVALID_HANDLE, SOCKET_TYPE_UNKNOWN, NULL, 0, 0);
+}
+
+
+/*************************************************************************************************/
+WiconnectResult Socket::init(uint8_t handle_, SocketType type_, const char *host_, uint16_t remotePort_, uint16_t localPort_)
+{
+    handle = handle_;
+    type = type_;
+    remotePort = remotePort_;
+    localPort = localPort_;
+    connected = true;
+
+    txBuffer.ptr = txBuffer.buffer;
+    rxBuffer.ptr = rxBuffer.buffer;
+
+    strncpy(host, host_, sizeof(host)-1);
+
+    return WICONNECT_SUCCESS;
+}
+
+/*************************************************************************************************/
+Socket::~Socket()
+{
+    while((handle != SOCKET_INVALID_HANDLE) && (close() == WICONNECT_PROCESSING))
+    {
+    }
+
+#ifdef WICONNECT_ENABLE_MALLOC
+    if(txBuffer.allocated && txBuffer.size > 0)
+    {
+        assert(wiconnect->_free != NULL);
+        wiconnect->_free(txBuffer.buffer);
+    }
+    if(rxBuffer.allocated && rxBuffer.size > 0)
+    {
+        assert(wiconnect->_free != NULL);
+        wiconnect->_free(rxBuffer.buffer);
+    }
+#endif
+}
+
+/*************************************************************************************************/
+bool Socket::isConnected()
+{
+    return connected;
+}
+
+/*************************************************************************************************/
+SocketType Socket::getType()
+{
+    return type;
+}
+
+/*************************************************************************************************/
+const char* Socket::getHost()
+{
+    return host;
+}
+
+/*************************************************************************************************/
+uint16_t Socket::getLocalPort()
+{
+    return localPort;
+}
+
+/*************************************************************************************************/
+uint16_t Socket::getRemotePort()
+{
+    return remotePort;
+}
+
+/*************************************************************************************************/
+uint8_t Socket::getHandle()
+{
+    return handle;
+}
+
+
+/*************************************************************************************************/
+WiconnectResult Socket::close()
+{
+    WiconnectResult result;
+    CHECK_CONNECTED();
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("close %d", handle)))
+    {
+        connected = false;
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::poll(bool *rxDataAvailablePtr)
+{
+    WiconnectResult result;
+    int32_t status;
+
+    CHECK_CONNECTED();
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    *rxDataAvailablePtr = false;
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand("poll %d", handle)))
+    {
+        if(!WICONNECT_FAILED(result, wiconnect->responseToInt32(&status)))
+        {
+            if(status == 2)
+            {
+                connected = false;
+            }
+            else if(status == 1)
+            {
+                *rxDataAvailablePtr = true;
+            }
+        }
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::write(int length, bool flush)
+{
+    CHECK_CONNECTED();
+
+    if( txBuffer.size == 0)
+    {
+        return WICONNECT_UNSUPPORTED;
+    }
+    else if(length > txBuffer.size)
+    {
+        return WICONNECT_OVERFLOW;
+    }
+    txBuffer.bytesPending = length;
+
+    return flush ? flushTxBuffer() : WICONNECT_SUCCESS;
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::write(const void* buffer, int length, bool flush)
+{
+    WiconnectResult result = WICONNECT_SUCCESS;
+    CHECK_CONNECTED();
+
+    if(txBuffer.size > 0)
+    {
+        // NOTE: txBuffer only available in blocking mode (so no need to check if a cmd is executing)
+
+        const uint8_t *src = (const uint8_t *)buffer;
+
+        while(length > 0)
+        {
+            int bytesToWrite = MIN(length, txBuffer.size - txBuffer.bytesPending);
+            uint8_t *dst = (uint8_t*)&txBuffer.buffer[txBuffer.bytesPending];
+            memcpy(dst, src, bytesToWrite);
+            txBuffer.bytesPending += bytesToWrite;
+            length -= bytesToWrite;
+            src += bytesToWrite;
+
+            if((txBuffer.bytesPending >= txBuffer.size) &&
+                WICONNECT_FAILED(result, flushTxBuffer()))
+            {
+                 break;
+            }
+        }
+
+        if(flush && txBuffer.bytesPending > 0)
+        {
+            result = flushTxBuffer();
+        }
+    }
+    else
+    {
+        if(WICONNECT_IS_IDLE())
+        {
+            txBuffer.ptr = (uint8_t*)buffer;
+            txBuffer.bytesPending = length;
+        }
+
+        result = flushTxBuffer();
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::read(void* buffer, uint16_t maxLength, uint16_t *bytesRead)
+{
+    WiconnectResult result;
+
+    CHECK_CONNECTED();
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(WICONNECT_SUCCEEDED(result, wiconnect->sendCommand((char*)buffer, maxLength, "read %d %d", handle, maxLength-2)))
+    {
+        *bytesRead = wiconnect->getLastCommandResponseLength();
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::read(uint8_t **bufferPtr, uint16_t *bytesReadPtr)
+{
+    WiconnectResult result = WICONNECT_SUCCESS;
+
+    CHECK_CONNECTED();
+
+    if(rxBuffer.size == 0)
+    {
+        return WICONNECT_UNSUPPORTED;
+    }
+    else if(bufferPtr != NULL && bytesReadPtr == NULL)
+    {
+        return WICONNECT_BAD_ARG;
+    }
+    else if(rxBuffer.bytesPending < rxBuffer.size - 2)
+    {
+        const int bytesToRead = rxBuffer.size - rxBuffer.bytesPending - 2;
+        char* ptr = (char*)&rxBuffer.buffer[rxBuffer.bytesPending];
+        if(!WICONNECT_FAILED(result, wiconnect->sendCommand(ptr, bytesToRead+2, "read %d %d", handle, bytesToRead)))
+        {
+            rxBuffer.bytesPending += wiconnect->getLastCommandResponseLength();
+        }
+    }
+
+    if(bufferPtr != NULL)
+    {
+        *bufferPtr = rxBuffer.buffer;
+        *bytesReadPtr = rxBuffer.bytesPending;
+        clearRxBuffer();
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::getc(uint8_t *c)
+{
+    WiconnectResult result;
+
+    if(rxBuffer.size == 0)
+    {
+        return WICONNECT_UNSUPPORTED;
+    }
+
+    read_data:
+    if(rxBuffer.bytesPending == 0 &&
+      WICONNECT_FAILED(result, read()))
+    {
+        return result;
+    }
+    else if(rxBuffer.ptr < &rxBuffer.buffer[rxBuffer.bytesPending])
+    {
+        *c = *rxBuffer.ptr;
+        ++rxBuffer.ptr;
+        return WICONNECT_SUCCESS;
+    }
+    else
+    {
+        clearRxBuffer();
+        goto read_data;
+    }
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::putc(uint8_t c, bool flush)
+{
+    WiconnectResult result = WICONNECT_SUCCESS;
+    CHECK_CONNECTED();
+
+    if(txBuffer.size == 0)
+    {
+        return WICONNECT_UNSUPPORTED;
+    }
+    else if(txBuffer.bytesPending < txBuffer.size)
+    {
+        uint8_t *ptr = (uint8_t*)&txBuffer.buffer[txBuffer.bytesPending];
+        *ptr = c;
+        ++txBuffer.bytesPending;
+
+        if(flush || txBuffer.bytesPending >= txBuffer.size)
+        {
+            result = flushTxBuffer();
+        }
+    }
+    else
+    {
+        result = WICONNECT_OVERFLOW;
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::puts(const char *s, bool flush)
+{
+    const int len = strlen(s);
+    return write(s, len, flush);
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::printf(const char* format, ...)
+{
+    WiconnectResult result = WICONNECT_SUCCESS;
+
+    CHECK_CONNECTED();
+    if(txBuffer.size == 0)
+    {
+        return WICONNECT_UNSUPPORTED;
+    }
+
+    const int available = txBuffer.size - txBuffer.bytesPending;
+    char *ptr = (char*)&txBuffer.buffer[txBuffer.bytesPending];
+    va_list args;
+    va_start(args, format);
+    const int len = vsnprintf(ptr, available, format, args);
+    if(len > available)
+    {
+        return WICONNECT_OVERFLOW;
+    }
+    else
+    {
+        txBuffer.bytesPending += len;
+    }
+
+    if(txBuffer.bytesPending >= txBuffer.size)
+    {
+        result = flushTxBuffer();
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Socket::flushTxBuffer()
+{
+    WiconnectResult result = WICONNECT_SUCCESS;
+
+    CHECK_CONNECTED();
+    CHECK_OTHER_COMMAND_EXECUTING();
+
+    if(txBuffer.bytesPending > 0)
+    {
+        result = wiconnect->sendCommand(ReaderFunc(this, &Socket::writeDataCallback), NULL, "write %d %d", handle, txBuffer.bytesPending);
+    }
+
+    CHECK_CLEANUP_COMMAND();
+
+    if(result != WICONNECT_PROCESSING)
+    {
+        txBuffer.ptr = txBuffer.buffer;
+        txBuffer.bytesPending = 0;
+    }
+
+    return result;
+}
+
+/*************************************************************************************************/
+void Socket::clearRxBuffer()
+{
+    rxBuffer.bytesPending = 0;
+    rxBuffer.ptr = rxBuffer.buffer;
+}
+
+/*************************************************************************************************/
+uint8_t* Socket::getTxBuffer()
+{
+    return txBuffer.buffer;
+}
+/*************************************************************************************************/
+int Socket::getTxBufferSize()
+{
+    return txBuffer.size;
+}
+/*************************************************************************************************/
+int Socket::getTxBufferBytesPending()
+{
+    return txBuffer.bytesPending;
+}
+/*************************************************************************************************/
+uint8_t* Socket::getRxBuffer()
+{
+    return rxBuffer.buffer;
+}
+/*************************************************************************************************/
+int Socket::getRxBufferSize()
+{
+    return rxBuffer.size;
+}
+/*************************************************************************************************/
+int Socket::getRxBufferBytesPending()
+{
+    return rxBuffer.bytesPending;
+}
+
+
+/*************************************************************************************************/
+WiconnectResult Socket::writeDataCallback(void *user, void *data, int maxReadSize, int *bytesRead)
+{
+    if(txBuffer.bytesPending == 0)
+    {
+        *bytesRead = EOF;
+    }
+    else
+    {
+        int bytesToWrite = MIN(maxReadSize, txBuffer.bytesPending);
+        memcpy(data, txBuffer.ptr, bytesToWrite);
+        txBuffer.ptr += bytesToWrite;
+        txBuffer.bytesPending -= bytesToWrite;
+        *bytesRead = bytesToWrite;
+    }
+
+    return WICONNECT_SUCCESS;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/wiconnect/AsyncCommand.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "CommandCommon.h"
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+
+
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::enqueueCommand(QueuedCommand *command, const Callback &commandCompleteHandler)
+{
+    if(commandQueue.isFull())
+    {
+        return WICONNECT_OVERFLOW;
+    }
+    command->setCompletedCallback(commandCompleteHandler);
+    DEBUG_INFO("Queuing command: %s", command->getCommand());
+    commandQueue.push(command);
+    processNextQueuedCommand();
+    return WICONNECT_SUCCESS;
+}
+
+/*************************************************************************************************/
+void Wiconnect::processNextQueuedCommand()
+{
+    if(commandQueue.isEmpty())
+    {
+        return;
+    }
+    else if(commandExecuting)
+    {
+        return;
+    }
+
+    WiconnectResult result = WICONNECT_SUCCESS;
+    CommandContext *context = (CommandContext*)commandContext;
+    CommandHeader *header = (CommandHeader*)commandHeaderBuffer;
+
+    commandExecuting = true;
+    currentQueuedCommand = commandQueue.pop();
+
+    DEBUG_INFO("Processing next cmd in queue");
+
+    strcpy(commandFormatBuffer, currentQueuedCommand->command);
+
+    RESET_CMD_HEADER(header);
+
+    memset(context, 0, sizeof(CommandContext));
+    if(currentQueuedCommand->responseBufferLen > 0)
+    {
+        context->responseBuffer = currentQueuedCommand->responseBuffer;
+        context->responseBufferLen = currentQueuedCommand->responseBufferLen;
+    }
+    else
+    {
+        context->responseBuffer = internalBuffer;
+        context->responseBufferLen = internalBufferSize;
+    }
+
+    context->responseBufferPtr = context->responseBuffer;
+    context->commandLen = strlen(commandFormatBuffer);
+    context->commandPtr = commandFormatBuffer;
+    context->reader = currentQueuedCommand->reader;
+    context->user = currentQueuedCommand->userData;
+    context->timeoutMs = currentQueuedCommand->timeoutMs;
+    context->callback = currentQueuedCommand->completeCallback;
+    context->nonBlocking = true;
+
+    DEBUG_CMD_SEND(commandFormatBuffer);
+
+    commandExecuting = true;
+    timeoutTimer.reset();
+
+    commandProcessorTimer.start(this, &Wiconnect::commandProcessingTimerHandler, commandProcessingPeriod);
+}
+
+/*************************************************************************************************/
+void Wiconnect::setCommandProcessingPeriod(uint32_t periodMs)
+{
+    commandProcessingPeriod = periodMs;
+}
+
+/*************************************************************************************************/
+void Wiconnect::commandProcessingTimerHandler()
+{
+    checkCurrentCommand();
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/wiconnect/CommandCommon.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "Wiconnect.h"
+#include "internal/common.h"
+#include "StringUtil.h"
+
+
+
+#define CHECK_NULL_BUFFER(buf) if(buf == NULL) return WICONNECT_NULL_BUFFER
+#define CHECK_INITIALIZED() if(!initialized) return WICONNECT_NOT_INITIALIZED
+#define RESET_CMD_HEADER(header)  memset(header, 0, sizeof(CommandHeader)); header->bytes_remaining = WICONNECT_HEADER_LENGTH
+
+#define DEBUG_CMD_SEND(cmd)         debugLog(">> CMD: %s", cmd)
+#define DEBUG_CMD_LOG(res)          debugLog("<< LOG: %s", res)
+#define DEBUG_CMD_RESPONSE(res)     debugLog("<< RES: %s", res)
+#define DEBUG_CMD_ERROR(code)       debugLog("<< ERR:(%d) %s", code, getLastCommandResponseCodeStr())
+#define DEBUG_ERROR(msg, ...)       debugLog("   ERR: " msg, ## __VA_ARGS__)
+#define DEBUG_INFO(msg, ...)        debugLog("   DBG: " msg, ## __VA_ARGS__)
+
+
+
+typedef enum
+{
+    WICONNECT_CMD_TYPE_NULL = 0,
+    WICONNECT_CMD_TYPE_REPLY = 'R',
+    WICONNECT_CMD_TYPE_LOG = 'L',
+    WICONNECT_CMD_TYPE_SAFEMODE = 'S'
+} ResponseType;
+
+typedef enum
+{
+    WICONNECT_CMD_CODE_NULL         = 0,
+    WICONNECT_CMD_SUCCESS           = 1, // The command was successful
+    WICONNECT_CMD_FAILED            = 2, // The command failed, most likely in the firmware
+    WICONNECT_CMD_PARSE_ERROR       = 3, // Failed to parse the command
+    WICONNECT_CMD_UNKNOWN           = 4, // Unknown command
+    WICONNECT_CMD_TOO_FEW_ARGS      = 5, // Not enough command arguments
+    WICONNECT_CMD_TOO_MANY_ARGS     = 6, // Too many command arguments
+    WICONNECT_CMD_UNKNOWN_OPTION    = 7, // Unknown option (e.g. known 'set' command option)
+    WICONNECT_CMD_BAD_ARGS          = 8, // Invalid command arguments
+} ResponseCode;
+
+#define WICONNECT_HEADER_LENGTH 9
+typedef struct
+{
+    ResponseType response_type;
+    ResponseCode response_code;
+    uint16_t response_len;
+    uint8_t len_buffer[WICONNECT_HEADER_LENGTH];
+    uint8_t *len_buffer_ptr;
+    uint8_t bytes_remaining;
+} CommandHeader;
+
+typedef struct
+{
+    char *responseBuffer;
+    char *responseBufferPtr;
+    int responseBufferLen;
+    ReaderFunc reader;
+    void *user;
+    char *commandPtr;
+    int commandLen;
+    int bytesToWrite;
+    int bytesToRead;
+    int timeoutMs;
+    Callback callback;
+    bool nonBlocking;
+} CommandContext;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/wiconnect/ProcessCommand.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "CommandCommon.h"
+
+
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::checkCurrentCommand()
+{
+    WiconnectResult result;
+
+    start:
+    CHECK_INITIALIZED();
+    if(!commandExecuting)
+    {
+        return WICONNECT_IDLE;
+    }
+
+    CommandContext *context = (CommandContext*)commandContext;
+
+    if(context->commandLen > 0)
+    {
+        const int timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs);
+        const int bytesToWrite = context->commandLen;
+        const int bytesWritten = serial.write(context->commandPtr, bytesToWrite, timeout);
+        context->commandPtr += bytesWritten;
+        context->commandLen -= bytesWritten;
+        if(bytesToWrite != bytesWritten)
+        {
+            if(timeoutTimer.timedOut(context->timeoutMs))
+            {
+                issueCommandCallback(WICONNECT_TIMEOUT);
+                return WICONNECT_TIMEOUT;
+            }
+            else
+            {
+                return WICONNECT_PROCESSING;
+            }
+        }
+    }
+
+    while(context->reader.isValid())
+    {
+        if(context->bytesToWrite == 0)
+        {
+            context->responseBufferPtr = context->responseBuffer;
+            if(WICONNECT_FAILED(result, context->reader.call(context->user, context->responseBuffer, context->responseBufferLen, &context->bytesToWrite)))
+            {
+                issueCommandCallback(result);
+                return result;
+            }
+            else if(context->bytesToWrite == EOF)
+            {
+                context->reader.setInvalid();
+                context->bytesToWrite = 0;
+                context->responseBufferPtr = context->responseBuffer;
+                break;
+            }
+            else
+            {
+                timeoutTimer.reset();
+            }
+        }
+        if(context->bytesToWrite > 0)
+        {
+            const int timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs);
+            const int bytesToWrite = context->bytesToWrite;
+            const int bytesWritten = serial.write(context->responseBufferPtr, bytesToWrite, timeout);
+            context->responseBufferPtr += bytesWritten;
+            context->bytesToWrite -= bytesWritten;
+            if(bytesToWrite != bytesWritten)
+            {
+                if(timeoutTimer.timedOut(context->timeoutMs))
+                {
+                    issueCommandCallback(WICONNECT_TIMEOUT);
+                    return WICONNECT_TIMEOUT;
+                }
+                else
+                {
+                    return WICONNECT_PROCESSING;
+                }
+            }
+        }
+    }
+
+    result = receiveResponse();
+    if(result == WICONNECT_PROCESSING && !context->nonBlocking)
+    {
+        goto start;
+    }
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::receiveResponse()
+{
+    for(;;)
+    {
+        WiconnectResult result = receivePacket();
+
+        if(result == WICONNECT_PROCESSING)
+        {
+            return WICONNECT_PROCESSING;
+        }
+        else if(result == WICONNECT_SUCCESS)
+        {
+            CommandHeader *header = (CommandHeader*)commandHeaderBuffer;
+            CommandContext *context = (CommandContext*)commandContext;
+
+            // TODO: need to notify safemode
+
+            if(header->response_type == WICONNECT_CMD_TYPE_REPLY || header->response_type == WICONNECT_CMD_TYPE_SAFEMODE)
+            {
+                if(header->response_code != WICONNECT_CMD_SUCCESS)
+                {
+                    DEBUG_CMD_ERROR(header->response_code);
+                    flush();
+                    issueCommandCallback(WICONNECT_CMD_RESPONSE_ERROR);
+                    return WICONNECT_CMD_RESPONSE_ERROR;
+                }
+                else if(header->response_len > 0)
+                {
+                    DEBUG_CMD_RESPONSE(context->responseBuffer);
+                    header->response_len -= 2;
+                    context->responseBuffer[header->response_len] = 0;
+                }
+                else
+                {
+                    *context->responseBuffer = 0;
+                }
+
+                issueCommandCallback(WICONNECT_SUCCESS);
+
+                return WICONNECT_SUCCESS;
+            }
+            else
+            {
+                DEBUG_CMD_LOG(context->responseBuffer);
+                RESET_CMD_HEADER(header);
+                context->responseBufferPtr = context->responseBuffer;
+            }
+        }
+        else
+        {
+            issueCommandCallback(result);
+            return result;
+        }
+    }
+
+    // shouldn't get here...
+    return WICONNECT_ERROR;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::receivePacket()
+{
+    CommandHeader *header = (CommandHeader*)commandHeaderBuffer;
+    CommandContext *context = (CommandContext*)commandContext;
+
+    if(header->bytes_remaining > 0)
+    {
+        uint16_t bytesReceived;
+        uint8_t buffer[WICONNECT_HEADER_LENGTH];
+
+        while(header->bytes_remaining > 0)
+        {
+            const int timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs);
+            bytesReceived = serial.read((char*)buffer, header->bytes_remaining, timeout);
+            if(bytesReceived == 0)
+            {
+                return timeoutTimer.timedOut(context->timeoutMs) ? WICONNECT_TIMEOUT : WICONNECT_PROCESSING;
+            }
+
+            for(uint8_t *ptr = buffer; bytesReceived > 0; ++ptr)
+            {
+                if(header->response_type == WICONNECT_CMD_TYPE_NULL)
+                {
+                    if( *ptr == WICONNECT_CMD_TYPE_REPLY ||
+                        *ptr == WICONNECT_CMD_TYPE_LOG ||
+                        *ptr == WICONNECT_CMD_TYPE_SAFEMODE)
+                    {
+                        header->response_type = (ResponseType)*ptr;
+                        -- header->bytes_remaining;
+                    }
+                    --bytesReceived;
+                }
+                else if(header->response_code == WICONNECT_CMD_CODE_NULL)
+                {
+                    if(*ptr >= '0' && *ptr <= '7')
+                    {
+                        header->response_code = (ResponseCode)(*ptr - '0' + 1);
+                        --header->bytes_remaining;
+                        header->len_buffer_ptr = header->len_buffer;
+                    }
+                    else
+                    {
+                        RESET_CMD_HEADER(header);
+                    }
+                    --bytesReceived;
+                }
+                else if(header->bytes_remaining > 2)
+                {
+                    uint8_t len_chars = MIN((int)bytesReceived, (int)(header->bytes_remaining-2));
+                    header->bytes_remaining -= len_chars;
+                    bytesReceived -= len_chars;
+                    while(len_chars-- > 0)
+                    {
+                        *header->len_buffer_ptr++ = *ptr++;
+                    }
+                    --ptr; // need to decrement since the for loop increments
+                    if(header->bytes_remaining == 2)
+                    {
+                        uint32_t packetLen;
+                        *header->len_buffer_ptr = 0;
+                        if(!StringUtil::strToUint32((const char*)header->len_buffer, &packetLen))
+                        {
+                            RESET_CMD_HEADER(header);
+                        }
+                        else
+                        {
+                            if((int)packetLen > context->responseBufferLen)
+                            {
+                                DEBUG_ERROR("Packet larger than response buffer: %d > %d", packetLen, context->responseBufferLen);
+                                return WICONNECT_OVERFLOW;
+                            }
+                            header->response_len = (uint16_t)packetLen;
+                            context->bytesToRead = packetLen;
+                        }
+                    }
+                }
+                else if(header->bytes_remaining == 2)
+                {
+                    --bytesReceived;
+                    if(*ptr == '\r')
+                    {
+                        header->bytes_remaining = 1;
+                    }
+                    else
+                    {
+                        RESET_CMD_HEADER(header);
+                    }
+                }
+                else
+                {
+                    --bytesReceived;
+                    if(*ptr == '\n')
+                    {
+                        header->bytes_remaining = 0;
+                        break;
+                    }
+                    else
+                    {
+                        RESET_CMD_HEADER(header);
+                    }
+                }
+            }
+        }
+    }
+
+    while(context->bytesToRead > 0)
+    {
+        const int timeout = context->nonBlocking ? 0 : timeoutTimer.remainingMs(context->timeoutMs);
+        const int bytesToRead = context->bytesToRead;
+        const int bytesReceived = serial.read(context->responseBufferPtr, bytesToRead, timeout);
+        context->responseBufferPtr += bytesReceived;
+        context->bytesToRead -= bytesReceived;
+
+        if(bytesReceived != bytesToRead)
+        {
+            return timeoutTimer.timedOut(context->timeoutMs) ? WICONNECT_TIMEOUT : WICONNECT_PROCESSING;
+        }
+        else if(context->bytesToRead == 0)
+        {
+            *context->responseBufferPtr = 0;
+        }
+    }
+
+    return (header->response_code != WICONNECT_CMD_CODE_NULL &&
+            header->response_type != WICONNECT_CMD_TYPE_NULL &&
+            context->bytesToRead == 0) ? WICONNECT_SUCCESS : WICONNECT_PROCESSING;
+}
+
+/*************************************************************************************************/
+void Wiconnect::issueCommandCallback(WiconnectResult result)
+{
+    CommandHeader *header = (CommandHeader*)commandHeaderBuffer;
+    CommandContext *context = (CommandContext*)commandContext;
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+    void *returnPtr = (currentQueuedCommand != NULL) ? (void*)currentQueuedCommand : (void*)context->responseBuffer;
+    currentQueuedCommand = NULL;
+    commandProcessorTimer.stop();
+#else
+    void *returnPtr = (void*)context->responseBuffer;
+#endif
+    context->callback.call(result, returnPtr, (void*)(uint32_t)header->response_len);
+    commandExecuting = false;
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+    processNextQueuedCommand();
+#endif
+}
+
+/*************************************************************************************************/
+void Wiconnect::stopCurrentCommand()
+{
+    internalProcessingState = 0;
+    issueCommandCallback(WICONNECT_ABORTED);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/wiconnect/SendCommand.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "CommandCommon.h"
+
+
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(const Callback &completeCallback, char *responseBuffer,
+                                       int responseBufferLen, int timeoutMs, const ReaderFunc &reader, void *user,
+                                       const char *cmd, va_list vaList)
+{
+    // preprocessor assertion
+    ct_assert(sizeof(commandContext) >=sizeof(CommandContext));
+    CHECK_INITIALIZED();
+    CHECK_NULL_BUFFER(responseBuffer);
+    if(commandExecuting)
+    {
+        return checkCurrentCommand();
+    }
+
+    CommandContext *context = (CommandContext*)commandContext;
+    CommandHeader *header = (CommandHeader*)commandHeaderBuffer;
+
+    int len = vsnprintf(commandFormatBuffer, sizeof(commandFormatBuffer)-3, cmd, vaList);
+
+    if(len > (int)(sizeof(commandFormatBuffer)-3))
+    {
+        DEBUG_ERROR("Command overflowed: %d > %d", len, sizeof(commandFormatBuffer)-3);
+        return WICONNECT_OVERFLOW;
+    }
+
+    commandFormatBuffer[len++] = '\r';
+    commandFormatBuffer[len++] = '\n';
+    commandFormatBuffer[len] = 0;
+
+    RESET_CMD_HEADER(header);
+
+    memset(context, 0, sizeof(CommandContext));
+    context->responseBuffer = responseBuffer;
+    context->responseBufferPtr = context->responseBuffer;
+    context->responseBufferLen = responseBufferLen;
+    context->commandLen = len;
+    context->commandPtr = commandFormatBuffer;
+    context->reader = reader;
+    context->user = user;
+    context->timeoutMs = timeoutMs;
+    context->callback = completeCallback;
+    context->nonBlocking = nonBlocking;
+
+    DEBUG_CMD_SEND(commandFormatBuffer);
+
+    commandExecuting = true;
+    flush(0);
+    timeoutTimer.reset();
+
+    return checkCurrentCommand();
+}
+
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(char *responseBuffer, int responseBufferLen, int timeoutMs,
+                                       const ReaderFunc &reader, void *user, const char *cmd, va_list vaList)
+{
+    return sendCommand(Callback(), responseBuffer, responseBufferLen, timeoutMs, reader, user, cmd, vaList);
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(char *responseBuffer, int responseBufferLen,  int timeoutMs,
+                                       const ReaderFunc &reader, void *user, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(Callback(), responseBuffer, responseBufferLen, timeoutMs, reader, user, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand( int timeoutMs, const ReaderFunc &reader, void *user, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(Callback(), internalBuffer, internalBufferSize, timeoutMs, reader, user, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(const ReaderFunc &reader, void *user, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(Callback(), internalBuffer, internalBufferSize, defaultTimeoutMs, reader, user, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(char *responseBuffer, int responseBufferLen,  int timeoutMs, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(Callback(), responseBuffer, responseBufferLen, timeoutMs, ReaderFunc(), NULL, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(const Callback &completeCallback, char *responseBuffer, int responseBufferLen, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(completeCallback, responseBuffer, responseBufferLen, defaultTimeoutMs, ReaderFunc(), NULL, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(char *responseBuffer, int responseBufferLen, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(Callback(), responseBuffer, responseBufferLen, defaultTimeoutMs, ReaderFunc(), NULL, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(const Callback &completeCallback, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(completeCallback, internalBuffer, internalBufferSize, defaultTimeoutMs, ReaderFunc(), NULL, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(Callback(), internalBuffer, internalBufferSize, defaultTimeoutMs, ReaderFunc(), NULL, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(const Callback &completeCallback, int timeoutMs, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(completeCallback, internalBuffer, internalBufferSize, timeoutMs, ReaderFunc(), NULL, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(int timeoutMs, const char *cmd, ...)
+{
+    WiconnectResult result;
+    va_list args;
+    va_start(args, cmd);
+    result = sendCommand(Callback(), internalBuffer, internalBufferSize, timeoutMs, ReaderFunc(), NULL, cmd, args);
+    va_end(args);
+    return result;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::sendCommand(const char *cmd, va_list vaList)
+{
+    return sendCommand(Callback(), internalBuffer, internalBufferSize, defaultTimeoutMs, ReaderFunc(), NULL, cmd, vaList);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/wiconnect/Wiconnect.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+#include "WiconnectInterface.h"
+#include "internal/common.h"
+
+
+
+
+
+using namespace wiconnect;
+
+
+
+
+
+#ifdef WICONNECT_ENABLE_MALLOC
+#define MALLOC_ARGS , void* (*mallocPtr)(size_t), void (*freePtr)(void*)
+#define MALLOC_CONSTRUCTORS  , _malloc(mallocPtr), _free(freePtr)
+#else
+#define MALLOC_ARGS
+#define MALLOC_CONSTRUCTORS
+#endif
+
+
+static Wiconnect* instance = NULL;
+
+
+
+
+/*************************************************************************************************/
+void Wiconnect::prepare(void *internalBuffer_, int internalBufferSize_, bool nonBlocking_)
+{
+    instance = this;
+    internalBufferAlloc = false;
+#ifdef WICONNECT_ENABLE_MALLOC
+    if(internalBufferSize_ > 0 && internalBuffer_ == NULL)
+    {
+        assert(_malloc != NULL);
+        internalBuffer = (char*)_malloc(internalBufferSize_);
+        internalBufferAlloc = true;
+    }
+    else
+#endif
+    {
+        internalBuffer = (char*)internalBuffer_;
+    }
+
+    internalProcessingState = 0;
+    currentCommandId = NULL;
+    internalBufferSize = internalBufferSize_;
+    nonBlocking = nonBlocking_;
+    commandExecuting = false;
+    initialized = false;
+    pinToGpioMapper = NULL;
+    defaultTimeoutMs = WICONNECT_DEFAULT_TIMEOUT;
+
+    memset(commandContext, 0, sizeof(commandContext));
+
+#ifdef WICONNECT_ASYNC_TIMER_ENABLED
+    commandProcessingPeriod = WICONNECT_DEFAULT_COMMAND_PROCESSING_PERIOD;
+    currentQueuedCommand = NULL;
+#endif
+}
+
+
+/*************************************************************************************************/
+Wiconnect::Wiconnect(const SerialConfig &serialConfig, void *internalBuffer, int internalBufferSize, Pin reset, Pin wake, bool nonBlocking MALLOC_ARGS) :
+        NetworkInterface(this), SocketInterface(this), FileInterface(this), serial(serialConfig, this), resetGpio(reset), wakeGpio(wake) MALLOC_CONSTRUCTORS
+{
+    prepare(internalBuffer, internalBufferSize, nonBlocking);
+}
+
+/*************************************************************************************************/
+Wiconnect::Wiconnect(const SerialConfig &serialConfig, Pin reset, Pin wake, bool nonBlocking MALLOC_ARGS) :
+    NetworkInterface(this), SocketInterface(this), FileInterface(this), serial(serialConfig, this), resetGpio(reset), wakeGpio(wake) MALLOC_CONSTRUCTORS
+{
+    prepare(NULL, 0, nonBlocking);
+}
+
+/*************************************************************************************************/
+Wiconnect::~Wiconnect()
+{
+#ifdef WICONNECT_ENABLE_MALLOC
+    if(internalBufferAlloc)
+    {
+        _free(internalBuffer);
+    }
+#endif
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::init(bool bringNetworkUp)
+{
+    WiconnectResult result;
+    int retries;
+    bool savedNonBlocking = nonBlocking;
+
+    if(WICONNECT_FAILED(result, reset()))
+    {
+        return result;
+    }
+
+    delayMs(1000);
+
+    initialized = true;
+    nonBlocking = false;
+
+    for(retries = 3; retries > 0; --retries)
+    {
+        result = sendCommand(CMD_SET_SYSTEM_COMMAND_MODE, "machine");
+        if(result != WICONNECT_SUCCESS)
+        {
+            delayMs(1000);
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    if(result == WICONNECT_SUCCESS && bringNetworkUp)
+    {
+        sendCommand(15000, "ping -g");
+    }
+
+    nonBlocking = savedNonBlocking;
+    if(result != WICONNECT_SUCCESS)
+    {
+        initialized = false;
+    }
+
+
+    return result;
+}
+
+/*************************************************************************************************/
+void Wiconnect::deinit(void)
+{
+    initialized = false;
+}
+
+/*************************************************************************************************/
+Wiconnect* Wiconnect::getInstance()
+{
+    return instance;
+}
+
+/*************************************************************************************************/
+bool Wiconnect::isInitialized()
+{
+    return initialized;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::reset()
+{
+    resetGpio = 0;
+    delayMs(10);
+    resetGpio = 1;
+    delayMs(1000);
+    return WICONNECT_SUCCESS;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::wakeup()
+{
+    wakeGpio = 1;
+    delayMs(1);
+    wakeGpio = 0;
+    return WICONNECT_SUCCESS;
+}
+
+/*************************************************************************************************/
+void Wiconnect::flush(int delayMs)
+{
+    if(delayMs != 0)
+    {
+        serial.write("\r\n\r\n", 4, 0);
+    }
+    delayMs(delayMs);
+    serial.flush();
+}
+
+/*************************************************************************************************/
+void Wiconnect::setPinToGpioMapper(PinToGpioMapper mapper)
+{
+    pinToGpioMapper = mapper;
+}
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::getVersion(char *versionBuffer, int versionBufferSize, const Callback &completeCallback)
+{
+    if(versionBuffer != NULL && versionBufferSize == 0)
+    {
+        return WICONNECT_BAD_ARG;
+    }
+    return sendCommand(completeCallback, versionBuffer, versionBufferSize, CMD_GET_VERSION);
+}
+
+/*************************************************************************************************/
+const char* Wiconnect::getWiconnectResultStr(WiconnectResult wiconnectResult)
+{
+    static const char* const wiconnectSuccessStrTable[] = {
+            "Success",                              // WICONNECT_SUCCESS
+            "Processing command",                   // WICONNECT_PROCESSING
+            "Idle",                                 // WICONNECT_IDLE
+            "Aborted",                              // WICONNECT_ABORTED
+    };
+    static const char* const wiconnectErrorStrTable[] = {
+            "",
+            "General error",                        // WICONNECT_ERROR
+            "WiConnect command code error",         // WICONNECT_CMD_RESPONSE_ERROR
+            "Null buffer",                          // WICONNECT_NULL_BUFFER
+            "Not initialized",                      // WICONNECT_NOT_INITIALIZED
+            "Overflow",                             // WICONNECT_OVERFLOW
+            "Timeout",                              // WICONNECT_TIMEOUT
+            "Response handler null",                // WICONNECT_RESPONSE_HANDLER_NULL
+            "Response parse error",                 // WICONNECT_RESPONSE_PARSE_ERROR
+            "Another command is executing",         // WICONNECT_ANOTHER_CMD_EXECUTING
+            "Bad argument(s)",                      // WICONNECT_BAD_ARG
+            "Unsupported",                          // WICONNECT_UNSUPPORTED
+            "Pin name to GPIO mapper null",         // WICONNECT_PINNAME_TO_GPIO_MAPPER_NULL
+            "Duplicate",                            // WICONNECT_DUPLICATE
+            "Not found",                            // WICONNECT_NOT_FOUND
+            "No mapping for pinname to GPIO",       // WICONNECT_PINNAME_TO_GPIO_NO_MAPPING
+            "Not connected",                        // WICONNECT_NOT_CONNECTED
+            "Underflow",                            // WICONNECT_UNDERFLOW
+    };
+
+    if((int)wiconnectResult >= (int)WICONNECT_SUCCESS)
+    {
+        return wiconnectSuccessStrTable[wiconnectResult];
+    }
+    else
+    {
+        wiconnectResult = (WiconnectResult)(-((int)wiconnectResult));
+        return wiconnectErrorStrTable[wiconnectResult];
+    }
+}
+
+
+/*************************************************************************************************/
+void Wiconnect::setDebugLogger(LogFunc logFunc)
+{
+    debugLogger = logFunc;
+}
+
+/*************************************************************************************************/
+void Wiconnect::debugLog(const char *msg, ...)
+{
+    if(!debugLogger.isValid())
+    {
+        return;
+    }
+
+    char buffer[96];
+    va_list args;
+    va_start(args, msg);
+    int len = vsnprintf(buffer, sizeof(buffer), msg, args);
+    va_end(args);
+
+    if(len > (int)(sizeof(buffer)-6))
+    {
+        char *p = &buffer[sizeof(buffer)-6];
+        *p++ = '.';
+        *p++ = '.';
+        *p++ = '.';
+        *p++ = '\r';
+        *p++ = '\n';
+        *p = 0;
+    }
+    else
+    {
+        if(buffer[len-2] != '\r')
+        {
+            char *p = &buffer[len];
+            *p++ = '\r';
+            *p++ = '\n';
+            *p = 0;
+        }
+    }
+    debugLogger.call(buffer);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internal/wiconnect/WiconnectCommand.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "CommandCommon.h"
+#include "StringUtil.h"
+
+
+
+/*************************************************************************************************/
+void Wiconnect::setCommandDefaultTimeout(int timeoutMs)
+{
+    defaultTimeoutMs = timeoutMs;
+}
+
+/*************************************************************************************************/
+int Wiconnect::getCommandDefaultTimeout()
+{
+    return defaultTimeoutMs;
+}
+
+/*************************************************************************************************/
+char* Wiconnect::getResponseBuffer()
+{
+    return internalBuffer;
+}
+
+/*************************************************************************************************/
+uint16_t Wiconnect::getLastCommandResponseLength()
+{
+    CommandHeader *header = (CommandHeader*)commandHeaderBuffer;
+    return header->response_len;
+}
+
+/*************************************************************************************************/
+const char* Wiconnect::getLastCommandResponseCodeStr()
+{
+    if(!initialized)
+    {
+        return NULL;
+    }
+    static const char* const response_error_strings[] ={
+            "Null",
+            "Success",
+            "Failed",
+            "Parse error",
+            "Unknown command",
+            "Too few arguments",
+            "Too many arguments",
+            "Unknown command option",
+            "Bad command arguments"
+    };
+    CommandHeader *header = (CommandHeader*)commandHeaderBuffer;
+
+    return response_error_strings[header->response_code];
+}
+
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::responseToUint32(uint32_t *uint32Ptr)
+{
+    CHECK_INITIALIZED();
+    return StringUtil::strToUint32(internalBuffer, uint32Ptr) ? WICONNECT_SUCCESS : WICONNECT_RESPONSE_PARSE_ERROR;
+}
+
+
+/*************************************************************************************************/
+WiconnectResult Wiconnect::responseToInt32(int32_t *int32Ptr)
+{
+    CHECK_INITIALIZED();
+    return StringUtil::strToInt32(internalBuffer, int32Ptr) ? WICONNECT_SUCCESS : WICONNECT_RESPONSE_PARSE_ERROR;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdk/mbed/Gpio.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+
+#include "platform.h"
+#include "gpio_api.h"
+
+
+
+/*************************************************************************************************/
+Gpio::Gpio(Pin pin) : DigitalOut(pin)
+{
+}
+
+/*************************************************************************************************/
+void Gpio::write(bool value)
+{
+    gpio_write(&gpio, (int)value);
+}
+
+/*************************************************************************************************/
+bool Gpio::read(void)
+{
+    const int v = gpio_read(&gpio);
+    return (bool)v;
+}
+
+/*************************************************************************************************/
+Gpio& Gpio::operator= (bool value)
+{
+    write(value);
+    return *this;
+}
+
+/*************************************************************************************************/
+Gpio& Gpio::operator= (const Gpio& other)
+{
+    memcpy((void*)&gpio, (void*)&other.gpio, sizeof(gpio));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdk/mbed/PeriodicTimer.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+
+#include "Ticker.h"
+
+
+/*************************************************************************************************/
+PeriodicTimer::PeriodicTimer()
+{
+    running = false;
+}
+
+/*************************************************************************************************/
+template<typename T>
+void PeriodicTimer::start(T* tptr, void (T::*mptr)(void), int timeoutMs)
+{
+    attach_us(tptr, mptr, timeoutMs*1000);
+    running = true;
+}
+template void PeriodicTimer::start<Wiconnect>(Wiconnect* tptr, void (Wiconnect::*mptr)(void), int timeoutMs);
+template void PeriodicTimer::start<NetworkInterface>(NetworkInterface* tptr, void (NetworkInterface::*mptr)(void), int timeoutMs);
+
+/*************************************************************************************************/
+void PeriodicTimer::stop(void)
+{
+    detach();
+    running = false;
+}
+
+/*************************************************************************************************/
+bool PeriodicTimer::isRunning()
+{
+    return running;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdk/mbed/PinIrqHandler.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+
+#include "Wiconnect.h"
+#include "types/PinIrqHandler.h"
+
+
+
+/*************************************************************************************************/
+PinIrqHandler::PinIrqHandler(PinName irqPin_, const Callback &callback_) : InterruptIn(irqPin_)
+{
+    irqPin = irqPin_;
+    callback = callback_;
+    mode(PullDown);
+    rise(this, &PinIrqHandler::irqHandler);
+    enable_irq();
+}
+
+/*************************************************************************************************/
+PinIrqHandler::~PinIrqHandler()
+{
+    disable_irq();
+}
+
+
+/*************************************************************************************************/
+void PinIrqHandler::irqHandler()
+{
+    callback.call(WICONNECT_SUCCESS, (void*)irqPin, NULL);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdk/mbed/TimeoutTimer.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+
+#include "Wiconnect.h"
+#include "us_ticker_api.h"
+
+/*************************************************************************************************/
+TimeoutTimer::TimeoutTimer()
+{
+    _start = 0;
+    us_ticker_init();
+}
+
+/*************************************************************************************************/
+void TimeoutTimer::reset(void)
+{
+    _start = us_ticker_read();
+}
+
+/*************************************************************************************************/
+uint32_t TimeoutTimer::remainingMs(uint32_t timeoutMs)
+{
+    const uint32_t diff = readUs() / 1000;
+    return (timeoutMs > diff) ? timeoutMs - diff : 0;
+}
+
+/*************************************************************************************************/
+uint32_t TimeoutTimer::readUs()
+{
+    return us_ticker_read() - _start;
+}
+
+/*************************************************************************************************/
+bool TimeoutTimer::timedOut(uint32_t timeoutMs)
+{
+    timeoutMs *= 1000;
+    return (timeoutMs <= readUs());
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdk/mbed/WiconnectSerial.cpp	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#include <assert.h>
+
+#include "Wiconnect.h"
+#include "internal/common.h"
+
+#ifndef WICONNECT_SERIAL_RX_BUFFER
+#error WICONNECT_SERIAL_RX_BUFFER NOT defined NOT currently supported
+#endif
+
+
+
+
+typedef struct
+{
+    uint16_t size;
+    uint8_t *start, *end;
+    volatile uint8_t *head;
+    volatile uint8_t *tail;
+    volatile uint16_t count;
+} SerialRxBuffer;
+
+
+/*************************************************************************************************/
+WiconnectSerial::WiconnectSerial(const SerialConfig  &config, Wiconnect *wiconnect) : RawSerial(config.tx, config.rx)
+{
+    ct_assert(sizeof(ringBuffer) >= sizeof(SerialRxBuffer));
+
+    baud(config.baud);
+
+    SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer;
+    memset(rxBuffer, 0, sizeof(SerialRxBuffer));
+    bufferAlloc = false;
+    if(config.serialRxBufferSize > 0)
+    {
+        if(config.serialRxBuffer != NULL)
+        {
+            rxBuffer->head = (uint8_t*)config.serialRxBuffer;
+        }
+#ifdef WICONNECT_ENABLE_MALLOC
+        else
+        {
+            assert(wiconnect->_malloc != NULL);
+            rxBuffer->start = (uint8_t*)wiconnect->_malloc(config.serialRxBufferSize);
+            bufferAlloc = true;
+        }
+#endif
+        rxBuffer->head = rxBuffer->tail = (volatile uint8_t*)rxBuffer->start;
+        rxBuffer->end = (uint8_t*)rxBuffer->head + config.serialRxBufferSize;
+        rxBuffer->size = config.serialRxBufferSize;
+        attach(this, &WiconnectSerial::rxIrqHandler, SerialBase::RxIrq);
+    }
+}
+
+/*************************************************************************************************/
+WiconnectSerial::~WiconnectSerial()
+{
+#ifdef WICONNECT_ENABLE_MALLOC
+    if(bufferAlloc)
+    {
+        SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer;
+        Wiconnect::getInstance()->_free(rxBuffer->start);
+    }
+#endif
+}
+
+/*************************************************************************************************/
+void WiconnectSerial::flush(void)
+{
+    while (readable())
+    {
+        int c = getc();
+    }
+
+    SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer;
+    rxBuffer->tail = rxBuffer->head = rxBuffer->start;
+    rxBuffer->count = 0;
+}
+
+/*************************************************************************************************/
+int WiconnectSerial::write(const void *data, int bytesToWrite, int timeoutMs)
+{
+    uint8_t *ptr = (uint8_t*)data;
+    int remaining = bytesToWrite;
+
+    while(remaining > 0)
+    {
+        if(!writeable())
+        {
+            timeoutTimer.reset();
+            while(!writeable())
+            {
+                if(timeoutMs == 0)
+                {
+                    if(timeoutTimer.readUs() >= 500)
+                    {
+                        goto exit;
+                    }
+                }
+                else
+                {
+                    if(timeoutTimer.readUs() >= timeoutMs*1000)
+                    {
+                        goto exit;
+                    }
+                }
+            }
+        }
+
+        putc(*ptr);
+        ++ptr;
+        --remaining;
+    }
+
+    exit:
+    return bytesToWrite - remaining;
+}
+
+/*************************************************************************************************/
+int WiconnectSerial::read(void *data, int bytesToRead, int timeoutMs)
+{
+    SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer;
+    uint8_t *ptr = (uint8_t*)data;
+    int remaining = bytesToRead;
+
+    while(remaining > 0)
+    {
+        if(rxBuffer->count == 0)
+        {
+            if(timeoutMs == 0)
+            {
+                break;
+            }
+            else
+            {
+                timeoutTimer.reset();
+                while(rxBuffer->count == 0)
+                {
+                    if(timeoutTimer.readUs() >= timeoutMs*1000)
+                    {
+                        goto exit;
+                    }
+                }
+            }
+        }
+
+        *ptr++ = *rxBuffer->tail++;
+        --remaining;
+        --rxBuffer->count;
+        if(rxBuffer->tail >= rxBuffer->end)
+            rxBuffer->tail = rxBuffer->start;
+    }
+
+exit:
+    return bytesToRead - remaining;
+}
+
+/*************************************************************************************************/
+void WiconnectSerial::rxIrqHandler(void)
+{
+    SerialRxBuffer *rxBuffer = (SerialRxBuffer*)ringBuffer;
+
+    while (readable() && rxBuffer->count < rxBuffer->size)
+    {
+        *rxBuffer->head++ = (uint8_t)getc();
+        ++rxBuffer->count;
+        if(rxBuffer->head >= rxBuffer->end)
+            rxBuffer->head = rxBuffer->start;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdk/mbed/sdk.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#define MBED_SDK
+
+#include "mbed.h"
+
+namespace wiconnect
+{
+
+#define WICONNECT_ASYNC_TIMER_ENABLED
+#define WICONNECT_ENABLE_MALLOC
+#define WICONNECT_SERIAL_RX_BUFFER
+#define WICONNECT_USE_DEFAULT_STRING_BUFFERS
+
+#define WICONNECT_DEFAULT_MALLOC malloc
+#define WICONNECT_DEFAULT_FREE free
+
+#define WICONNECT_DEFAULT_BAUD 115200
+#define WICONNECT_DEFAULT_TIMEOUT 3000 // ms
+#define WICONNECT_MAX_QUEUED_COMMANDS 8
+#define WICONNECT_DEFAULT_COMMAND_PROCESSING_PERIOD 50 // ms
+
+#define WICONNECT_SOCKET_DEFAULT_RX_BUFFER_SIZE 256
+#define WICONNECT_SOCKET_DEFAULT_TX_BUFFER_SIZE 256
+
+#define WICONNECT_DEFAULT_NONBLOCKING false
+
+#define WICONNECT_GPIO_BASE_CLASS : DigitalOut
+#define WICONNECT_SERIAL_BASE_CLASS : RawSerial
+#define WICONNECT_PERIODIC_TIMER_BASE_CLASS : Ticker
+#define WICONNECT_EXTERNAL_INTERRUPT_GPIO_BASE_CLASS : InterruptIn
+
+
+#define WICONNECT_MAX_PIN_IRQ_HANDLERS 3
+#define WICONNECT_MAX_HOST_SIZE 64
+#define WICONNECT_MAX_FILENAME_SIZE 96
+
+#define PIN_NC NC
+
+
+typedef PinName Pin;
+
+typedef struct _SerialConfig
+{
+    Pin rx;
+    Pin tx;
+    Pin cts;
+    Pin rts;
+    int baud;
+    void *serialRxBuffer;
+    int serialRxBufferSize;
+
+    _SerialConfig(Pin rx, Pin tx, Pin cts, Pin rts, int baud = WICONNECT_DEFAULT_BAUD, void *serialRxBuffer = NULL, int serialRxBufferSize = 0)
+    {
+        this->rx =rx;
+        this->tx =tx;
+        this->cts =cts;
+        this->rts =rts;
+        this->baud = baud;
+        this->serialRxBuffer =serialRxBuffer;
+        this->serialRxBufferSize =serialRxBufferSize;
+    }
+
+    _SerialConfig(Pin rx, Pin tx, int baud = WICONNECT_DEFAULT_BAUD)
+    {
+        this->rx =rx;
+        this->tx =tx;
+        this->cts =PIN_NC;
+        this->rts =PIN_NC;
+        this->baud = baud;
+        this->serialRxBuffer =NULL;
+        this->serialRxBufferSize =0;
+    }
+
+} SerialConfig;
+
+
+
+#define delayMs(ms) wait_ms(ms)
+
+
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/Callback.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include "WiconnectTypes.h"
+#include "FunctionPointer.h"
+
+
+
+namespace wiconnect
+{
+
+
+typedef void (*_Callback)(WiconnectResult result, void *arg1, void *arg2);
+
+class Callback : public FunctionPointer
+{
+public:
+    /*************************************************************************************************/
+    Callback(_Callback func = 0)
+    {
+        _function = (void*)func;
+        _membercaller = NULL;
+        _object = NULL;
+    }
+
+    /*************************************************************************************************/
+    template<typename T>
+    Callback(T *object, void (T::*member)(WiconnectResult result, void *arg1, void *arg2))
+    {
+        _object = static_cast<void*>(object);
+        memcpy(_member, (char*)&member, sizeof(member));
+        _membercaller = (void*)&Callback::membercaller<T>;
+        _function = 0;
+    }
+
+    /*************************************************************************************************/
+    void call(WiconnectResult result, void *arg1, void *arg2)
+    {
+        if (_function)
+        {
+            ((_Callback)_function)(result, arg1, arg2);
+        }
+        else if (_object)
+        {
+            typedef void (*membercallerFunc)(void*, char*, WiconnectResult result, void *arg1, void *arg2);
+            ((membercallerFunc)_membercaller)(_object, _member, result, arg1, arg2);
+        }
+    }
+
+private:
+
+    /*************************************************************************************************/
+    template<typename T>
+    static void membercaller(void *object, char *member, WiconnectResult result, void *arg1, void *arg2)
+    {
+        T* o = static_cast<T*>(object);
+        void (T::*m)(WiconnectResult result, void *arg1, void *arg2);
+        memcpy((char*)&m, member, sizeof(m));
+        (o->*m)(result, arg1, arg2);
+    }
+
+};
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/CommandQueue.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include "WiconnectTypes.h"
+
+
+namespace wiconnect
+{
+
+
+class CommandQueue
+{
+public:
+    /*************************************************************************************************/
+    CommandQueue()
+    {
+        head = tail = queue;
+        count = 0;
+    }
+
+    /*************************************************************************************************/
+    bool isFull()
+    {
+        return count == WICONNECT_MAX_QUEUED_COMMANDS;
+    }
+
+    /*************************************************************************************************/
+    bool isEmpty()
+    {
+        return count == 0;
+    }
+
+    /*************************************************************************************************/
+    bool push(QueuedCommand *cmd)
+    {
+        if(isFull())
+        {
+            return false;
+        }
+        ++count;
+        *tail = cmd;
+        if(++tail >= queue + WICONNECT_MAX_QUEUED_COMMANDS)
+        {
+            tail = queue;
+        }
+
+        return true;
+    }
+
+    /*************************************************************************************************/
+    QueuedCommand* pop()
+    {
+        if(isEmpty())
+            return NULL;
+
+        QueuedCommand* cmd = *head;
+        --count;
+        if(++head >= queue + WICONNECT_MAX_QUEUED_COMMANDS)
+        {
+            head = queue;
+        }
+        return cmd;
+    }
+
+protected:
+    QueuedCommand* queue[WICONNECT_MAX_QUEUED_COMMANDS];
+    QueuedCommand** head;
+    QueuedCommand** tail;
+    int count;
+};
+
+
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/File.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include "Wiconnect.h"
+
+namespace wiconnect
+{
+
+
+class File
+{
+public:
+    File(int rxBufferLen = 0, void *rxBuffer = NULL);
+    ~File();
+
+    const char* getName() const;
+    uint32_t getSize() const;
+    FileType getType() const;
+    FileFlags getFlags() const;
+    uint32_t getVersion() const;
+    const char* getVersionStr(char *buffer = NULL) const;
+
+    WiconnectResult close();
+    WiconnectResult read(void* buffer, uint16_t maxLength, uint16_t *bytesRead);
+    WiconnectResult read(uint8_t **bufferPtr = NULL, uint16_t *bytesReadPtr = NULL);
+    WiconnectResult getc(uint8_t *c);
+    void clearRxBuffer();
+
+    const File* getNext() const;
+    const File* getPrevious() const;
+
+protected:
+    WiconnectResult openForRead(uint8_t handle, const char *filename);
+    WiconnectResult initWithListing(const char *typeStr, const char *flagsStr, const char* sizeStr, const char *versionStr, const char *nameStr);
+
+    uint8_t handle;
+    bool readEnabled;
+    char name[WICONNECT_MAX_FILENAME_SIZE];
+    uint32_t size;
+    FileType type;
+    FileFlags flags;
+    uint32_t version;
+    Wiconnect *wiconnect;
+    File *next;
+    File *previous;
+
+    Buffer rxBuffer;
+
+    void* operator new(size_t size);
+    void operator delete(void*);
+
+    friend class FileInterface;
+    friend class FileList;
+};
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/FileList.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include "Wiconnect.h"
+#include "types/File.h"
+
+namespace wiconnect
+{
+
+class FileList
+{
+public:
+    FileList(int bufferLen = 0, void *buffer = NULL);
+    ~FileList();
+
+    const File* getListHead() const;
+    int getCount() const;
+    const File* getResult(int i) const;
+    const File* operator [](int i) const;
+
+protected:
+    File *listHead, *listTail;
+    uint8_t *buffer;
+    uint8_t *bufferPtr;
+    int bufferLen;
+    int count;
+
+    WiconnectResult add(const char *typeStr, const char *flagsStr, const char* sizeStr, const char *versionStr, const char *nameStr);
+
+    friend class FileInterface;
+};
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/FunctionPointer.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+namespace wiconnect
+{
+
+class FunctionPointer
+{
+public:
+    /*************************************************************************************************/
+    FunctionPointer& operator=( const FunctionPointer& other )
+    {
+        _object = other._object;
+        _function = other._function;
+        _membercaller = other._membercaller;
+        memcpy(_member, other._member, sizeof(_member));
+        return *this;
+    }
+
+    /*************************************************************************************************/
+    bool isValid() const
+    {
+        return (_function != NULL) || (_object != NULL);
+    }
+
+    /*************************************************************************************************/
+    void setInvalid()
+    {
+        _function = NULL;
+        _object = NULL;
+    }
+
+protected:
+    void *_object;
+    void *_function;
+    char _member[16];
+    void *_membercaller;
+};
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/Gpio.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include "WiconnectTypes.h"
+
+
+namespace wiconnect
+{
+
+class Gpio WICONNECT_GPIO_BASE_CLASS
+{
+public:
+    Gpio(Pin pin);
+
+    void write(bool value);
+
+    bool read(void);
+
+    Gpio& operator= (bool value);
+
+    Gpio& operator= (const Gpio& other);
+
+};
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/LogFunc.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "WiconnectTypes.h"
+#include "FunctionPointer.h"
+
+namespace wiconnect
+{
+
+typedef int (*_LogFunc)(const char *str);
+
+class LogFunc : public FunctionPointer
+{
+public:
+    /*************************************************************************************************/
+    LogFunc(_LogFunc func = 0)
+    {
+        _function = (void*)func;
+        _membercaller = NULL;
+        _object = NULL;
+    }
+
+    /*************************************************************************************************/
+    template<typename T>
+    LogFunc(T *object, WiconnectResult (T::*member)(const char *str))
+    {
+        _object = static_cast<void*>(object);
+        memcpy(_member, (char*)&member, sizeof(member));
+        _membercaller = (void*)&LogFunc::membercaller<T>;
+        _function = 0;
+    }
+
+    /*************************************************************************************************/
+    int call(const char *str)
+    {
+        if (_function)
+        {
+            return ((_LogFunc)_function)(str);
+        }
+        else if (_object)
+        {
+            typedef int (*membercallerFunc)(void*, char*, const char *str);
+            return ((membercallerFunc)_membercaller)(_object, _member, str);
+        }
+        else
+        {
+            return -1;
+        }
+    }
+
+private:
+
+    /*************************************************************************************************/
+    template<typename T>
+    static int membercaller(void *object, char *member, const char *str)
+    {
+        T* o = static_cast<T*>(object);
+        int (T::*m)(const char *str);
+        memcpy((char*)&m, member, sizeof(m));
+        return (o->*m)(str);
+    }
+};
+
+
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/PeriodicTimer.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "WiconnectTypes.h"
+
+
+namespace wiconnect
+{
+
+class PeriodicTimer WICONNECT_PERIODIC_TIMER_BASE_CLASS
+{
+public:
+    PeriodicTimer();
+
+    template<typename T>
+    void start(T* tptr, void (T::*mptr)(void), int timeoutMs);
+    void stop(void);
+    bool isRunning();
+protected:
+    bool running;
+};
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/PinIrqHandler.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+
+
+namespace wiconnect
+{
+
+
+class SocketIrqHandlerMap;
+
+class PinIrqHandler WICONNECT_EXTERNAL_INTERRUPT_GPIO_BASE_CLASS
+{
+public:
+    PinIrqHandler(Pin irqPin, const Callback &callback);
+    //~PinIrqHandler();
+
+    void irqHandler();
+
+protected:
+    PinName irqPin;
+    Callback callback;
+
+    friend class SocketIrqHandlerMap;
+};
+
+
+typedef uint8_t PinIrqHandlerBuffer[sizeof(PinIrqHandler)];
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/QueuedCommand.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include "WiconnectTypes.h"
+
+
+namespace wiconnect
+{
+
+class QueuedCommand
+{
+public:
+    void *userData;
+
+
+    QueuedCommand(int responseBufferLen, char *responseBuffer, int timeoutMs, const ReaderFunc &reader, void *user, const char *cmd, va_list vaList);
+    QueuedCommand(int responseBufferLen, char *responseBuffer, int timeoutMs, const char *cmd, ...);
+    QueuedCommand(int responseBufferLen, char *responseBuffer, const char *cmd, ...);
+    QueuedCommand(int timeoutMs_, const char *cmd, ...);
+    QueuedCommand(const char *cmd, ...);
+    ~QueuedCommand();
+
+    char *getResponseBuffer();
+    int getResponseBufferLen();
+    int getTimeoutMs();
+    ReaderFunc getReader();
+    void * getReaderUserData();
+    char* getCommand();
+    Callback getCompletedCallback();
+    void setCompletedCallback(const Callback &cb);
+
+    QueuedCommand& operator=( const QueuedCommand& other );
+    void* operator new(size_t size);
+    void operator delete(void*);
+
+protected:
+    char *responseBuffer;
+    int responseBufferLen;
+    int timeoutMs;
+    ReaderFunc reader;
+    void *user;
+    char command[WICONNECT_MAX_CMD_SIZE];
+    Callback completeCallback;
+#ifdef WICONNECT_ENABLE_MALLOC
+    bool allocatedBuffer;
+#endif
+    friend class NetworkInterface;
+    friend class Wiconnect;
+
+    void initialize(int responseBufferLen, char *responseBuffer_, int timeoutMs_, const ReaderFunc &reader_, void *user_, const char *cmd_, va_list vaList);
+};
+
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/ReaderFunc.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "WiconnectTypes.h"
+#include "FunctionPointer.h"
+
+
+namespace wiconnect
+{
+
+typedef WiconnectResult (*_ReaderFunc)(void *user, void *data, int maxReadSize, int *bytesRead);
+
+class ReaderFunc : public FunctionPointer
+{
+public:
+
+    /*************************************************************************************************/
+    ReaderFunc(_ReaderFunc func = 0)
+    {
+        _function = (void*)func;
+        _membercaller = NULL;
+        _object = NULL;
+    }
+
+    /*************************************************************************************************/
+    template<typename T>
+    ReaderFunc(T *object, WiconnectResult (T::*member)(void *user, void *data, int maxReadSize, int *bytesRead))
+    {
+        _object = static_cast<void*>(object);
+        memcpy(_member, (char*)&member, sizeof(member));
+        _membercaller = (void*)&ReaderFunc::membercaller<T>;
+        _function = 0;
+    }
+
+    /*************************************************************************************************/
+    WiconnectResult call(void *user, void *data, int maxReadSize, int *bytesRead)
+    {
+        if (_function)
+        {
+            return ((_ReaderFunc)_function)(user, data, maxReadSize, bytesRead);
+        }
+        else if (_object)
+        {
+            typedef WiconnectResult (*membercallerFunc)(void*, char*, void *user, void *data, int maxReadSize, int *bytesRead);
+            return ((membercallerFunc)_membercaller)(_object, _member, user, data, maxReadSize, bytesRead);
+        }
+        else
+        {
+            return WICONNECT_ERROR;
+        }
+    }
+
+private:
+
+    /*************************************************************************************************/
+    template<typename T>
+    static WiconnectResult membercaller(void *object, char *member, void *user, void *data, int maxReadSize, int *bytesRead)
+    {
+        T* o = static_cast<T*>(object);
+        WiconnectResult (T::*m)(void *user, void *data, int maxReadSize, int *bytesRead);
+        memcpy((char*)&m, member, sizeof(m));
+        return (o->*m)(user, data, maxReadSize, bytesRead);
+    }
+};
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/ScanResult.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+
+#include "WiconnectTypes.h"
+#include "StringUtil.h"
+
+
+namespace wiconnect
+{
+
+
+class ScanResult
+{
+public:
+    uint8_t getChannel() const;
+    NetworkSignalStrength getSignalStrength() const;
+    const MacAddress* getMacAddress() const;
+    NetworkSecurity getSecurityType() const;
+    uint32_t getRate() const;
+    const char* getRateStr(char *buffer = NULL) const;
+    const Ssid* getSsid() const;
+
+    const ScanResult* getNext() const;
+    const ScanResult* getPrevious() const;
+
+protected:
+    ScanResult();
+
+    WiconnectResult init(const char *channelStr, const char *rssiStr, const char* macStr, const char *rateStr, const char *secStr, const char *ssidStr);
+    ScanResult *next;
+    ScanResult *previous;
+    uint8_t channel;
+    int16_t rssi;
+    MacAddress mac;
+    uint32_t rate;
+    NetworkSecurity security;
+    Ssid ssid;
+
+    void* operator new(size_t size);
+    void operator delete(void*);
+
+    friend class ScanResultList;
+};
+
+
+
+
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/ScanResultList.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "WiconnectTypes.h"
+#include "types/ScanResult.h"
+
+
+
+namespace wiconnect
+{
+
+
+
+class ScanResultList
+{
+public:
+    ScanResultList(int bufferLen = 0, void *buffer = NULL);
+    ~ScanResultList();
+
+    const ScanResult* getListHead() const;
+    int getCount() const;
+    const ScanResult* getResult(int i) const;
+    const ScanResult* operator [](int i) const;
+
+protected:
+    ScanResult *listHead, *listTail;
+    uint8_t *buffer;
+    uint8_t *bufferPtr;
+    int bufferLen;
+    int count;
+
+    WiconnectResult add(const char *channelStr, const char *rssiStr, const char* macStr, const char *rateStr, const char *secStr, const char *ssidStr);
+
+
+    friend class NetworkInterface;
+};
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/Socket.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+#include "WiconnectTypes.h"
+
+namespace wiconnect
+{
+
+
+class Socket
+{
+public:
+    Socket(int rxBufferLen = 0, void *rxBuffer = NULL, int txBufferLen = 0, void *txBuffer = NULL);
+    ~Socket();
+
+    WiconnectResult close();
+    WiconnectResult poll(bool *rxDataAvailablePtr);
+    WiconnectResult write(const void* buffer, int length, bool flush = false);
+    WiconnectResult write(int length, bool flush = true);
+    WiconnectResult read(void* buffer, uint16_t maxLength, uint16_t *bytesRead);
+    WiconnectResult read(uint8_t **bufferPtr = NULL, uint16_t *bytesReadPtr = NULL);
+    WiconnectResult putc(uint8_t c, bool flush = false);
+    WiconnectResult puts(const char *s, bool flush = false);
+    WiconnectResult getc(uint8_t *c);
+    WiconnectResult printf(const char* format, ...);
+    WiconnectResult flushTxBuffer();
+    void clearRxBuffer();
+
+    uint8_t *getTxBuffer();
+    int getTxBufferSize();
+    int getTxBufferBytesPending();
+    uint8_t *getRxBuffer();
+    int getRxBufferSize();
+    int getRxBufferBytesPending();
+
+    bool isConnected();
+    SocketType getType();
+    const char* getHost();
+    uint16_t getLocalPort();
+    uint16_t getRemotePort();
+    uint8_t getHandle();
+
+protected:
+    bool connected;
+    SocketType type;
+    uint8_t handle;
+    char host[WICONNECT_MAX_HOST_SIZE];
+    uint16_t localPort;
+    uint16_t remotePort;
+    Wiconnect *wiconnect;
+    Buffer txBuffer;
+    Buffer rxBuffer;
+
+    WiconnectResult init(uint8_t handle, SocketType type, const char *host, uint16_t remotePort, uint16_t localPort);
+
+    WiconnectResult writeDataCallback(void *user, void *data, int maxReadSize, int *bytesRead);
+
+    friend class SocketInterface;
+};
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/SocketIrqHandlerMap.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "Wiconnect.h"
+#include "types/PinIrqHandler.h"
+
+namespace wiconnect
+{
+
+class SocketIrqHandlerMap
+{
+public:
+    /*************************************************************************************************/
+    SocketIrqHandlerMap()
+    {
+        memset(handlers, 0, sizeof(handlers));
+    }
+
+    /*************************************************************************************************/
+    ~SocketIrqHandlerMap()
+    {
+        for(int i = 0; i < WICONNECT_MAX_PIN_IRQ_HANDLERS; ++i)
+        {
+            if(handlers[i] != NULL)
+            {
+                handlers[i]->~PinIrqHandler();
+            }
+        }
+    }
+
+    /*************************************************************************************************/
+    bool pinIsRegistered(Pin pin)
+    {
+        for(int i = 0; i < WICONNECT_MAX_PIN_IRQ_HANDLERS; ++i)
+        {
+            if(handlers[i] != NULL && handlers[i]->irqPin == pin)
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /*************************************************************************************************/
+    WiconnectResult registerHandler(Pin pin, const Callback &callback)
+    {
+        if(pinIsRegistered(pin))
+        {
+            return WICONNECT_DUPLICATE;
+        }
+
+        PinIrqHandler *handler = NULL;
+
+        for(int i = 0; i < WICONNECT_MAX_PIN_IRQ_HANDLERS; ++i)
+        {
+            if(handlers[i] == NULL)
+            {
+                handler = (PinIrqHandler*)&handlerBuffers[i];
+                handlers[i] = handler;
+            }
+        }
+
+        if(handler == NULL)
+        {
+            return WICONNECT_NOT_FOUND;
+        }
+
+        *handler = PinIrqHandler(pin, callback);
+
+        return WICONNECT_SUCCESS;
+    }
+
+    /*************************************************************************************************/
+    WiconnectResult unregisterHandler(Pin pin)
+    {
+        for(int i = 0; i < WICONNECT_MAX_PIN_IRQ_HANDLERS; ++i)
+        {
+            if(handlers[i] != NULL && handlers[i]->irqPin == pin)
+            {
+                handlers[i]->~PinIrqHandler();
+                handlers[i] = NULL;
+                return WICONNECT_SUCCESS;
+            }
+        }
+
+        return WICONNECT_NOT_FOUND;
+    }
+
+private:
+    PinIrqHandler *handlers[WICONNECT_MAX_PIN_IRQ_HANDLERS];
+    PinIrqHandlerBuffer handlerBuffers[WICONNECT_MAX_PIN_IRQ_HANDLERS];
+};
+
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/TimeoutTimer.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+
+namespace wiconnect
+{
+
+class TimeoutTimer
+{
+public:
+    TimeoutTimer();
+
+    void reset(void);
+
+    uint32_t remainingMs(uint32_t timeoutMs);
+    uint32_t readUs();
+
+    bool timedOut(uint32_t timeoutMs);
+
+protected:
+    uint32_t _start;
+
+};
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types/WiconnectSerial.h	Mon Aug 11 09:58:24 2014 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014, ACKme Networks
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of ACKme Networks.
+ */
+
+#pragma once
+
+#include "WiconnectTypes.h"
+
+
+namespace wiconnect
+{
+
+class WiconnectSerial WICONNECT_SERIAL_BASE_CLASS
+{
+public:
+    WiconnectSerial(const SerialConfig  &config, Wiconnect *wiconnect = NULL);
+    //~WiconnectSerial();
+
+    void flush(void);
+    int write(const void *data, int bytesToWrite, int timeoutMs);
+    int read(void *data, int bytesToRead, int timeoutMs);
+
+protected:
+    TimeoutTimer timeoutTimer;
+#ifdef WICONNECT_SERIAL_RX_BUFFER
+    uint8_t ringBuffer[32];
+    bool bufferAlloc;
+    void rxIrqHandler(void);
+#endif
+};
+
+
+}
+
+
+