W5200(WIZ820io) network interface

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Sat Apr 14 17:21:11 2012 +0000
Child:
1:803123933c5a
Commit message:

Changed in this revision

DHCPClient.cpp Show annotated file Show diff for this revision Revisions of this file
DHCPClient.h Show annotated file Show diff for this revision Revisions of this file
EthernetNetIf.lib Show annotated file Show diff for this revision Revisions of this file
MyNetDnsRequest.cpp Show annotated file Show diff for this revision Revisions of this file
MyNetDnsRequest.h Show annotated file Show diff for this revision Revisions of this file
MyNetIf.cpp Show annotated file Show diff for this revision Revisions of this file
MyNetIf.h Show annotated file Show diff for this revision Revisions of this file
MyNetTcpSocket.cpp Show annotated file Show diff for this revision Revisions of this file
MyNetTcpSocket.h Show annotated file Show diff for this revision Revisions of this file
MyNetUdpSocket.cpp Show annotated file Show diff for this revision Revisions of this file
MyNetUdpSocket.h Show annotated file Show diff for this revision Revisions of this file
TinyHTTP.cpp Show annotated file Show diff for this revision Revisions of this file
TinyHTTP.h Show annotated file Show diff for this revision Revisions of this file
Utils.cpp Show annotated file Show diff for this revision Revisions of this file
Utils.h Show annotated file Show diff for this revision Revisions of this file
WIZ820ioNetIf.cpp Show annotated file Show diff for this revision Revisions of this file
WIZ820ioNetIf.h Show annotated file Show diff for this revision Revisions of this file
dnsname.h Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mymain.cpp Show annotated file Show diff for this revision Revisions of this file
w5100.cpp Show annotated file Show diff for this revision Revisions of this file
w5100.h Show annotated file Show diff for this revision Revisions of this file
w5200NetIf.cpp Show annotated file Show diff for this revision Revisions of this file
w5200NetIf.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DHCPClient.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,151 @@
+// DHCPClient.cpp 2012/4/14
+// DHCP Client for WIZ820io(W5200)
+#include "mbed.h"
+#include "w5100.h"
+#include "UDPSocket.h"
+#include "DHCPClient.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#include "Utils.h"
+#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__)
+#else //DEBUG
+#define PRINT_FUNC()
+#endif //DEBUG
+
+int DHCPClient::discover(uint8_t buf[], int size) {
+    memset(buf, 0x00, size);
+    const uint8_t headers[] = {0x01,0x01,0x06,0x00,
+                               0x12,0x34,0x56,0x78}; // xid
+    memcpy(buf, headers, sizeof(headers));
+    int t = clock();
+    xid[0] = t<<24;
+    xid[1] = t<<16;
+    xid[2] = t<<8;
+    xid[3] = t;
+    memcpy(buf+DHCP_OFFSET_XID, xid, 4);
+    W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR);
+    const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
+                               0x35,0x01,0x01, // DHCP DISCOVER
+                               0xff};
+    memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options));
+    uint8_t ip[4] = {0,0,0,0};
+    W5100.setIPAddress(ip);
+    return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options);
+}
+
+int DHCPClient::request(uint8_t buf[], int size) {
+    memset(buf, 0x00, size);
+    const uint8_t headers[] = {0x01,0x01,0x06,0x00,
+                               0x12,0x34,0x56,0x78}; // xid
+    memcpy(buf, headers, sizeof(headers));
+    memcpy(buf+DHCP_OFFSET_XID, xid, 4);
+    memcpy(buf+DHCP_OFFSET_YIADDR, yiaddr, 4);
+    W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR);
+    const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
+                               0x35,0x01,0x03, // DHCP REQUEST
+                               0x32,0x04,0x00,0x00,0x00,0x00, // request IP
+                               0xff};
+    memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options));
+    memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE+9, yiaddr, 4);
+    return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options);
+}
+
+int DHCPClient::offer_ack(uint8_t buf[], int size) {
+    memcpy(yiaddr, &buf[DHCP_OFFSET_YIADDR], 4);   
+    uint8_t *p;
+    int msg_type = -1;
+    p = buf + DHCP_OFFSET_OPTIONS;
+    while(*p != 0xff && p < (uint8_t*)&buf[DHCP_MAX_PACKET_SIZE]) {
+        int code = *p++;
+        if (code == 0x00) {
+            continue;
+        }
+        int len = *p++;
+#ifdef DEBUG           
+        char codeStr[24];
+        snprintf(codeStr, sizeof(codeStr), "DHCP option: %d", code);
+        printfBytes(codeStr, p, len);
+#endif //DEBUG
+        if (code == 53) {
+           msg_type = *p;
+        } else if (code == 1) {
+            memcpy(netmask, p, 4); // Subnet mask address
+        } else if (code == 3) {
+            memcpy(gateway, p, 4); // Gateway IP address 
+        } else if (code == 6) {// DNS
+            memcpy(dnsaddr, p, 4);
+        }
+        p += len;
+    }
+    return msg_type;
+}
+
+bool DHCPClient::verify(uint8_t buf[], int len) {
+    if (len < DHCP_OFFSET_OPTIONS) {
+        return false;
+    }
+    if (buf[DHCP_OFFSET_OP] != 0x02) {
+        return false;
+    }
+    if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) {
+        return false;
+    }
+    return true;
+}
+
+void DHCPClient::callback(UDPSocketEvent e)
+{
+    PRINT_FUNC();
+    uint8_t buf[DHCP_MAX_PACKET_SIZE];
+    Host host;
+    int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host);
+    if (!verify(buf, len)) {
+        return;
+    }
+    int r = offer_ack(buf, len);
+    if (r == 2) { // OFFER
+        request(buf, 300);
+        Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast
+        m_udp->sendto((char*)buf, 300, &server);
+    } else if (r == 5) { // ACK
+        exit_flag = true;
+    }
+}
+
+int DHCPClient::setup(int timeout_ms)
+{
+    PRINT_FUNC();   
+    Timer t;
+    t.start();
+    m_udp = new UDPSocket;
+    m_udp->setOnEvent(this, &DHCPClient::callback);
+    Host local(IpAddr(0,0,0,0), 68);
+    Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast
+    m_udp->bind(local);
+    uint8_t buf[300];
+    discover(buf, sizeof(buf));
+    m_udp->sendto((char*)buf, sizeof(buf), &server);
+    exit_flag = false;
+    int err = 0;
+    while(1) {
+        Net::poll();
+        if (exit_flag) {
+            break;
+        }
+        if (t.read_ms() > timeout_ms) {
+            err = -1;
+            break;
+        }
+#ifdef DEBUG            
+        wait_ms(500);
+#endif //DEBUG
+    }
+    delete m_udp;
+    return err;
+}
+
+DHCPClient::DHCPClient() {
+    m_udp = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DHCPClient.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,34 @@
+// DHCPClient.h 2012/4/13
+#ifndef DHCPCLIENT_H
+#define DHCPCLIENT_H
+#include "UDPSocket.h"
+
+
+#define DHCP_OFFSET_OP 0
+#define DHCP_OFFSET_XID 4
+#define DHCP_OFFSET_YIADDR 16
+#define DHCP_OFFSET_CHADDR 28
+#define DHCP_OFFSET_MAGIC_COOKIE 236
+#define DHCP_OFFSET_OPTIONS 240
+#define DHCP_MAX_PACKET_SIZE 600
+
+class DHCPClient {
+    int discover(uint8_t buf[], int size);
+    int request(uint8_t buf[], int size);
+    int offer_ack(uint8_t buf[], int size);
+    bool verify(uint8_t buf[], int len);
+public:
+    void callback(UDPSocketEvent e);
+    int setup(int timeout_ms = 15000);
+    DHCPClient();
+    uint8_t chaddr[6]; // MAC
+    uint8_t yiaddr[4]; // IP
+    uint8_t dnsaddr[4]; // DNS
+    uint8_t gateway[4];
+    uint8_t netmask[4];
+private:
+    UDPSocket* m_udp;
+    uint8_t xid[4];
+    bool exit_flag;
+};
+#endif //DHCPCLIENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetNetIf.lib	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/sherckuith/code/EthernetNetIf/#479ce5546098
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyNetDnsRequest.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,176 @@
+// MyNetDnsRequest.cpp 2012/4/13
+#include "mbed.h"
+#include "MyNetDnsRequest.h"
+#include "UDPSocket.h"
+#include <string>
+#include "dnsname.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#include "Utils.h"
+#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__)
+#else //DEBUG
+#define PRINT_FUNC()
+#endif //DEBUG
+
+
+MyNetDnsRequest::MyNetDnsRequest(const char* hostname) : NetDnsRequest(hostname), 
+    m_state(MYNETDNS_START), m_cbFired(false), m_closing(false), m_udp(NULL) {
+    PRINT_FUNC();
+}
+
+MyNetDnsRequest::MyNetDnsRequest(Host* pHost) : NetDnsRequest(pHost), 
+    m_state(MYNETDNS_START), m_cbFired(false), m_closing(false), m_udp(NULL) {
+    PRINT_FUNC();
+}
+
+MyNetDnsRequest::~MyNetDnsRequest() {
+    PRINT_FUNC();
+    if (m_udp) {
+        delete m_udp;
+    }
+}
+
+void MyNetDnsRequest::callback(UDPSocketEvent e)
+{
+    PRINT_FUNC();
+    uint8_t buf[512];
+    Host host;
+    int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host);
+    if (memcmp(buf, m_id, 2) != 0) { //verify
+        return;
+    }
+    int rcode = response(buf, len);
+    if (rcode == 0) {
+        m_state = MYNETDNS_OK;
+    } else {
+        m_state = MYNETDNS_NOTFOUND;
+    }
+}
+
+int MyNetDnsRequest::response(uint8_t buf[], int size) {
+    PRINT_FUNC();
+#ifdef DEBUG
+    printHex(buf, size);
+#endif //DEBUG
+    int rcode = buf[3] & 0x0f;
+    if (rcode != 0) {
+        return rcode;
+    }
+    int qdcount = buf[4]<<8|buf[5];
+    int ancount = buf[6]<<8|buf[7];
+    int pos = 12;
+    while(qdcount-- > 0) {
+        dnsname qname(buf);
+        pos = qname.decode(pos); // qname
+        pos += 4; // qtype qclass
+    }
+    while(ancount-- > 0) {
+        dnsname name(buf);
+        pos = name.decode(pos); // name
+        int type = buf[pos]<<8|buf[pos+1];
+        pos += 8; // type class TTL  
+        int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2;
+        int rdata_pos = pos;
+        pos += rdlength;
+        if (type == 1) { // A record
+            m_ip = IpAddr(buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
+        }
+#ifdef DEBUG
+        printf("%s", name.str.c_str());
+        if (type == 1) {
+            printf(" A %d.%d.%d.%d\n", 
+                buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
+        } else if (type == 5) {
+            dnsname rdname(buf);
+            rdname.decode(rdata_pos);
+            printf(" CNAME %s\n", rdname.str.c_str());
+        } else {
+            printf(" TYPE:%d", type);
+            printfBytes(" RDATA:", &buf[rdata_pos], rdlength);
+        }
+#endif //DEBUG
+    }
+    return rcode;
+}
+
+int MyNetDnsRequest::query(uint8_t buf[], int size, const char* hostname) {
+    PRINT_FUNC();
+    const uint8_t header[] = {
+        0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0
+        0x00,0x01,0x00,0x00, // qdcount=1 ancount=0
+        0x00,0x00,0x00,0x00};// nscount=0 arcount=0 
+    const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN
+    memcpy(buf, header, sizeof(header));
+    int t = clock();
+    m_id[0] = t>>8;
+    m_id[1] = t;
+    memcpy(buf, m_id, 2); 
+    dnsname qname(buf);
+    int pos = qname.encode(sizeof(header), (char*)hostname);
+    memcpy(buf+pos, tail, sizeof(tail));
+    pos += sizeof(tail);
+    return pos;
+}
+
+void MyNetDnsRequest::resolve(const char* hostname) {
+    PRINT_FUNC();
+    if (m_udp == NULL) {
+        m_udp = new UDPSocket;
+    }
+    m_udp->setOnEvent(this, &MyNetDnsRequest::callback);
+    Host local(IpAddr(0,0,0,0), 1243);
+    Host server(IpAddr(8,8,8,8), 53); // DNS
+    m_udp->bind(local);
+    uint8_t buf[256];                
+    int size = query(buf, sizeof(buf), hostname);
+#ifdef DEBUG
+    printf("hostname:[%s]\n", hostname);
+    printHex(buf, size);
+#endif
+    m_udp->sendto((char*)buf, size, &server);
+    m_timer.reset();
+    m_timer.start();
+}
+
+void MyNetDnsRequest::poll() {
+    PRINT_FUNC();
+#ifdef DEBUG
+    printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp);
+    wait_ms(400);
+#endif //DEBUG
+    switch(m_state) {
+        case MYNETDNS_START:
+            resolve(m_hostname);
+            m_state = MYNETDNS_PROCESSING;
+            break;
+        case MYNETDNS_PROCESSING: 
+            break;
+        case MYNETDNS_NOTFOUND: 
+            onReply(NETDNS_FOUND); 
+            break;
+        case MYNETDNS_ERROR: 
+            onReply(NETDNS_ERROR);
+            break;
+        case MYNETDNS_OK:
+            onReply(NETDNS_FOUND); 
+            break;
+    }
+    if (m_timer.read_ms() > 3000) {
+        m_timer.stop();
+        m_state = MYNETDNS_ERROR;
+    }
+    if(m_closing && (m_state!=MYNETDNS_PROCESSING)) {
+        NetDnsRequest::close();
+    }
+}
+
+void MyNetDnsRequest::close() {
+    PRINT_FUNC();
+    if(m_state != MYNETDNS_PROCESSING) {
+        NetDnsRequest::close();
+    } else {
+        m_closing = true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyNetDnsRequest.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,35 @@
+// MyNetDnsRequest.h 2012/4/13
+#ifndef MYNETDNSREQUEST_H
+#define MYNETDNSREQUEST_H
+#include "if/net/netdnsrequest.h"
+#include "UDPSocket.h"
+ 
+class MyNetDnsRequest : public NetDnsRequest {
+public:
+    MyNetDnsRequest(const char* hostname);
+    MyNetDnsRequest(Host* pHost);
+    virtual ~MyNetDnsRequest();
+    virtual void poll();
+    virtual void close();
+protected:
+    void callback(UDPSocketEvent e);
+    int response(uint8_t buf[], int size);
+    int query(uint8_t buf[], int size, const char* hostname);
+    void resolve(const char* hostname);
+    uint8_t m_id[2];
+    Timer m_timer;
+private:
+    enum MyNetDnsState
+    {
+        MYNETDNS_START,
+        MYNETDNS_PROCESSING, //Req has not completed
+        MYNETDNS_NOTFOUND,
+        MYNETDNS_ERROR,
+        MYNETDNS_OK
+    };
+    MyNetDnsState m_state;
+    bool m_cbFired;
+    bool m_closing;
+    UDPSocket *m_udp;
+};
+#endif //MYNETDNSREQUEST_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyNetIf.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,52 @@
+// MyNetIf.cpp 2012/4/13
+#include "mbed.h"
+#include "MyNetIf.h"
+#include "MyNetTcpSocket.h"
+#include "MyNetUdpSocket.h"
+#include "MyNetDnsRequest.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#include "Utils.h"
+#define PRINT_FUNC() printf("%d:%s\n", __LINE__,__PRETTY_FUNCTION__)
+#else //DEBUG
+#define PRINT_FUNC()
+#endif //DEBUG
+
+MyNetIf::MyNetIf() : NetIf(), m_init(false)
+{
+    PRINT_FUNC();
+}
+
+MyNetIf::~MyNetIf() {
+    PRINT_FUNC();
+}
+
+void MyNetIf::init() {
+    PRINT_FUNC();
+}
+
+NetTcpSocket* MyNetIf::tcpSocket() {
+    PRINT_FUNC();
+    return new MyNetTcpSocket();
+}
+
+NetUdpSocket* MyNetIf::udpSocket() {
+    PRINT_FUNC();
+    return new MyNetUdpSocket();
+}
+
+NetDnsRequest* MyNetIf::dnsRequest(const char* hostname) {
+    PRINT_FUNC();
+    return new MyNetDnsRequest(hostname);
+}
+
+NetDnsRequest* MyNetIf::dnsRequest(Host* pHost) {
+    PRINT_FUNC();
+    return new MyNetDnsRequest(pHost);
+}
+
+void MyNetIf::poll() {
+    PRINT_FUNC();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyNetIf.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,23 @@
+#ifndef MYIPNETIF_H
+#define MYIPNETIF_H
+#include "mbed.h"
+#include "core/net.h"
+#include "if/net/netif.h"
+
+class MyNetIf : public NetIf {
+public:
+    MyNetIf();
+    
+    void init();
+
+    virtual ~MyNetIf();
+    virtual NetTcpSocket* tcpSocket();
+    virtual NetUdpSocket* udpSocket();
+    virtual NetDnsRequest* dnsRequest(const char* hostname);
+    virtual NetDnsRequest* dnsRequest(Host* pHost);
+    
+    virtual void poll();
+private:
+    bool m_init;
+};
+#endif //MYIPNETIF_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyNetTcpSocket.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,166 @@
+// MyNetTcpSocket.cpp 2012/4/15
+#include "mbed.h"
+#include "w5100.h"
+#include "MyNetTcpSocket.h"
+
+#define DEBUG
+
+#ifdef DEBUG
+#include "Utils.h"
+#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__)
+#else //DEBUG
+#define PRINT_FUNC()
+#endif //DEBUG
+
+MyNetTcpSocket::MyNetTcpSocket() : NetTcpSocket()  {
+    PRINT_FUNC();
+    _socket = 1;
+    W5100.writeSnMR(_socket, SnMR:: TCP); // set TCP mode
+}
+
+MyNetTcpSocket::~MyNetTcpSocket() {
+    PRINT_FUNC();
+}
+
+NetTcpSocketErr MyNetTcpSocket::bind(const Host& me) {
+    PRINT_FUNC();
+    int port = me.getPort();
+    W5100.writeSnPORT(_socket, port);
+    return NETTCPSOCKET_OK;
+}
+
+NetTcpSocketErr MyNetTcpSocket::listen() {
+    PRINT_FUNC();
+    W5100.execCmdSn(_socket, Sock_OPEN); // set OPEN command
+    W5100.execCmdSn(_socket, Sock_LISTEN); // listen
+#ifdef DEBUG
+    uint8_t ip[4];
+    printf("socket:%d SnMR:%02x SnIR:%02x SnSR:%02x\n", _socket, 
+        W5100.readSnMR(_socket), W5100.readSnIR(_socket), W5100.readSnSR(_socket));
+    W5100.getIPAddress(ip);
+    printf("SIPR: %d.%d.%d.%d Sn_PORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnPORT(_socket));
+#endif //DEBUG
+    return NETTCPSOCKET_OK;
+}
+
+NetTcpSocketErr MyNetTcpSocket::connect(const Host& host) {
+    PRINT_FUNC();
+    uint8_t ip[4];
+    ip[0] = host.getIp()[0];
+    ip[1] = host.getIp()[1];
+    ip[2] = host.getIp()[2];
+    ip[3] = host.getIp()[3];
+    int port = host.getPort();
+    W5100.writeSnDIPR(_socket, ip);
+    W5100.writeSnDPORT(_socket, port);
+    if (W5100.readSnPORT(_socket) == 0) {
+        W5100.writeSnPORT(_socket, 1024 + _socket);
+    }
+    W5100.execCmdSn(_socket, Sock_OPEN); // set OPEN command
+    W5100.execCmdSn(_socket, Sock_CONNECT);
+#ifdef DEBUG
+    printf("socket:%d SnMR:%02x SnIR:%02x SnSR:%02x\n", _socket, 
+        W5100.readSnMR(_socket), W5100.readSnIR(_socket), W5100.readSnSR(_socket));
+    W5100.getIPAddress(ip);
+    printf("SIPR: %d.%d.%d.%d Sn_PORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnPORT(_socket));
+    W5100.readSnDIPR(_socket, ip);
+    printf("Sn_DIPR: %d.%d.%d.%d Sn_DPORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnDPORT(_socket));
+#endif //DEBUG
+    return NETTCPSOCKET_OK;
+}
+
+NetTcpSocketErr MyNetTcpSocket::accept(Host* pClient, NetTcpSocket** ppNewNetTcpSocket) {
+    PRINT_FUNC();
+    uint8_t ip[4];
+    W5100.readSnDIPR(_socket, ip);
+    pClient->setIp(IpAddr(ip[0],ip[1],ip[2],ip[3]));
+    int port = W5100.readSnDPORT(_socket);
+    pClient->setPort(port);
+    
+    return NETTCPSOCKET_OK;
+}
+
+int /*if < 0 : NetTcpSocketErr*/ MyNetTcpSocket::send(const char* buf, int len) {
+    PRINT_FUNC();
+#ifdef DEBUG
+    printf("buf:%p, len=%d\n", buf, len);
+    printHex((u8*)buf, len);
+#endif //DEBUG
+    if (len > 0) {
+        W5100.send_data_processing(_socket, (uint8_t*)buf, len);
+        W5100.execCmdSn(_socket, Sock_SEND);
+    }
+    return len;
+}
+
+int /*if < 0 : NetTcpSocketErr*/ MyNetTcpSocket::recv(char* buf, int len){
+    PRINT_FUNC();
+    int size = W5100.getRXReceivedSize(_socket);
+    if (size > len) {
+        size = len;
+    }
+    if (size > 0) {
+        W5100.recv_data_processing(_socket, (uint8_t*)buf, size);
+        W5100.execCmdSn(_socket, Sock_RECV);
+    }
+#ifdef DEBUG
+    printHex((uint8_t*)buf, size);
+#endif //DEBUG
+    return size;
+}
+
+NetTcpSocketErr MyNetTcpSocket::close() {
+    PRINT_FUNC();
+    if(m_closed) {
+        return NETTCPSOCKET_OK;
+    }
+    m_closed = true;
+    cleanUp();
+    W5100.execCmdSn(_socket, Sock_DISCON);
+    W5100.execCmdSn(_socket, Sock_CLOSE);
+    return NETTCPSOCKET_OK;
+}
+
+NetTcpSocketErr MyNetTcpSocket::poll(){
+    PRINT_FUNC();
+    NetTcpSocket::flushEvents();
+#ifdef DEBUG
+    printf("socket:%d SnMR:%02x SnIR:%02x SnSR:%02x\n", _socket, 
+        W5100.readSnMR(_socket), W5100.readSnIR(_socket), W5100.readSnSR(_socket));
+    uint8_t ip[4];
+    W5100.readSnDIPR(_socket, ip);
+    printf("Sn_DIPR: %d.%d.%d.%d Sn_DPORT: %d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnDPORT(_socket));
+    printf("Sn_RX_RSR:%d, Sn_RX_RD:%d, Sn_RX_WR:%d\n",
+                W5100.readSnRX_RSR(_socket), W5100.readSnRX_RD(_socket), W5100.readSnRX_WR(_socket));
+    printf("Sn_TX_FSR:%d, Sn_TX_RD:%d, Sn_TX_WR:%d\n",
+                W5100.readSnTX_FSR(_socket), W5100.readSnTX_RD(_socket), W5100.readSnTX_WR(_socket));
+    wait_ms(500);
+#endif //DEBUG
+    if (W5100.readSnSR(_socket) == 0x1c) {
+        queueEvent(NETTCPSOCKET_CONRST);
+    }
+    if (W5100.getRXReceivedSize(_socket) > 0) {
+        queueEvent(NETTCPSOCKET_READABLE);
+    }
+    if (W5100.readSnSR(_socket) == 0x17) {
+        queueEvent(NETTCPSOCKET_CONNECTED);
+        if (W5100.getTXFreeSize(_socket) > 0) {
+            queueEvent(NETTCPSOCKET_WRITEABLE);
+        }
+    }
+    return NETTCPSOCKET_OK;
+}
+
+void MyNetTcpSocket::cleanUp() //Flush input buffer
+{
+    PRINT_FUNC();
+    while(1) {
+        int len = W5100.getRXReceivedSize(_socket);
+        if (len <= 0) {
+            break;
+        }
+        uint8_t temp[8];
+        W5100.recv_data_processing(_socket, temp, sizeof(temp));
+        W5100.execCmdSn(_socket, Sock_RECV);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyNetTcpSocket.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,24 @@
+// MyNetTcpSocket.h 2012/4/14
+#ifndef MYNETTCPSOCKET_H
+#define MYNETTCPSOCKET_H
+#include "if/net/nettcpsocket.h"
+
+class MyNetTcpSocket : public NetTcpSocket {
+public:
+    MyNetTcpSocket();
+    virtual ~MyNetTcpSocket();
+    virtual NetTcpSocketErr bind(const Host& me);
+    virtual NetTcpSocketErr listen();
+    virtual NetTcpSocketErr connect(const Host& host);
+    virtual NetTcpSocketErr accept(Host* pClient, NetTcpSocket** ppNewNetTcpSocket);
+    virtual int /*if < 0 : NetTcpSocketErr*/ send(const char* buf, int len);
+    virtual int /*if < 0 : NetTcpSocketErr*/ recv(char* buf, int len);
+    virtual NetTcpSocketErr close();
+    virtual NetTcpSocketErr poll();
+protected:
+    int _socket;
+private:
+    void cleanUp(); //Flush input buffer
+    queue<MyNetTcpSocket*> m_lpInNetTcpSocket;
+};
+#endif //MYNETTCPSOCKET_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyNetUdpSocket.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,126 @@
+// MyNetUdpSocket.cpp 2012/4/15
+#include "mbed.h"
+#include "MyNetUdpSocket.h"
+#include "w5100.h"
+
+#define DEBUG
+
+#ifdef DEBUG
+#include "Utils.h"
+#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__)
+#else //DEBUG
+#define PRINT_FUNC()
+#endif //DEBUG
+
+MyNetUdpSocket::MyNetUdpSocket() : NetUdpSocket()  {
+    PRINT_FUNC();
+    _socket = 0;
+    W5100.writeSnMR(_socket, SnMR::UDP); // set UDP mode
+}
+
+MyNetUdpSocket::~MyNetUdpSocket() {
+    PRINT_FUNC();
+    close();
+}
+
+NetUdpSocketErr MyNetUdpSocket::bind(const Host& me) {
+    PRINT_FUNC();
+    int port = me.getPort();
+    W5100.writeSnPORT(_socket, port);
+    W5100.execCmdSn( _socket, Sock_OPEN); // set OPEN command
+    return NETUDPSOCKET_OK;
+}
+
+int /*if < 0 : NetUdpSocketErr*/ MyNetUdpSocket::sendto(const char* buf, int len, Host* pHost) {
+    PRINT_FUNC();
+    uint8_t ip[4];
+    ip[0] = pHost->getIp()[0];
+    ip[1] = pHost->getIp()[1];
+    ip[2] = pHost->getIp()[2];
+    ip[3] = pHost->getIp()[3];
+    int port = pHost->getPort();
+    W5100.writeSnDIPR(_socket, ip);
+    W5100.writeSnDPORT(_socket, port);
+    W5100.send_data_processing(_socket, (uint8_t*)buf, len);
+    W5100.execCmdSn(_socket, Sock_SEND);
+#ifdef DEBUG
+    printHex((u8*)buf, len);
+    W5100.getIPAddress(ip);
+    printf("SIPR: %d.%d.%d.%d Sn_PORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnPORT(_socket));
+    W5100.readSnDIPR(_socket, ip);
+    printf("Sn_DIPR: %d.%d.%d.%d Sn_DPORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnDPORT(_socket));
+#endif //DEBUG
+    return len;
+}
+
+int /*if < 0 : NetUdpSocketErr*/ MyNetUdpSocket::recvfrom(char* buf, int len, Host* pHost) {
+    PRINT_FUNC();
+    int size = W5100.getRXReceivedSize(_socket);
+    if (size < 8) {
+        return -1;
+    }
+    uint8_t info[8];
+    W5100.recv_data_processing(_socket, info, 8);
+    W5100.execCmdSn(_socket, Sock_RECV);
+    pHost->setIp(IpAddr(info[0],info[1],info[2],info[3]));
+    pHost->setPort(info[4]<<8|info[5]);
+    size -= 8;
+    if (size > len) {
+        size = len;
+    }    
+    W5100.recv_data_processing(_socket, (uint8_t*)buf, size);
+    W5100.execCmdSn(_socket, Sock_RECV);
+#ifdef DEBUG
+    printfBytes("UDP PACKET-INFO", (u8*)info, 8);
+    printHex((u8*)buf, size);
+#endif //DEBUG
+    return size;
+}
+
+NetUdpSocketErr MyNetUdpSocket::close() {
+    PRINT_FUNC();
+    if(m_closed) {
+        return NETUDPSOCKET_OK;
+    }
+    m_closed = true;
+    cleanUp();
+    return NETUDPSOCKET_OK;
+}
+
+NetUdpSocketErr MyNetUdpSocket::poll() {
+    PRINT_FUNC();
+    NetUdpSocket::flushEvents();
+#ifdef DEBUG
+    printf("socket:%d SnMR:%02x SnIR:%02x SnSR:%02x\n", _socket, 
+        W5100.readSnMR(_socket), W5100.readSnIR(_socket), W5100.readSnSR(_socket));
+    uint8_t ip[4];
+    W5100.readSnDIPR(_socket, ip);
+    printf("Sn_DIPR: %d.%d.%d.%d Sn_DPORT: %d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnDPORT(_socket));
+    uint8_t mac[6];
+    W5100.readSnDHAR(_socket, mac);
+    printf("Sn_DHAR: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+    printf("Sn_RX_RSR:%d, Sn_RX_RD:%d, Sn_RX_WR:%d\n",
+                W5100.readSnRX_RSR(_socket), W5100.readSnRX_RD(_socket), W5100.readSnRX_WR(_socket));
+    printf("Sn_TX_FSR:%d, Sn_TX_RD:%d, Sn_TX_WR:%d\n",
+                W5100.readSnTX_FSR(_socket), W5100.readSnTX_RD(_socket), W5100.readSnTX_WR(_socket));
+    wait_ms(500);    
+#endif //DEBUG
+    if (W5100.getRXReceivedSize(_socket) > 0) {
+        queueEvent(NETUDPSOCKET_READABLE);
+    }
+    return NETUDPSOCKET_OK;
+}
+
+void MyNetUdpSocket::cleanUp() //Flush input buffer
+{
+    PRINT_FUNC();
+    while(1) {
+        int len = W5100.getRXReceivedSize(_socket);
+        if (len <= 0) {
+            break;
+        }
+        uint8_t temp[8];
+        W5100.recv_data_processing(_socket, temp, sizeof(temp));
+        W5100.execCmdSn(_socket, Sock_RECV);
+    }    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyNetUdpSocket.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,20 @@
+// MyNetUdpSocket.h 2012/4/14
+#ifndef MYNETUDPSOCKET_H
+#define MYNETUDPSOCKET_H
+#include "if/net/netudpsocket.h"
+
+class MyNetUdpSocket: public NetUdpSocket {
+public:
+    MyNetUdpSocket();
+    virtual ~MyNetUdpSocket();
+    virtual NetUdpSocketErr bind(const Host& me);
+    virtual int /*if < 0 : NetUdpSocketErr*/ sendto(const char* buf, int len, Host* pHost);
+    virtual int /*if < 0 : NetUdpSocketErr*/ recvfrom(char* buf, int len, Host* pHost);
+    virtual NetUdpSocketErr close();
+    virtual NetUdpSocketErr poll();
+protected:
+    int _socket;
+private:
+    void cleanUp(); //Flush input buffer
+};
+#endif //MYNETUDPSOCKET_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TinyHTTP.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,240 @@
+/*
+ * mbed Tiny HTTP Client
+ * Copyright (c) 2011 Hiroshi Suga
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+/** @file
+ * @brief Tiny HTTP Client
+ */
+
+#include "mbed.h"
+#include "EthernetNetIf.h"
+#include "TCPSocket.h"
+#include "DNSRequest.h"
+#include "TinyHTTP.h"
+#include <ctype.h>
+
+
+TCPSocket *http;
+volatile int tcp_ready, tcp_readable, tcp_writable;
+volatile int dns_status;
+
+// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+int base64enc(const char *input, unsigned int length, char *output, int len) {
+  static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  unsigned int c, c1, c2, c3;
+
+  if (len < ((((length-1)/3)+1)<<2)) return -1;
+  for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
+    c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
+    c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
+    c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
+
+    c = ((c1 & 0xFC) >> 2);
+    output[j+0] = base64[c];
+    c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
+    output[j+1] = base64[c];
+    c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
+    output[j+2] = (length>i+1)?base64[c]:'=';
+    c = (c3 & 0x3F);
+    output[j+3] = (length>i+2)?base64[c]:'=';
+  }
+  output[(((length-1)/3)+1)<<2] = '\0';
+  return 0;
+}
+
+// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+int urlencode(char *str, char *buf, int len) {
+  static const char to_hex[] = "0123456789ABCDEF";
+//  char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
+  char *pstr = str, *pbuf = buf;
+
+  if (len < (strlen(str) * 3 + 1)) return -1;
+  while (*pstr) {
+    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') {
+      *pbuf++ = *pstr;
+    } else if (*pstr == ' ') {
+      *pbuf++ = '+';
+    } else { 
+      *pbuf++ = '%';
+      *pbuf++ = to_hex[(*pstr >> 4) & 0x0f];
+      *pbuf++ = to_hex[*pstr & 0x0f];
+    }
+    pstr++;
+  }
+  *pbuf = '\0';
+  return 0;
+}
+
+
+void isr_http (TCPSocketEvent e) {
+
+#ifdef DEBUG
+    printf("tcp(%d)\r\n", e);
+#endif
+    switch(e) {
+    case TCPSOCKET_CONNECTED:
+        tcp_ready = 1;
+        break;
+
+    case TCPSOCKET_READABLE: //Incoming data
+        tcp_readable = 1;
+        break;
+
+    case TCPSOCKET_WRITEABLE: //We can send data
+        tcp_writable = 1;
+        break;
+
+    case TCPSOCKET_CONTIMEOUT:
+    case TCPSOCKET_CONRST:
+    case TCPSOCKET_CONABRT:
+    case TCPSOCKET_ERROR:
+    case TCPSOCKET_DISCONNECTED:
+        tcp_ready = 0;
+        break;
+    }
+}
+
+void createauth (char *user, char *pwd, char *buf, int len) {
+    char tmp[80];
+
+    strncpy(buf, "Authorization: Basic ", len);
+    snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
+    base64enc(tmp, strlen(tmp), &buf[strlen(buf)], len - strlen(buf));
+    strncat(buf, "\r\n", len - strlen(buf));
+}
+
+void isr_dns (DNSReply r) {
+
+#ifdef DEBUG
+    printf("dns(%d)\r\n", r);
+#endif
+    if (r == DNS_FOUND) {
+        dns_status = 1;
+    } else {
+        dns_status = -1;
+    }
+}
+
+int httpRequest (int method, Host *host, char *uri, char *head, char *body) {
+    TCPSocketErr err;
+    Timer timeout;
+    char buf[1500];
+    int i, ret = -1;
+
+    http = new TCPSocket;
+    tcp_ready = 0;
+    tcp_readable = 0;
+    tcp_writable = 0;
+
+    http->setOnEvent(isr_http);
+
+    // connect
+    if (host->getIp().isNull()) {
+        // resolv
+        DNSRequest dns;
+        dns_status = 0;
+        dns.setOnReply(isr_dns);
+        if (dns.resolve(host) != DNS_OK) goto exit;
+        timeout.reset();
+        timeout.start();
+        while (timeout.read_ms() < HTTP_TIMEOUT) {
+            if (dns_status) break;
+            Net::poll();
+        }
+        timeout.stop();
+        if (dns_status <= 0) goto exit;
+#ifdef DEBUG
+        printf("%s [%d.%d.%d.%d]\r\n", host->getName(), (unsigned char)host->getIp()[0], (unsigned char)host->getIp()[1], (unsigned char)host->getIp()[2], (unsigned char)host->getIp()[3]);
+#endif
+    }
+    if (! host->getPort()) {
+        host->setPort(HTTP_PORT);
+    }
+    err = http->connect(*host);
+    if (err != TCPSOCKET_OK) goto exit;
+
+    // wait connect
+    timeout.reset();
+    timeout.start();
+    while (timeout.read_ms() < HTTP_TIMEOUT) {
+        if (tcp_ready) break;
+        Net::poll();
+    }
+    timeout.stop();
+    if (! tcp_ready) goto exit;
+
+    // send request
+    if (method == METHOD_POST) {
+        http->send("POST ", 5);
+    } else {
+        http->send("GET ", 4);
+    }
+    http->send(uri, strlen(uri));
+    http->send(" HTTP/1.1\r\nHost: ", 17);
+    http->send(host->getName(), strlen(host->getName()));
+    http->send("\r\n", 2);
+    http->send("Connection: close\r\n", 19);
+    if (head) {
+        http->send(head, strlen(head));
+    }
+    if (method == METHOD_POST) {
+        sprintf(buf, "Content-Length: %d\r\n", strlen(body));
+        http->send(buf, strlen(buf));
+    }
+    http->send("\r\n", 2);
+
+    // post method
+    if (method == METHOD_POST && body) {
+        http->send(body, strlen(body));
+    }
+
+    // wait responce
+    timeout.reset();
+    timeout.start();
+    while (timeout.read_ms() < HTTP_TIMEOUT) {
+        if (tcp_readable) break;
+        Net::poll();
+    }
+    timeout.stop();
+    if (! tcp_readable) goto exit;
+
+    // recv responce
+    i = http->recv(buf, sizeof(buf) - 1);
+    buf[i] = 0;
+    if (i < sizeof(buf) - 1) tcp_readable = 0;
+    if (strncmp(buf, "HTTP/", 5) == 0) {
+        ret = atoi(&buf[9]);
+    }
+#ifdef DEBUG
+    printf(buf);
+#endif
+
+    // recv dummy
+    timeout.reset();
+    timeout.start();
+    while (timeout.read_ms() < HTTP_TIMEOUT) {
+        if (tcp_readable) {
+            i = http->recv(buf, sizeof(buf) - 1);
+            buf[i] = 0;
+            if (i < sizeof(buf) - 1) tcp_readable = 0;
+#ifdef DEBUG
+            printf(buf);
+#endif
+            timeout.reset();
+        } else
+        if (! tcp_ready) {
+            break;
+        }
+        Net::poll();
+    }
+    timeout.stop();
+
+exit:
+    http->resetOnEvent();
+    http->close();
+    delete http;
+
+    return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TinyHTTP.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,38 @@
+/*
+ * mbed Tiny HTTP Client
+ * Copyright (c) 2011 Hiroshi Suga
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+/** @file
+ * @brief Tiny HTTP Client
+ */
+
+#ifndef TinyHTTP_h
+#define TinyHTTP_h
+
+#define DEBUG
+
+#define HTTP_PORT 80
+#define HTTP_TIMEOUT 15000 // ms
+
+#define METHOD_GET 0
+#define METHOD_POST 1
+
+/** send http request
+ * @param method METHOD_GET or METHOD_POST
+ * @param host http server
+ * @param uri URI
+ * @param head http header (CR+LF) (or NULL)
+ * @param body POST body (or NULL)
+ * @return http code, -1:failue
+ */
+int httpRequest (int method, Host *host, char *uri, char *head, char *body);
+
+void createauth (char *user, char *pwd, char *buf, int len);
+
+int base64enc(const char *input, unsigned int length, char *output, int len);
+
+int urlencode(char *str, char *buf, int len);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utils.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,48 @@
+
+
+#include "mbed.h"
+#include "Utils.h"
+
+void printfBytes(const char* s, const u8* data, int len)
+{
+    printf("%s %d:",s,len);
+    if (len > 256)
+        len = 256;
+    while (len-- > 0)
+        printf(" %02X",*data++);
+    printf("\n");
+}
+
+void printHexLine(const u8* d, int addr, int len)
+{
+    printf("%04X ",addr);
+    int i;
+    for (i = 0; i < len; i++)
+        printf("%02X ",d[i]);
+    for (;i < 16; i++)
+        printf("   ");
+    char s[16+1];
+    memset(s,0,sizeof(s));
+    for (i = 0; i < len; i++)
+    {
+        int c = d[i];
+        if (c < 0x20 || c > 0x7E)
+            c = '.';
+        s[i] = c;
+    }
+    printf("%s\n",s);
+}
+
+void printHex(const u8* d, int len)
+{
+    int addr = 0;
+    while (len)
+    {
+        int count = len;
+        if (count > 16)
+            count = 16;
+        printHexLine(d+addr,addr,count);
+        addr += 16;
+        len -= count;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utils.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,37 @@
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+void DelayMS(int ms);
+
+void printfBytes(const char* label,const u8* data, int len);
+void printHex(const u8* d, int len);
+
+#ifndef min
+#define min(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+inline int LE16(const u8* d)
+{
+    return d[0] | (d[1] << 8);
+}
+
+inline u32 BE32(const u8* d)
+{
+    return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+}
+
+inline void BE32(u32 n, u8* d)
+{
+    d[0] = (u8)(n >> 24);
+    d[1] = (u8)(n >> 16);
+    d[2] = (u8)(n >> 8);
+    d[3] = (u8)n;
+}
+
+inline void BE16(u32 n, u8* d)
+{
+    d[0] = (u8)(n >> 8);
+    d[1] = (u8)n;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WIZ820ioNetIf.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,22 @@
+// WIZ820ioNetIf.cpp 2012/4/13
+#include "WIZ820ioNetIf.h"
+#include "w5100.h"
+
+bool wait_linkup(int timeout = 5000) {
+    Timer link_t;
+    link_t.start();
+    while(link_t.read_ms() < timeout) {
+        if (0x20 & W5100.readPHYSTATUS()) {
+            return true;
+        }
+         wait_ms(50);
+    }  
+    return false;
+}
+
+int WIZ820ioNetIf::setup(int timeout_ms) {
+    W5100.hardware_reset();
+    W5100.init();
+    wait_linkup();
+    return w5200NetIf::setup(timeout_ms);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WIZ820ioNetIf.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,9 @@
+// WIZ820ioNetIf.h 2012/4/13
+#ifndef WIZ820IO_NETIF_H
+#define WIZ820IO_NETIF_H
+#include "w5200NetIf.h"
+class WIZ820ioNetIf : public w5200NetIf {
+public:
+    int setup(int timeout_ms = 15000);
+};
+#endif //WIZ820IO_NETIF_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dnsname.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,51 @@
+// dnsname.h 2012/4/13
+#ifndef DNSNAME_H
+#define DNSNAME_H
+class dnsname {
+public:
+    uint8_t *buf;
+    string str;
+    dnsname(uint8_t *s) {
+        buf = s;
+    }
+    int decode(int pos) {
+        while(1) {
+            int len = buf[pos++];
+            if (len == 0x00) {
+                break;
+            }
+            if ((len&0xc0) == 0xc0) { //compress
+                int offset = (len&0x3f)<<8|buf[pos];
+                decode(offset);
+                return pos+1;
+            }
+            if (!str.empty()) {
+                str.append(".");
+            }
+            str.append((const char*)(buf+pos), len);
+            pos += len;
+        }
+        return pos;
+    }
+
+    int encode(int pos, char* s) {
+        while(*s) {  
+            char *f = strchr(s, '.');
+            if (f == NULL) {
+                int len = strlen(s);
+                buf[pos++] = len;
+                memcpy(buf+pos, s, len);
+                pos += len;
+                break;
+            }
+            int len = f - s;
+            buf[pos++] = len;
+            memcpy(buf+pos, s, len);
+            s = f+1;
+            pos += len;
+        }
+        buf[pos++] = 0x00;
+        return pos;
+    }
+};
+#endif //DNSNAME_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/737756e0b479
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mymain.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,13 @@
+#include "mbed.h"
+#include "WIZ820ioNetIf.h"
+#include "TinyHTTP.h"
+#include <host.h>
+
+int main() {
+    WIZ820ioNetIf eth;
+    eth.setup();
+    Host host;
+    host.setName("www.wiznet.co.kr");
+    int status = httpRequest(METHOD_GET, &host, "/", NULL, NULL);
+    printf("status: %d\n", status);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/w5100.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "w5100.h"
+#ifndef MBED
+#include <avr/interrupt.h>
+#endif //MBED
+
+// W5100 controller instance
+W5100Class W5100;
+
+#define TX_RX_MAX_BUF_SIZE 2048
+#define TX_BUF 0x1100
+#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
+
+#ifdef W5200
+#define TXBUF_BASE 0x8000
+#define RXBUF_BASE 0xC000
+#else
+#define TXBUF_BASE 0x4000
+#define RXBUF_BASE 0x6000
+#endif
+
+#ifdef MBED
+SPI spi(p11, p12, p13); // mosi, miso, sclk
+DigitalOut _cs(p14);
+DigitalOut _reset(p15);
+inline void delay(int n) { wait_ms(n); }
+inline static void initSS(){ _cs = 1; }
+inline static void setSS() { _cs = 0; }
+inline static void resetSS() { _cs = 1; }
+
+void W5100Class::hardware_reset() {
+  _reset = 1;
+  _reset = 0;
+  wait_us(2);
+  _reset = 1;
+  wait_ms(150);
+}
+#endif //MBED
+
+void W5100Class::init(void)
+{
+  initSS();
+  writeMR(1<<RST);
+  
+#ifdef W5200
+  for (int i=0; i<MAX_SOCK_NUM; i++) {
+    write((0x4000 + i * 0x100 + 0x001F), 2);
+    write((0x4000 + i * 0x100 + 0x001E), 2);
+  }
+#else  
+  writeTMSR(0x55);
+  writeRMSR(0x55);
+#endif
+
+  for (int i=0; i<MAX_SOCK_NUM; i++) {
+    SBASE[i] = TXBUF_BASE + SSIZE * i;
+    RBASE[i] = RXBUF_BASE + RSIZE * i;
+  }
+}
+
+uint16_t W5100Class::getTXFreeSize(SOCKET s)
+{
+  uint16_t val=0, val1=0;
+  do {
+    val1 = readSnTX_FSR(s);
+    if (val1 != 0)
+      val = readSnTX_FSR(s);
+  } 
+  while (val != val1);
+  return val;
+}
+
+uint16_t W5100Class::getRXReceivedSize(SOCKET s)
+{
+  uint16_t val=0,val1=0;
+  do {
+    val1 = readSnRX_RSR(s);
+    if (val1 != 0)
+      val = readSnRX_RSR(s);
+  } 
+  while (val != val1);
+  return val;
+}
+
+
+void W5100Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
+{
+  // This is same as having no offset in a call to send_data_processing_offset
+  send_data_processing_offset(s, 0, data, len);
+}
+
+void W5100Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
+{
+  uint16_t ptr = readSnTX_WR(s);
+  ptr += data_offset;
+  uint16_t offset = ptr & SMASK;
+  uint16_t dstAddr = offset + SBASE[s];
+
+  if (offset + len > SSIZE) 
+  {
+    // Wrap around circular buffer
+    uint16_t size = SSIZE - offset;
+    write(dstAddr, data, size);
+    write(SBASE[s], data + size, len - size);
+  } 
+  else {
+    write(dstAddr, data, len);
+  }
+
+  ptr += len;
+  writeSnTX_WR(s, ptr);
+}
+
+
+void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
+{
+  uint16_t ptr;
+  ptr = readSnRX_RD(s);
+  read_data(s, (uint8_t *)ptr, data, len);
+  if (!peek)
+  {
+    ptr += len;
+    writeSnRX_RD(s, ptr);
+  }
+}
+
+void W5100Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
+{
+  uint16_t size;
+  uint16_t src_mask;
+  uint16_t src_ptr;
+
+#ifdef MBED
+  src_mask = (int)src & RMASK;
+#else 
+  src_mask = (uint16_t)src & RMASK;
+#endif //MBED
+  src_ptr = RBASE[s] + src_mask;
+
+  if( (src_mask + len) > RSIZE ) 
+  {
+    size = RSIZE - src_mask;
+    read(src_ptr, (uint8_t *)dst, size);
+    dst += size;
+    read(RBASE[s], (uint8_t *) dst, len - size);
+  } 
+  else
+    read(src_ptr, (uint8_t *) dst, len);
+}
+
+
+uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
+{
+  setSS();  
+  
+#ifdef W5200
+  spi.write(_addr >> 8);
+  spi.write(_addr & 0xFF);
+  spi.write(0x80);
+  spi.write(0x01);
+#else    
+  spi.write(0xF0);
+  spi.write(_addr >> 8);
+  spi.write(_addr & 0xFF);
+#endif  
+  spi.write(_data);
+  resetSS();
+  return 1;
+}
+
+uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
+{
+    
+#ifdef W5200
+    setSS();
+    spi.write(_addr >> 8);
+    spi.write(_addr & 0xFF);
+    spi.write((0x80 | ((_len & 0x7F00) >> 8)));
+    spi.write(_len & 0x00FF);
+
+  for (uint16_t i=0; i<_len; i++)
+  {
+    spi.write(_buf[i]);
+
+  }
+    resetSS();
+#else    
+    
+  for (uint16_t i=0; i<_len; i++)
+  {
+    setSS();    
+    spi.write(0xF0);
+    spi.write(_addr >> 8);
+    spi.write(_addr & 0xFF);
+    _addr++;
+    spi.write(_buf[i]);
+    resetSS();
+  }
+#endif
+  
+  return _len;
+}
+
+uint8_t W5100Class::read(uint16_t _addr)
+{
+  setSS();  
+#ifdef W5200
+  spi.write(_addr >> 8);
+  spi.write(_addr & 0xFF);
+  spi.write(0x00);
+  spi.write(0x01);
+#else
+  spi.write(0x0F);
+  spi.write(_addr >> 8);
+  spi.write(_addr & 0xFF);
+#endif
+  
+  uint8_t _data = spi.write(0);
+  resetSS();
+  return _data;
+}
+
+uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
+{
+#ifdef W5200
+    setSS();
+    spi.write(_addr >> 8);
+    spi.write(_addr & 0xFF);
+    spi.write((0x00 | ((_len & 0x7F00) >> 8)));
+    spi.write(_len & 0x00FF);
+
+  for (uint16_t i=0; i<_len; i++)
+  {
+    _buf[i] = spi.write(0);
+
+  }
+    resetSS();
+
+#else    
+    
+  for (uint16_t i=0; i<_len; i++)
+  {
+    setSS();
+    spi.write(0x0F);
+    spi.write(_addr >> 8);
+    spi.write(_addr & 0xFF);
+    _addr++;
+    _buf[i] = spi.write(0);
+    resetSS();
+  }
+#endif  
+  return _len;
+}
+
+void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) {
+  // Send command to socket
+  writeSnCR(s, _cmd);
+  // Wait for command to complete
+  while (readSnCR(s))
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/w5100.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either the GNU General Public License version 2
+ * or the GNU Lesser General Public License version 2.1, both as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef    W5100_H_INCLUDED
+#define    W5100_H_INCLUDED
+#define MBED
+#ifdef MBED
+#include "mbed.h"
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+#else //MBED
+#include <avr/pgmspace.h>
+#include <SPI.h>
+#endif //MBED
+#define W5200
+
+#ifdef W5200
+#define MAX_SOCK_NUM 8
+#else
+#define MAX_SOCK_NUM 4
+#endif
+
+
+typedef uint8_t SOCKET;
+
+#ifndef W5200
+#define IDM_OR  0x8000
+#define IDM_AR0 0x8001
+#define IDM_AR1 0x8002
+#define IDM_DR  0x8003
+#endif
+
+/*
+class MR {
+public:
+  static const uint8_t RST   = 0x80;
+  static const uint8_t PB    = 0x10;
+  static const uint8_t PPPOE = 0x08;
+  static const uint8_t LB    = 0x04;
+  static const uint8_t AI    = 0x02;
+  static const uint8_t IND   = 0x01;
+};
+*/
+/*
+class IR {
+public:
+  static const uint8_t CONFLICT = 0x80;
+  static const uint8_t UNREACH  = 0x40;
+  static const uint8_t PPPoE    = 0x20;
+  static const uint8_t SOCK0    = 0x01;
+  static const uint8_t SOCK1    = 0x02;
+  static const uint8_t SOCK2    = 0x04;
+  static const uint8_t SOCK3    = 0x08;
+  static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); };
+};
+*/
+
+class SnMR {
+public:
+  static const uint8_t CLOSE  = 0x00;
+  static const uint8_t TCP    = 0x01;
+  static const uint8_t UDP    = 0x02;
+  static const uint8_t IPRAW  = 0x03;
+  static const uint8_t MACRAW = 0x04;
+  static const uint8_t PPPOE  = 0x05;
+  static const uint8_t ND     = 0x20;
+  static const uint8_t MULTI  = 0x80;
+};
+
+enum SockCMD {
+  Sock_OPEN      = 0x01,
+  Sock_LISTEN    = 0x02,
+  Sock_CONNECT   = 0x04,
+  Sock_DISCON    = 0x08,
+  Sock_CLOSE     = 0x10,
+  Sock_SEND      = 0x20,
+  Sock_SEND_MAC  = 0x21,
+  Sock_SEND_KEEP = 0x22,
+  Sock_RECV      = 0x40
+};
+
+/*class SnCmd {
+public:
+  static const uint8_t OPEN      = 0x01;
+  static const uint8_t LISTEN    = 0x02;
+  static const uint8_t CONNECT   = 0x04;
+  static const uint8_t DISCON    = 0x08;
+  static const uint8_t CLOSE     = 0x10;
+  static const uint8_t SEND      = 0x20;
+  static const uint8_t SEND_MAC  = 0x21;
+  static const uint8_t SEND_KEEP = 0x22;
+  static const uint8_t RECV      = 0x40;
+};
+*/
+
+class SnIR {
+public:
+  static const uint8_t SEND_OK = 0x10;
+  static const uint8_t TIMEOUT = 0x08;
+  static const uint8_t RECV    = 0x04;
+  static const uint8_t DISCON  = 0x02;
+  static const uint8_t CON     = 0x01;
+};
+
+class SnSR {
+public:
+  static const uint8_t CLOSED      = 0x00;
+  static const uint8_t INIT        = 0x13;
+  static const uint8_t LISTEN      = 0x14;
+  static const uint8_t SYNSENT     = 0x15;
+  static const uint8_t SYNRECV     = 0x16;
+  static const uint8_t ESTABLISHED = 0x17;
+  static const uint8_t FIN_WAIT    = 0x18;
+  static const uint8_t CLOSING     = 0x1A;
+  static const uint8_t TIME_WAIT   = 0x1B;
+  static const uint8_t CLOSE_WAIT  = 0x1C;
+  static const uint8_t LAST_ACK    = 0x1D;
+  static const uint8_t UDP         = 0x22;
+  static const uint8_t IPRAW       = 0x32;
+  static const uint8_t MACRAW      = 0x42;
+  static const uint8_t PPPOE       = 0x5F;
+};
+
+class IPPROTO {
+public:
+  static const uint8_t IP   = 0;
+  static const uint8_t ICMP = 1;
+  static const uint8_t IGMP = 2;
+  static const uint8_t GGP  = 3;
+  static const uint8_t TCP  = 6;
+  static const uint8_t PUP  = 12;
+  static const uint8_t UDP  = 17;
+  static const uint8_t IDP  = 22;
+  static const uint8_t ND   = 77;
+  static const uint8_t RAW  = 255;
+};
+
+class W5100Class {
+public:
+#ifdef MBED
+  void hardware_reset();
+#endif //MBED
+  void init();
+
+  /**
+   * @brief    This function is being used for copy the data form Receive buffer of the chip to application buffer.
+   * 
+   * It calculate the actual physical address where one has to read
+   * the data from Receive buffer. Here also take care of the condition while it exceed
+   * the Rx memory uper-bound of socket.
+   */
+  void read_data(SOCKET s, volatile uint8_t * src, volatile uint8_t * dst, uint16_t len);
+  
+  /**
+   * @brief     This function is being called by send() and sendto() function also. 
+   * 
+   * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
+   * register. User should read upper byte first and lower byte later to get proper value.
+   */
+  void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len);
+  /**
+   * @brief A copy of send_data_processing that uses the provided ptr for the
+   *        write offset.  Only needed for the "streaming" UDP API, where
+   *        a single UDP packet is built up over a number of calls to
+   *        send_data_processing_ptr, because TX_WR doesn't seem to get updated
+   *        correctly in those scenarios
+   * @param ptr value to use in place of TX_WR.  If 0, then the value is read
+   *        in from TX_WR
+   * @return New value for ptr, to be used in the next call
+   */
+// FIXME Update documentation
+  void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len);
+
+  /**
+   * @brief    This function is being called by recv() also.
+   * 
+   * This function read the Rx read pointer register
+   * and after copy the data from receive buffer update the Rx write pointer register.
+   * User should read upper byte first and lower byte later to get proper value.
+   */
+  void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0);
+
+  inline void setGatewayIp(uint8_t *_addr);
+  inline void getGatewayIp(uint8_t *_addr);
+
+  inline void setSubnetMask(uint8_t *_addr);
+  inline void getSubnetMask(uint8_t *_addr);
+
+  inline void setMACAddress(uint8_t * addr);
+  inline void getMACAddress(uint8_t * addr);
+
+  inline void setIPAddress(uint8_t * addr);
+  inline void getIPAddress(uint8_t * addr);
+
+  inline void setRetransmissionTime(uint16_t timeout);
+  inline void setRetransmissionCount(uint8_t _retry);
+
+  void execCmdSn(SOCKET s, SockCMD _cmd);
+  
+  uint16_t getTXFreeSize(SOCKET s);
+  uint16_t getRXReceivedSize(SOCKET s);
+  
+
+  // W5100 Registers
+  // ---------------
+private:
+  static uint8_t write(uint16_t _addr, uint8_t _data);
+  static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len);
+  static uint8_t read(uint16_t addr);
+  static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len);
+  
+#define __GP_REGISTER8(name, address)             \
+  static inline void write##name(uint8_t _data) { \
+    write(address, _data);                        \
+  }                                               \
+  static inline uint8_t read##name() {            \
+    return read(address);                         \
+  }
+#define __GP_REGISTER16(name, address)            \
+  static void write##name(uint16_t _data) {       \
+    write(address,   _data >> 8);                 \
+    write(address+1, _data & 0xFF);               \
+  }                                               \
+  static uint16_t read##name() {                  \
+    uint16_t res = read(address);                 \
+    res = (res << 8) + read(address + 1);         \
+    return res;                                   \
+  }
+#define __GP_REGISTER_N(name, address, size)      \
+  static uint16_t write##name(uint8_t *_buff) {   \
+    return write(address, _buff, size);           \
+  }                                               \
+  static uint16_t read##name(uint8_t *_buff) {    \
+    return read(address, _buff, size);            \
+  }
+
+public:
+  __GP_REGISTER8 (MR,     0x0000);    // Mode
+  __GP_REGISTER_N(GAR,    0x0001, 4); // Gateway IP address
+  __GP_REGISTER_N(SUBR,   0x0005, 4); // Subnet mask address
+  __GP_REGISTER_N(SHAR,   0x0009, 6); // Source MAC address
+  __GP_REGISTER_N(SIPR,   0x000F, 4); // Source IP address
+  __GP_REGISTER8 (IR,     0x0015);    // Interrupt
+  __GP_REGISTER8 (IMR,    0x0016);    // Interrupt Mask
+  __GP_REGISTER16(RTR,    0x0017);    // Timeout address
+  __GP_REGISTER8 (RCR,    0x0019);    // Retry count
+  
+  #ifndef W5200
+  __GP_REGISTER8 (RMSR,   0x001A);    // Receive memory size
+  __GP_REGISTER8 (TMSR,   0x001B);    // Transmit memory size
+  #endif
+  __GP_REGISTER8 (PATR,   0x001C);    // Authentication type address in PPPoE mode
+  
+  __GP_REGISTER8 (VERSIONR,0x001f);   // Chip version
+  
+  __GP_REGISTER8 (PTIMER, 0x0028);    // PPP LCP Request Timer
+  __GP_REGISTER8 (PMAGIC, 0x0029);    // PPP LCP Magic Number
+  #ifndef W5200
+  __GP_REGISTER_N(UIPR,   0x002A, 4); // Unreachable IP address in UDP mode
+  __GP_REGISTER16(UPORT,  0x002E);    // Unreachable Port address in UDP mode
+#endif
+  __GP_REGISTER8 (PHYSTATUS,0x0035);  // PHY Status
+  
+#undef __GP_REGISTER8
+#undef __GP_REGISTER16
+#undef __GP_REGISTER_N
+
+  // W5100 Socket registers
+  // ----------------------
+private:
+  static inline uint8_t readSn(SOCKET _s, uint16_t _addr);
+  static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data);
+  static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
+  static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
+
+#ifdef W5200
+  static const uint16_t CH_BASE = 0x4000;
+#else
+  static const uint16_t CH_BASE = 0x0400;
+#endif  
+
+  static const uint16_t CH_SIZE = 0x0100;
+
+#define __SOCKET_REGISTER8(name, address)                    \
+  static inline void write##name(SOCKET _s, uint8_t _data) { \
+    writeSn(_s, address, _data);                             \
+  }                                                          \
+  static inline uint8_t read##name(SOCKET _s) {              \
+    return readSn(_s, address);                              \
+  }
+#define __SOCKET_REGISTER16(name, address)                   \
+  static void write##name(SOCKET _s, uint16_t _data) {       \
+    writeSn(_s, address,   _data >> 8);                      \
+    writeSn(_s, address+1, _data & 0xFF);                    \
+  }                                                          \
+  static uint16_t read##name(SOCKET _s) {                    \
+    uint16_t res = readSn(_s, address);                      \
+    res = (res << 8) + readSn(_s, address + 1);              \
+    return res;                                              \
+  }
+#define __SOCKET_REGISTER_N(name, address, size)             \
+  static uint16_t write##name(SOCKET _s, uint8_t *_buff) {   \
+    return writeSn(_s, address, _buff, size);                \
+  }                                                          \
+  static uint16_t read##name(SOCKET _s, uint8_t *_buff) {    \
+    return readSn(_s, address, _buff, size);                 \
+  }
+  
+public:
+  __SOCKET_REGISTER8(SnMR,        0x0000)        // Mode
+  __SOCKET_REGISTER8(SnCR,        0x0001)        // Command
+  __SOCKET_REGISTER8(SnIR,        0x0002)        // Interrupt
+  __SOCKET_REGISTER8(SnSR,        0x0003)        // Status
+  __SOCKET_REGISTER16(SnPORT,     0x0004)        // Source Port
+  __SOCKET_REGISTER_N(SnDHAR,     0x0006, 6)     // Destination Hardw Addr
+  __SOCKET_REGISTER_N(SnDIPR,     0x000C, 4)     // Destination IP Addr
+  __SOCKET_REGISTER16(SnDPORT,    0x0010)        // Destination Port
+  __SOCKET_REGISTER16(SnMSSR,     0x0012)        // Max Segment Size
+  __SOCKET_REGISTER8(SnPROTO,     0x0014)        // Protocol in IP RAW Mode
+  __SOCKET_REGISTER8(SnTOS,       0x0015)        // IP TOS
+  __SOCKET_REGISTER8(SnTTL,       0x0016)        // IP TTL
+  __SOCKET_REGISTER16(SnTX_FSR,   0x0020)        // TX Free Size
+  __SOCKET_REGISTER16(SnTX_RD,    0x0022)        // TX Read Pointer
+  __SOCKET_REGISTER16(SnTX_WR,    0x0024)        // TX Write Pointer
+  __SOCKET_REGISTER16(SnRX_RSR,   0x0026)        // RX Free Size
+  __SOCKET_REGISTER16(SnRX_RD,    0x0028)        // RX Read Pointer
+  __SOCKET_REGISTER16(SnRX_WR,    0x002A)        // RX Write Pointer (supported?)
+  
+#undef __SOCKET_REGISTER8
+#undef __SOCKET_REGISTER16
+#undef __SOCKET_REGISTER_N
+
+
+private:
+  static const uint8_t  RST = 7; // Reset BIT
+
+#ifdef W5200
+  static const int SOCKETS = 8;
+#else
+  static const int SOCKETS = 4;
+#endif
+
+  static const uint16_t SMASK = 0x07FF; // Tx buffer MASK
+  static const uint16_t RMASK = 0x07FF; // Rx buffer MASK
+public:
+  static const uint16_t SSIZE = 2048; // Max Tx buffer size
+private:
+  static const uint16_t RSIZE = 2048; // Max Rx buffer size
+  uint16_t SBASE[SOCKETS]; // Tx buffer base address
+  uint16_t RBASE[SOCKETS]; // Rx buffer base address
+
+private:
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+  inline static void initSS()    { DDRB  |=  _BV(4); };
+  inline static void setSS()     { PORTB &= ~_BV(4); };
+  inline static void resetSS()   { PORTB |=  _BV(4); };
+#elif defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
+  inline static void initSS()    { DDRB  |=  _BV(0); };
+  inline static void setSS()     { PORTB &= ~_BV(0); };
+  inline static void resetSS()   { PORTB |=  _BV(0); }; 
+#else
+#ifndef MBED
+  inline static void initSS()    { DDRB  |=  _BV(2); };
+  inline static void setSS()     { PORTB &= ~_BV(2); };
+  inline static void resetSS()   { PORTB |=  _BV(2); };
+#endif //MBED
+#endif
+
+};
+
+extern W5100Class W5100;
+
+uint8_t W5100Class::readSn(SOCKET _s, uint16_t _addr) {
+  return read(CH_BASE + _s * CH_SIZE + _addr);
+}
+
+uint8_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) {
+  return write(CH_BASE + _s * CH_SIZE + _addr, _data);
+}
+
+uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) {
+  return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
+}
+
+uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) {
+  return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
+}
+
+void W5100Class::getGatewayIp(uint8_t *_addr) {
+  readGAR(_addr);
+}
+
+void W5100Class::setGatewayIp(uint8_t *_addr) {
+  writeGAR(_addr);
+}
+
+void W5100Class::getSubnetMask(uint8_t *_addr) {
+  readSUBR(_addr);
+}
+
+void W5100Class::setSubnetMask(uint8_t *_addr) {
+  writeSUBR(_addr);
+}
+
+void W5100Class::getMACAddress(uint8_t *_addr) {
+  readSHAR(_addr);
+}
+
+void W5100Class::setMACAddress(uint8_t *_addr) {
+  writeSHAR(_addr);
+}
+
+void W5100Class::getIPAddress(uint8_t *_addr) {
+  readSIPR(_addr);
+}
+
+void W5100Class::setIPAddress(uint8_t *_addr) {
+  writeSIPR(_addr);
+}
+
+void W5100Class::setRetransmissionTime(uint16_t _timeout) {
+  writeRTR(_timeout);
+}
+
+void W5100Class::setRetransmissionCount(uint8_t _retry) {
+  writeRCR(_retry);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/w5200NetIf.cpp	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,64 @@
+// w5200NetIf.cpp 2012/4/13
+#include "w5200NetIf.h"
+#include "DHCPClient.h"
+#include "w5100.h"
+
+w5200NetIf:: w5200NetIf():MyNetIf(), m_netmask(255,255,255,255), m_gateway(), m_hostname(NULL) {
+    m_hostname = NULL;
+    m_useDhcp = true;
+}
+
+w5200NetIf::w5200NetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns) :MyNetIf(), m_hostname(NULL) {
+    m_hostname = NULL;
+    m_ip = ip;
+    m_netmask = netmask;
+    m_gateway = gateway;
+    m_dns = dns;
+    m_useDhcp = false;
+}
+
+int w5200NetIf::IPrenew(int timeout_ms) {
+    printf("DHCP Started, waiting for IP...\n");  
+    DHCPClient dhcp;
+    int err = dhcp.setup(timeout_ms);
+    if (err == (-1)) {
+        printf("Timeout.\n");
+        return err;
+    }
+    printf("Connected, IP: %d.%d.%d.%d\n", dhcp.yiaddr[0], dhcp.yiaddr[1], dhcp.yiaddr[2], dhcp.yiaddr[3]);
+    m_ip = IpAddr(dhcp.yiaddr[0], dhcp.yiaddr[1], dhcp.yiaddr[2], dhcp.yiaddr[3]);
+    m_netmask = IpAddr(dhcp.netmask[0],dhcp.netmask[1],dhcp.netmask[2],dhcp.netmask[3]);
+    m_gateway = IpAddr(dhcp.gateway[0],dhcp.gateway[1],dhcp.gateway[2],dhcp.gateway[3]);
+    uint8_t t[4];
+    t[0] = m_ip[0];
+    t[1] = m_ip[1];
+    t[2] = m_ip[2];
+    t[3] = m_ip[3];
+    W5100.writeSIPR(t);
+    t[0] = m_netmask[0];
+    t[1] = m_netmask[1];
+    t[2] = m_netmask[2];
+    t[3] = m_netmask[3];
+    W5100.writeSUBR(t);
+    t[0] = m_gateway[0];
+    t[1] = m_gateway[1];
+    t[2] = m_gateway[2];
+    t[3] = m_gateway[3];
+    W5100.writeGAR(t);
+    return err;
+}
+
+int w5200NetIf::IPrelease(int timeout_ms) {
+    return -1;
+}
+
+int w5200NetIf::setup(int timeout_ms) {
+    MyNetIf::init();
+    uint8_t mac[6] = {0x00,0x00,0x5e,0x00,0x01,0x01};
+    W5100.setMACAddress(mac);
+    printf("HW Addr is : %02x:%02x:%02x:%02x:%02x:%02x.\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
+    if(! m_useDhcp) {
+        return 0;
+    }
+    return IPrenew(timeout_ms);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/w5200NetIf.h	Sat Apr 14 17:21:11 2012 +0000
@@ -0,0 +1,20 @@
+// w5200NetIf.h 2012/4/13
+#ifndef W5200_NETIF_H
+#define W5200_NETIF_H
+#include "MyNetIf.h"
+
+class w5200NetIf : public MyNetIf {
+public:
+    w5200NetIf();
+    w5200NetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns);
+    int IPrenew(int timeout_ms = 15000);
+    int IPrelease(int timeout_ms = 15000);
+    int setup(int timeout_ms = 15000);
+private:
+    bool m_useDhcp;
+    IpAddr m_netmask;
+    IpAddr m_gateway;
+    IpAddr m_dns;
+    const char* m_hostname;
+};
+#endif //W5200_NETIF_H