Commit Iniziale, progetto funzionante caricato su box ETcontroller in
cantina
This commit is contained in:
BIN
WIZnetInterface/.DS_Store
vendored
Normal file
BIN
WIZnetInterface/.DS_Store
vendored
Normal file
Binary file not shown.
212
WIZnetInterface/DHCPClient/DHCPClient.cpp
Normal file
212
WIZnetInterface/DHCPClient/DHCPClient.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
// DHCPClient.cpp 2013/4/10
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "DHCPClient.h"
|
||||
|
||||
#define DBG_DHCP 0
|
||||
|
||||
#if DBG_DHCP
|
||||
#define DBG(...) do{debug("[%s:%d]", __PRETTY_FUNCTION__,__LINE__);debug(__VA_ARGS__);} while(0);
|
||||
#define DBG_HEX(A,B) do{debug("[%s:%d]\r\n", __PRETTY_FUNCTION__,__LINE__);debug_hex(A,B);} while(0);
|
||||
#else
|
||||
#define DBG(...) while(0);
|
||||
#define DBG_HEX(A,B) while(0);
|
||||
#endif
|
||||
|
||||
int DHCPClient::discover()
|
||||
{
|
||||
m_pos = 0;
|
||||
const uint8_t header[] = {0x01,0x01,0x06,0x00};
|
||||
add_buf((uint8_t*)header, sizeof(header));
|
||||
uint32_t x = time(NULL) + rand();
|
||||
xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x;
|
||||
add_buf(xid, 4);
|
||||
fill_buf(20, 0x00);
|
||||
add_buf(chaddr, 6);
|
||||
fill_buf(10+192, 0x00);
|
||||
const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
|
||||
53,1,DHCPDISCOVER, // DHCP option 53: DHCP Discover
|
||||
55,4,1,3,15,6,
|
||||
255};
|
||||
add_buf((uint8_t*)options, sizeof(options));
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
int DHCPClient::request()
|
||||
{
|
||||
m_pos = 0;
|
||||
const uint8_t header[] = {0x01,0x01,0x06,0x00};
|
||||
add_buf((uint8_t*)header, sizeof(header));
|
||||
add_buf(xid, 4);
|
||||
fill_buf(12, 0x00);
|
||||
add_buf(siaddr, 4);
|
||||
fill_buf(4, 0x00); // giaddr
|
||||
add_buf(chaddr, 6);
|
||||
fill_buf(10+192, 0x00);
|
||||
const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
|
||||
53,1,DHCPREQUEST, // DHCP option 53: DHCP Request
|
||||
55,4,1,3,15,6, // DHCP option 55:
|
||||
};
|
||||
add_buf((uint8_t*)options, sizeof(options));
|
||||
add_option(50, yiaddr, 4);
|
||||
add_option(54, siaddr, 4);
|
||||
add_option(255);
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
int DHCPClient::offer(uint8_t buf[], int size) {
|
||||
memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4);
|
||||
memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4);
|
||||
uint8_t *p;
|
||||
int msg_type = -1;
|
||||
p = buf + DHCP_OFFSET_OPTIONS;
|
||||
while(*p != 255 && p < (buf+size)) {
|
||||
uint8_t code = *p++;
|
||||
if (code == 0) { // Pad Option
|
||||
continue;
|
||||
}
|
||||
int len = *p++;
|
||||
|
||||
DBG("DHCP option: %d\r\n", code);
|
||||
DBG_HEX(p, len);
|
||||
|
||||
switch(code) {
|
||||
case 53:
|
||||
msg_type = *p;
|
||||
break;
|
||||
case 1:
|
||||
memcpy(netmask, p, 4); // Subnet mask address
|
||||
break;
|
||||
case 3:
|
||||
memcpy(gateway, p, 4); // Gateway IP address
|
||||
break;
|
||||
case 6: // DNS server
|
||||
memcpy(dnsaddr, p, 4);
|
||||
break;
|
||||
case 51: // IP lease time
|
||||
break;
|
||||
case 54: // DHCP server
|
||||
memcpy(siaddr, p, 4);
|
||||
break;
|
||||
}
|
||||
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()
|
||||
{
|
||||
Endpoint host;
|
||||
int recv_len = m_udp->receiveFrom(host, (char*)m_buf, sizeof(m_buf));
|
||||
if (recv_len < 0) {
|
||||
return;
|
||||
}
|
||||
if (!verify(m_buf, recv_len)) {
|
||||
return;
|
||||
}
|
||||
int r = offer(m_buf, recv_len);
|
||||
if (r == DHCPOFFER) {
|
||||
int send_size = request();
|
||||
m_udp->sendTo(m_server, (char*)m_buf, send_size);
|
||||
} else if (r == DHCPACK) {
|
||||
exit_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DHCPClient::add_buf(uint8_t c)
|
||||
{
|
||||
m_buf[m_pos++] = c;
|
||||
}
|
||||
|
||||
void DHCPClient::add_buf(uint8_t* buf, int len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
add_buf(buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void DHCPClient::fill_buf(int len, uint8_t data)
|
||||
{
|
||||
while(len-- > 0) {
|
||||
add_buf(data);
|
||||
}
|
||||
}
|
||||
|
||||
void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len)
|
||||
{
|
||||
add_buf(code);
|
||||
if (len > 0) {
|
||||
add_buf((uint8_t)len);
|
||||
add_buf(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
int DHCPClient::setup(int timeout_ms)
|
||||
{
|
||||
eth = WIZnet_Chip::getInstance();
|
||||
if (eth == NULL) {
|
||||
return -1;
|
||||
}
|
||||
eth->reg_rd_mac(SHAR, chaddr);
|
||||
int interval_ms = 5*1000; // 5000msec
|
||||
if (timeout_ms < interval_ms) {
|
||||
interval_ms = timeout_ms;
|
||||
}
|
||||
m_udp = new UDPSocket;
|
||||
m_udp->init();
|
||||
m_udp->set_blocking(false);
|
||||
eth->reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0"
|
||||
m_udp->bind(68); // local port
|
||||
m_server.set_address("255.255.255.255", 67); // DHCP broadcast
|
||||
exit_flag = false;
|
||||
int err = 0;
|
||||
int seq = 0;
|
||||
int send_size;
|
||||
while(!exit_flag) {
|
||||
switch(seq) {
|
||||
case 0:
|
||||
m_retry = 0;
|
||||
seq++;
|
||||
break;
|
||||
case 1:
|
||||
send_size = discover();
|
||||
m_udp->sendTo(m_server, (char*)m_buf, send_size);
|
||||
m_interval.reset();
|
||||
m_interval.start();
|
||||
seq++;
|
||||
break;
|
||||
case 2:
|
||||
callback();
|
||||
if (m_interval.read_ms() > interval_ms) {
|
||||
DBG("m_retry: %d\n", m_retry);
|
||||
if (++m_retry >= (timeout_ms/interval_ms)) {
|
||||
err = -1;
|
||||
exit_flag = true;
|
||||
}
|
||||
seq--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms());
|
||||
delete m_udp;
|
||||
return err;
|
||||
}
|
||||
|
||||
DHCPClient::DHCPClient() {
|
||||
}
|
||||
|
||||
55
WIZnetInterface/DHCPClient/DHCPClient.h
Normal file
55
WIZnetInterface/DHCPClient/DHCPClient.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// DHCPClient.h 2013/4/10
|
||||
#ifndef DHCPCLIENT_H
|
||||
#define DHCPCLIENT_H
|
||||
#include "wiznet.h"
|
||||
#include "UDPSocket.h"
|
||||
|
||||
#define DHCP_OFFSET_OP 0
|
||||
#define DHCP_OFFSET_XID 4
|
||||
#define DHCP_OFFSET_YIADDR 16
|
||||
#define DHCP_OFFSET_SIADDR 20
|
||||
#define DHCP_OFFSET_OPTIONS 240
|
||||
#define DHCP_MAX_PACKET_SIZE 600
|
||||
|
||||
// DHCP Message Type
|
||||
#define DHCPDISCOVER 1
|
||||
#define DHCPOFFER 2
|
||||
#define DHCPREQUEST 3
|
||||
#define DHCPDECLINE 4
|
||||
#define DHCPACK 5
|
||||
#define DHCPNAK 6
|
||||
#define DHCPRELEASE 7
|
||||
#define DHCPINFORM 8
|
||||
|
||||
class DHCPClient {
|
||||
public:
|
||||
DHCPClient();
|
||||
int setup(int timeout_ms = 15*1000);
|
||||
uint8_t chaddr[6]; // MAC
|
||||
uint8_t yiaddr[4]; // IP
|
||||
uint8_t dnsaddr[4]; // DNS
|
||||
uint8_t gateway[4];
|
||||
uint8_t netmask[4];
|
||||
uint8_t siaddr[4];
|
||||
private:
|
||||
int discover();
|
||||
int request();
|
||||
int offer(uint8_t buf[], int size);
|
||||
void add_buf(uint8_t* buf, int len);
|
||||
void fill_buf(int len, uint8_t data = 0x00);
|
||||
void add_buf(uint8_t c);
|
||||
void add_option(uint8_t code, uint8_t* buf = NULL, int len = 0);
|
||||
bool verify(uint8_t buf[], int len);
|
||||
void callback();
|
||||
UDPSocket* m_udp;
|
||||
Endpoint m_server;
|
||||
uint8_t xid[4];
|
||||
bool exit_flag;
|
||||
Timer m_interval;
|
||||
int m_retry;
|
||||
uint8_t m_buf[DHCP_MAX_PACKET_SIZE];
|
||||
int m_pos;
|
||||
WIZnet_Chip* eth;
|
||||
};
|
||||
#endif //DHCPCLIENT_H
|
||||
|
||||
174
WIZnetInterface/DNSClient/DNSClient.cpp
Normal file
174
WIZnetInterface/DNSClient/DNSClient.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
// DNSClient.cpp 2013/8/27
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
#include "DNSClient.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "dnsname.h"
|
||||
#include "wiznet.h"
|
||||
|
||||
#define DBG_DNS 0
|
||||
|
||||
#if DBG_DNS
|
||||
#define DBG2(...) do{debug("[DNS]%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
|
||||
#else
|
||||
#define DBG2(...) while(0);
|
||||
#endif
|
||||
|
||||
DNSClient::DNSClient(const char* hostname) : m_state(MYNETDNS_START), m_udp(NULL) {
|
||||
m_hostname = hostname;
|
||||
}
|
||||
|
||||
DNSClient::DNSClient(Endpoint* pHost) : m_state(MYNETDNS_START), m_udp(NULL) {
|
||||
}
|
||||
|
||||
DNSClient::~DNSClient() {
|
||||
if (m_udp) {
|
||||
delete m_udp;
|
||||
}
|
||||
}
|
||||
|
||||
void DNSClient::callback()
|
||||
{
|
||||
uint8_t buf[512];
|
||||
Endpoint host;
|
||||
int len = m_udp->receiveFrom(host, (char*)buf, sizeof(buf));
|
||||
if (len < 0) {
|
||||
return;
|
||||
}
|
||||
if (memcmp(buf+0, m_id, 2) != 0) { //verify
|
||||
return;
|
||||
}
|
||||
int rcode = response(buf, len);
|
||||
if (rcode == 0) {
|
||||
m_state = MYNETDNS_OK;
|
||||
} else {
|
||||
m_state = MYNETDNS_NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
int DNSClient::response(uint8_t buf[], int size) {
|
||||
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
|
||||
ip = (buf[rdata_pos]<<24) | (buf[rdata_pos+1]<<16) | (buf[rdata_pos+2]<<8) | buf[rdata_pos+3];
|
||||
}
|
||||
#if DBG_DNS
|
||||
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
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
int DNSClient::query(uint8_t buf[], int size, const char* hostname) {
|
||||
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 = rand();
|
||||
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 DNSClient::resolve(const char* hostname) {
|
||||
if (m_udp == NULL) {
|
||||
m_udp = new UDPSocket;
|
||||
}
|
||||
m_udp->init();
|
||||
m_udp->set_blocking(false);
|
||||
Endpoint server;
|
||||
server.set_address("8.8.8.8", 53); // DNS
|
||||
m_udp->bind(rand()&0x7fff);
|
||||
uint8_t buf[256];
|
||||
int size = query(buf, sizeof(buf), hostname);
|
||||
#if DBG_DNS
|
||||
printf("hostname:[%s]\n", hostname);
|
||||
printHex(buf, size);
|
||||
#endif
|
||||
m_udp->sendTo(server, (char*)buf, size);
|
||||
m_interval.reset();
|
||||
m_interval.start();
|
||||
}
|
||||
|
||||
void DNSClient::poll() {
|
||||
#if DBG_DNS
|
||||
printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp);
|
||||
wait_ms(400);
|
||||
#endif
|
||||
switch(m_state) {
|
||||
case MYNETDNS_START:
|
||||
m_retry = 0;
|
||||
resolve(m_hostname);
|
||||
m_state = MYNETDNS_PROCESSING;
|
||||
break;
|
||||
case MYNETDNS_PROCESSING:
|
||||
break;
|
||||
case MYNETDNS_NOTFOUND:
|
||||
break;
|
||||
case MYNETDNS_ERROR:
|
||||
break;
|
||||
case MYNETDNS_OK:
|
||||
DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms());
|
||||
break;
|
||||
}
|
||||
if (m_interval.read_ms() > 1000) {
|
||||
m_interval.stop();
|
||||
DBG2("timeout m_retry=%d\n", m_retry);
|
||||
if (++m_retry >= 2) {
|
||||
m_state = MYNETDNS_ERROR;
|
||||
} else {
|
||||
resolve(m_hostname);
|
||||
m_state = MYNETDNS_PROCESSING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DNSClient::lookup(const char* hostname) {
|
||||
m_hostname = hostname;
|
||||
m_state = MYNETDNS_START;
|
||||
while(1) {
|
||||
poll();
|
||||
callback();
|
||||
if (m_state != MYNETDNS_PROCESSING) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return m_state == MYNETDNS_OK;
|
||||
}
|
||||
|
||||
35
WIZnetInterface/DNSClient/DNSClient.h
Normal file
35
WIZnetInterface/DNSClient/DNSClient.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// DNSClient.h 2013/4/5
|
||||
#pragma once
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
class DNSClient {
|
||||
public:
|
||||
DNSClient(const char* hostname = NULL);
|
||||
DNSClient(Endpoint* pHost);
|
||||
virtual ~DNSClient();
|
||||
bool lookup(const char* hostname = NULL);
|
||||
uint32_t ip;
|
||||
protected:
|
||||
void poll();
|
||||
void callback();
|
||||
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_interval;
|
||||
int m_retry;
|
||||
const char* m_hostname;
|
||||
private:
|
||||
enum MyNetDnsState
|
||||
{
|
||||
MYNETDNS_START,
|
||||
MYNETDNS_PROCESSING, //Req has not completed
|
||||
MYNETDNS_NOTFOUND,
|
||||
MYNETDNS_ERROR,
|
||||
MYNETDNS_OK
|
||||
};
|
||||
MyNetDnsState m_state;
|
||||
UDPSocket *m_udp;
|
||||
};
|
||||
|
||||
52
WIZnetInterface/DNSClient/dnsname.h
Normal file
52
WIZnetInterface/DNSClient/dnsname.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// dnsname.h 2013/8/27
|
||||
#pragma once
|
||||
//#include <string>
|
||||
#include "pico_string.h"
|
||||
class dnsname {
|
||||
public:
|
||||
uint8_t *buf;
|
||||
pico_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;
|
||||
}
|
||||
};
|
||||
|
||||
54
WIZnetInterface/Socket/Endpoint.cpp
Normal file
54
WIZnetInterface/Socket/Endpoint.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "Socket.h"
|
||||
#include "Endpoint.h"
|
||||
|
||||
Endpoint::Endpoint() {
|
||||
reset_address();
|
||||
}
|
||||
Endpoint::~Endpoint() {}
|
||||
|
||||
void Endpoint::reset_address(void) {
|
||||
_ipAddress[0] = '\0';
|
||||
_port = 0;
|
||||
}
|
||||
|
||||
int Endpoint::set_address(const char* host, const int port) {
|
||||
//Resolve DNS address or populate hard-coded IP address
|
||||
WIZnet_Chip* eth = WIZnet_Chip::getInstance();
|
||||
if (eth == NULL) {
|
||||
error("Endpoint constructor error: no WIZnet chip instance available!\r\n");
|
||||
return -1;
|
||||
}
|
||||
uint32_t addr;
|
||||
if (!eth->gethostbyname(host, &addr)) {
|
||||
return -1;
|
||||
}
|
||||
snprintf(_ipAddress, sizeof(_ipAddress), "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff);
|
||||
_port = port;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* Endpoint::get_address() {
|
||||
return _ipAddress;
|
||||
}
|
||||
|
||||
int Endpoint::get_port() {
|
||||
return _port;
|
||||
}
|
||||
|
||||
65
WIZnetInterface/Socket/Endpoint.h
Normal file
65
WIZnetInterface/Socket/Endpoint.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ENDPOINT_H
|
||||
#define ENDPOINT_H
|
||||
|
||||
#include "wiznet.h"
|
||||
|
||||
class UDPSocket;
|
||||
|
||||
/**
|
||||
IP Endpoint (address, port)
|
||||
*/
|
||||
class Endpoint {
|
||||
friend class UDPSocket;
|
||||
|
||||
public:
|
||||
/** IP Endpoint (address, port)
|
||||
*/
|
||||
Endpoint(void);
|
||||
|
||||
~Endpoint(void);
|
||||
|
||||
/** Reset the address of this endpoint
|
||||
*/
|
||||
void reset_address(void);
|
||||
|
||||
/** Set the address of this endpoint
|
||||
\param host The endpoint address (it can either be an IP Address or a hostname that will be resolved with DNS).
|
||||
\param port The endpoint port
|
||||
\return 0 on success, -1 on failure (when an hostname cannot be resolved by DNS).
|
||||
*/
|
||||
int set_address(const char* host, const int port);
|
||||
|
||||
/** Get the IP address of this endpoint
|
||||
\return The IP address of this endpoint.
|
||||
*/
|
||||
char* get_address(void);
|
||||
|
||||
/** Get the port of this endpoint
|
||||
\return The port of this endpoint
|
||||
*/
|
||||
int get_port(void);
|
||||
|
||||
protected:
|
||||
char _ipAddress[16];
|
||||
int _port;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
49
WIZnetInterface/Socket/Socket.cpp
Normal file
49
WIZnetInterface/Socket/Socket.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Socket.h"
|
||||
|
||||
Socket::Socket() : _sock_fd(-1),_blocking(true), _timeout(1500)
|
||||
{
|
||||
eth = WIZnet_Chip::getInstance();
|
||||
if (eth == NULL) {
|
||||
error("Socket constructor error: no W5500 instance available!\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Socket::set_blocking(bool blocking, unsigned int timeout)
|
||||
{
|
||||
_blocking = blocking;
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
int Socket::close()
|
||||
{
|
||||
// add this code refer from EthernetInterface.
|
||||
// update by Patrick Pollet
|
||||
int res;
|
||||
res = eth->close(_sock_fd);
|
||||
_sock_fd = -1;
|
||||
return (res)? 0: -1;
|
||||
}
|
||||
|
||||
Socket::~Socket()
|
||||
{
|
||||
close(); //Don't want to leak
|
||||
}
|
||||
|
||||
59
WIZnetInterface/Socket/Socket.h
Normal file
59
WIZnetInterface/Socket/Socket.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SOCKET_H_
|
||||
#define SOCKET_H_
|
||||
|
||||
#include "wiznet.h"
|
||||
|
||||
#define htons(x) __REV16(x)
|
||||
#define ntohs(x) __REV16(x)
|
||||
#define htonl(x) __REV(x)
|
||||
#define ntohl(x) __REV(x)
|
||||
|
||||
/** Socket file descriptor and select wrapper
|
||||
*/
|
||||
class Socket {
|
||||
public:
|
||||
/** Socket
|
||||
*/
|
||||
Socket();
|
||||
|
||||
/** Set blocking or non-blocking mode of the socket and a timeout on
|
||||
blocking socket operations
|
||||
\param blocking true for blocking mode, false for non-blocking mode.
|
||||
\param timeout timeout in ms [Default: (1500)ms].
|
||||
*/
|
||||
void set_blocking(bool blocking, unsigned int timeout=1500);
|
||||
|
||||
/** Close the socket file descriptor
|
||||
*/
|
||||
int close();
|
||||
|
||||
~Socket();
|
||||
|
||||
protected:
|
||||
int _sock_fd;
|
||||
bool _blocking;
|
||||
int _timeout;
|
||||
|
||||
WIZnet_Chip* eth;
|
||||
};
|
||||
|
||||
|
||||
#endif /* SOCKET_H_ */
|
||||
|
||||
139
WIZnetInterface/Socket/TCPSocketConnection.cpp
Normal file
139
WIZnetInterface/Socket/TCPSocketConnection.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "TCPSocketConnection.h"
|
||||
#include <cstring>
|
||||
|
||||
using std::memset;
|
||||
using std::memcpy;
|
||||
|
||||
// not a big code.
|
||||
// refer from EthernetInterface by mbed official driver
|
||||
TCPSocketConnection::TCPSocketConnection() :
|
||||
_is_connected(false)
|
||||
{
|
||||
}
|
||||
|
||||
int TCPSocketConnection::connect(const char* host, const int port)
|
||||
{
|
||||
if (_sock_fd < 0) {
|
||||
_sock_fd = eth->new_socket();
|
||||
if (_sock_fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (set_address(host, port) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (!eth->connect(_sock_fd, get_address(), port)) {
|
||||
return -1;
|
||||
}
|
||||
set_blocking(false);
|
||||
// add code refer from EthernetInterface.
|
||||
_is_connected = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TCPSocketConnection::is_connected(void)
|
||||
{
|
||||
// force update recent state.
|
||||
_is_connected = eth->is_connected(_sock_fd);
|
||||
return _is_connected;
|
||||
}
|
||||
|
||||
|
||||
bool TCPSocketConnection::is_fin_received(void)
|
||||
{
|
||||
return eth->is_fin_received(_sock_fd);
|
||||
}
|
||||
|
||||
int TCPSocketConnection::send(char* data, int length)
|
||||
{
|
||||
// add to cover exception.
|
||||
if ((_sock_fd < 0) || !_is_connected)
|
||||
return -1;
|
||||
|
||||
int size = eth->wait_writeable(_sock_fd, _blocking ? -1 : _timeout);
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (size > length) {
|
||||
size = length;
|
||||
}
|
||||
return eth->send(_sock_fd, data, size);
|
||||
}
|
||||
|
||||
// -1 if unsuccessful, else number of bytes written
|
||||
int TCPSocketConnection::send_all(char* data, int length)
|
||||
{
|
||||
|
||||
int writtenLen = 0;
|
||||
while (writtenLen < length) {
|
||||
int size = eth->wait_writeable(_sock_fd, _blocking ? -1 : _timeout);
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (size > (length-writtenLen)) {
|
||||
size = (length-writtenLen);
|
||||
}
|
||||
int ret = eth->send(_sock_fd, data + writtenLen, size);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
writtenLen += ret;
|
||||
}
|
||||
return writtenLen;
|
||||
}
|
||||
|
||||
// -1 if unsuccessful, else number of bytes received
|
||||
int TCPSocketConnection::receive(char* data, int length)
|
||||
{
|
||||
// add to cover exception.
|
||||
if ((_sock_fd < 0) || !_is_connected)
|
||||
return -1;
|
||||
|
||||
int size = eth->wait_readable(_sock_fd, _blocking ? -1 : _timeout);
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (size > length) {
|
||||
size = length;
|
||||
}
|
||||
return eth->recv(_sock_fd, data, size);
|
||||
}
|
||||
|
||||
// -1 if unsuccessful, else number of bytes received
|
||||
int TCPSocketConnection::receive_all(char* data, int length)
|
||||
{
|
||||
int readLen = 0;
|
||||
while (readLen < length) {
|
||||
int size = eth->wait_readable(_sock_fd, _blocking ? -1 :_timeout);
|
||||
if (size <= 0) {
|
||||
break;
|
||||
}
|
||||
if (size > (length - readLen)) {
|
||||
size = length - readLen;
|
||||
}
|
||||
int ret = eth->recv(_sock_fd, data + readLen, size);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
readLen += ret;
|
||||
}
|
||||
return readLen;
|
||||
}
|
||||
|
||||
85
WIZnetInterface/Socket/TCPSocketConnection.h
Normal file
85
WIZnetInterface/Socket/TCPSocketConnection.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TCPSOCKET_H
|
||||
#define TCPSOCKET_H
|
||||
|
||||
#include "Socket.h"
|
||||
#include "Endpoint.h"
|
||||
|
||||
/**
|
||||
TCP socket connection
|
||||
*/
|
||||
class TCPSocketConnection: public Socket, public Endpoint {
|
||||
friend class TCPSocketServer;
|
||||
|
||||
public:
|
||||
/** TCP socket connection
|
||||
*/
|
||||
TCPSocketConnection();
|
||||
|
||||
/** Connects this TCP socket to the server
|
||||
\param host The host to connect to. It can either be an IP Address or a hostname that will be resolved with DNS.
|
||||
\param port The host's port to connect to.
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
int connect(const char* host, const int port);
|
||||
|
||||
/** Check if the socket is connected
|
||||
\return true if connected, false otherwise.
|
||||
*/
|
||||
bool is_connected(void);
|
||||
|
||||
/** Check if FIN signal received.
|
||||
\return true if received, false otherwise.
|
||||
*/
|
||||
bool is_fin_received(void);
|
||||
/** Send data to the remote host.
|
||||
\param data The buffer to send to the host.
|
||||
\param length The length of the buffer to send.
|
||||
\return the number of written bytes on success (>=0) or -1 on failure
|
||||
*/
|
||||
int send(char* data, int length);
|
||||
|
||||
/** Send all the data to the remote host.
|
||||
\param data The buffer to send to the host.
|
||||
\param length The length of the buffer to send.
|
||||
\return the number of written bytes on success (>=0) or -1 on failure
|
||||
*/
|
||||
int send_all(char* data, int length);
|
||||
|
||||
/** Receive data from the remote host.
|
||||
\param data The buffer in which to store the data received from the host.
|
||||
\param length The maximum length of the buffer.
|
||||
\return the number of received bytes on success (>=0) or -1 on failure
|
||||
*/
|
||||
int receive(char* data, int length);
|
||||
|
||||
/** Receive all the data from the remote host.
|
||||
\param data The buffer in which to store the data received from the host.
|
||||
\param length The maximum length of the buffer.
|
||||
\return the number of received bytes on success (>=0) or -1 on failure
|
||||
*/
|
||||
int receive_all(char* data, int length);
|
||||
|
||||
private:
|
||||
bool _is_connected;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
99
WIZnetInterface/Socket/TCPSocketServer.cpp
Normal file
99
WIZnetInterface/Socket/TCPSocketServer.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "TCPSocketServer.h"
|
||||
|
||||
TCPSocketServer::TCPSocketServer() {}
|
||||
|
||||
// Server initialization
|
||||
int TCPSocketServer::bind(int port)
|
||||
{
|
||||
|
||||
if (_sock_fd < 0) {
|
||||
_sock_fd = eth->new_socket();
|
||||
if (_sock_fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// set the listen_port for next connection.
|
||||
listen_port = port;
|
||||
// set TCP protocol
|
||||
eth->setProtocol(_sock_fd, TCP);
|
||||
// set local port
|
||||
eth->sreg<uint16_t>(_sock_fd, Sn_PORT, port);
|
||||
// connect the network
|
||||
eth->scmd(_sock_fd, OPEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TCPSocketServer::listen(int backlog)
|
||||
{
|
||||
if (_sock_fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (backlog != 1) {
|
||||
return -1;
|
||||
}
|
||||
eth->scmd(_sock_fd, LISTEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int TCPSocketServer::accept(TCPSocketConnection& connection)
|
||||
{
|
||||
if (_sock_fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(1) {
|
||||
if (t.read_ms() > _timeout && _blocking == false) {
|
||||
return -1;
|
||||
}
|
||||
if (eth->sreg<uint8_t>(_sock_fd, Sn_SR) == SOCK_ESTABLISHED) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint32_t ip = eth->sreg<uint32_t>(_sock_fd, Sn_DIPR);
|
||||
char host[16];
|
||||
snprintf(host, sizeof(host), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
|
||||
uint16_t port = eth->sreg<uint16_t>(_sock_fd, Sn_DPORT);
|
||||
// change this server socket to connection socket.
|
||||
connection._sock_fd = _sock_fd;
|
||||
connection._is_connected = true;
|
||||
connection.set_address(host, port);
|
||||
|
||||
// and then, for the next connection, server socket should be assigned new one.
|
||||
_sock_fd = -1; // want to assign new available _sock_fd.
|
||||
if(bind(listen_port) < 0) {
|
||||
// modified by Patrick Pollet
|
||||
error("No more socket for listening, bind error");
|
||||
return -1;
|
||||
} else {
|
||||
//return -1;
|
||||
if(listen(1) < 0) {
|
||||
// modified by Patrick Pollet
|
||||
error("No more socket for listening, listen error");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
57
WIZnetInterface/Socket/TCPSocketServer.h
Normal file
57
WIZnetInterface/Socket/TCPSocketServer.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TCPSOCKETSERVER_H
|
||||
#define TCPSOCKETSERVER_H
|
||||
|
||||
#include "Socket.h"
|
||||
#include "TCPSocketConnection.h"
|
||||
|
||||
/** TCP Server.
|
||||
*/
|
||||
class TCPSocketServer : public Socket
|
||||
{
|
||||
public:
|
||||
/** Instantiate a TCP Server.
|
||||
*/
|
||||
TCPSocketServer();
|
||||
|
||||
/** Bind a socket to a specific port.
|
||||
\param port The port to listen for incoming connections on.
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
int bind(int port);
|
||||
|
||||
/** Start listening for incoming connections.
|
||||
\param backlog number of pending connections that can be queued up at any
|
||||
one time [Default: 1].
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
int listen(int backlog=1);
|
||||
|
||||
/** Accept a new connection.
|
||||
\param connection A TCPSocketConnection instance that will handle the incoming connection.
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
int accept(TCPSocketConnection& connection);
|
||||
|
||||
private :
|
||||
int listen_port;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
112
WIZnetInterface/Socket/UDPSocket.cpp
Normal file
112
WIZnetInterface/Socket/UDPSocket.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
static int udp_local_port;
|
||||
|
||||
UDPSocket::UDPSocket()
|
||||
{
|
||||
}
|
||||
|
||||
// After init function, bind() should be called.
|
||||
int UDPSocket::init(void)
|
||||
{
|
||||
if (_sock_fd < 0) {
|
||||
_sock_fd = eth->new_socket();
|
||||
}
|
||||
if (eth->setProtocol(_sock_fd, UDP) == false) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Server initialization
|
||||
int UDPSocket::bind(int port)
|
||||
{
|
||||
if (_sock_fd < 0) {
|
||||
_sock_fd = eth->new_socket();
|
||||
if (_sock_fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// set local port
|
||||
if (port != 0) {
|
||||
eth->sreg<uint16_t>(_sock_fd, Sn_PORT, port);
|
||||
} else {
|
||||
udp_local_port++;
|
||||
eth->sreg<uint16_t>(_sock_fd, Sn_PORT, udp_local_port);
|
||||
}
|
||||
// set udp protocol
|
||||
eth->setProtocol(_sock_fd, UDP);
|
||||
eth->scmd(_sock_fd, OPEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -1 if unsuccessful, else number of bytes written
|
||||
int UDPSocket::sendTo(Endpoint &remote, char *packet, int length)
|
||||
{
|
||||
int size = eth->wait_writeable(_sock_fd, _blocking ? -1 : _timeout, length-1);
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
}
|
||||
confEndpoint(remote);
|
||||
int ret = eth->send(_sock_fd, packet, length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -1 if unsuccessful, else number of bytes received
|
||||
int UDPSocket::receiveFrom(Endpoint &remote, char *buffer, int length)
|
||||
{
|
||||
uint8_t info[8];
|
||||
int size = eth->wait_readable(_sock_fd, _blocking ? -1 : _timeout, sizeof(info));
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
}
|
||||
eth->recv(_sock_fd, (char*)info, sizeof(info));
|
||||
readEndpoint(remote, info);
|
||||
int udp_size = info[6]<<8|info[7];
|
||||
//TEST_ASSERT(udp_size <= (size-sizeof(info)));
|
||||
if (udp_size > (size-sizeof(info))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Perform Length check here to prevent buffer overrun */
|
||||
/* fixed by Sean Newton (https://developer.mbed.org/users/SeanNewton/) */
|
||||
if (udp_size > length) {
|
||||
//printf("udp_size: %d\n",udp_size);
|
||||
return -1;
|
||||
}
|
||||
return eth->recv(_sock_fd, buffer, udp_size);
|
||||
}
|
||||
|
||||
void UDPSocket::confEndpoint(Endpoint & ep)
|
||||
{
|
||||
char * host = ep.get_address();
|
||||
// set remote host
|
||||
eth->sreg_ip(_sock_fd, Sn_DIPR, host);
|
||||
// set remote port
|
||||
eth->sreg<uint16_t>(_sock_fd, Sn_DPORT, ep.get_port());
|
||||
}
|
||||
|
||||
void UDPSocket::readEndpoint(Endpoint & ep, uint8_t info[])
|
||||
{
|
||||
char addr[17];
|
||||
snprintf(addr, sizeof(addr), "%d.%d.%d.%d", info[0], info[1], info[2], info[3]);
|
||||
uint16_t port = info[4]<<8|info[5];
|
||||
ep.set_address(addr, port);
|
||||
}
|
||||
|
||||
69
WIZnetInterface/Socket/UDPSocket.h
Normal file
69
WIZnetInterface/Socket/UDPSocket.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UDPSOCKET_H
|
||||
#define UDPSOCKET_H
|
||||
|
||||
#include "Endpoint.h"
|
||||
#include "Socket.h"
|
||||
|
||||
/**
|
||||
UDP Socket
|
||||
*/
|
||||
class UDPSocket: public Socket {
|
||||
|
||||
public:
|
||||
/** Instantiate an UDP Socket.
|
||||
*/
|
||||
UDPSocket();
|
||||
|
||||
/** Init the UDP Client Socket without binding it to any specific port
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
int init(void);
|
||||
|
||||
/** Bind a UDP Server Socket to a specific port
|
||||
\param port The port to listen for incoming connections on
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
int bind(int port = -1);
|
||||
|
||||
/** Send a packet to a remote endpoint
|
||||
\param remote The remote endpoint
|
||||
\param packet The packet to be sent
|
||||
\param length The length of the packet to be sent
|
||||
\return the number of written bytes on success (>=0) or -1 on failure
|
||||
*/
|
||||
int sendTo(Endpoint &remote, char *packet, int length);
|
||||
|
||||
/** Receive a packet from a remote endpoint
|
||||
\param remote The remote endpoint
|
||||
\param buffer The buffer for storing the incoming packet data. If a packet
|
||||
is too long to fit in the supplied buffer, excess bytes are discarded
|
||||
\param length The length of the buffer
|
||||
\return the number of received bytes on success (>=0) or -1 on failure
|
||||
*/
|
||||
int receiveFrom(Endpoint &remote, char *buffer, int length);
|
||||
|
||||
private:
|
||||
void confEndpoint(Endpoint & ep);
|
||||
void readEndpoint(Endpoint & ep, uint8_t info[]);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
403
WIZnetInterface/WIZnet/W5100.cpp
Normal file
403
WIZnetInterface/WIZnet/W5100.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <mbed.h>
|
||||
#include "mbed_debug.h"
|
||||
#include "wiznet.h"
|
||||
#include "DNSClient.h"
|
||||
|
||||
#ifdef USE_W5100
|
||||
|
||||
//Debug is disabled by default
|
||||
#if 0
|
||||
#define DBG(...) do{debug("%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
|
||||
//#define DBG(x, ...) debug("[WIZnet_Chip:DBG]"x"\r\n", ##__VA_ARGS__);
|
||||
#define WARN(x, ...) debug("[WIZnet_Chip:WARN]"x"\r\n", ##__VA_ARGS__);
|
||||
#define ERR(x, ...) debug("[WIZnet_Chip:ERR]"x"\r\n", ##__VA_ARGS__);
|
||||
#else
|
||||
#define DBG(x, ...)
|
||||
#define WARN(x, ...)
|
||||
#define ERR(x, ...)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define INFO(x, ...) debug("[WIZnet_Chip:INFO]"x"\r\n", ##__VA_ARGS__);
|
||||
#else
|
||||
#define INFO(x, ...)
|
||||
#endif
|
||||
|
||||
#define DBG_SPI 0
|
||||
|
||||
WIZnet_Chip* WIZnet_Chip::inst;
|
||||
|
||||
WIZnet_Chip::WIZnet_Chip(PinName mosi, PinName miso, PinName sclk, PinName _cs, PinName _reset):
|
||||
cs(_cs), reset_pin(_reset)
|
||||
{
|
||||
spi = new SPI(mosi, miso, sclk);
|
||||
|
||||
spi->format(8,0);
|
||||
spi->frequency(2000000);
|
||||
|
||||
cs = 1;
|
||||
reset_pin = 1;
|
||||
|
||||
inst = this;
|
||||
}
|
||||
|
||||
WIZnet_Chip::WIZnet_Chip(SPI* spi, PinName _cs, PinName _reset):
|
||||
cs(_cs), reset_pin(_reset)
|
||||
{
|
||||
this->spi = spi;
|
||||
|
||||
this->spi->format(8,0);
|
||||
this->spi->frequency(2000000);
|
||||
|
||||
cs = 1;
|
||||
reset_pin = 1;
|
||||
|
||||
inst = this;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::setip()
|
||||
{
|
||||
reg_wr<uint32_t>(SIPR, ip);
|
||||
reg_wr<uint32_t>(GAR, gateway);
|
||||
reg_wr<uint32_t>(SUBR, netmask);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::setProtocol(int socket, Protocol p)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
sreg<uint8_t>(socket, Sn_MR, p);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::connect(int socket, const char * host, int port, int timeout_ms)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
sreg<uint8_t>(socket, Sn_MR, TCP);
|
||||
scmd(socket, OPEN);
|
||||
sreg_ip(socket, Sn_DIPR, host);
|
||||
sreg<uint16_t>(socket, Sn_DPORT, port);
|
||||
sreg<uint16_t>(socket, Sn_PORT, new_port());
|
||||
scmd(socket, eCONNECT);
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(!is_connected(socket)) {
|
||||
if (t.read_ms() > timeout_ms) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::gethostbyname(const char* host, uint32_t* ip)
|
||||
{
|
||||
uint32_t addr = str_to_ip(host);
|
||||
char buf[17];
|
||||
snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff);
|
||||
if (strcmp(buf, host) == 0) {
|
||||
*ip = addr;
|
||||
return true;
|
||||
}
|
||||
DNSClient client;
|
||||
if(client.lookup(host)) {
|
||||
*ip = client.ip;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::disconnect()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::is_connected(int socket)
|
||||
{
|
||||
if (sreg<uint8_t>(socket, Sn_SR) == SOCK_ESTABLISHED) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool WIZnet_Chip::is_fin_received(int socket)
|
||||
{
|
||||
uint8_t tmpSn_SR;
|
||||
tmpSn_SR = sreg<uint8_t>(socket, Sn_SR);
|
||||
// packet sending is possible, when state is SOCK_CLOSE_WAIT.
|
||||
if (tmpSn_SR == SOCK_CLOSE_WAIT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WIZnet_Chip::reset()
|
||||
{
|
||||
reset_pin = 1;
|
||||
reset_pin = 0;
|
||||
wait_us(2); // 2us
|
||||
reset_pin = 1;
|
||||
wait_ms(150); // 150ms
|
||||
|
||||
reg_wr<uint8_t>(MR, 1<<7);
|
||||
reg_wr_mac(SHAR, mac);
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::close(int socket)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
// if not connected, return
|
||||
if (sreg<uint8_t>(socket, Sn_SR) == SOCK_CLOSED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
scmd(socket, CLOSE);
|
||||
sreg<uint8_t>(socket, Sn_IR, 0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::wait_readable(int socket, int wait_time_ms, int req_size)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(1) {
|
||||
int size = 0; int size1 = 0;
|
||||
do {
|
||||
size = sreg<uint16_t>(socket, Sn_RX_RSR);
|
||||
if (size != 0) size1 = sreg<uint16_t>(socket, Sn_RX_RSR);
|
||||
}while(size != size1);
|
||||
|
||||
if (size > req_size) {
|
||||
return size;
|
||||
}
|
||||
if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::wait_writeable(int socket, int wait_time_ms, int req_size)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(1) {
|
||||
//int size = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
// during the reading Sn_TX_FSR, it has the possible change of this register.
|
||||
// so read twice and get same value then use size information.
|
||||
int size, size2;
|
||||
do {
|
||||
size = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
size2 = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
} while (size != size2);
|
||||
if (size > req_size) {
|
||||
return size;
|
||||
}
|
||||
if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::send(int socket, const char * str, int len)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
uint16_t base = 0x4000 + socket * 0x800; // each socket has 2K buffer
|
||||
uint16_t ptr = sreg<uint16_t>(socket, Sn_TX_WR);
|
||||
uint16_t dst = base + (ptr&(0x800-1));
|
||||
if ((dst + len) > (base+0x800)) {
|
||||
int len2 = base + 0x800 - dst;
|
||||
spi_write(dst, (uint8_t*)str, len2);
|
||||
spi_write(base, (uint8_t*)str+len2, len-len2);
|
||||
} else {
|
||||
spi_write(dst, (uint8_t*)str, len);
|
||||
}
|
||||
sreg<uint16_t>(socket, Sn_TX_WR, ptr + len);
|
||||
scmd(socket, SEND);
|
||||
return len;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::recv(int socket, char* buf, int len)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
uint16_t base = 0x6000 + socket * 0x800; // each socket has 2K buffer
|
||||
uint16_t ptr = sreg<uint16_t>(socket, Sn_RX_RD);
|
||||
uint16_t src = base + (ptr&(0x800-1));
|
||||
if ((src + len) > (base+0x800)) {
|
||||
int len2 = base + 0x800 - src;
|
||||
spi_read(src, (uint8_t*)buf, len2);
|
||||
spi_read(base, (uint8_t*)buf+len2, len-len2);
|
||||
} else {
|
||||
spi_read(src, (uint8_t*)buf, len);
|
||||
}
|
||||
sreg<uint16_t>(socket, Sn_RX_RD, ptr + len);
|
||||
scmd(socket, RECV);
|
||||
return len;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::new_socket()
|
||||
{
|
||||
for(int s = 0; s < MAX_SOCK_NUM; s++) {
|
||||
if (sreg<uint8_t>(s, Sn_SR) == SOCK_CLOSED) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t WIZnet_Chip::new_port()
|
||||
{
|
||||
uint16_t port = rand();
|
||||
port |= 49152;
|
||||
return port;
|
||||
}
|
||||
|
||||
void WIZnet_Chip::scmd(int socket, Command cmd)
|
||||
{
|
||||
sreg<uint8_t>(socket, Sn_CR, cmd);
|
||||
while(sreg<uint8_t>(socket, Sn_CR));
|
||||
}
|
||||
|
||||
void WIZnet_Chip::spi_write(uint16_t addr, const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
cs = 0;
|
||||
spi->write(0xf0);
|
||||
spi->write(addr >> 8);
|
||||
spi->write(addr & 0xff);
|
||||
addr++;
|
||||
spi->write(buf[i]);
|
||||
cs = 1;
|
||||
}
|
||||
#if DBG_SPI
|
||||
debug("[SPI]W %04x(%d)", addr, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
debug(" %02x", buf[i]);
|
||||
if (i > 16) {
|
||||
debug(" ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void WIZnet_Chip::spi_read(uint16_t addr, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
cs = 0;
|
||||
spi->write(0x0f);
|
||||
spi->write(addr >> 8);
|
||||
spi->write(addr & 0xff);
|
||||
addr++;
|
||||
buf[i] = spi->write(0);
|
||||
cs = 1;
|
||||
}
|
||||
#if DBG_SPI
|
||||
debug("[SPI]R %04x(%d)", addr, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
debug(" %02x", buf[i]);
|
||||
if (i > 16) {
|
||||
debug(" ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("\r\n");
|
||||
if ((addr&0xf0ff)==0x4026 || (addr&0xf0ff)==0x4003) {
|
||||
wait_ms(200);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t str_to_ip(const char* str)
|
||||
{
|
||||
uint32_t ip = 0;
|
||||
char* p = (char*)str;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
ip |= atoi(p);
|
||||
p = strchr(p, '.');
|
||||
if (p == NULL) {
|
||||
break;
|
||||
}
|
||||
ip <<= 8;
|
||||
p++;
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
void printfBytes(char* str, uint8_t* buf, int len)
|
||||
{
|
||||
printf("%s %d:", str, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
printf(" %02x", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void printHex(uint8_t* buf, int len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
if ((i%16) == 0) {
|
||||
printf("%p", buf+i);
|
||||
}
|
||||
printf(" %02x", buf[i]);
|
||||
if ((i%16) == 15) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void debug_hex(uint8_t* buf, int len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
if ((i%16) == 0) {
|
||||
debug("%p", buf+i);
|
||||
}
|
||||
debug(" %02x", buf[i]);
|
||||
if ((i%16) == 15) {
|
||||
debug("\n");
|
||||
}
|
||||
}
|
||||
debug("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
269
WIZnetInterface/WIZnet/W5100.h
Normal file
269
WIZnetInterface/WIZnet/W5100.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
|
||||
#define TEST_ASSERT(A) while(!(A)){debug("\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
|
||||
|
||||
#define DEFAULT_WAIT_RESP_TIMEOUT 500
|
||||
|
||||
enum Protocol {
|
||||
CLOSED = 0,
|
||||
TCP = 1,
|
||||
UDP = 2,
|
||||
};
|
||||
|
||||
enum Command {
|
||||
OPEN = 0x01,
|
||||
LISTEN = 0x02,
|
||||
eCONNECT = 0x04,
|
||||
DISCON = 0x08,
|
||||
CLOSE = 0x10,
|
||||
SEND = 0x20,
|
||||
SEND_MAC = 0x21,
|
||||
SEND_KEEP = 0x22,
|
||||
RECV = 0x40,
|
||||
|
||||
};
|
||||
|
||||
enum Interrupt {
|
||||
INT_CON = 0x01,
|
||||
INT_DISCON = 0x02,
|
||||
INT_RECV = 0x04,
|
||||
INT_TIMEOUT = 0x08,
|
||||
INT_SEND_OK = 0x10,
|
||||
};
|
||||
|
||||
enum Status {
|
||||
SOCK_CLOSED = 0x00,
|
||||
SOCK_INIT = 0x13,
|
||||
SOCK_LISTEN = 0x14,
|
||||
SOCK_ESTABLISHED = 0x17,
|
||||
SOCK_CLOSE_WAIT = 0x1c,
|
||||
SOCK_UDP = 0x22,
|
||||
};
|
||||
|
||||
#define MAX_SOCK_NUM 4
|
||||
|
||||
#define MR 0x0000
|
||||
#define GAR 0x0001
|
||||
#define SUBR 0x0005
|
||||
#define SHAR 0x0009
|
||||
#define SIPR 0x000f
|
||||
|
||||
// W5100 socket
|
||||
#define Sn_MR 0x0400
|
||||
#define Sn_CR 0x0401
|
||||
#define Sn_IR 0x0402
|
||||
#define Sn_SR 0x0403
|
||||
#define Sn_PORT 0x0404
|
||||
#define Sn_DIPR 0x040c
|
||||
#define Sn_DPORT 0x0410
|
||||
//#define Sn_RXBUF_SIZE 0x401e
|
||||
//#define Sn_TXBUF_SIZE 0x401f
|
||||
#define Sn_TX_FSR 0x0420
|
||||
#define Sn_TX_WR 0x0424
|
||||
#define Sn_RX_RSR 0x0426
|
||||
#define Sn_RX_RD 0x0428
|
||||
|
||||
class WIZnet_Chip {
|
||||
public:
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
* @param spi spi class
|
||||
* @param cs cs of the W5200
|
||||
* @param reset reset pin of the W5200
|
||||
*/
|
||||
WIZnet_Chip(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset);
|
||||
WIZnet_Chip(SPI* spi, PinName cs, PinName reset);
|
||||
|
||||
/*
|
||||
* Connect the W5200 module to the ssid contained in the constructor.
|
||||
*
|
||||
* @return true if connected, false otherwise
|
||||
*/
|
||||
bool setip();
|
||||
|
||||
/*
|
||||
* Disconnect the W5200 module from the access point
|
||||
*
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool disconnect();
|
||||
|
||||
/*
|
||||
* Open a tcp connection with the specified host on the specified port
|
||||
*
|
||||
* @param host host (can be either an ip address or a name. If a name is provided, a dns request will be established)
|
||||
* @param port port
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool connect(int socket, const char * host, int port, int timeout_ms = 10*1000);
|
||||
|
||||
/*
|
||||
* Set the protocol (UDP or TCP)
|
||||
*
|
||||
* @param p protocol
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool setProtocol(int socket, Protocol p);
|
||||
|
||||
/*
|
||||
* Reset the W5100 module
|
||||
*/
|
||||
void reset();
|
||||
|
||||
|
||||
int wait_readable(int socket, int wait_time_ms, int req_size = 0);
|
||||
|
||||
int wait_writeable(int socket, int wait_time_ms, int req_size = 0);
|
||||
|
||||
/*
|
||||
* Check if a tcp link is active
|
||||
*
|
||||
* @returns true if successful
|
||||
*/
|
||||
bool is_connected(int socket);
|
||||
|
||||
/*
|
||||
* Check if FIN received.
|
||||
*
|
||||
* @returns true if successful
|
||||
*/
|
||||
bool is_fin_received(int socket);
|
||||
|
||||
/*
|
||||
* Close a tcp connection
|
||||
*
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool close(int socket);
|
||||
|
||||
/*
|
||||
* @param str string to be sent
|
||||
* @param len string length
|
||||
*/
|
||||
int send(int socket, const char * str, int len);
|
||||
|
||||
int recv(int socket, char* buf, int len);
|
||||
|
||||
/*
|
||||
* Return true if the module is using dhcp
|
||||
*
|
||||
* @returns true if the module is using dhcp
|
||||
*/
|
||||
bool isDHCP() {
|
||||
return dhcp;
|
||||
}
|
||||
|
||||
bool gethostbyname(const char* host, uint32_t* ip);
|
||||
|
||||
static WIZnet_Chip * getInstance() {
|
||||
return inst;
|
||||
};
|
||||
|
||||
int new_socket();
|
||||
uint16_t new_port();
|
||||
void scmd(int socket, Command cmd);
|
||||
|
||||
template<typename T>
|
||||
void sreg(int socket, uint16_t addr, T data) {
|
||||
reg_wr<T>(addr+0x100*socket, data);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T sreg(int socket, uint16_t addr) {
|
||||
return reg_rd<T>(addr+0x100*socket);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void reg_wr(uint16_t addr, T data) {
|
||||
uint8_t buf[sizeof(T)];
|
||||
*reinterpret_cast<T*>(buf) = data;
|
||||
for(int i = 0; i < sizeof(buf)/2; i++) { // Little Endian to Big Endian
|
||||
uint8_t t = buf[i];
|
||||
buf[i] = buf[sizeof(buf)-1-i];
|
||||
buf[sizeof(buf)-1-i] = t;
|
||||
}
|
||||
spi_write(addr, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T reg_rd(uint16_t addr) {
|
||||
uint8_t buf[sizeof(T)];
|
||||
spi_read(addr, buf, sizeof(buf));
|
||||
for(int i = 0; i < sizeof(buf)/2; i++) { // Big Endian to Little Endian
|
||||
uint8_t t = buf[i];
|
||||
buf[i] = buf[sizeof(buf)-1-i];
|
||||
buf[sizeof(buf)-1-i] = t;
|
||||
}
|
||||
return *reinterpret_cast<T*>(buf);
|
||||
}
|
||||
|
||||
void reg_rd_mac(uint16_t addr, uint8_t* data) {
|
||||
spi_read(addr, data, 6);
|
||||
}
|
||||
|
||||
void reg_wr_ip(uint16_t addr, const char* ip) {
|
||||
uint8_t buf[4];
|
||||
char* p = (char*)ip;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
buf[i] = atoi(p);
|
||||
p = strchr(p, '.');
|
||||
if (p == NULL) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
spi_write(addr, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void sreg_ip(int socket, uint16_t addr, const char* ip) {
|
||||
reg_wr_ip(addr+0x100*socket, ip);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t mac[6];
|
||||
uint32_t ip;
|
||||
uint32_t netmask;
|
||||
uint32_t gateway;
|
||||
uint32_t dnsaddr;
|
||||
bool dhcp;
|
||||
|
||||
static WIZnet_Chip* inst;
|
||||
|
||||
void reg_wr_mac(uint16_t addr, uint8_t* data) {
|
||||
spi_write(addr, data, 6);
|
||||
}
|
||||
|
||||
void spi_write(uint16_t addr, const uint8_t *buf, uint16_t len);
|
||||
void spi_read(uint16_t addr, uint8_t *buf, uint16_t len);
|
||||
SPI* spi;
|
||||
DigitalOut cs;
|
||||
DigitalOut reset_pin;
|
||||
};
|
||||
|
||||
extern uint32_t str_to_ip(const char* str);
|
||||
extern void printfBytes(char* str, uint8_t* buf, int len);
|
||||
extern void printHex(uint8_t* buf, int len);
|
||||
extern void debug_hex(uint8_t* buf, int len);
|
||||
402
WIZnetInterface/WIZnet/W5200.cpp
Normal file
402
WIZnetInterface/WIZnet/W5200.cpp
Normal file
@@ -0,0 +1,402 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
#include "wiznet.h"
|
||||
#include "DNSClient.h"
|
||||
|
||||
#ifdef USE_W5200
|
||||
|
||||
//Debug is disabled by default
|
||||
#if 0
|
||||
#define DBG(...) do{debug("%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
|
||||
//#define DBG(x, ...) debug("[WIZnet_Chip:DBG]"x"\r\n", ##__VA_ARGS__);
|
||||
#define WARN(x, ...) debug("[WIZnet_Chip:WARN]"x"\r\n", ##__VA_ARGS__);
|
||||
#define ERR(x, ...) debug("[WIZnet_Chip:ERR]"x"\r\n", ##__VA_ARGS__);
|
||||
#else
|
||||
#define DBG(x, ...)
|
||||
#define WARN(x, ...)
|
||||
#define ERR(x, ...)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define INFO(x, ...) debug("[WIZnet_Chip:INFO]"x"\r\n", ##__VA_ARGS__);
|
||||
#else
|
||||
#define INFO(x, ...)
|
||||
#endif
|
||||
|
||||
#define DBG_SPI 0
|
||||
|
||||
WIZnet_Chip* WIZnet_Chip::inst;
|
||||
|
||||
WIZnet_Chip::WIZnet_Chip(PinName mosi, PinName miso, PinName sclk, PinName _cs, PinName _reset):
|
||||
cs(_cs), reset_pin(_reset)
|
||||
{
|
||||
spi = new SPI(mosi, miso, sclk);
|
||||
cs = 1;
|
||||
reset_pin = 1;
|
||||
inst = this;
|
||||
}
|
||||
|
||||
WIZnet_Chip::WIZnet_Chip(SPI* spi, PinName _cs, PinName _reset):
|
||||
cs(_cs), reset_pin(_reset)
|
||||
{
|
||||
this->spi = spi;
|
||||
cs = 1;
|
||||
reset_pin = 1;
|
||||
inst = this;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::setip()
|
||||
{
|
||||
reg_wr<uint32_t>(SIPR, ip);
|
||||
reg_wr<uint32_t>(GAR, gateway);
|
||||
reg_wr<uint32_t>(SUBR, netmask);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::setProtocol(int socket, Protocol p)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
sreg<uint8_t>(socket, Sn_MR, p);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::connect(int socket, const char * host, int port, int timeout_ms)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
sreg<uint8_t>(socket, Sn_MR, TCP);
|
||||
scmd(socket, OPEN);
|
||||
sreg_ip(socket, Sn_DIPR, host);
|
||||
sreg<uint16_t>(socket, Sn_DPORT, port);
|
||||
sreg<uint16_t>(socket, Sn_PORT, new_port());
|
||||
scmd(socket, CONNECT);
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(!is_connected(socket)) {
|
||||
if (t.read_ms() > timeout_ms) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool WIZnet_Chip::is_fin_received(int socket)
|
||||
{
|
||||
uint8_t tmpSn_SR;
|
||||
tmpSn_SR = sreg<uint8_t>(socket, Sn_SR);
|
||||
// packet sending is possible, when state is SOCK_CLOSE_WAIT.
|
||||
if (tmpSn_SR == SOCK_CLOSE_WAIT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::gethostbyname(const char* host, uint32_t* ip)
|
||||
{
|
||||
uint32_t addr = str_to_ip(host);
|
||||
char buf[17];
|
||||
snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff);
|
||||
if (strcmp(buf, host) == 0) {
|
||||
*ip = addr;
|
||||
return true;
|
||||
}
|
||||
DNSClient client;
|
||||
if(client.lookup(host)) {
|
||||
*ip = client.ip;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::disconnect()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::is_connected(int socket)
|
||||
{
|
||||
if (sreg<uint8_t>(socket, Sn_SR) == SOCK_ESTABLISHED) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WIZnet_Chip::reset()
|
||||
{
|
||||
reset_pin = 1;
|
||||
reset_pin = 0;
|
||||
wait_us(2); // 2us
|
||||
reset_pin = 1;
|
||||
wait_ms(150); // 150ms
|
||||
|
||||
reg_wr<uint8_t>(MR, 1<<7);
|
||||
|
||||
reg_wr_mac(SHAR, mac);
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::close(int socket)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
// if not connected, return
|
||||
if (sreg<uint8_t>(socket, Sn_SR) == SOCK_CLOSED) {
|
||||
return true;
|
||||
}
|
||||
if (sreg<uint8_t>(socket, Sn_MR) == TCP) {
|
||||
scmd(socket, DISCON);
|
||||
}
|
||||
scmd(socket, CLOSE);
|
||||
sreg<uint8_t>(socket, Sn_IR, 0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::wait_readable(int socket, int wait_time_ms, int req_size)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(1) {
|
||||
//int size = sreg<uint16_t>(socket, Sn_RX_RSR);
|
||||
// during the reading Sn_RX_RXR, it has the possible change of this register.
|
||||
// so read twice and get same value then use size information.
|
||||
int size, size2;
|
||||
do {
|
||||
size = sreg<uint16_t>(socket, Sn_RX_RSR);
|
||||
size2 = sreg<uint16_t>(socket, Sn_RX_RSR);
|
||||
} while (size != size2);
|
||||
|
||||
if (size > req_size) {
|
||||
return size;
|
||||
}
|
||||
if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::wait_writeable(int socket, int wait_time_ms, int req_size)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(1) {
|
||||
//int size = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
// during the reading Sn_TX_FSR, it has the possible change of this register.
|
||||
// so read twice and get same value then use size information.
|
||||
int size, size2;
|
||||
do {
|
||||
size = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
size2 = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
} while (size != size2);
|
||||
|
||||
if (size > req_size) {
|
||||
return size;
|
||||
}
|
||||
if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::send(int socket, const char * str, int len)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
uint16_t base = 0x8000 + socket * 0x800;
|
||||
uint16_t ptr = sreg<uint16_t>(socket, Sn_TX_WR);
|
||||
uint16_t dst = base + (ptr&(0x800-1));
|
||||
if ((dst + len) > (base+0x800)) {
|
||||
int len2 = base + 0x800 - dst;
|
||||
spi_write(dst, (uint8_t*)str, len2);
|
||||
spi_write(base, (uint8_t*)str+len2, len-len2);
|
||||
} else {
|
||||
spi_write(dst, (uint8_t*)str, len);
|
||||
}
|
||||
sreg<uint16_t>(socket, Sn_TX_WR, ptr + len);
|
||||
scmd(socket, SEND);
|
||||
return len;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::recv(int socket, char* buf, int len)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
uint16_t base = 0xc000 + socket * 0x800;
|
||||
uint16_t ptr = sreg<uint16_t>(socket, Sn_RX_RD);
|
||||
uint16_t src = base + (ptr&(0x800-1));
|
||||
if ((src + len) > (base+0x800)) {
|
||||
int len2 = base + 0x800 - src;
|
||||
spi_read(src, (uint8_t*)buf, len2);
|
||||
spi_read(base, (uint8_t*)buf+len2, len-len2);
|
||||
} else {
|
||||
spi_read(src, (uint8_t*)buf, len);
|
||||
}
|
||||
sreg<uint16_t>(socket, Sn_RX_RD, ptr + len);
|
||||
scmd(socket, RECV);
|
||||
return len;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::new_socket()
|
||||
{
|
||||
for(int s = 0; s < 8; s++) {
|
||||
if (sreg<uint8_t>(s, Sn_SR) == SOCK_CLOSED) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t WIZnet_Chip::new_port()
|
||||
{
|
||||
uint16_t port = rand();
|
||||
port |= 49152;
|
||||
return port;
|
||||
}
|
||||
|
||||
void WIZnet_Chip::scmd(int socket, Command cmd)
|
||||
{
|
||||
sreg<uint8_t>(socket, Sn_CR, cmd);
|
||||
while(sreg<uint8_t>(socket, Sn_CR));
|
||||
}
|
||||
|
||||
void WIZnet_Chip::spi_write(uint16_t addr, const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
cs = 0;
|
||||
spi->write(addr >> 8);
|
||||
spi->write(addr & 0xff);
|
||||
spi->write((0x80 | ((len & 0x7f00) >> 8)));
|
||||
spi->write(len & 0xff);
|
||||
for(int i = 0; i < len; i++) {
|
||||
spi->write(buf[i]);
|
||||
}
|
||||
cs = 1;
|
||||
|
||||
#if DBG_SPI
|
||||
debug("[SPI]W %04x(%d)", addr, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
debug(" %02x", buf[i]);
|
||||
if (i > 16) {
|
||||
debug(" ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void WIZnet_Chip::spi_read(uint16_t addr, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
cs = 0;
|
||||
spi->write(addr >> 8);
|
||||
spi->write(addr & 0xff);
|
||||
spi->write((0x00 | ((len & 0x7f00) >> 8)));
|
||||
spi->write(len & 0xff);
|
||||
for(int i = 0; i < len; i++) {
|
||||
buf[i] = spi->write(0);
|
||||
}
|
||||
cs = 1;
|
||||
|
||||
#if DBG_SPI
|
||||
debug("[SPI]R %04x(%d)", addr, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
debug(" %02x", buf[i]);
|
||||
if (i > 16) {
|
||||
debug(" ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("\r\n");
|
||||
if ((addr&0xf0ff)==0x4026 || (addr&0xf0ff)==0x4003) {
|
||||
wait_ms(200);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t str_to_ip(const char* str)
|
||||
{
|
||||
uint32_t ip = 0;
|
||||
char* p = (char*)str;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
ip |= atoi(p);
|
||||
p = strchr(p, '.');
|
||||
if (p == NULL) {
|
||||
break;
|
||||
}
|
||||
ip <<= 8;
|
||||
p++;
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
void printfBytes(char* str, uint8_t* buf, int len)
|
||||
{
|
||||
printf("%s %d:", str, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
printf(" %02x", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void printHex(uint8_t* buf, int len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
if ((i%16) == 0) {
|
||||
printf("%p", buf+i);
|
||||
}
|
||||
printf(" %02x", buf[i]);
|
||||
if ((i%16) == 15) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void debug_hex(uint8_t* buf, int len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
if ((i%16) == 0) {
|
||||
debug("%p", buf+i);
|
||||
}
|
||||
debug(" %02x", buf[i]);
|
||||
if ((i%16) == 15) {
|
||||
debug("\n");
|
||||
}
|
||||
}
|
||||
debug("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
271
WIZnetInterface/WIZnet/W5200.h
Normal file
271
WIZnetInterface/WIZnet/W5200.h
Normal file
@@ -0,0 +1,271 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
|
||||
#define TEST_ASSERT(A) while(!(A)){debug("\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
|
||||
|
||||
#define DEFAULT_WAIT_RESP_TIMEOUT 500
|
||||
|
||||
enum Protocol {
|
||||
CLOSED = 0,
|
||||
TCP = 1,
|
||||
UDP = 2,
|
||||
};
|
||||
|
||||
enum Command {
|
||||
OPEN = 0x01,
|
||||
LISTEN = 0x02,
|
||||
CONNECT = 0x04,
|
||||
DISCON = 0x08,
|
||||
CLOSE = 0x10,
|
||||
SEND = 0x20,
|
||||
SEND_MAC = 0x21,
|
||||
SEND_KEEP = 0x22,
|
||||
RECV = 0x40,
|
||||
|
||||
};
|
||||
|
||||
enum Interrupt {
|
||||
INT_CON = 0x01,
|
||||
INT_DISCON = 0x02,
|
||||
INT_RECV = 0x04,
|
||||
INT_TIMEOUT = 0x08,
|
||||
INT_SEND_OK = 0x10,
|
||||
};
|
||||
|
||||
enum Status {
|
||||
SOCK_CLOSED = 0x00,
|
||||
SOCK_INIT = 0x13,
|
||||
SOCK_LISTEN = 0x14,
|
||||
SOCK_SYNSENT = 0x15,
|
||||
SOCK_ESTABLISHED = 0x17,
|
||||
SOCK_CLOSE_WAIT = 0x1c,
|
||||
SOCK_UDP = 0x22,
|
||||
};
|
||||
|
||||
#define MAX_SOCK_NUM 8
|
||||
|
||||
#define MR 0x0000
|
||||
#define GAR 0x0001
|
||||
#define SUBR 0x0005
|
||||
#define SHAR 0x0009
|
||||
#define SIPR 0x000f
|
||||
#define PHYSTATUS 0x0035
|
||||
|
||||
// W5200 socket
|
||||
#define Sn_MR 0x4000
|
||||
#define Sn_CR 0x4001
|
||||
#define Sn_IR 0x4002
|
||||
#define Sn_SR 0x4003
|
||||
#define Sn_PORT 0x4004
|
||||
#define Sn_DIPR 0x400c
|
||||
#define Sn_DPORT 0x4010
|
||||
#define Sn_RXBUF_SIZE 0x401e
|
||||
#define Sn_TXBUF_SIZE 0x401f
|
||||
#define Sn_TX_FSR 0x4020
|
||||
#define Sn_TX_WR 0x4024
|
||||
#define Sn_RX_RSR 0x4026
|
||||
#define Sn_RX_RD 0x4028
|
||||
|
||||
class WIZnet_Chip {
|
||||
public:
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
* @param spi spi class
|
||||
* @param cs cs of the W5200
|
||||
* @param reset reset pin of the W5200
|
||||
*/
|
||||
WIZnet_Chip(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset);
|
||||
WIZnet_Chip(SPI* spi, PinName cs, PinName reset);
|
||||
|
||||
/*
|
||||
* Connect the W5200 module to the ssid contained in the constructor.
|
||||
*
|
||||
* @return true if connected, false otherwise
|
||||
*/
|
||||
bool setip();
|
||||
|
||||
/*
|
||||
* Disconnect the W5200 module from the access point
|
||||
*
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool disconnect();
|
||||
|
||||
/*
|
||||
* Open a tcp connection with the specified host on the specified port
|
||||
*
|
||||
* @param host host (can be either an ip address or a name. If a name is provided, a dns request will be established)
|
||||
* @param port port
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool connect(int socket, const char * host, int port, int timeout_ms = 10*1000);
|
||||
|
||||
/*
|
||||
* Set the protocol (UDP or TCP)
|
||||
*
|
||||
* @param p protocol
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool setProtocol(int socket, Protocol p);
|
||||
|
||||
/*
|
||||
* Reset the W5200 module
|
||||
*/
|
||||
void reset();
|
||||
|
||||
|
||||
int wait_readable(int socket, int wait_time_ms, int req_size = 0);
|
||||
|
||||
int wait_writeable(int socket, int wait_time_ms, int req_size = 0);
|
||||
|
||||
/*
|
||||
* Check if a tcp link is active
|
||||
*
|
||||
* @returns true if successful
|
||||
*/
|
||||
bool is_connected(int socket);
|
||||
|
||||
/*
|
||||
* Check if FIN received.
|
||||
*
|
||||
* @returns true if successful
|
||||
*/
|
||||
bool is_fin_received(int socket);
|
||||
|
||||
/*
|
||||
* Close a tcp connection
|
||||
*
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool close(int socket);
|
||||
|
||||
/*
|
||||
* @param str string to be sent
|
||||
* @param len string length
|
||||
*/
|
||||
int send(int socket, const char * str, int len);
|
||||
|
||||
int recv(int socket, char* buf, int len);
|
||||
|
||||
/*
|
||||
* Return true if the module is using dhcp
|
||||
*
|
||||
* @returns true if the module is using dhcp
|
||||
*/
|
||||
bool isDHCP() {
|
||||
return dhcp;
|
||||
}
|
||||
|
||||
bool gethostbyname(const char* host, uint32_t* ip);
|
||||
|
||||
static WIZnet_Chip * getInstance() {
|
||||
return inst;
|
||||
};
|
||||
|
||||
int new_socket();
|
||||
uint16_t new_port();
|
||||
void scmd(int socket, Command cmd);
|
||||
|
||||
template<typename T>
|
||||
void sreg(int socket, uint16_t addr, T data) {
|
||||
reg_wr<T>(addr+0x100*socket, data);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T sreg(int socket, uint16_t addr) {
|
||||
return reg_rd<T>(addr+0x100*socket);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void reg_wr(uint16_t addr, T data) {
|
||||
uint8_t buf[sizeof(T)];
|
||||
*reinterpret_cast<T*>(buf) = data;
|
||||
for(int i = 0; i < sizeof(buf)/2; i++) { // Little Endian to Big Endian
|
||||
uint8_t t = buf[i];
|
||||
buf[i] = buf[sizeof(buf)-1-i];
|
||||
buf[sizeof(buf)-1-i] = t;
|
||||
}
|
||||
spi_write(addr, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T reg_rd(uint16_t addr) {
|
||||
uint8_t buf[sizeof(T)];
|
||||
spi_read(addr, buf, sizeof(buf));
|
||||
for(int i = 0; i < sizeof(buf)/2; i++) { // Big Endian to Little Endian
|
||||
uint8_t t = buf[i];
|
||||
buf[i] = buf[sizeof(buf)-1-i];
|
||||
buf[sizeof(buf)-1-i] = t;
|
||||
}
|
||||
return *reinterpret_cast<T*>(buf);
|
||||
}
|
||||
|
||||
void reg_rd_mac(uint16_t addr, uint8_t* data) {
|
||||
spi_read(addr, data, 6);
|
||||
}
|
||||
|
||||
void reg_wr_ip(uint16_t addr, const char* ip) {
|
||||
uint8_t buf[4];
|
||||
char* p = (char*)ip;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
buf[i] = atoi(p);
|
||||
p = strchr(p, '.');
|
||||
if (p == NULL) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
spi_write(addr, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void sreg_ip(int socket, uint16_t addr, const char* ip) {
|
||||
reg_wr_ip(addr+0x100*socket, ip);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t mac[6];
|
||||
uint32_t ip;
|
||||
uint32_t netmask;
|
||||
uint32_t gateway;
|
||||
uint32_t dnsaddr;
|
||||
bool dhcp;
|
||||
|
||||
static WIZnet_Chip* inst;
|
||||
|
||||
void reg_wr_mac(uint16_t addr, uint8_t* data) {
|
||||
spi_write(addr, data, 6);
|
||||
}
|
||||
|
||||
void spi_write(uint16_t addr, const uint8_t *buf, uint16_t len);
|
||||
void spi_read(uint16_t addr, uint8_t *buf, uint16_t len);
|
||||
SPI* spi;
|
||||
DigitalOut cs;
|
||||
DigitalOut reset_pin;
|
||||
};
|
||||
|
||||
extern uint32_t str_to_ip(const char* str);
|
||||
extern void printfBytes(char* str, uint8_t* buf, int len);
|
||||
extern void printHex(uint8_t* buf, int len);
|
||||
extern void debug_hex(uint8_t* buf, int len);
|
||||
427
WIZnetInterface/WIZnet/W5500.cpp
Normal file
427
WIZnetInterface/WIZnet/W5500.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
#include "wiznet.h"
|
||||
#include "DNSClient.h"
|
||||
|
||||
#ifdef USE_W5500
|
||||
//Debug is disabled by default
|
||||
#if 0
|
||||
#define DBG(...) do{debug("%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
|
||||
//#define DBG(x, ...) debug("[W5500:DBG]"x"\r\n", ##__VA_ARGS__);
|
||||
#define WARN(x, ...) debug("[W5500:WARN]"x"\r\n", ##__VA_ARGS__);
|
||||
#define ERR(x, ...) debug("[W5500:ERR]"x"\r\n", ##__VA_ARGS__);
|
||||
#else
|
||||
#define DBG(x, ...)
|
||||
#define WARN(x, ...)
|
||||
#define ERR(x, ...)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define INFO(x, ...) debug("[W5500:INFO]"x"\r\n", ##__VA_ARGS__);
|
||||
#else
|
||||
#define INFO(x, ...)
|
||||
#endif
|
||||
|
||||
#define DBG_SPI 0
|
||||
|
||||
WIZnet_Chip* WIZnet_Chip::inst;
|
||||
|
||||
WIZnet_Chip::WIZnet_Chip(PinName mosi, PinName miso, PinName sclk, PinName _cs, PinName _reset):
|
||||
cs(_cs), reset_pin(_reset)
|
||||
{
|
||||
spi = new SPI(mosi, miso, sclk);
|
||||
cs = 1;
|
||||
reset_pin = 1;
|
||||
inst = this;
|
||||
}
|
||||
|
||||
WIZnet_Chip::WIZnet_Chip(SPI* spi, PinName _cs, PinName _reset):
|
||||
cs(_cs), reset_pin(_reset)
|
||||
{
|
||||
this->spi = spi;
|
||||
cs = 1;
|
||||
reset_pin = 1;
|
||||
inst = this;
|
||||
}
|
||||
|
||||
// Set the IP
|
||||
bool WIZnet_Chip::setip()
|
||||
{
|
||||
reg_wr<uint32_t>(SIPR, ip);
|
||||
reg_wr<uint32_t>(GAR, gateway);
|
||||
reg_wr<uint32_t>(SUBR, netmask);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::setProtocol(int socket, Protocol p)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
sreg<uint8_t>(socket, Sn_MR, p);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::connect(int socket, const char * host, int port, int timeout_ms)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
sreg<uint8_t>(socket, Sn_MR, TCP);
|
||||
scmd(socket, OPEN);
|
||||
sreg_ip(socket, Sn_DIPR, host);
|
||||
sreg<uint16_t>(socket, Sn_DPORT, port);
|
||||
sreg<uint16_t>(socket, Sn_PORT, new_port());
|
||||
scmd(socket, CONNECT);
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(!is_connected(socket)) {
|
||||
if (t.read_ms() > timeout_ms) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::gethostbyname(const char* host, uint32_t* ip)
|
||||
{
|
||||
uint32_t addr = str_to_ip(host);
|
||||
char buf[17];
|
||||
snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff);
|
||||
if (strcmp(buf, host) == 0) {
|
||||
*ip = addr;
|
||||
return true;
|
||||
}
|
||||
DNSClient client;
|
||||
if(client.lookup(host)) {
|
||||
*ip = client.ip;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::disconnect()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WIZnet_Chip::is_connected(int socket)
|
||||
{
|
||||
uint8_t tmpSn_SR;
|
||||
tmpSn_SR = sreg<uint8_t>(socket, Sn_SR);
|
||||
// packet sending is possible, when state is SOCK_CLOSE_WAIT.
|
||||
if ((tmpSn_SR == SOCK_ESTABLISHED) || (tmpSn_SR == SOCK_CLOSE_WAIT)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool WIZnet_Chip::is_fin_received(int socket)
|
||||
{
|
||||
uint8_t tmpSn_SR;
|
||||
tmpSn_SR = sreg<uint8_t>(socket, Sn_SR);
|
||||
// packet sending is possible, when state is SOCK_CLOSE_WAIT.
|
||||
if (tmpSn_SR == SOCK_CLOSE_WAIT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Reset the chip & set the buffer
|
||||
void WIZnet_Chip::reset()
|
||||
{
|
||||
reset_pin = 1;
|
||||
reset_pin = 0;
|
||||
wait_us(500); // 500us (w5500)
|
||||
reset_pin = 1;
|
||||
wait_ms(400); // 400ms (w5500)
|
||||
|
||||
#if defined(USE_WIZ550IO_MAC)
|
||||
reg_rd_mac(SHAR, mac); // read the MAC address inside the module
|
||||
#endif
|
||||
|
||||
reg_wr_mac(SHAR, mac);
|
||||
|
||||
// set RX and TX buffer size
|
||||
for (int socket = 0; socket < MAX_SOCK_NUM; socket++) {
|
||||
sreg<uint8_t>(socket, Sn_RXBUF_SIZE, 2);
|
||||
sreg<uint8_t>(socket, Sn_TXBUF_SIZE, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool WIZnet_Chip::close(int socket)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return false;
|
||||
}
|
||||
// if not connected, return
|
||||
if (sreg<uint8_t>(socket, Sn_SR) == SOCK_CLOSED) {
|
||||
return true;
|
||||
}
|
||||
if (sreg<uint8_t>(socket, Sn_MR) == TCP) {
|
||||
scmd(socket, DISCON);
|
||||
}
|
||||
scmd(socket, CLOSE);
|
||||
sreg<uint8_t>(socket, Sn_IR, 0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::wait_readable(int socket, int wait_time_ms, int req_size)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(1) {
|
||||
//int size = sreg<uint16_t>(socket, Sn_RX_RSR);
|
||||
// during the reading Sn_RX_RXR, it has the possible change of this register.
|
||||
// so read twice and get same value then use size information.
|
||||
int size, size2;
|
||||
do {
|
||||
size = sreg<uint16_t>(socket, Sn_RX_RSR);
|
||||
size2 = sreg<uint16_t>(socket, Sn_RX_RSR);
|
||||
} while (size != size2);
|
||||
|
||||
if (size > req_size) {
|
||||
return size;
|
||||
}
|
||||
if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::wait_writeable(int socket, int wait_time_ms, int req_size)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
Timer t;
|
||||
t.reset();
|
||||
t.start();
|
||||
while(1) {
|
||||
//int size = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
// during the reading Sn_TX_FSR, it has the possible change of this register.
|
||||
// so read twice and get same value then use size information.
|
||||
int size, size2;
|
||||
do {
|
||||
size = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
size2 = sreg<uint16_t>(socket, Sn_TX_FSR);
|
||||
} while (size != size2);
|
||||
|
||||
if (size > req_size) {
|
||||
return size;
|
||||
}
|
||||
if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::send(int socket, const char * str, int len)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
uint16_t ptr = sreg<uint16_t>(socket, Sn_TX_WR);
|
||||
uint8_t cntl_byte = (0x14 + (socket << 5));
|
||||
spi_write(ptr, cntl_byte, (uint8_t*)str, len);
|
||||
sreg<uint16_t>(socket, Sn_TX_WR, ptr + len);
|
||||
scmd(socket, SEND);
|
||||
uint8_t tmp_Sn_IR;
|
||||
while (( (tmp_Sn_IR = sreg<uint8_t>(socket, Sn_IR)) & INT_SEND_OK) != INT_SEND_OK) {
|
||||
// @Jul.10, 2014 fix contant name, and udp sendto function.
|
||||
switch (sreg<uint8_t>(socket, Sn_SR)) {
|
||||
case SOCK_CLOSED :
|
||||
close(socket);
|
||||
return 0;
|
||||
//break;
|
||||
case SOCK_UDP :
|
||||
// ARP timeout is possible.
|
||||
if ((tmp_Sn_IR & INT_TIMEOUT) == INT_TIMEOUT) {
|
||||
sreg<uint8_t>(socket, Sn_IR, INT_TIMEOUT);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
while ((sreg<uint8_t>(socket, Sn_IR) & INT_SEND_OK) != INT_SEND_OK) {
|
||||
if (sreg<uint8_t>(socket, Sn_SR) == CLOSED) {
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
sreg<uint8_t>(socket, Sn_IR, INT_SEND_OK);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::recv(int socket, char* buf, int len)
|
||||
{
|
||||
if (socket < 0) {
|
||||
return -1;
|
||||
}
|
||||
uint16_t ptr = sreg<uint16_t>(socket, Sn_RX_RD);
|
||||
uint8_t cntl_byte = (0x18 + (socket << 5));
|
||||
spi_read(ptr, cntl_byte, (uint8_t*)buf, len);
|
||||
sreg<uint16_t>(socket, Sn_RX_RD, ptr + len);
|
||||
scmd(socket, RECV);
|
||||
return len;
|
||||
}
|
||||
|
||||
int WIZnet_Chip::new_socket()
|
||||
{
|
||||
for(int s = 0; s < MAX_SOCK_NUM; s++) {
|
||||
if (sreg<uint8_t>(s, Sn_SR) == SOCK_CLOSED) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t WIZnet_Chip::new_port()
|
||||
{
|
||||
uint16_t port = rand();
|
||||
port |= 49152;
|
||||
return port;
|
||||
}
|
||||
|
||||
void WIZnet_Chip::scmd(int socket, Command cmd)
|
||||
{
|
||||
sreg<uint8_t>(socket, Sn_CR, cmd);
|
||||
while(sreg<uint8_t>(socket, Sn_CR));
|
||||
}
|
||||
|
||||
void WIZnet_Chip::spi_write(uint16_t addr, uint8_t cb, const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
cs = 0;
|
||||
spi->write(addr >> 8);
|
||||
spi->write(addr & 0xff);
|
||||
spi->write(cb);
|
||||
for(int i = 0; i < len; i++) {
|
||||
spi->write(buf[i]);
|
||||
}
|
||||
cs = 1;
|
||||
|
||||
#if DBG_SPI
|
||||
debug("[SPI]W %04x(%02x %d)", addr, cb, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
debug(" %02x", buf[i]);
|
||||
if (i > 16) {
|
||||
debug(" ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void WIZnet_Chip::spi_read(uint16_t addr, uint8_t cb, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
cs = 0;
|
||||
spi->write(addr >> 8);
|
||||
spi->write(addr & 0xff);
|
||||
spi->write(cb);
|
||||
for(int i = 0; i < len; i++) {
|
||||
buf[i] = spi->write(0);
|
||||
}
|
||||
cs = 1;
|
||||
|
||||
#if DBG_SPI
|
||||
debug("[SPI]R %04x(%02x %d)", addr, cb, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
debug(" %02x", buf[i]);
|
||||
if (i > 16) {
|
||||
debug(" ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("\r\n");
|
||||
if ((addr&0xf0ff)==0x4026 || (addr&0xf0ff)==0x4003) {
|
||||
wait_ms(200);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t str_to_ip(const char* str)
|
||||
{
|
||||
uint32_t ip = 0;
|
||||
char* p = (char*)str;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
ip |= atoi(p);
|
||||
p = strchr(p, '.');
|
||||
if (p == NULL) {
|
||||
break;
|
||||
}
|
||||
ip <<= 8;
|
||||
p++;
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
void printfBytes(char* str, uint8_t* buf, int len)
|
||||
{
|
||||
printf("%s %d:", str, len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
printf(" %02x", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void printHex(uint8_t* buf, int len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
if ((i%16) == 0) {
|
||||
printf("%p", buf+i);
|
||||
}
|
||||
printf(" %02x", buf[i]);
|
||||
if ((i%16) == 15) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void debug_hex(uint8_t* buf, int len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
if ((i%16) == 0) {
|
||||
debug("%p", buf+i);
|
||||
}
|
||||
debug(" %02x", buf[i]);
|
||||
if ((i%16) == 15) {
|
||||
debug("\n");
|
||||
}
|
||||
}
|
||||
debug("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
280
WIZnetInterface/WIZnet/W5500.h
Normal file
280
WIZnetInterface/WIZnet/W5500.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
|
||||
#define TEST_ASSERT(A) while(!(A)){debug("\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
|
||||
|
||||
#define DEFAULT_WAIT_RESP_TIMEOUT 500
|
||||
|
||||
enum Protocol {
|
||||
CLOSED = 0,
|
||||
TCP = 1,
|
||||
UDP = 2,
|
||||
};
|
||||
|
||||
enum Command {
|
||||
OPEN = 0x01,
|
||||
LISTEN = 0x02,
|
||||
CONNECT = 0x04,
|
||||
DISCON = 0x08,
|
||||
CLOSE = 0x10,
|
||||
SEND = 0x20,
|
||||
SEND_MAC = 0x21,
|
||||
SEND_KEEP = 0x22,
|
||||
RECV = 0x40,
|
||||
|
||||
};
|
||||
|
||||
enum Interrupt {
|
||||
INT_CON = 0x01,
|
||||
INT_DISCON = 0x02,
|
||||
INT_RECV = 0x04,
|
||||
INT_TIMEOUT = 0x08,
|
||||
INT_SEND_OK = 0x10,
|
||||
};
|
||||
|
||||
enum Status {
|
||||
SOCK_CLOSED = 0x00,
|
||||
SOCK_INIT = 0x13,
|
||||
SOCK_LISTEN = 0x14,
|
||||
SOCK_SYNSENT = 0x15,
|
||||
SOCK_ESTABLISHED = 0x17,
|
||||
SOCK_CLOSE_WAIT = 0x1c,
|
||||
SOCK_UDP = 0x22,
|
||||
};
|
||||
|
||||
#define MAX_SOCK_NUM 8
|
||||
|
||||
#define MR 0x0000
|
||||
#define GAR 0x0001
|
||||
#define SUBR 0x0005
|
||||
#define SHAR 0x0009
|
||||
#define SIPR 0x000f
|
||||
#define PHYSTATUS 0x0035
|
||||
|
||||
// W5500 socket register
|
||||
#define Sn_MR 0x0000
|
||||
#define Sn_CR 0x0001
|
||||
#define Sn_IR 0x0002
|
||||
#define Sn_SR 0x0003
|
||||
#define Sn_PORT 0x0004
|
||||
#define Sn_DIPR 0x000c
|
||||
#define Sn_DPORT 0x0010
|
||||
#define Sn_RXBUF_SIZE 0x001e
|
||||
#define Sn_TXBUF_SIZE 0x001f
|
||||
#define Sn_TX_FSR 0x0020
|
||||
#define Sn_TX_WR 0x0024
|
||||
#define Sn_RX_RSR 0x0026
|
||||
#define Sn_RX_RD 0x0028
|
||||
|
||||
class WIZnet_Chip {
|
||||
public:
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
* @param spi spi class
|
||||
* @param cs cs of the W5500
|
||||
* @param reset reset pin of the W5500
|
||||
*/
|
||||
WIZnet_Chip(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset);
|
||||
WIZnet_Chip(SPI* spi, PinName cs, PinName reset);
|
||||
|
||||
/*
|
||||
* Connect the W5500 to the ssid contained in the constructor.
|
||||
*
|
||||
* @return true if connected, false otherwise
|
||||
*/
|
||||
bool setip();
|
||||
|
||||
/*
|
||||
* Disconnect the connection
|
||||
*
|
||||
* @ returns true
|
||||
*/
|
||||
bool disconnect();
|
||||
|
||||
/*
|
||||
* Open a tcp connection with the specified host on the specified port
|
||||
*
|
||||
* @param host host (can be either an ip address or a name. If a name is provided, a dns request will be established)
|
||||
* @param port port
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool connect(int socket, const char * host, int port, int timeout_ms = 10*1000);
|
||||
|
||||
/*
|
||||
* Set the protocol (UDP or TCP)
|
||||
*
|
||||
* @param p protocol
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool setProtocol(int socket, Protocol p);
|
||||
|
||||
/*
|
||||
* Reset the W5500
|
||||
*/
|
||||
void reset();
|
||||
|
||||
int wait_readable(int socket, int wait_time_ms, int req_size = 0);
|
||||
|
||||
int wait_writeable(int socket, int wait_time_ms, int req_size = 0);
|
||||
|
||||
/*
|
||||
* Check if a tcp link is active
|
||||
*
|
||||
* @returns true if successful
|
||||
*/
|
||||
bool is_connected(int socket);
|
||||
|
||||
/*
|
||||
* Check if FIN received.
|
||||
*
|
||||
* @returns true if successful
|
||||
*/
|
||||
bool is_fin_received(int socket);
|
||||
|
||||
/*
|
||||
* Close a tcp connection
|
||||
*
|
||||
* @ returns true if successful
|
||||
*/
|
||||
bool close(int socket);
|
||||
|
||||
/*
|
||||
* @param str string to be sent
|
||||
* @param len string length
|
||||
*/
|
||||
int send(int socket, const char * str, int len);
|
||||
|
||||
int recv(int socket, char* buf, int len);
|
||||
|
||||
/*
|
||||
* Return true if the module is using dhcp
|
||||
*
|
||||
* @returns true if the module is using dhcp
|
||||
*/
|
||||
bool isDHCP() {
|
||||
return dhcp;
|
||||
}
|
||||
|
||||
bool gethostbyname(const char* host, uint32_t* ip);
|
||||
|
||||
static WIZnet_Chip * getInstance() {
|
||||
return inst;
|
||||
};
|
||||
|
||||
int new_socket();
|
||||
uint16_t new_port();
|
||||
void scmd(int socket, Command cmd);
|
||||
|
||||
template<typename T>
|
||||
void sreg(int socket, uint16_t addr, T data) {
|
||||
reg_wr<T>(addr, (0x0C + (socket << 5)), data);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T sreg(int socket, uint16_t addr) {
|
||||
return reg_rd<T>(addr, (0x08 + (socket << 5)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void reg_wr(uint16_t addr, T data) {
|
||||
return reg_wr(addr, 0x04, data);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void reg_wr(uint16_t addr, uint8_t cb, T data) {
|
||||
uint8_t buf[sizeof(T)];
|
||||
*reinterpret_cast<T*>(buf) = data;
|
||||
for(int i = 0; i < sizeof(buf)/2; i++) { // Little Endian to Big Endian
|
||||
uint8_t t = buf[i];
|
||||
buf[i] = buf[sizeof(buf)-1-i];
|
||||
buf[sizeof(buf)-1-i] = t;
|
||||
}
|
||||
spi_write(addr, cb, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T reg_rd(uint16_t addr) {
|
||||
return reg_rd<T>(addr, 0x00);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T reg_rd(uint16_t addr, uint8_t cb) {
|
||||
uint8_t buf[sizeof(T)];
|
||||
spi_read(addr, cb, buf, sizeof(buf));
|
||||
for(int i = 0; i < sizeof(buf)/2; i++) { // Big Endian to Little Endian
|
||||
uint8_t t = buf[i];
|
||||
buf[i] = buf[sizeof(buf)-1-i];
|
||||
buf[sizeof(buf)-1-i] = t;
|
||||
}
|
||||
return *reinterpret_cast<T*>(buf);
|
||||
}
|
||||
|
||||
void reg_rd_mac(uint16_t addr, uint8_t* data) {
|
||||
spi_read(addr, 0x00, data, 6);
|
||||
}
|
||||
|
||||
void reg_wr_ip(uint16_t addr, uint8_t cb, const char* ip) {
|
||||
uint8_t buf[4];
|
||||
char* p = (char*)ip;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
buf[i] = atoi(p);
|
||||
p = strchr(p, '.');
|
||||
if (p == NULL) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
spi_write(addr, cb, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void sreg_ip(int socket, uint16_t addr, const char* ip) {
|
||||
reg_wr_ip(addr, (0x0C + (socket << 5)), ip);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t mac[6];
|
||||
uint32_t ip;
|
||||
uint32_t netmask;
|
||||
uint32_t gateway;
|
||||
uint32_t dnsaddr;
|
||||
bool dhcp;
|
||||
|
||||
static WIZnet_Chip* inst;
|
||||
|
||||
void reg_wr_mac(uint16_t addr, uint8_t* data) {
|
||||
spi_write(addr, 0x04, data, 6);
|
||||
}
|
||||
|
||||
void spi_write(uint16_t addr, uint8_t cb, const uint8_t *buf, uint16_t len);
|
||||
void spi_read(uint16_t addr, uint8_t cb, uint8_t *buf, uint16_t len);
|
||||
SPI* spi;
|
||||
DigitalOut cs;
|
||||
DigitalOut reset_pin;
|
||||
};
|
||||
|
||||
extern uint32_t str_to_ip(const char* str);
|
||||
extern void printfBytes(char* str, uint8_t* buf, int len);
|
||||
extern void printHex(uint8_t* buf, int len);
|
||||
extern void debug_hex(uint8_t* buf, int len);
|
||||
43
WIZnetInterface/WIZnet/wiznet.h
Normal file
43
WIZnetInterface/WIZnet/wiznet.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
|
||||
//#define USE_W5500
|
||||
//#define USE_W5200
|
||||
#define USE_W5100
|
||||
|
||||
#if defined(USE_W5500)
|
||||
#include "W5500.h"
|
||||
|
||||
//#define USE_WIZ550IO_MAC // using the MAC address stored in the WIZ550io
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(USE_W5200)
|
||||
#include "W5200.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_W5100)
|
||||
#include "W5100.h"
|
||||
|
||||
#endif
|
||||
119
WIZnetInterface/WIZnetInterface.cpp
Normal file
119
WIZnetInterface/WIZnetInterface.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "WIZnetInterface.h"
|
||||
#include "DHCPClient.h"
|
||||
|
||||
WIZnetInterface::WIZnetInterface(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset) :
|
||||
WIZnet_Chip(mosi, miso, sclk, cs, reset)
|
||||
{
|
||||
ip_set = false;
|
||||
}
|
||||
|
||||
WIZnetInterface::WIZnetInterface(SPI* spi, PinName cs, PinName reset) :
|
||||
WIZnet_Chip(spi, cs, reset)
|
||||
{
|
||||
ip_set = false;
|
||||
}
|
||||
|
||||
int WIZnetInterface::init(uint8_t * mac)
|
||||
{
|
||||
dhcp = true;
|
||||
for (int i =0; i < 6; i++) this->mac[i] = mac[i];
|
||||
reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WIZnetInterface::init(uint8_t * mac, const char* ip, const char* mask, const char* gateway)
|
||||
{
|
||||
dhcp = false;
|
||||
for (int i =0; i < 6; i++) this->mac[i] = mac[i];
|
||||
this->ip = str_to_ip(ip);
|
||||
strcpy(ip_string, ip);
|
||||
ip_set = true;
|
||||
this->netmask = str_to_ip(mask);
|
||||
this->gateway = str_to_ip(gateway);
|
||||
reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Connect Bring the interface up, start DHCP if needed.
|
||||
int WIZnetInterface::connect()
|
||||
{
|
||||
if (dhcp) {
|
||||
int r = IPrenew();
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (WIZnet_Chip::setip() == false) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Disconnect Bring the interface down.
|
||||
int WIZnetInterface::disconnect()
|
||||
{
|
||||
if (WIZnet_Chip::disconnect() == false) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* WIZnetInterface::getIPAddress()
|
||||
{
|
||||
uint32_t ip = reg_rd<uint32_t>(SIPR);
|
||||
snprintf(ip_string, sizeof(ip_string), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
|
||||
return ip_string;
|
||||
}
|
||||
|
||||
char* WIZnetInterface::getNetworkMask()
|
||||
{
|
||||
uint32_t ip = reg_rd<uint32_t>(SUBR);
|
||||
snprintf(mask_string, sizeof(mask_string), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
|
||||
return mask_string;
|
||||
}
|
||||
|
||||
char* WIZnetInterface::getGateway()
|
||||
{
|
||||
uint32_t ip = reg_rd<uint32_t>(GAR);
|
||||
snprintf(gw_string, sizeof(gw_string), "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
|
||||
return gw_string;
|
||||
}
|
||||
|
||||
char* WIZnetInterface::getMACAddress()
|
||||
{
|
||||
uint8_t mac[6];
|
||||
reg_rd_mac(SHAR, mac);
|
||||
snprintf(mac_string, sizeof(mac_string), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
return mac_string;
|
||||
|
||||
}
|
||||
|
||||
int WIZnetInterface::IPrenew(int timeout_ms)
|
||||
{
|
||||
DHCPClient dhcp;
|
||||
int err = dhcp.setup(timeout_ms);
|
||||
if (err == (-1)) {
|
||||
return -1;
|
||||
}
|
||||
//printf("Connected, IP: %d.%d.%d.%d\n", dhcp.yiaddr[0], dhcp.yiaddr[1], dhcp.yiaddr[2], dhcp.yiaddr[3]);
|
||||
ip = (dhcp.yiaddr[0] <<24) | (dhcp.yiaddr[1] <<16) | (dhcp.yiaddr[2] <<8) | dhcp.yiaddr[3];
|
||||
gateway = (dhcp.gateway[0]<<24) | (dhcp.gateway[1]<<16) | (dhcp.gateway[2]<<8) | dhcp.gateway[3];
|
||||
netmask = (dhcp.netmask[0]<<24) | (dhcp.netmask[1]<<16) | (dhcp.netmask[2]<<8) | dhcp.netmask[3];
|
||||
dnsaddr = (dhcp.dnsaddr[0]<<24) | (dhcp.dnsaddr[1]<<16) | (dhcp.dnsaddr[2]<<8) | dhcp.dnsaddr[3];
|
||||
return 0;
|
||||
}
|
||||
88
WIZnetInterface/WIZnetInterface.h
Normal file
88
WIZnetInterface/WIZnetInterface.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "wiznet.h"
|
||||
|
||||
/** Interface using Wiznet chip to connect to an IP-based network
|
||||
*
|
||||
*/
|
||||
class WIZnetInterface: public WIZnet_Chip {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param mosi mbed pin to use for SPI
|
||||
* \param miso mbed pin to use for SPI
|
||||
* \param sclk mbed pin to use for SPI
|
||||
* \param cs chip select of the WIZnet_Chip
|
||||
* \param reset reset pin of the WIZnet_Chip
|
||||
*/
|
||||
WIZnetInterface(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset);
|
||||
WIZnetInterface(SPI* spi, PinName cs, PinName reset);
|
||||
|
||||
/** Initialize the interface with DHCP.
|
||||
* Initialize the interface and configure it to use DHCP (no connection at this point).
|
||||
* \return 0 on success, a negative number on failure
|
||||
*/
|
||||
int init(uint8_t * mac); //With DHCP
|
||||
|
||||
/** Initialize the interface with a static IP address.
|
||||
* Initialize the interface and configure it with the following static configuration (no connection at this point).
|
||||
* \param ip the IP address to use
|
||||
* \param mask the IP address mask
|
||||
* \param gateway the gateway to use
|
||||
* \return 0 on success, a negative number on failure
|
||||
*/
|
||||
int init(uint8_t * mac, const char* ip, const char* mask, const char* gateway);
|
||||
|
||||
/** Connect
|
||||
* Bring the interface up, start DHCP if needed.
|
||||
* \return 0 on success, a negative number on failure
|
||||
*/
|
||||
int connect();
|
||||
|
||||
/** Disconnect
|
||||
* Bring the interface down
|
||||
* \return 0 on success, a negative number on failure
|
||||
*/
|
||||
int disconnect();
|
||||
|
||||
/** Get IP address & MAC address
|
||||
*
|
||||
* @ returns ip address
|
||||
*/
|
||||
char* getIPAddress();
|
||||
char* getNetworkMask();
|
||||
char* getGateway();
|
||||
char* getMACAddress();
|
||||
|
||||
int IPrenew(int timeout_ms = 15*1000);
|
||||
|
||||
private:
|
||||
char ip_string[20];
|
||||
char mask_string[20];
|
||||
char gw_string[20];
|
||||
char mac_string[20];
|
||||
bool ip_set;
|
||||
};
|
||||
|
||||
#include "TCPSocketConnection.h"
|
||||
#include "TCPSocketServer.h"
|
||||
#include "UDPSocket.h"
|
||||
46
WIZnetInterface/pico_string.h
Normal file
46
WIZnetInterface/pico_string.h
Normal file
@@ -0,0 +1,46 @@
|
||||
// pico_string.h 2013/8/27
|
||||
#pragma once
|
||||
class pico_string {
|
||||
public:
|
||||
pico_string(){
|
||||
_len = 0;
|
||||
_buf = (char*)malloc(1);
|
||||
if (_buf) {
|
||||
_buf[0] = '\0';
|
||||
}
|
||||
}
|
||||
~pico_string() {
|
||||
if (_buf) {
|
||||
free(_buf);
|
||||
}
|
||||
}
|
||||
bool empty() {
|
||||
return _len == 0;
|
||||
}
|
||||
void append(const char* s, int len) {
|
||||
if (_buf == NULL) {
|
||||
return;
|
||||
}
|
||||
char* p = (char*)malloc(_len+len+1);
|
||||
if (p == NULL) {
|
||||
return;
|
||||
}
|
||||
memcpy(p, _buf, _len);
|
||||
memcpy(p+_len, s, len);
|
||||
p[_len+len] = '\0';
|
||||
free(_buf);
|
||||
_buf = p;
|
||||
}
|
||||
void append(const char* s) {
|
||||
append(s, strlen(s));
|
||||
}
|
||||
char* c_str() {
|
||||
if (_buf) {
|
||||
return _buf;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
private:
|
||||
char* _buf;
|
||||
int _len;
|
||||
};
|
||||
Reference in New Issue
Block a user