Implementation of the WifiPlusClick hardware module.

Dependents:   WifiPlusKlickExample

WifiPlusClick Libary

Overview

http://www.mikroe.com/img/development-tools/accessory-boards/click/wifi-plus/wifi_plus_click_main.png

This library implements the functionality exposed by a WifiPlusClick module from MikroElektronika (http://www.mikroe.com/click/wifi-plus/).

The WifiPlusClick module is an easy to handle module which provides access to up to 8 simultaneous socket objects - which is an an important aspect when you want to implement your own web server.

When I first started with the more commonly used Wifly module, I found out that the Wifly module does not reliably serve webpages which include other resources like images, JavaScript files or CSS files. The root cause seems to be the limitation that Wifly is only able to handle a single socket at this time. So I searched for an alternative and found this (actually cheaper) alternative :

WifiPlusClick HW Module

This module comes with its own limitations. The WifiPlusClick Module interface does not allow to use broadcasting or multicasting on UDP sockets. There are some additional limitations, but I think these are not so important. The following functionality is provided by the module and my library implementation :

  1. Wifi functionality
    1. Connections using AD-HOC or INFRASTRUCTURE mode
    2. List all available Wifi beacons
    3. WEP and WPA/WPA2 security modes including binary and ASCII keys
    4. reading binary WPA key after successfull Connection to speed up connection time
  2. Socket functionality
    1. UDP sockets
    2. TCP sockets

Limitations

I found the following limitations:

  1. UDP sockets cannot use multicasting or broadcasting
  2. set_option functionality is not provided by the HW
  3. 8 sockets can be configured with 1024 bytes of buffer each or 1 socket with 8192 bytes of buffer.

Sample application

Here is my sample application which you can use as a starting point.

Import programWifiPlusKlickExample

Example application of the WifiPlusClick library for use of WifiPlusClick HW Module from Mikroe.com

NOTE

The implementation of the Sockets in this library is still not completely tested. I only tested the TCP part of the sockets. Please let me know what your experiences are when using the library. I will be working on a multithreaded version of this library...

Files at this revision

API Documentation at this revision

Comitter:
leihen
Date:
Mon Jul 29 15:15:21 2013 +0000
Commit message:
Initial Version of the WifiPlusClick Library.
; Tested in INFRASTRUCTURE mode only.

Changed in this revision

Helper/DnsQuery.cpp Show annotated file Show diff for this revision Revisions of this file
Helper/DnsQuery.h Show annotated file Show diff for this revision Revisions of this file
Socket/Endpoint.cpp Show annotated file Show diff for this revision Revisions of this file
Socket/Endpoint.h Show annotated file Show diff for this revision Revisions of this file
Socket/Socket.cpp Show annotated file Show diff for this revision Revisions of this file
Socket/Socket.h Show annotated file Show diff for this revision Revisions of this file
Socket/TCPSocketConnection.cpp Show annotated file Show diff for this revision Revisions of this file
Socket/TCPSocketConnection.h Show annotated file Show diff for this revision Revisions of this file
Socket/TCPSocketServer.cpp Show annotated file Show diff for this revision Revisions of this file
Socket/TCPSocketServer.h Show annotated file Show diff for this revision Revisions of this file
Socket/UDPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
Socket/UDPSocket.h Show annotated file Show diff for this revision Revisions of this file
Wifi.cpp Show annotated file Show diff for this revision Revisions of this file
Wifi.h Show annotated file Show diff for this revision Revisions of this file
WifiPlusClick.cpp Show annotated file Show diff for this revision Revisions of this file
WifiPlusClick.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 2a179bd4cc02 Helper/DnsQuery.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Helper/DnsQuery.cpp	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,205 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "DnsQuery.h"
+
+#define DEBUG
+#include "debug.h"
+
+
+
+DnsQuery::DnsQuery(Wifi* wifi, IPADDRESS_t *dnsip)
+    : _wifi(wifi)
+{
+    _dnsip.sin_addr.o1 = dnsip->sin_addr.o1;
+    _dnsip.sin_addr.o2 = dnsip->sin_addr.o2;
+    _dnsip.sin_addr.o3 = dnsip->sin_addr.o3;
+    _dnsip.sin_addr.o4 = dnsip->sin_addr.o4;
+    INFO("Setting   DNS = %d.%d.%d.%d !", dnsip->sin_addr.o1, dnsip->sin_addr.o2, dnsip->sin_addr.o3, dnsip->sin_addr.o4);
+    INFO("Accepting DNS = %d.%d.%d.%d !", _dnsip.sin_addr.o1, _dnsip.sin_addr.o2, _dnsip.sin_addr.o3, _dnsip.sin_addr.o4);
+}
+
+bool DnsQuery::gethostbyname(const char* hostname, IPADDRESS_t &ipaddress)
+{
+    int len = 0;
+    if (hostname == NULL)
+        return false;
+    len = strlen(hostname);
+    if ((len >128) || (len == 0))
+        return false;
+    memset (&ipaddress, 0, sizeof(ipaddress));
+    
+    int packetlen = /* size of HEADER structure */ 12 + /* size of QUESTION Structure */5 + len + 1;
+    char *packet = new char[packetlen]; /* this is the UDP packet to send to the DNS */
+    if (packet == NULL)
+        return false;
+    
+    //  Fill the header
+    memset(packet, 0, packetlen);
+    packet[1] = 1;      //  ID = 1
+    packet[5] = 1;      // QDCOUNT = 1 (contains one question)
+
+    int c = 13;         //  point to NAME element in question section or request
+    int cnt = 12;       //  points to the counter of
+    packet[cnt] = 0;
+    for (int i = 0 ; i < len ; i++) {
+        if (hostname[i] != '.') {
+            //  Copy the character and increment the character counter
+            packet[cnt]++;
+            packet[c++] = hostname[i];
+        } else {
+            //  Finished with this part, so go to the next
+            cnt = c++;
+            packet[cnt] = 0;
+        }
+    }
+    
+    //  Terminate this domain name with a zero entry
+    packet[c++] = 0;
+    
+    //  Set QTYPE
+    packet[c++] = 0;
+    packet[c++] = 1;
+    //  Set QCLASS
+    packet[c++] = 0;
+    packet[c++] = 1;
+    
+    //  REMOVE ME !!!!
+    std::printf("--> DUMPING UDP PACKET : ");
+    int port;
+    for( int i = 0 ; i < c ; i++) {
+        std::printf("%02x ", packet[i]);
+    }
+    std::printf("\n\n\n");
+    //  Ready to send to DNS
+    SOCKET_HANDLE_t sock = _wifi->SocketCreate(UDP);
+    if (sock == InvalidSocketHandle) {
+        delete packet;
+        return false;
+    }
+ 
+    INFO("Using %d.%d.%d.%d as DNS !", _dnsip.sin_addr.o1, _dnsip.sin_addr.o2, _dnsip.sin_addr.o3, _dnsip.sin_addr.o4);
+    if (!_wifi->SocketSendTo(sock, &_dnsip, 53, packet, packetlen)) {
+        delete packet;
+        _wifi->SocketClose(sock);
+        return false;
+    }
+    
+    delete packet;
+    
+    packet = new char [1024];
+    if (packet == NULL) {
+        _wifi->SocketClose(sock);
+        return false;
+    }
+    
+    //  Receive the answer from DNS
+    Timer t;
+    int recvd = 0;
+    t.start();
+    
+    while (t.read_ms() < 10000) {
+        if ((recvd = _wifi->SocketRecvFrom (sock, NULL, &port, packet, 1024)) > 0 ) {
+            //  process input
+            std::printf("Received %d bytes from DNS !\n", recvd);
+            if (!resolve(packet, ipaddress)) {
+                break;
+            }
+                        
+            //  cleanup and return
+            delete packet;
+            _wifi->SocketClose(sock);
+            return true;
+        } else {
+            ERR("SocketRecvFrom returned %d !", recvd);
+        }
+    }    
+
+    delete packet;
+    
+    _wifi->SocketClose(sock);
+        
+    return false;
+}
+
+
+bool DnsQuery::resolve(char* resp, IPADDRESS_t &ipaddress)
+{
+    int ID = (((int)resp[0]) <<8) + resp[1];
+    int QR = resp[2] >>7;
+    int Opcode = (resp[2]>>3) & 0x0F;
+    int RCODE = (resp[3] & 0x0F);
+    int ANCOUNT = (((int)resp[6])<<8)+ resp[7];
+    
+    INFO("Resolving response : ID = %d, QR = %d, Opcode = %d, RCODE = %d", ID, QR, Opcode, RCODE);
+    if ((ID != 1) || (QR != 1) || (Opcode != 0) || (RCODE != 0)) {
+        ERR("Received non matching response from DNS !");
+        return false;
+    }
+    
+    int c = 12;
+    int d;
+    //  Skip domain question
+    while(  (d=resp[c++]) != 0) {
+        c+=d;
+    }
+    c+= 4; //   skip QTYPE and QCLASS
+    
+    //  Here comes the resource record
+    for (int ans = 0 ; ans < ANCOUNT; ans++) {
+        if (parseRR(resp, c, ipaddress)) {
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+bool DnsQuery::parseRR(char *resp, int& c, IPADDRESS_t& adr )
+{
+    int n = 0;
+    
+    while( (n=resp[c++]) != 0) {
+        if ((n & 0xc0) != 0) {
+            //  This is a link
+            c++;
+            break;
+        } else {
+            c+= n;  //  skip this segment, not interested in string domain names
+        }
+    }
+    
+    int TYPE = (((int)resp[c])<<8) + resp[c+1];
+    int CLASS = (((int)resp[c+2])<<8) + resp[c+3];
+    int RDLENGTH = (((int)resp[c+8])<<8) + resp[c+9];
+
+    INFO("Record of TYPE=%d and CLASS=%d detected !", TYPE, CLASS);
+    c+= 10;
+    if ((CLASS == 1) && (TYPE == 1)) {
+        adr.sin_addr.o1 = resp[c];
+        adr.sin_addr.o2 = resp[c+1];
+        adr.sin_addr.o3 = resp[c+2];
+        adr.sin_addr.o4 = resp[c+3];
+        c+= RDLENGTH;
+        return true;
+    } else {
+    }
+    c+= RDLENGTH;
+    
+    return false;
+}
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 Helper/DnsQuery.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Helper/DnsQuery.h	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,68 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __DNSQUERY_H__
+#define __DNSQUERY_H__
+
+#include "Wifi.h"
+
+
+/** Class DnsQuery implements DNS over UDP functionality.
+  * Example as a typical use case :
+  * @code
+  * #include "mbed.h"
+  * #include "DnsQuery.h"
+  *
+  * void main(void)
+  * {
+  *     IPADDRESS_t ipAddress;  // will receive the ip address of the host
+  *     IPADDRESS_t dnsIp = { 192, 168, 178, 1 };      // Ip Address of the DNS server
+  *     
+  *     DnsQuery dns(Wifi::getInstance(), &dnsIp);
+  *     if (dns.gethostbyname("mbed.org", ipAddress)) {
+  *         printf("Ip-Address of mbed.org is %d.%d.%d.%d\n", ipAddress.sin_addr.o1, ipAddress.sin_addr.o2, ipAddress.sin_addr.o3, ipAddress.sin_addr.o4);
+  *     } else {
+  *         printf("Unable to obtain IP-Address\n");
+  *     }
+  * }
+  * @endcode
+  */
+class DnsQuery
+{
+public:
+    /** Constructor to instantiate a DnsQuery object.
+      * @param wifi : A valid pointer to a Wifi Object, which can be used to obtain a UDP socket object.
+      * @param dnsip : A valid pointer which holds the IPAddress of the DNS server to query.
+      */
+    DnsQuery(Wifi* wifi, IPADDRESS_t* dnsip);
+    
+    /** Function gethostbyname implements the functionality to query a domain name server for an IP-Address of a given hostname.
+      * @param hostname : the hostname of interest as a string.
+      * @param ipaddress : a reference to a IPADDRESS_t object which will receive the resolved IP Address of the host in question.
+      * @returns true if successfull, or false otherwise.
+      */
+    bool gethostbyname(const char* hostname, IPADDRESS_t &ipaddress);
+protected:
+    bool resolve(char* resp, IPADDRESS_t &ipaddress);
+    bool parseRR(char *resp, int& c, IPADDRESS_t& adr );
+
+protected:
+    Wifi* _wifi;
+    IPADDRESS_t _dnsip;
+};
+
+#endif // __DNSQUERY_H__
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 Socket/Endpoint.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/Endpoint.cpp	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,51 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "Socket/Socket.h"
+#include "Socket/Endpoint.h"
+#include <cstring>
+
+using std::memset;
+
+Endpoint::Endpoint() 
+{
+    wifi = Wifi::getInstance();
+    if (wifi == NULL)
+        error("Endpoint constructor error: no wifi instance available!\r\n");
+    reset_address();
+}
+Endpoint::~Endpoint() {}
+
+void Endpoint::reset_address(void) {
+    _ipAddress.sin_addr.o1 = _ipAddress.sin_addr.o2 = _ipAddress.sin_addr.o3 = _ipAddress.sin_addr.o4 = 0;
+    _port = 0;
+}
+
+int Endpoint::set_address(const char* host, const int port) {
+    //Resolve DNS address or populate hard-coded IP address
+    wifi->gethostbyname(host, &_ipAddress);
+    _port = port;
+    return 0;
+}
+
+char* Endpoint::get_address() {
+    return (char*)&_ipAddress;
+}
+
+int   Endpoint::get_port() {
+    return _port;
+}
diff -r 000000000000 -r 2a179bd4cc02 Socket/Endpoint.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/Endpoint.h	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,65 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef ENDPOINT_H
+#define ENDPOINT_H
+
+#include "Wifi.h"
+
+class UDPSocket;
+
+/**
+IP Endpoint (address, port)
+*/
+class Endpoint {
+    friend class UDPSocket;
+
+public:
+    /** IP Endpoint (address, port)
+     */
+    Endpoint(void);
+    
+    ~Endpoint(void);
+    
+    /** Reset the address of this endpoint
+     */
+    void reset_address(void);
+    
+    /** Set the address of this endpoint
+    \param host The endpoint address (it can either be an IP Address or a hostname that will be resolved with DNS).
+    \param port The endpoint port
+    \return 0 on success, -1 on failure (when an hostname cannot be resolved by DNS).
+     */
+    int  set_address(const char* host, const int port);
+    
+    /** Get the IP address of this endpoint
+    \return The IP address of this endpoint.
+     */
+    char* get_address(void);
+    
+    /** Get the port of this endpoint
+    \return The port of this endpoint
+     */
+    int get_port(void);
+
+protected:
+    IPADDRESS_t _ipAddress;
+    int _port;
+    Wifi * wifi;
+};
+
+#endif
diff -r 000000000000 -r 2a179bd4cc02 Socket/Socket.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/Socket.cpp	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,47 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "Socket.h"
+
+
+Socket::Socket() : _blocking(true), _timeout(4),  _socket(InvalidSocketHandle)
+{
+}
+
+Socket::~Socket()
+{
+    close();
+}
+
+void Socket::set_blocking(bool blocking, unsigned int timeout)
+{
+    _blocking = blocking;
+    _timeout = timeout;
+}
+
+
+int Socket::close(bool shutdown)
+{
+    if (_socket == InvalidSocketHandle) {
+        return -1;
+    }
+    
+    Wifi::getInstance()->SocketClose(_socket);
+    
+    return 0;
+}
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 Socket/Socket.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/Socket.h	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,64 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __SOCKET_H__
+#define __SOCKET_H__
+
+
+#include "Wifi.h"
+
+/** Class socket is the base class implementation for TCP and UDP sockets. As the socket class does not provide a full implementation of any kind, it is not recommended to use it.
+  * Class socket is required to implement the base functionality for UDP and TCP sockets in the WifiPlusClick library implementation.
+  * @note Please note that in this implementation the set_option function is not working as the WifiPlusClick module does not support this functionality.
+  */
+class Socket
+{
+public:
+    /** Constructor of socket object.
+      */
+    Socket();
+    
+    /** Function set_blocking sets the socket into a blocking or non-blocking status. In case of a blocking socket a timeout can be specified.
+      * @param blocking : set to true if time consuming socket operations shall block execution until they are finished or until a timeout occurs. If set to false, socket operations will terminated immediately.
+      * @param timeout  : a timeout value in milliseconds for use in blocking operations.
+      */
+    void set_blocking(bool blocking, unsigned int timeout = 1500);
+    
+    /** Function set_option is not working as expected, because there this functionality is not supported by the WifiPlusClick module. 
+      * @note This functionality is just kept for compatibility reasons. */
+    int set_option(int level, int optname, const void* optval, int socklen);
+    
+    /** Function close will close the socket.
+      * @param shutdown : This parameter will actually be ignored by the implementation.
+      * @returns :
+      *     -1 if not successfull
+      *     >=0 if successfull
+      */
+    int close( bool shutdown = true );
+    
+    ~Socket();
+    
+protected:
+    bool _blocking;
+    unsigned int _timeout;
+
+protected:
+    SOCKET_HANDLE_t     _socket;
+};
+
+
+#endif // __SOCKET_H__
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 Socket/TCPSocketConnection.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/TCPSocketConnection.cpp	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,117 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "TCPSocketConnection.h"
+
+TCPSocketConnection::TCPSocketConnection() 
+    : _is_connected(false)
+{
+}
+
+int TCPSocketConnection::connect(const char *host, const int port)
+{
+    _socket = Wifi::getInstance()->SocketCreate(TCP);
+    if (_socket == InvalidSocketHandle)
+        return -1;
+        
+    if (set_address(host, port) != 0) 
+        return -1;
+        
+    if (!Wifi::getInstance()->SocketConnect(_socket, reinterpret_cast<IPADDRESS_t*>(get_address()), port)) {
+        close();
+        return -1;
+    }
+    _is_connected = true;
+    
+    return 0;
+}
+
+bool TCPSocketConnection::is_connected()
+{
+    return _is_connected;
+}
+
+int TCPSocketConnection::send(char *data, int length)
+{
+    if ((_socket == InvalidSocketHandle) || !_is_connected)
+        return -1;
+        
+    int n = Wifi::getInstance()->SocketSend(_socket, data, length);
+    
+    return n;
+}
+
+int TCPSocketConnection::send_all(char *data, int length)
+{
+    if ((_socket == InvalidSocketHandle) || !_is_connected)
+        return -1;
+        
+    int n = 0;
+    
+    Timer t;
+    t.start();
+    
+    while( n < length) {
+        int r = Wifi::getInstance()->SocketSend(_socket, &data[n], length-n);
+        if (r == -1) {
+            return n;
+        }
+        n += r;
+        
+        if (_blocking && (t.read_ms() > _timeout)) {
+            break;
+        }
+    }
+    
+    return n;  
+}
+
+int TCPSocketConnection::recv(char *data, int length)
+{
+    if ((_socket == InvalidSocketHandle) || !_is_connected)
+        return -1;
+        
+    int n = Wifi::getInstance()->SocketRecv(_socket, data, length);
+    
+    return n;
+}
+
+int TCPSocketConnection::recv_all(char *data, int length)
+{
+    if ((_socket == InvalidSocketHandle) || !_is_connected)
+        return -1;
+        
+    int n = 0;
+    
+    Timer t;
+    t.start();
+    
+    while( n < length) {
+        int r = Wifi::getInstance()->SocketRecv(_socket, &data[n], length-n);
+        if (r == -1) {
+            return n;
+        }
+        n += r;
+        
+        if (_blocking && (t.read_ms() > _timeout)) {
+            break;
+        }
+    }
+    
+    return n;
+}
diff -r 000000000000 -r 2a179bd4cc02 Socket/TCPSocketConnection.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/TCPSocketConnection.h	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,80 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __TCPSOCKETCONNECTION_H__
+#define __TCPSOCKETCONNECTION_H__
+
+#include "Socket.h"
+#include "Endpoint.h"
+
+/** Class TCPSocketConnection inherits from Socket and Endpoint. Implements the client TCP socket functionality.
+  */
+class TCPSocketConnection : public Socket, public Endpoint
+{
+    friend class TCPSocketServer;
+public:
+    /** Public constructor to instantiate an object of class TCPSocketConnection */
+    TCPSocketConnection();
+    
+    /** Function connect allows to create an unused socket object to a remote host on a remote port.
+      * @param host : remote host to which to initiate a TCP connection.
+      * @param port : remote port to which to initiate a TCP connection.
+      * @returns : 0 if successfull or -1 on failure.
+      */
+    int connect(const char *host, const int port);
+    
+    /** Function to query wheather the socket is already connected with a remote instance.
+      * @returns : true if already connected or false otherwise.
+      */
+    bool is_connected(void);
+    
+    /** Function send allows to send data to an already connected TCP socket.
+      * @param data : pointer to a valid data buffer.
+      * @param length : Number of bytes from data buffer to send.
+      * @returns : number of bytes actually sent or -1 on failure.
+      */
+    int send(char *data, int length);
+    
+    /** Function send_all allows to send data to an already connected TCP socket. The function will try to send all the data specified by length.
+      * If a timeout occurs in a blocking configuration the function returns the number of bytes actually sent.
+      * @param data : pointer to a valid data buffer.
+      * @param length : Number of bytes from data buffer to send.
+      * @returns : number of bytes actually send or -1 on failure.
+      */
+    int send_all(char *data, int length);
+    
+    /** Function recv allows to receive data from an already connected TCP socket. Please note that this function will return once a first bunch
+      * of data has been received. It will not wait until all the requested data is available.
+      * @param data : pointer to a valid data buffer which will receive the received data. The buffer must be big enough to hold all the requested data.
+      * @param length : Maximum numnber of bytes to receive.
+      * @returns : number of bytes actually received and stored in data buffer or -1 on failure.
+      */
+    int recv(char *data, int length);
+    
+    /** Function recv_all allows to receive data entirely from an already connected TCP socket. Please note that this function will only return if
+      * all the requested data was received or a timeout occured.
+      * @param data : pointer to a valid data buffer which will receive the received data. The buffer must be big enough to hold all the requested data.
+      * @param length : Number of bytes to receive.
+      * @returns : number of bytes actually received and stored in data buffer or -1 on failure.
+      */
+    int recv_all(char * data, int length);
+    
+private:
+    bool _is_connected;
+};
+
+#endif // __TCPSOCKETCONNECTION_H__
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 Socket/TCPSocketServer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/TCPSocketServer.cpp	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,94 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "TCPSocketServer.h"
+
+TCPSocketServer::TCPSocketServer() 
+{
+}
+
+
+int TCPSocketServer::bind(int port)
+{
+    _socket = Wifi::getInstance()->SocketCreate(TCP);
+    
+    if (_socket == InvalidSocketHandle) {
+        return -1;
+    }
+        
+    if (!Wifi::getInstance()->SocketBind(_socket, port)) {
+        Wifi::getInstance()->SocketClose(_socket);
+        return -1;
+    }
+    
+    return 0;
+}
+
+int TCPSocketServer::listen(int backlog)
+{
+    if (_socket == InvalidSocketHandle)
+        return -1;
+        
+    if (!Wifi::getInstance()->SocketListen(_socket, backlog)) {
+        Wifi::getInstance()->SocketClose(_socket);
+        return -1;
+    }
+    
+    return backlog;
+}
+
+int TCPSocketServer::accept(TCPSocketConnection &connection)
+{
+    if (_socket == InvalidSocketHandle)
+        return -1;
+        
+    if (_blocking) {
+        Timer t;
+        
+        t.start();
+        
+        while( t.read_ms() < _timeout ) {
+            if (Wifi::getInstance()->SocketAccept(_socket, connection._socket, connection._port, connection._ipAddress)) {
+                if (connection._socket == InvalidSocketHandle) {
+                } else {
+                    connection._is_connected = true;
+                    return 0;
+                }
+            } else {
+                break;
+            }
+        }
+        
+        //  Attempt timed out
+        return -1;
+    } else {
+        //  non blocking, so we just check wheather we are connected
+        if (Wifi::getInstance()->SocketAccept(_socket, connection._socket, connection._port, connection._ipAddress)) {
+            if (connection._socket == InvalidSocketHandle) {
+                connection._is_connected = false;
+                return -1;
+            } else {
+                connection._is_connected = true;
+                return 0;
+            }
+        } else {
+            connection._is_connected = false;
+            return -1;
+        } 
+    }
+}
diff -r 000000000000 -r 2a179bd4cc02 Socket/TCPSocketServer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/TCPSocketServer.h	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,55 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __TCPSOCKETSERVER_H__
+#define __TCPSOCKETSERVER_H__
+
+#include "Socket/Socket.h"
+#include "Socket/TCPSocketConnection.h"
+
+/** Class TCPSocketServer inherits from class Socket. Implements the TCP server socket which is used to listen for a new incoming connection.
+  * This implementation can have a backlog of up to 8 sockets. Please note that the number of listening sockets depends on how the WifiPlusClick
+  * Module has been configured.
+  */
+class TCPSocketServer : public Socket
+{
+public:
+    /** Public constructor to instantiate an object of TCPSocketServer. */
+    TCPSocketServer();
+    
+    /** Bind function to bind the TCPSocketServer to a specific local port as a precondition to listen to new connection requests.
+      * @param port : local port to which the server socket shall be bound.
+      * @returns : 0 if successfull, or -1 on failure.
+      */
+    int bind(int port);
+    
+    /** Listen function allows a bound socket to listen for incoming connections. The number of connectable socket objects can be specified.
+      * @note: the number of sockets is a configurable resource on WifiPlusClick modules. Use the configuration function Wifi::SocketAllocate to
+      * specify the number of sockets to allocate.
+      * @param backlog : number of sockets which are connectable in the listen state.
+      * @returns : the new backlog number, or -1 on failure
+      */
+    int listen( int backlog = 1 );
+    
+    /** Accept function will be used on a bound and listening socket. Function will return if a socket connection has been made or a timeout occured.
+      * @param connection : A reference to a TCCPSocketConnection object which will be a valid client socket if a connection has been made.
+      * @returns : 0 if successfull, or -1 on failure.
+      */
+    int accept(TCPSocketConnection& connection);
+};
+
+#endif //   __TCPSOCKETSERVER_H__
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 Socket/UDPSocket.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/UDPSocket.cpp	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,70 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "Socket/UDPSocket.h"
+
+
+
+UDPSocket::UDPSocket()
+{
+}
+
+int UDPSocket::init()
+{
+    _socket = Wifi::getInstance()->SocketCreate(UDP);
+    
+    if (_socket == InvalidSocketHandle)
+        return -1;
+    
+    return 0;
+}
+
+int UDPSocket::bind(unsigned int port)
+{
+    _socket = Wifi::getInstance()->SocketCreate(UDP);
+    
+    if (_socket == InvalidSocketHandle)
+        return -1;
+        
+    if (!Wifi::getInstance()->SocketBind(_socket, port)) {
+        close();
+        return -1;
+    }
+    
+    return 0;
+}
+
+int UDPSocket::sendTo(Endpoint &remote, char *packet, int length)
+{
+    if (_socket == InvalidSocketHandle)
+        return -1;
+    if (packet == NULL) 
+        return -1;
+        
+    return Wifi::getInstance()->SocketSendTo(_socket, &remote._ipAddress, remote._port, packet, length);
+}
+
+int UDPSocket::receiveFrom(Endpoint &remote, char *packet, int length)
+{
+    if (_socket == InvalidSocketHandle)
+        return -1;
+    if (packet == NULL)
+        return -1;
+
+    return Wifi::getInstance()->SocketRecvFrom(_socket, &remote._ipAddress, &remote._port, packet, length);
+}
diff -r 000000000000 -r 2a179bd4cc02 Socket/UDPSocket.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Socket/UDPSocket.h	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,72 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __UDPSOCKET_H__
+#define __UDPSOCKET_H__
+
+#include "Socket/Socket.h"
+#include "Socket/Endpoint.h"
+
+/** Class UDPSocket, inherits from class Socket and implements the functionality of a UDP Socket when using a WifiPlusClick module.
+  * @note Please note that the functionality provided by a WifiPlusClick module is limited. Neither broadcasting nor multicasting functionality is possible.
+  */
+class UDPSocket : public Socket
+{
+public:
+    /** UDPSocket constructor to instantiate a UDPSocket object.  */
+    UDPSocket();
+    
+    /** Function init provides initialization of the UDPSocket object.
+      * @returns : true if successfull, or false otherwise.
+      */
+    int init(void);
+    
+    /** Function bind will bind a UDPSocket to a local port. The socket object should not already have been used for other purposes before.
+      * @note Please note that there is currently no check implemented as to wheather or not the socket has already been used before.
+      * @parameter port : The port to which to bind the UDPSocket to. If the port is specified as zero, a non-zero value beginning with 1024 will be selected.
+      * @returns : 0 if successfull, or -1 otherwise.
+      */
+    int bind(unsigned int port = 0);
+    
+    /** Function join_multicast_group.
+      * @note This function is not implemented as the WifiPlusClick module does not support this functionality.
+      */
+    int join_multicast_group(const char *address);
+    
+    /** Function set_broadcasting.
+      * @note This fnction is not implemented as the WifiPlusClick module does not support this functionality.
+      */
+    int set_broadcasting(bool broadcast=true);
+    
+    /** Function sendTo implements sending of a packet to a specific endpoint. Make sure to use it on an initialized or bound socket.
+      * @param remote : a reference to a valid endpoint specifying the remote ip-address and the remote port where to send the packet.
+      * @param packet : a pointer to a valid buffer containing the packet data to send.
+      * @param length : Specifies the number of data bytes to send.
+      * @returns : the number of databytes actually sent or -1 on failure.
+      */
+    int sendTo(Endpoint &remote, char *packet, int length);
+    
+    /** Function receiveFrom implements receiving a packet of data on a socket. The remote address will be provided on return. Make sure to use it on an initialized or bound socket.
+      * @param remote : a reference to an endpoint, which will receive the remote ip-address and the remote port from where data was returned.
+      * @param packet : a data buffer which will receive the received data. The buffer must be at least as larget as length bytes.
+      * @param length : The maximum number of bytes to receive. Please make sure that the buffer packet is large enough to hold this data completely.
+      * @returns : the number of databytes actually received or -1 on failure. @note there may be more data received than what the buffer can store. Any data that does not fit in the buffer is discarded !
+      */
+    int receiveFrom(Endpoint &remote, char *packet, int length);
+};
+
+#endif // __UDPSOCKET_H__
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 Wifi.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wifi.cpp	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,1113 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "Wifi.h"
+#include "DnsQuery.h"
+
+#define DEBUG
+#include "debug.h"
+
+#define LOBYTE(x)       ((x)&0xFF)
+#define HIBYTE(x)       (((x)>>8)&0xFF)
+
+static Wifi::RX_STATE_t   state = Wifi::Idle;
+static int ResponseType = 0;
+static int DataLen = 0;
+static int DataPtr = 0;
+
+Wifi* Wifi::_Wifi = NULL;
+  
+
+Wifi::Wifi(PinName tx, PinName rx, PinName rst)
+    : m_wifi(tx, rx), m_reset(rst), m_msgReceived(false), m_ackReceived(false), m_bWifiConnected(false), m_WifiConnectionError(NoFailure), m_lastError(NoError)
+    , m_bScanResultsReady(false), m_NumLastScanResults(0)
+{
+    _Wifi = this;
+    m_reset = 1;
+    m_wifi.baud(115200);
+    m_wifi.format(8, Serial::None, 2);
+
+    m_buffer = new char [1024];
+
+    if (m_buffer == NULL) {
+        ERR("Failed to allocate buffer !");
+        error("WIFI");
+    }
+    
+    m_wifi.attach(this, &Wifi::rx_int);
+}
+
+void Wifi::Reset()
+{
+    m_reset = 0;
+    wait(0.2);
+    m_msgReceived = 0;
+    m_ackReceived = false;
+    m_bWifiConnected = false;
+    m_WifiConnectionError = NoFailure;
+    state = Idle;
+    m_reset = 1;
+    wait(0.2);
+}
+
+void Wifi::SendCommand(CMD_MSG_t cmd, int msgDataLen1, char* pData1, int msgDataLen2, char* pData2)
+{
+    //  Wifi Plus Click has little endian format (means LSB comes first)
+    //  btw. MBED is also little endian format
+    //  Send Header
+    m_wifi.putc(0x55);
+    m_wifi.putc(0xAA);
+    //  Send Message Command
+    m_wifi.putc( LOBYTE((short)cmd) );
+    m_wifi.putc( HIBYTE((short)cmd) );
+    //  Send Message Data1 Length
+    m_wifi.putc( LOBYTE((short)msgDataLen1+msgDataLen2) );
+    m_wifi.putc( HIBYTE((short)msgDataLen1+msgDataLen2) );
+    
+    //  Send Data1
+    if ((msgDataLen1 > 0) && (pData1 != NULL)) {
+        for (int i = 0 ; i < msgDataLen1 ; i++) {
+            m_wifi.putc(pData1[i]);
+        }
+    }
+    //  Send Data2
+    if ((msgDataLen2 > 0) && (pData2 != NULL)) {
+        for (int i = 0 ; i < msgDataLen2 ; i++) {
+            m_wifi.putc(pData2[i]);
+        }
+    }
+    
+    //  Reset Acknowledge Recevied flag
+    m_ackReceived = false;
+    m_lastError = NoError;
+    //  Send Trailer
+    m_wifi.putc(0x45);
+}
+    
+void Wifi::rx_int()
+{
+    char c = m_wifi.getc();
+
+    switch (state) {
+        case    Idle:
+            if (c == 0x55) {
+                state = Header1_received;
+            } else {
+                if (c == 0x00) {
+                    m_ackReceived = true;
+                    INFO("ACK");
+                } else {
+                    INFO("c = 0x%02x", c);
+                }
+            }
+            break;
+        case    Header1_received:
+            if (c == 0xAA) {
+                state = Header2_received;
+                ResponseType = 0;
+                DataLen = 0;
+            } else {
+                if (c == 0x55) {
+                    state = Header1_received;
+                } else {
+                    state = Idle;
+                }
+            }
+            break;
+        case    Header2_received:
+            ResponseType = c;
+            state = MessageType_low_received;
+            break;
+        case    MessageType_low_received:
+            ResponseType |= (((short)c)<<8);
+            state = MessageType_high_received;
+            break;
+        case    MessageType_high_received:
+            DataLen = c;
+            state = DataLen_low_received;
+            break;
+        case    DataLen_low_received:
+            DataLen |= (((short)c)<<8);
+            if (DataLen == 0) {
+                state = Awaiting_trailer;
+            } else {
+                DataPtr = 0;
+                state = Data_receiving;
+            }
+            break;
+        case    Data_receiving:
+            m_buffer[DataPtr++] = c;
+            if (DataPtr == DataLen) {
+                state = Awaiting_trailer;
+            }
+            break;
+        case Awaiting_trailer:
+            if (c != 0x45) {
+                ERR("Trailer information received is incorrect !");
+                ERR("Full Message : ");
+                ERR("Response Type : 0x%02x", ResponseType);
+                for ( int i = 0; i < DataPtr++ ; i++) {
+                    ERR ("0x%02x", m_buffer[i]);
+                }
+                ERR("Trailer : 0x%02x", c);
+            } else {
+                //  Complete Message received, so submit it for processing
+                SubmitResponse((RSP_MSG_t)ResponseType, DataLen);
+            }
+            state = Idle;
+            break;
+        default:
+            state = Idle;
+    }
+}
+
+void Wifi::SubmitResponse(RSP_MSG_t rsp, int msgLen)
+{
+    //  Check if Event was received
+    if (rsp == EVENT_MSG) {
+        INFO("EVENT !!!!");
+        switch( m_buffer[0] ) {
+            case Event_IP_Address_Assigned :
+                //  IP Address assigned, set the IP Address
+                m_ipAddress.sin_addr.o1 = m_buffer[2];
+                m_ipAddress.sin_addr.o2 = m_buffer[3];
+                m_ipAddress.sin_addr.o3 = m_buffer[4];
+                m_ipAddress.sin_addr.o4 = m_buffer[5];
+                INFO("NEW IPADDRESS SET !");
+                return;
+            case Event_WiFi_Connection_Status_Changed :
+                if ((m_buffer[1] == 1) || (m_buffer[1] == 4)) {
+                    m_bWifiConnected = true;
+                    m_WifiConnectionError = NoFailure;
+                    INFO("EVENT      WIFI CONNECTED !");
+                    DigitalOut led2(LED2);
+                    led2 = 1;
+                } else {
+                    DigitalOut led2(LED2);
+                    led2 = 0;
+                    m_bWifiConnected = false;
+                    m_WifiConnectionError = (CONN_ERROR_t)m_buffer[2];
+                    if (m_buffer[1] != 2) {
+                        m_WifiConnectionError = (CONN_ERROR_t)((char)m_WifiConnectionError+20);
+                        DigitalOut led3(LED3);
+                        led3 = 1;
+                        
+                    }
+                    INFO("EVENT     WIFI DISCONNECTED !");
+                }
+                return;
+            case Event_Error_Event :
+                INFO("ERROR EVENT %d (%d, %d, %d, %d) !", *((short*)&m_buffer[2]), m_buffer[4], m_buffer[5], m_buffer[6], m_buffer[7]);
+                m_lastError = (ERR_t)*((short*)&m_buffer[2]);
+                return ;
+            case Event_WiFi_Scan_Results_Ready :
+                m_NumLastScanResults = m_buffer[1];
+                INFO("SCAN RESULTS (#%d) READY !", m_NumLastScanResults);
+                m_bScanResultsReady = true;
+                return ;
+            default:
+                INFO("EVT %d", m_buffer[0])
+                break;
+        }
+    } 
+
+    if (m_msgReceived) {
+        ERR("BUFFER FULL !");
+    }
+    m_msgResponse = rsp;
+    m_msgDataLen = msgLen;
+    m_msgReceived = true;
+    INFO("Message received (%d)", rsp);
+}
+
+
+bool Wifi::WaitMessage(RSP_MSG_t msg, int timeout)
+{
+    Timer t;
+    
+    t.start();
+    
+    while(t.read_ms() < timeout) {
+        if (m_msgReceived) {
+            //  Successfully received a message
+            if (m_msgResponse == msg) {
+                //  Successfull received correct message
+                m_msgReceived = false;
+                return true;
+            } else {
+                //  Not the message we wanted to hear, so wait for next one
+                m_msgReceived = false;
+            }
+        }
+    }
+    
+    //  Timeout
+    return false;
+}
+
+bool Wifi::WaitEvent(EVT_MSG_t evt, int timeout)
+{
+    Timer t;
+    
+    t.start();
+    
+    while(t.read_ms() < timeout) {
+        if (m_msgReceived) {
+            //  Successfully received a message
+            if ((m_msgResponse == EVENT_MSG) && (m_buffer[0] == evt)) {
+                //  Successfull received correct message
+                m_msgReceived = false;
+                return true;
+            } else {
+                //  Not the message or eventwe wanted to hear, so wait for next one
+                m_msgReceived = false;
+            }
+        }
+    }
+    
+    //  Timeout
+    return false;
+}
+
+bool Wifi::WaitAck(int timeout)
+{
+    Timer t;
+    
+    t.start();
+    
+    while(t.read_ms() < timeout) {
+        if (m_ackReceived) {
+            INFO("ACK after %d ms", t.read_ms());
+            m_ackReceived = false;
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+
+
+
+bool Wifi::ResetMsg()
+{
+    bool bRetVal = false;
+    
+    INFO("SENDING RESET_MSG");
+    SendCommand(RESET_MSG, 0, NULL);
+
+    if (WaitMessage (ACK_MSG, 1000)) {
+        //  Now wait for the Startup Event
+        
+        if (WaitEvent (Event_Startup_Event, 10000)) {
+            //  Startup Event received
+            bRetVal = true;
+            INFO("Successfully Reset the device !");
+            INFO("Startup condition : 0x%02d", m_buffer[1]);
+        } else {
+            ERR("Did not receive a startup event from device after reset !");
+        }
+    } else {
+        ERR("Did not get acknowledge from WifiPlusClick Board !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::GetVersionMsg(char &sw_ver_lo, char &sw_ver_hi, char &rad_ver_lo, char &rad_ver_hi)
+{
+    bool bRetVal = false;
+    
+    INFO("SENDING GET_VERSION_MSG");
+    SendCommand(GET_VERSION_MSG, 0, NULL);
+    
+    if (WaitAck (1000)) {
+        //  Now wait for the asynchroneous Startup Event
+        
+        if (WaitEvent (Event_Startup_Event, 2000)) {
+            //  Startup Event received
+            bRetVal = true;
+            sw_ver_hi = m_buffer[3];
+            sw_ver_lo = m_buffer[2];
+            rad_ver_hi = m_buffer[5];
+            rad_ver_lo = m_buffer[4];
+        } else {
+            ERR("Did not receive an answer event from device after GET_VERSION_MSG !");
+        }
+    } else {
+        ERR("Did not get acknowledge from WifiPlusClick Board !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::GpioMsg(GPIO_IDX_t pin, GPIO_OP_t operation, GPIO_RES_t &result)
+{
+    char buf[2] = { (char)pin, (char)operation };
+    bool bRetVal = false;
+    
+    INFO("SENDING GPIO_MSG");
+    SendCommand(GPIO_MSG, 2, buf);
+    
+    if (WaitMessage (GPIO_RESPONSE_MSG, 1000)) {
+        bRetVal = true;
+        result = (GPIO_RES_t)m_buffer[1];
+    } else {
+        ERR("Did not get answer from device after GPIO_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetIpAddress(bool bUseDHCP, IPADDRESS_t *ipAddress)
+{
+    bool bRetVal = false;
+    char buf[18] = {255, (bUseDHCP ? 0 : 1), 0};
+            
+    if (!bUseDHCP) {
+        if ( ipAddress == NULL) {
+            ERR("Invalid argument, ipAdress is NULL !");
+            return false;
+        }
+        memcpy( &buf[2], (void*)ipAddress, 16 );
+    } else {
+        memset( &buf[2], 0, 16);
+    }
+    
+    INFO("SENDING SET_IP_ADDRESS_MSG");
+    SendCommand(SET_IP_ADDRESS_MSG, 18, buf);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_IP_ADDRESS_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetSubnetMask(IPADDRESS_t *NetworkMask)
+{
+    bool bRetVal = false;
+    
+    if (NetworkMask == NULL)
+        return false;
+        
+    INFO("SENDING SET_NETWORK_MASK_MSG");
+    SendCommand(SET_NETWORK_MASK_MSG, 16, NetworkMask->sin_addr.o);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_NETWORK_MASK_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetGatewayIpAddress(IPADDRESS_t *IPAddress)
+{
+    bool bRetVal = false;
+    
+    if (IPAddress == NULL)
+        return false;
+        
+    INFO("SENDING SET_GATEWAY_IP_ADDRESS");
+    SendCommand(SET_GATEWAY_IP_ADDRESS_MSG, 16, IPAddress->sin_addr.o);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_GATEWAY_IP_ADDRESS_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::GetNetworkStatus(char *MacAddress, IPADDRESS_t *IPAddress, IPADDRESS_t *NetworkMask, IPADDRESS_t *GatewayAddress, NET_STAT_t &stat)
+{
+    bool bRetVal = false;
+    
+    INFO("SENDING GET_NETWORK_STATUS_MSG");
+    SendCommand(GET_NETWORK_STATUS_MSG, 0, NULL);
+    
+    if (WaitMessage (NETWORK_STATUS_RESPONSE_MSG, 1000)) {
+        if (MacAddress != NULL) {
+            memcpy (MacAddress, &m_buffer[1], 6);
+        }
+        if (IPAddress != NULL) {
+            memcpy( IPAddress, &m_buffer[7], 4);
+        }
+        if (NetworkMask != NULL) {
+            memcpy( NetworkMask, &m_buffer[23], 4);
+        }
+        if (GatewayAddress != NULL) {
+            memcpy( GatewayAddress, &m_buffer[39], 4);
+        }
+        stat = (NET_STAT_t)m_buffer[55];
+        bRetVal = true;
+    } else {
+        ERR("Did not get Response after GET_NETWORK_STATUS_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetMACAddress( char MACAddress[6])
+{
+    bool bRetVal = false;
+    
+    INFO("SENDING SET_MACADDRESS_MSG");
+    SendCommand(SET_MACADDRESS_MSG, 6, MACAddress);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_MACADDRESS_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetARPTime(unsigned short ARPTime)
+{
+    char buf[2] = { ARPTime&0xFF, (ARPTime>>8)&0xFF };
+    
+    bool bRetVal = false;
+    
+    INFO("SENDING SET_ARP_TIME_MSG");
+    SendCommand(SET_ARP_TIME_MSG, 2, buf);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_ARP_TIME_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetNetworkMode(char ProfileNum, NETW_MODE_t NetMode)
+{
+    char buf[2] = { ProfileNum, (char)NetMode };
+    bool bRetVal = false;
+    
+    INFO("SENDING SET_CP_NETWORK_MODE_MSG");
+    SendCommand(SET_CP_NETWORK_MODE_MSG, 2, buf);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_CP_NETWORK_MODE_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetPowerSaveMode(POWERSAVE_MODE_t pwrsave, short DTIM_Listen)
+{
+    bool bRetVal = false;
+    char buf[4] = { (char)pwrsave, 0, LOBYTE(DTIM_Listen), HIBYTE(DTIM_Listen) };
+    
+    INFO("SENDING SET_POWER_SAVE_MODE_MSG");
+    SendCommand(SET_POWER_SAVE_MODE_MSG, 4, buf);
+    
+    if (WaitMessage(ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_POWER_SAVE_MODE_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+
+bool Wifi::SetSSID(char Profile, const char* ssid)
+{
+    bool bRetVal = false;
+    char len = strlen(ssid);
+    char buf[2] = { Profile, len };
+    
+    if (len <= 32 ) {        
+        INFO("SENDING SET_CP_SSID_MSG");
+        SendCommand(SET_CP_SSID_MSG, 2, buf, len, (char*)ssid);
+        
+        if (WaitMessage (ACK_MSG, 10000)) {
+            if (m_lastError != NoError) {
+                ERR("Failed to set SSID with error code %d", m_lastError);
+                m_lastError = NoError;
+            } else {
+                bRetVal = true;
+            }
+        } else {
+            ERR("Did not get acknowledge after SET_CP_SSID_MSG !");
+        }
+    } else {
+        ERR("SSID is too long !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetRegionalDomain(DOMAIN_COUNTRY_CODE_t dcode)
+{
+    bool bRetVal = false;
+    char buf[2] = { (char)dcode, 0 };
+    
+    INFO("SENDING SET_REGIONAL_DOMAIN_MSG");
+    SendCommand(SET_REGIONAL_DOMAIN_MSG, 2, buf);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_REGIONAL_DOMAIN_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetChannelList(char numListItems, char *ListItems)
+{
+    bool bRetVal = false;
+    char buf[2] = { numListItems, 0 };
+        
+    INFO("SENDING SET_CHANNEL_LIST_MSG");
+    SendCommand(SET_CHANNEL_LIST_MSG, 2, buf, numListItems, ListItems);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_CHANNEL_LIST_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetRetryCount(char infrastructureRetryCount, char adhocRetryCount)
+{
+    bool bRetVal = false;
+    char buf[2] = { infrastructureRetryCount, adhocRetryCount };
+    
+    INFO("SENDING SET_LIST_RETRY_COUNT_MSG");
+    SendCommand(SET_LIST_RETRY_COUNT_MSG, 2, buf);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_LIST_RETRY_COUNT_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetSecurityOpen(char Profile)
+{
+    bool bRetVal = false;
+    char buf[2] = { Profile, 0 };
+    
+    INFO("SENDING SET_CP_SECURITY_OPEN_MSG");
+    SendCommand(SET_CP_SECURITY_OPEN_MSG, 2, buf);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_CP_SECURITY_OPEN_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetSecurityWEP40(char Profile, bool bSharedKey, char DefaultWEPKeyIdx, char SecurityKeys[20])
+{
+    bool bRetVal = false;
+    char buf[4];
+    
+    buf[0] = Profile;
+    buf[1] = bSharedKey ? 1 : 0;
+    buf[2] = DefaultWEPKeyIdx;
+    
+    INFO("SENDING SET_CP_SECURITY_WEP40_MSG");
+    SendCommand(SET_CP_SECURITY_WEP40_MSG, 4, buf, 20, SecurityKeys);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_CP_SECURITY_WEP40_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetSecurityWEP104(char Profile, bool bSharedKey, char DefaultWEPKeyIdx, char SecurityKeys[52])
+{
+    bool bRetVal = false;
+    char buf[4];
+    
+    buf[0] = Profile;
+    buf[1] = bSharedKey ? 1 : 0;
+    buf[2] = DefaultWEPKeyIdx;
+    
+    INFO("SENDING SET_CP_SECURITY_WEP104_MSG");
+    SendCommand(SET_CP_SECURITY_WEP104_MSG, 4, buf, 52, SecurityKeys);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        bRetVal = true;
+    } else {
+        ERR("Did not get acknowledge after SET_CP_SECURITY_WEP104_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SetSecurityWPA(char Profile, WPA_SECURITY_t sec, int len, const char* secKeyOrPSK)
+{
+    bool bRetVal = false;
+    char buf[4];
+    if ((secKeyOrPSK == NULL) || (*secKeyOrPSK == 0))
+        return false;
+            
+    if (buf != NULL) {
+        buf[0] = Profile;
+        buf[1] = sec;
+        buf[2] = 0;
+        buf[3] = len;
+        
+        INFO("SENDING SET_CP_SECURITY_WPA_MSG");
+        SendCommand(SET_CP_SECURITY_WPA_MSG, 4, buf, len, (char*)secKeyOrPSK);
+        
+        if (WaitMessage (ACK_MSG, 1000)) {
+            bRetVal = true;
+        } else {
+            ERR("Did not get acknowledge after SET_CP_SECURITY_WPA_MSG !");
+        }
+    } else {
+        ERR("Out of memory error in SetCPSecurityWPA !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::GetWPAKey(char Profile, char Key[32])
+{
+    bool bRetVal = false;
+    char buf[2] = { Profile, 0 };
+    
+    INFO("SENDING GET_CP_WPAKEY_MSG");
+    SendCommand(GET_CP_WPAKEY_MSG, 2, buf);
+    
+    if (WaitMessage (WPAKEY_RESPONSE_MSG, 1000)) {
+        bRetVal = true;
+        memcpy(Key, m_buffer, 32);
+    } else {
+        ERR("Did not get answer from device !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::ScanStartMsg(char Profile)
+{
+    bool bRetVal = false;
+    
+    if (m_bWifiConnected) {
+        ERR("Can not start scan while Wifi is connected !");
+    } else {
+        char buf[2] = { Profile, 0 };
+        
+        INFO("SENDING SCAN_START_MSG");
+        m_bScanResultsReady = false;
+        m_NumLastScanResults = 0;
+        SendCommand(SCAN_START_MSG, 2, buf);
+        
+        if (WaitMessage (ACK_MSG, 1000)) {
+            bRetVal = true;
+        } else {
+            ERR("Did not get acknowledge after SCAN_START_MSG !");
+        }
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::ScanGetResults(char index, char ssid[32], AP_CONFIG_t &apCfg, short &beaconInterval, short &ATIMWindow, char &RSSI, NETW_MODE_t &bssType, char &channelNo)
+{
+    bool bRetVal = false;
+    
+    if (!m_bScanResultsReady) {
+        ERR("No scan results !");
+    } else {
+        if (index >= m_NumLastScanResults) {
+            ERR ("No more scan results !");
+        } else {
+            char buf[2] = { index, 0 };
+            
+            INFO("SENDING SCAN_GET_RESULTS_MSG");
+            SendCommand(SCAN_GET_RESULTS_MSG, 2, buf);
+            
+            if (WaitMessage (SCAN_RESULT_MSG, 1000)) {
+                bRetVal = true;
+                memcpy(ssid, &m_buffer[7], m_buffer[6]);
+                memcpy(&apCfg, &m_buffer[39], 1);
+                beaconInterval = *(short*)&m_buffer[40];
+                ATIMWindow = *(short*)&m_buffer[42];
+                RSSI = m_buffer[52];
+                bssType = (NETW_MODE_t)m_buffer[55];
+                channelNo = m_buffer[56];
+            } else {
+                ERR("Did not receive message after SCAN_GET_RESULTS_MSG !");
+            }
+        }
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::Connect(char Profile)
+{
+    bool bRetVal = false;
+    
+    if (m_bWifiConnected) {
+        ERR("WIFI is already connected !");
+    } else {
+        char buf[2] = { Profile, 0 };
+        
+        INFO("SENDING WIFI_CONNECT_MSG");
+        SendCommand(WIFI_CONNECT_MSG, 2, buf);
+        
+        if (WaitMessage (ACK_MSG, 1000)) {
+            bRetVal = true;
+        } else {
+            ERR("Did not get any acknowledge after WIFI_CONNECT_MSG !");
+        }
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::Disconnect()
+{
+    bool bRetVal = false;
+    
+    if (!m_bWifiConnected) {
+        ERR("WIFI is not yet connected !");
+    } else {        
+        INFO("SENDING WIFI_DISCONNECT_MSG");
+        SendCommand(WIFI_DISCONNECT_MSG, 0, NULL);
+        
+        if (WaitMessage (ACK_MSG, 1000)) {
+            bRetVal = true;
+        } else {
+            ERR("Did not get any acknowledge after WIFI_DISCONNECT_MSG !");
+        }
+        
+   }
+    
+    return bRetVal;
+}
+
+
+bool Wifi::SocketAllocate(char nTCPSvr, char nTCPClnt, unsigned short TCPSvrRxBuf, unsigned short TCPSvrTxBuf, unsigned short TCPClntRxBuf, unsigned short TCPClntTxBuf)
+{
+    bool bRetVal = false;
+    __packed struct _sendBuf {
+        char _nTcpSvr;
+        char _nTcpClnt;
+        unsigned short _TcpSvrRxBuf, _TcpSvrTxBuf, _TcpClntRxBuf, _TcpClntTxBuf;
+    } buf = { nTCPSvr, nTCPClnt, TCPSvrRxBuf, TCPSvrTxBuf, TCPClntRxBuf, TCPClntTxBuf };
+    
+    INFO("SENDING SOCKET_ALLOCATE_MSG");
+    SendCommand(SOCKET_ALLOCATE_MSG, sizeof(buf), (char*)&buf);
+    
+    if (WaitMessage (SOCKET_ALLOCATE_RESPONSE_MSG, 2000)) {
+        if (m_buffer[0] == 0) {
+            bRetVal = true;
+        } else if (m_buffer[0] == 0xFF) {
+            ERR("Too many sockets requested in SOCKET_ALLOCATE_MSG !");
+        } else  if (m_buffer[0] == 0xFE) {
+            ERR("Too much buffer requested in SOCKET_ALLOCATE_MSG !");
+        } else {
+            ERR("Unknown error in SOCKET_ALLOCATE_MSG !");
+        }
+    } else {
+        ERR("Did not get expected message SOCKET_ALLOCATE_RESPONSE_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+
+
+SOCKET_HANDLE_t Wifi::SocketCreate( SOCKET_TYPE_t sockType )
+{
+    char sockHandle = InvalidSocketHandle;
+    char buf[2] = { sockType, 0 };
+    
+    INFO("SENDING SOCKET_CREATE_MSG");
+    SendCommand(SOCKET_CREATE_MSG, 2, buf);
+    
+    if (WaitMessage (SOCKET_CREATE_RESPONSE_MSG, 1000)) {
+        sockHandle = (SOCKET_HANDLE_t)m_buffer[0];
+        if (m_buffer[0] == 254) {
+            ERR("Invalid socket handle received after SOCKET_CREATE_MSG !");
+        } else if (m_buffer[0] == 255) {
+            ERR("Unknown socket type specified in call to SOCKET_CREATE_MSG !");
+        } else {
+            INFO("Valid socket handle received !");
+        }
+    } else {
+        ERR("Did not get expected response after SOCKET_CREATE_MSG !");
+    }
+    
+    return (SOCKET_HANDLE_t)sockHandle;
+}
+
+bool Wifi::SocketClose(SOCKET_HANDLE_t hSock)
+{
+    bool bRetVal = false;
+    char buf[2] = { hSock, 0 };
+
+    INFO("SENDING SOCKET_CLOSE_MSG");
+    m_lastError = NoError;
+    SendCommand(SOCKET_CLOSE_MSG, 2, buf);
+    
+    if (WaitMessage (ACK_MSG, 1000)) {
+        wait(0.1);
+        if (m_lastError != NoError) {
+            bRetVal = false;
+        } else {
+            bRetVal = true;
+        }                
+    } else {
+        ERR("Did not get expected acknowledge message after SOCKET_CLOSE_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SocketBind(SOCKET_HANDLE_t hSock, int Port)
+{
+    bool bRetVal = false;
+    char buf[4] = { LOBYTE(Port), HIBYTE(Port), hSock, 0 };
+
+    INFO("SENDING SOCKET_BIND_MSG");
+    SendCommand(SOCKET_BIND_MSG, 4, buf);
+    
+    if (WaitMessage (SOCKET_BIND_RESPONSE_MSG, 1000)) {
+        if (m_buffer[2] == 0) {
+            bRetVal = true;
+        } else {
+            ERR("Bind operation return non-zero result !");
+        }
+    } else {
+        ERR("Did not get expected acknowledge message after SOCKET_CLOSE_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+bool Wifi::SocketListen(SOCKET_HANDLE_t hSock, int& Backlog)
+{
+    bool bRetVal = false;
+    char buf[2] = { hSock, Backlog };
+    
+    INFO("SENDING SOCKET_LISTEN_MSG");
+    SendCommand(SOCKET_LISTEN_MSG, 2, buf);
+    
+    if (WaitMessage (SOCKET_LISTEN_RESPONSE_MSG, 1000)) {
+        Backlog = m_buffer[1];
+        if (m_buffer[0] != 255) {
+            if (m_buffer[0] != 254) {
+                bRetVal = true;
+            } else {
+                ERR("SOCKET Listen failed because a socket connection is currently in progress !");
+            }
+        } else {
+            ERR("Socket Listen failed because the socket is already connected !");
+        }
+    } else {
+        ERR("Did not get expected acknowledge message after SOCKET_LISTEN_RESPONSE !");
+    }
+
+    return bRetVal;
+}
+
+bool Wifi::SocketAccept(SOCKET_HANDLE_t hSock, SOCKET_HANDLE_t &client, int &remotePort, IPADDRESS_t &remoteAddress)
+{
+    bool bRetVal = false;
+    char buf[2] = { hSock, 0 };
+    
+    INFO("SENDING SOCKET_ACCEPT_MSG");
+    SendCommand(SOCKET_ACCEPT_MSG, 2, buf);
+    
+    if (WaitMessage (SOCKET_ACCEPT_RESPONSE_MSG, 1000)) {
+        client = (SOCKET_HANDLE_t)m_buffer[0];
+        remotePort = m_buffer[1] + ((int)m_buffer[2])<<8;
+        memcpy(&remoteAddress, (const void*)&m_buffer[3], 4);
+        bRetVal = true;
+    } else {
+        ERR("Did not get expected response after SOCKET_ACCEPT_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+SOCKET_HANDLE_t Wifi::SocketConnect(SOCKET_HANDLE_t hSock, IPADDRESS_t *IpAddress, int Port)
+{
+    SOCKET_HANDLE_t bRetVal = InvalidSocketHandle;
+    char buf[4] = { hSock, 0, LOBYTE(Port), HIBYTE(Port) };
+    
+    INFO("SENDING SOCKET_CONNECT_MSG");
+    SendCommand(SOCKET_CONNECT_MSG, 4, buf, 16, (char*)IpAddress);
+    
+    if (WaitMessage (SOCKET_CONNECT_RESPONSE_MSG, 1000)) {
+        bRetVal = (SOCKET_HANDLE_t)m_buffer[0];
+    } else {
+        ERR("Did not get expected response after SOCKET_CONNECT_MSG !");
+    }
+    
+    return bRetVal;
+}
+
+int Wifi::SocketSend(SOCKET_HANDLE_t hSock, char* data, int length)
+{
+    int nRetVal = -1;
+    char buf[4] = { hSock, 0, LOBYTE(length), HIBYTE(length) };
+    
+    INFO("SENDING SOCKET_SEND_MSG");
+    SendCommand(SOCKET_SEND_MSG, 4, buf, length, data);
+    
+    if (WaitMessage (SOCKET_SEND_RESPONSE_MSG, 1000)) {
+        nRetVal = m_buffer[0] + ((int)m_buffer[1])<<8;
+    } else {
+        ERR("Did not get expected response after SOCKET_SEND_MSG !");
+    }
+    
+    return nRetVal;
+}
+
+int Wifi::SocketRecv(SOCKET_HANDLE_t hSock, char* data, int length)
+{
+    int nRetVal = -1;
+    char buf[4] = { hSock, 0, LOBYTE(length), HIBYTE(length) };
+    
+    INFO("SENDING SOCKET_RECV_MSG");
+    SendCommand(SOCKET_RECV_MSG, 4, buf);
+    
+    if (WaitMessage (SOCKET_RECV_RESPONSE_MSG, 1000)) {
+        nRetVal = m_buffer[2] + ((int)m_buffer[3])<<8;
+        memcpy(data, &m_buffer[4], nRetVal);
+    } else {
+        ERR("Did not get expected response after SOCKET_RECV_MSG !");
+    }
+    
+    return nRetVal;
+}
+
+int Wifi::SocketSendTo(SOCKET_HANDLE_t hSock, IPADDRESS_t* remoteAddress, int remotePort, char *data, int length)
+{
+    int nRetVal = -1;
+    char buf[22] = { hSock, 0, LOBYTE(remotePort), HIBYTE(remotePort) };
+    
+    memcpy(&buf[4], remoteAddress, 16);
+    buf[20] = LOBYTE(length);
+    buf[21] = HIBYTE(length);
+    INFO("SENDING SOCKET_SEND_TO_MSG");
+    SendCommand(SOCKET_SEND_TO_MSG, 22, buf, length, data);
+    
+    if (WaitMessage (SOCKET_SEND_TO_RESPONSE_MSG, 1000)) {
+        nRetVal = m_buffer[0] + (((int)m_buffer[1])<<8);
+    } else {
+        ERR("Did not get expected response after SOCKET_SEND_TO_MSG !");
+    }
+    
+    return nRetVal;
+}
+
+int Wifi::SocketRecvFrom(SOCKET_HANDLE_t hSock, IPADDRESS_t *remoteAddress, int *port, char *data, int length)
+{
+    int nRetVal = -1;
+    char buf[4] = { hSock, 0, LOBYTE(length), HIBYTE(length) };
+    
+    INFO("SENDING SOCKET_RECV_FROM_MSG");
+    SendCommand(SOCKET_RECV_FROM_MSG, 4, buf);
+
+    if (WaitMessage (SOCKET_RECV_FROM_RESPONSE_MSG, 1000)) {
+        if (port != NULL)
+            *port = m_buffer[2] + (((int)m_buffer[3])<<8);
+        if (remoteAddress != NULL)
+            memcpy(remoteAddress, &m_buffer[4], 4);
+        nRetVal = m_buffer[20] + (((int)m_buffer[21])<<8);
+        
+        memcpy(data, &m_buffer[22], nRetVal > length ? length : nRetVal);
+        if (nRetVal > length) {
+            INFO("Socket received %d bytes on port %d which is more than the %d provided by buffer !", nRetVal, *port, length);
+        }
+    } else {
+        ERR("Did not get expected response after SOCKET_RECV_FROM_MSG !");
+    }
+    
+    return nRetVal;
+}
+
+
+int Wifi::gethostbyname(const char* host, IPADDRESS_t *IpAddress)
+{
+    //  First issue a get network status message to retrieve the gateway address. The gateway will be used as the DNS.
+    IPADDRESS_t GatewayIP;
+    NET_STAT_t     netStat;
+    
+    if (IpAddress == NULL)
+        return -1;
+    
+    //  Get the gateway ip address for use as DNS server
+    if (!GetNetworkStatus(NULL, NULL, NULL, &GatewayIP, netStat)) {
+        return -1;
+    }
+    INFO("Using gateway on %d.%d.%d.%d as DNS !", GatewayIP.sin_addr.o1, GatewayIP.sin_addr.o2, GatewayIP.sin_addr.o3, GatewayIP.sin_addr.o4);        
+    //  Now create the DNS query
+    DnsQuery    dns(this, &GatewayIP);
+    
+    if( !dns.gethostbyname(host, *IpAddress) ) {
+        ERR("Failed to get host by name !");
+        return -1;
+    }
+    
+    return 0;
+}
+
+int Wifi::convert(const char* hostip, IPADDRESS_t *ipAddress)
+{
+    if ((hostip == NULL) || (ipAddress == NULL))
+        return -1;
+        
+    int nCnt = 0;
+    int val = 0;
+    while(*hostip != 0) {
+        if (*hostip != '.') {
+            val = val*10 + (*hostip)-'0';
+        } else {
+            if (nCnt > 3)
+                return -1;
+            ipAddress->sin_addr.o[nCnt++] = val;
+            val = 0;
+        }
+    }
+    ipAddress->sin_addr.o[nCnt++] = val;
+
+    return 0;
+}
diff -r 000000000000 -r 2a179bd4cc02 Wifi.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wifi.h	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,601 @@
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __WIFI_H__
+#define __WIFI_H__
+
+#include "mbed.h"
+
+typedef enum {
+    //  Control Messages
+    RESET_MSG   = 170,  /*!< RESET_MSG */
+    GET_VERSION_MSG = 23, /*!< GET_VERSION_MSG */
+    GPIO_MSG = 172,
+    //  Network Configuration Messages
+    SET_IP_ADDRESS_MSG = 41,
+    SET_NETWORK_MASK_MSG = 42,
+    SET_GATEWAY_IP_ADDRESS_MSG = 44,
+    GET_NETWORK_STATUS_MSG = 48,
+    SET_MACADDRESS_MSG = 49,
+    SET_ARP_TIME_MSG = 173,
+    //  Wi-Fi General Configuration Messages
+    SET_CP_NETWORK_MODE_MSG = 55,
+    SET_CP_SSID_MSG = 57,
+    SET_REGIONAL_DOMAIN_MSG = 56,
+    SET_CHANNEL_LIST_MSG = 58,
+    SET_LIST_RETRY_COUNT_MSG = 59,
+    //  Wi-Fi Power Management Messages
+    SET_POWER_SAVE_MODE_MSG = 102,
+    //  Wi-Fi Security Configuration Messages
+    SET_CP_SECURITY_OPEN_MSG = 65,
+    SET_CP_SECURITY_WEP40_MSG = 66,
+    SET_CP_SECURITY_WEP104_MSG = 67,
+    SET_CP_SECURITY_WPA_MSG = 68,
+    GET_CP_WPAKEY_MSG = 71,
+    //  Wi-Fi Scanning Messages
+    SCAN_START_MSG = 80,
+    SCAN_GET_RESULTS_MSG = 81,
+    //  Wi-Fi Connection Messages
+    WIFI_CONNECT_MSG = 90,
+    WIFI_DISCONNECT_MSG = 91,
+    //  ICMP (Ping) Messages
+    PING_SEND_MSG = 121,
+    //  Socket Messages
+    SOCKET_CREATE_MSG = 110,
+    SOCKET_CLOSE_MSG = 111,
+    SOCKET_BIND_MSG = 112,
+    SOCKET_CONNECT_MSG = 113,
+    SOCKET_LISTEN_MSG = 114,
+    SOCKET_ACCEPT_MSG = 115,
+    SOCKET_SEND_MSG = 116,
+    SOCKET_RECV_MSG = 117,
+    SOCKET_SEND_TO_MSG = 118,
+    SOCKET_RECV_FROM_MSG = 119,
+    SOCKET_ALLOCATE_MSG = 122,
+
+} CMD_MSG_t;
+
+
+typedef enum {
+    ACK_MSG = 0,
+    EVENT_MSG = 1,
+    
+    //  Control Message Responses
+    GPIO_RESPONSE_MSG = 50,
+    //  Network Configuration Message Responses
+    NETWORK_STATUS_RESPONSE_MSG = 48,
+    //  Wi-Fi Security Configuration Message Responses
+    WPAKEY_RESPONSE_MSG = 0x31,
+    //  Wi-Fi Scanning Message Responses
+    SCAN_RESULT_MSG = 22,
+    //  Socket Message Responses
+    SOCKET_CREATE_RESPONSE_MSG = 23,
+    SOCKET_BIND_RESPONSE_MSG = 24,
+    SOCKET_CONNECT_RESPONSE_MSG = 25,
+    SOCKET_LISTEN_RESPONSE_MSG = 26,
+    SOCKET_ACCEPT_RESPONSE_MSG = 27,
+    SOCKET_SEND_RESPONSE_MSG = 28,
+    SOCKET_RECV_RESPONSE_MSG = 29,
+    SOCKET_SEND_TO_RESPONSE_MSG = 30,
+    SOCKET_RECV_FROM_RESPONSE_MSG = 31,
+    SOCKET_ALLOCATE_RESPONSE_MSG = 32,
+        
+} RSP_MSG_t;
+
+typedef enum {
+    Event_IP_Address_Assigned = 16,
+    Event_WiFi_Connection_Status_Changed = 8,
+    Event_WiFi_Scan_Results_Ready = 9,
+    Event_Ping_Response = 26,
+    Event_Error_Event = 255,
+    Event_Startup_Event = 27,
+    
+} EVT_MSG_t;
+
+
+typedef enum {
+    GPIO0 = 0,
+    GPIO1,
+    GPIO2,
+    GPIO3,
+    GPIO4,
+    GPIO5,
+    GPIO6,
+    GPIO7
+} GPIO_IDX_t;
+
+typedef enum {
+    GPIO_OP_OUTPUT_LOW = 0,
+    GPIO_OP_OUTPUT_HIGH = 1,
+    GPIO_OP_READ_INPUT=2
+} GPIO_OP_t;
+
+typedef enum {
+    GPIO_RES_OUTPUT_LOW = 0,
+    GPIO_RES_OUTPUT_HIGH= 1,
+    GPIO_RES_INPUT_LOW  = 2,
+    GPIO_RES_INPUT_HIGH = 3,
+    GPIO_RES_INVALID_INDEX= 255
+} GPIO_RES_t;
+
+typedef struct {
+    union {
+        struct {
+            char o1, o2, o3, o4;
+        };
+        char o[4];
+    } sin_addr;
+    operator char* () { return (char*)this; }
+} IPADDRESS_t;
+
+typedef enum {
+    NoFailure=0,
+    
+    JoinFailure=2,
+    AuthenticationFailure,
+    AssociationFailure,
+    WEPHandshakeFailure,
+    PSKCalculationFailure,
+    PSKHandshakeFailure,
+    AdHocJoinFailure,
+    SecurityMismatchFailure,
+    NoSuitableAPFoundFailure,
+    RetryForeverNotSupportedFailure,
+    
+    BeaconTimeOut=21,
+    DeauthReceivedDE,
+    DisassociateReceived
+} CONN_ERROR_t;
+
+typedef enum {
+    NotConnected_StaticIP = 0,
+    Connected_StaticIP = 1,
+    NotConnected_DHCP = 2,
+    Connected_DHCP = 3
+} NET_STAT_t;
+
+typedef enum {
+    INFRASTRUCTURE = 1,
+    ADHOC = 2
+} NETW_MODE_t;
+
+typedef enum {
+    NoError = 0,
+    BaudRateGeneratorError = 60,
+    InvalidConnectionProfileError = 61,
+    WiFiAlreadyConnectedError = 62,
+    WiFiAlreadyDisconnectedError = 63,
+    CloseSocketFailedError = 64,
+    SocketSendToTimeOutError = 65,
+    ScanIndexOutOfRangeError = 66,
+    ICMPPingFloodError = 67,
+    ICMPPingInUseError = 68,
+    SocketRecvFromError = 69,
+    SerialTransmitBufferAllocationError = 71,
+    GeneralAssertError = 72,
+    InvalidPowersaveModeError = 73,
+    BusyInHibernateModeError = 74,
+    BusyInScanModeError = 75,
+    Unknown = 0xFFFF
+}  ERR_t;
+
+typedef enum {
+    WPA_PSK = 3,
+    WPA_PASSPHRASE = 4,
+    WPA2_PSK = 5,
+    WPA2_PASSPHRASE = 6,
+    WPA_OR_WPA2_PSK = 7,
+    WPA_OR_WPA2_PASSPHRASE = 8
+} WPA_SECURITY_t;
+
+typedef __packed struct {
+    char IE:1;
+    char res:3;
+    char Privacy:1;
+    char Preamble:1;
+    char WPA:1;
+    char WPA2:1;
+} AP_CONFIG_t;
+
+typedef enum {
+    FCC = 0,
+    IC,
+    ETSI,
+    SPAIN,
+    FRANCE,
+    JAPANA,
+    JAPANB
+} DOMAIN_COUNTRY_CODE_t;
+
+typedef enum {
+    HIBERNATE = 1,          // Radio off
+    PSPOLL_AP_SUGGESTED_DTIM = 2,  
+    PSPOLL_SELF_SET_DTIM = 3,
+    FULLY_POWERED = 4
+} POWERSAVE_MODE_t;
+
+typedef enum {
+    InvalidSocketHandle=254,
+    UnknownSocketType=255
+} SOCKET_HANDLE_t;
+
+typedef enum {
+    UDP=0,
+    TCP=1
+} SOCKET_TYPE_t;
+
+
+
+/** Class Wifi encapsulates communication and access to Wifi Plus Click module. */
+/*!\copyright { Henry Leinen } */
+class Wifi
+{
+public:
+    typedef enum {
+        Idle,                  
+        Header1_received,           
+        Header2_received,           
+        MessageType_low_received,
+        MessageType_high_received,
+        DataLen_low_received,
+        Data_receiving,
+        Awaiting_trailer
+    } RX_STATE_t;
+
+protected:
+    Serial          m_wifi;
+    DigitalOut      m_reset;
+    char*           m_buffer;
+    
+    bool            m_msgReceived;
+    RSP_MSG_t       m_msgResponse;
+    short           m_msgDataLen;
+    bool            m_ackReceived;
+
+//  Event data
+    IPADDRESS_t     m_ipAddress;
+    bool            m_bWifiConnected;
+    CONN_ERROR_t    m_WifiConnectionError;
+    
+    ERR_t           m_lastError;
+
+    bool            m_bScanResultsReady;
+    char            m_NumLastScanResults;
+    
+public:
+    static Wifi*     _Wifi;
+    static Wifi*    getInstance()
+    {
+        if (_Wifi==NULL) {
+            error("NOWIFI");
+        }
+        return _Wifi;
+    }
+                
+public:
+    Wifi(PinName tx, PinName rx, PinName rst);
+
+    bool AwaitScanResults(int timeout) {
+        Timer t;
+        t.start();
+        while(t.read() < timeout) {
+            if (m_bScanResultsReady) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    bool AwaitConnected(int timeout, ERR_t *err = NULL) {
+        Timer t;
+        t.start();
+        while(t.read() < timeout) {
+            if (m_bWifiConnected) {
+                return true;
+            }
+            wait(0.1);
+        }
+        if (err)
+            *err = m_lastError;
+        return false;
+    }        
+    
+    bool AwaitDisconnected(int timeout, ERR_t *err = NULL) {
+        Timer t;
+        t.start();
+        while(t.read() < timeout) {
+            if (!m_bWifiConnected) {
+                return true;
+            }
+            wait(0.1);
+        }
+        if (err)
+            *err = m_lastError;
+        return false;
+    }
+    
+    void Reset();
+
+    /** Function to reset the Wifi Plus Click Device. PLEASE NOTE, it will loose all its current settings
+      * @returns true if successful or false otherwise 
+      */
+    bool ResetMsg();
+    /** Function retrieves the software and radio version of the Wifi Plus Click Board.
+      * @param sw_ver_lo : receives the low WiComm Socket Version number
+      * @param sw_ver_hi : recevies the high WiComm Socket Version number
+      * @param rad_ver_lo: receives the low Radio version number
+      * @param rad_ver_hi: receives the high Radio version number
+      * @returns true if successful or false otherwise
+      */
+    bool GetVersionMsg(char &sw_ver_lo, char &sw_ver_hi, char &rad_ver_lo, char &rad_ver_hi);
+    /** Function will set a GPIO pin to a specific output level or will set it to input.
+      * The function will return the result of the operation.
+      * @param pin : Reference to the GPIO pin of interest
+      * @param operation: the operation to perform on the GPIO pin. Set to specific output level or read as input
+      * @param result : a reference to a variable which receives the actual status of the GPIO pin
+      */
+    bool GpioMsg(GPIO_IDX_t pin, GPIO_OP_t operation, GPIO_RES_t &result);
+    
+    /** Function to set the IP address of the Wifi Plus Click device.
+      * @param bUseDHCP : set to true if DHCP shall be used, or set to false if you want to specify a static IP address
+      * @param IPAddress: pointer to an IP address.
+      *                   Please note that the IP adress will only be used if bUseDHCP is set to false
+      * @returns : true if successfull, or false otherwise. The function will not check for any asynchroneous result.
+      */
+    bool SetIpAddress(bool bUseDHCP, IPADDRESS_t *IPAddress);
+    /** Function to set the network mask of the Wifi Plus Click device.
+      * @param NetworkMask : the Network mask to use.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetSubnetMask(IPADDRESS_t *NetworkMask);
+    /** Function to set the gateway ip address to use. If the gateway ip address is set to 0.0.0.0 the Wifi Plus Click will not use
+      * a gateway.
+      * @param IPAddress : Pointer to an IPADDRESS specifying the IP Address of the gateway to use. 
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetGatewayIpAddress(IPADDRESS_t *IPAddress);
+    /** Function to retrieve the current network status of the Wifi Plus Click device.
+      * @param MacAddress : pointer to an array of 6 Bytes to retrieve the MAC Address. Set to NULL if not required.
+      * @param IPAddress  : pointer to an IPADDRESS_t structure which receives the IP address. Set to NULL if not required.
+      * @oaram NetworkMask : pointer to an IPADDRESS_t structure which receives the network mask. Set to NULL if not requried.
+      * @param GatewayAddress : pointer to an IPADDRESS_t structure which receives the gateway address. Set to NULL if no required.
+      * @param stat : will receive the actual status.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool GetNetworkStatus(char *MacAddress, IPADDRESS_t *IPAddress, IPADDRESS_t *NetworkMask, IPADDRESS_t *GatewayAddress, NET_STAT_t &stat);
+    /** Function to set the MAC Address of the device. This command should only be used during initialization
+      * @param MacAddress : the MAC address to use.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetMACAddress(char MacAddress[6]);
+    /** Function to set the address resolution time from 1 to 65535 seconds.
+      * @param ARPTime : either 0 to disable ARP or time in seconds.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetARPTime(unsigned short ARPTime);
+    /** Function to set the network mode for one of two available profiles.
+      * @param Profile : can be profile number one or 2
+      * @param NetMode : can be either INFRASTRUCTURE or ADHOC
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetNetworkMode(char Profile, NETW_MODE_t NetMode);
+    /** Function to set the SSID for one of two profiles.
+      * @param Profile : can be profile number one or two.
+      * @param ssid : a string descibing the ssid.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetSSID(char Profile, const char* ssid);
+    /** Function switches device into one of 3 power saving modes, or sets it into awake mode.
+      * @param pwrsave : specifies which powersaving mode to set.
+      * @param DTIM_Listen : if pwrsave is in mode PSPOLL_SELF_DTIM uses this value as the DTIM listen interval. Value is given in units of 100ms.
+      * @returns : true if successfull, or false otherwise
+      */
+    bool SetPowerSaveMode(POWERSAVE_MODE_t pwrsave, short DTIM_Listen);
+    /** Function to set the regional domain for all CPs.
+      * @param dcode : domain country code valid for all CPs.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetRegionalDomain(DOMAIN_COUNTRY_CODE_t dcode);
+    /** Function to set the channels on which to scan.
+      * @param numListItems : the number of channels given in the list.
+      * @param ListItems : array consisting of numListItems channel numbers.
+      * @returns : true if successfull, or false otherwise
+      */
+    bool SetChannelList(char numListItems, char ListItems[]);
+    /** Function to specify the connection managaer retry count. There are separate values for infrastructure and ad hoc mode.
+      * Please note that a number of 0 means no retries and 255 means retry forever.
+      * @param infrastructureRetryCount : number of retries in infrastructure mode
+      * @param adhocRetryCount : number of retries in ad-hoc mode.
+      * @returns : true if successfull, or false otherwise
+      */
+    bool SetRetryCount(char infrastructureRetryCount=255, char adhocRetryCount=5);
+    /** Function to set the Security mode to OPN 
+      * @param Profile : can be profile number one or two.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetSecurityOpen(char Profile);
+    /** Function to set the WEP40 security mode.
+      * @param Profile : can be profile number one or two.
+      * @param bShareKey : set to true for shared key, or false for open key
+      * @param DefaultWEPKeyIdx : the index (0-3) into the key array
+      * @param SecurityKeys : array or 4 security keys with 5 bytes each
+      * @returns : true if successfull, or false otherwise
+      */
+    bool SetSecurityWEP40(char Profile, bool bSharedKey, char DefaultWEPKeyIdx, char SecurityKeys[20]);
+    /** Function to set the WEP104 security mode.
+      * @param Profile : can be profile number one or two.
+      * @param bShareKey : set to true for shared key, or false for open key
+      * @param DefaultWEPKeyIdx : the index (0-3) into the key array
+      * @param SecurityKeys : array or 4 security keys with 13 bytes each
+      * @returns : true if successfull, or false otherwise
+      */
+    bool SetSecurityWEP104(char Profile, bool bSharedKey, char DefaultWEPKeyIdx, char SecurityKeys[52]);
+    /** Function to set the WPA security mode.
+      * @param Profile : can be profile number one or two.
+      * @param sec : can be one of the define security types.
+      * @param len : length of the security key or passphrase.
+      * @param secKeyOrPSK : security key or passphrase.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SetSecurityWPA(char Profile, WPA_SECURITY_t sec, int len, const char* secKeyOrPSK);
+    /** Function to retrieve the WPA Key from the Wifi Plus Click device for a selected profile.
+      * @param Profile : can be profile number one or two.
+      * @param Key : will receive the key.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool GetWPAKey(char Profile, char Key[32]);
+    /** Function to initiate the scan on one or both Profiles using the settings downloaded to the Wifi Plus Click.
+      * Please NOTE that the device will only accept the REBOOT message while a scan is active. A scan can only be
+      * started if the device is not connected.
+      * @param Profile : can be profile number one or two.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool ScanStartMsg(char Profile);
+    /** Function to retrieve a specific scan result. Will only work after scan has been started and finished.
+      * @param index : specify the result item to return. When this index is too high the function returns with a false return value.
+      * @param ssid : will receive the SSID of the item.
+      * @param apCfg : will receive the access points configuration.
+      * @param beaconInterval : will receive the beacon interval time.
+      * @param ATIMWindow : will receive the ATIM Window.
+      * @param RSSI : will receive the RSSI level.
+      * @param bssType : will receive information about the BSS type (INFRASTRUCTURE oR ADHOC).
+      * @param channelNo : will receive on which channel the AP transmits.
+      * @returns : true if successfull, false otherwise.
+      */
+    bool ScanGetResults(char index, char ssid[32], AP_CONFIG_t &apCfg, short &beaconInterval, short &ATIMWindow, char &RSSI, NETW_MODE_t &bssType, char &channelNo);
+    
+    /** Function to connect using the specified profile and the settings previously downloaded to the device. Please Note that the connection
+      * state will be transmitted asynchroneously be the device. You need to monitor the connected state.
+      * @param Profile : can be profile number one or two.
+      * @returns : true if successfully submitted, or false otherwise.
+      */
+    bool Connect(char Profile);
+    /** Function to disconnect from any connected AP.
+      * @returns : true if successful, or false otherwise.
+      */
+    bool Disconnect();
+    
+    
+    /** @name Socket Functions
+        In the following section, all socket relevant functions are contained.
+       */
+    ///@{
+    
+    /** Function to allocate the internal memory of the device and the number of sockets (which in total is limited to 8).
+      * @param nTCPSvr : Number of server sockets to allocate.
+      * @param nTCPClnt: Number of client sockets to allocate.
+      * @param TCPSvrRxBuf : Size (in bytes) to allocate for the receive buffer for each server socket.
+      * @param TCPSvrTxBuf : Size (in bytes) to allocate for the transmit buffer for each server socket.
+      * @param TCPClntRxBuf: Size (in bytes) to allocate for the receive buffer for each client socket.
+      * @param TCPClntTxBuf: Size (in bytes) to allocate for the transmit buffer for each client socket.
+      * @returns : true if successful, or false otherwise. Can return false if the requestet internal memory exceededs the total of 8192 internal byte orif the maximum number of
+      * 8 sockets is exceeded.
+      */
+    bool SocketAllocate(char nTCPSvr, char nTCPClnt, unsigned short TCPSvrRxBuf, unsigned short TCPSvrTxBuf, unsigned short TCPClntRxBuf, unsigned short TCPClntTxBuf);
+    
+    /** Function to create a new socket object of the given type.
+      * @param sockType : Specifies the type of socket to create (UDP or TCP).
+      * @returns : Either a valid socket handle or InvalidSocketHandle or UnknownSocketType.
+      */
+    SOCKET_HANDLE_t SocketCreate( SOCKET_TYPE_t sockType );
+    /** Function to close a previously created socket.
+      * @param hSock: Valid socket handle, which has been created by a previous call to SocketCreate.
+      * @returns : true if successful, or false if an error occured
+      */
+    bool SocketClose(SOCKET_HANDLE_t hSock);
+    /** Function to bind to a specific port using the given socket.
+      * @param hSock : Valid socket handle.
+      * @param Port  : local port to bind to.
+      * @returns : true if successfull, or false otherwise.
+      */
+    bool SocketBind(SOCKET_HANDLE_t hSock, int Port);
+    /** Function to prepare the a number of sockets for accepting remote connections 
+      * @param hSock : Valid socket handle.
+      * @param Backlog : Number of sockets to set in listening mode, will receive the number of new unassigned backlog count
+      * @return : true if successfull, or false otherwise.
+      */
+    bool SocketListen(SOCKET_HANDLE_t hSock, int &Backlog);
+    /** Function to accept a new remote connection. Will work asynchroneously, means if no new connection was accepted, will return immediately.
+      * @param hSock : Valid socket handle.
+      * @param client : reference to a variable which receives the new socket handle of the connection socket or InvalidSocketHandle if no connection could be made at this time.
+      * @param remotePort : receives the remote port of the remote connection.
+      * @param remoteAddress : receives the remote address of the remote connection.
+      * @returns : true if successfull, or false otherwise. PLEASE NOTE that even if no connection was made, the return result may be true.
+      */
+    bool SocketAccept(SOCKET_HANDLE_t hSock, SOCKET_HANDLE_t &client, int &remotePort, IPADDRESS_t &remoteAddress);
+    /** Function to connect the socket to a remote socket specified by IpAddress and Port.
+      * @param hSock : Valid socket handle.
+      * @param IpAddress : valid IP Address of the remote host to connect with.
+      * @param Port : Port of the remote host to connect with.
+      * @returns : true if a connection has been made successfully or false otherwise. 
+      */
+    SOCKET_HANDLE_t SocketConnect(SOCKET_HANDLE_t hSock, IPADDRESS_t *IpAddress, int Port);    
+    /** Function to send data on the connected socket
+      * @param hSock : Valid socket handle.
+      * @param data : Pointer to a buffer containing the data to send.
+      * @param length : Number of bytes in the buffer to send.
+      * @returns : Number of bytes actually sent over the connection.
+      */
+    int SocketSend(SOCKET_HANDLE_t hSock, char* data, int length);
+    /** Function to receive data from the connected socket.
+      * @param hSock : Valid socket handle of a socket which is already connected.
+      * @param data : Pointer to a valid buffer which shall receive the data.
+      * @param length : Maximum number of bytes which can be received and stored in the provided buffer.
+      * @returns : Number of bytes actually received over the connection or -1 if a fault occured.
+      */
+    int SocketRecv(SOCKET_HANDLE_t hSock, char* data, int length);
+    /** Function to send data over a connectionless socket.
+      * @param hSock : Valid socket handle.
+      * @param remoteAddress : The ip address of the remote destination to send the data to.
+      * @param remotePort : The port of the remote destination to send the data to.
+      * @param data : Pointer to a buffer which contains the data to send.
+      * @param length : The number of bytes to sent to the specified address.
+      * @returns : Number of bytes actually sent or -1 if a fault occured.
+      */
+    int SocketSendTo(SOCKET_HANDLE_t hSock, IPADDRESS_t* remoteAddress, int remotePort, char *data, int length);
+    /** Function to receive data over a connectionless socket.
+      * @param hSock : Valid socket handle.
+      * @param remoteAddress : The ip address of the remote origin from where to receive the data.
+      * @param remotePort : Point to receive the port of the remote origin from where to receive the data or NULL if not needed.
+      * @param data : Pointer to a buffer which will receive the data.
+      * @param length : Number of bytes to receive and which fit into the provided buffer.
+      * @returns : Number of bytes actually received or -1 if a fault occured.
+      */
+    int SocketRecvFrom(SOCKET_HANDLE_t hSock, IPADDRESS_t *remoteAddress, int *remotePort, char *data, int length);
+    
+    ///@}
+    
+    
+    /** This is the main cyclic function, which needs to be called as often as possible.
+     * The function will check if a new message has been received and will decode and dispatch it.
+     */        
+    void Poll();
+    
+    
+    int gethostbyname(const char* host, IPADDRESS_t *IpAddress);
+    int convert(const char *hostip, IPADDRESS_t *IpAddress);
+protected:    
+    void SendCommand(CMD_MSG_t cmd, int msgLen1, char *pData1, int msgLen2 = 0, char* pData2 = NULL);
+    void rx_int();
+    
+    void SubmitResponse(RSP_MSG_t rsp, int msgLen);
+    bool WaitMessage(RSP_MSG_t msg, int timeout);
+    bool WaitEvent(EVT_MSG_t evt, int timeout);
+    bool WaitAck(int timeout);
+};
+
+#endif //__WIFI_H__
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 WifiPlusClick.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WifiPlusClick.cpp	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,53 @@
+#include "mbed.h"
+#include "WifiPlusClick.h"
+
+
+
+WifiPlusClick::WifiPlusClick(PinName tx, PinName rx, PinName rst, bool dhcp, const char * ssid, WPA_SECURITY_t sec, const char* passphrase, int plen)
+    : Wifi(tx, rx, rst)
+{
+    char ChannelList[11] = {1,2,5,6,7,8,9,10,11, 12, 13};
+    Reset();
+    wait(.8);
+
+    //   Set to european domain  
+    SetRegionalDomain(ETSI);
+    SetChannelList(5, ChannelList);
+    SetARPTime(1);
+    SetRetryCount(20,20);
+    
+    SetSSID(1, ssid);
+    SetSecurityWPA(1, sec, plen, passphrase);
+}
+
+bool WifiPlusClick::connect()
+{
+    SetNetworkMode(1, INFRASTRUCTURE);
+    SetIpAddress(true, NULL);
+    
+    Connect(1);
+    
+    return AwaitConnected(60);
+}
+
+bool WifiPlusClick::connect(IPADDRESS_t *ipAddress, IPADDRESS_t *subnetMask, IPADDRESS_t *ipGateway)
+{
+    if ((ipAddress == NULL) || (subnetMask == NULL) || (ipGateway == NULL))
+        return false;
+        
+    SetNetworkMode(1, ADHOC);
+    SetIpAddress(false, ipAddress);
+    SetSubnetMask(subnetMask);
+    SetGatewayIpAddress(ipGateway);
+    
+    Connect(1);
+    
+    return AwaitConnected(60); 
+}
+
+bool WifiPlusClick::disconnect()
+{
+    Disconnect();
+    
+    return AwaitDisconnected(60);
+}
\ No newline at end of file
diff -r 000000000000 -r 2a179bd4cc02 WifiPlusClick.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WifiPlusClick.h	Mon Jul 29 15:15:21 2013 +0000
@@ -0,0 +1,18 @@
+#ifndef __WIFIPLUSCLICK_H__
+#define __WIFIPLUSCLICK_H__
+
+#include "Wifi.h"
+
+class WifiPlusClick : public Wifi
+{
+public:
+    WifiPlusClick(PinName tx, PinName rx, PinName rst, bool dhcp, const char * ssid, WPA_SECURITY_t sec, const char* passphrase, int plen);
+    
+    bool connect();
+    
+    bool connect(IPADDRESS_t *ipAddress, IPADDRESS_t* subnetMask, IPADDRESS_t* ipGateway);
+ 
+    bool disconnect();   
+};
+
+#endif // __WIFIPLUSCLICK_H__