W5200(WIZ820io) network interface
Revision 0:61831b843b44, committed 2012-04-14
- Comitter:
- va009039
- Date:
- Sat Apr 14 17:21:11 2012 +0000
- Child:
- 1:803123933c5a
- Commit message:
Changed in this revision
--- /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