Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.
Dependents: mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more
Library for ENC28J60 Ethernet modules.
Ported to mbed from Norbert Truchsess's UIPEthernet library for Arduino. Thank you Norbert!
- Full support for persistent (streaming) TCP/IP and UDP connections Client and Server each, ARP, ICMP, DHCP and DNS.
- Works with both Mbed OS 2 and Mbed OS 5.
Usage:
- Import the library into your project.
- Add
#include "UipEthernet.h"
tomain.cpp
- Create one instance of the UipEthernet class initialized with the MAC address you'd like to use and SPI pins of the connected Mbed board.
Example programs:
Import programWebSwitch_ENC28J60
HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.
Import programHTTPServer_Echo_ENC28J60
A simple HTTP server echoing received requests. Ethernet connection is over an ENC28J60 board. Usage: Type the server's IP address into you web browser and hit <ENTER>.
Import programTcpServer_ENC28J60
Simple TCP/IP Server using the UIPEthernet library for ENC28J60 Ethernet boards.
Import programTcpClient_ENC28J60
Simple TCP/IP Client using the UIPEthernet library for ENC28J60 Ethernet boards.
Import programUdpServer_ENC28J60
Simple UDP Server using the UIPEthernet library for ENC28J60 Ethernet boards.
Import programUdpClient_ENC28J60
Simple UDP Client using the UIPEthernet library for ENC28J60 Ethernet boards.
Import programMQTT_Hello_ENC28J60
MQTT Client example program. Ethernet connection is via an ENC28J60 module.
Revision 4:d774541a34da, committed 2015-03-08
- Comitter:
- hudakz
- Date:
- Sun Mar 08 20:26:56 2015 +0000
- Parent:
- 3:5b17e4656dd0
- Child:
- 5:59a504be7998
- Commit message:
- Version 1.09 (fixed leaking client-data caused by race-condition on remote close)
Changed in this revision
--- a/Dhcp.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/Dhcp.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -3,8 +3,8 @@ #include <string.h> #include <stdlib.h> #include "Dhcp.h" -#include "utility/util.h" -#include "utility/uip_clock.h" +#include "utility/util.h" +#include "utility/millis.h" /** * @brief @@ -62,19 +62,19 @@ int result = 0; - unsigned long startTime = clock_time(); + unsigned long startTime = millis(); while(_dhcp_state != STATE_DHCP_LEASED) { if(_dhcp_state == STATE_DHCP_START) { _dhcpTransactionId++; - send_DHCP_MESSAGE(DHCP_DISCOVER, ((clock_time() - startTime) / 1000)); + send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); _dhcp_state = STATE_DHCP_DISCOVER; } else if(_dhcp_state == STATE_DHCP_REREQUEST) { _dhcpTransactionId++; - send_DHCP_MESSAGE(DHCP_REQUEST, ((clock_time() - startTime) / 1000)); + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); _dhcp_state = STATE_DHCP_REQUEST; } else @@ -86,7 +86,7 @@ // We'll use the transaction ID that the offer came with, // rather than the one we were up to _dhcpTransactionId = respId; - send_DHCP_MESSAGE(DHCP_REQUEST, ((clock_time() - startTime) / 1000)); + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); _dhcp_state = STATE_DHCP_REQUEST; } } @@ -129,7 +129,7 @@ _dhcp_state = STATE_DHCP_START; } - if(result != 1 && ((clock_time() - startTime) > _timeout)) + if(result != 1 && ((millis() - startTime) > _timeout)) break; } @@ -279,14 +279,14 @@ uint8_t type = 0; uint8_t opt_len = 0; - unsigned long startTime = clock_time(); + unsigned long startTime = millis(); while(_dhcpUdpSocket.parsePacket() <= 0) { - if((clock_time() - startTime) > responseTimeout) { + if((millis() - startTime) > responseTimeout) { return 255; } - wait(0.050); + wait_ms(50); } // start reading in the packet @@ -412,7 +412,7 @@ int DhcpClass::checkLease(void) { //this uses a signed / unsigned trick to deal with millis overflow - unsigned long now = clock_time(); + unsigned long now = millis(); signed long snow = (long)now; int rc = DHCP_CHECK_NONE; if(_lastCheck != 0) {
--- a/Dns.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/Dns.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -1,15 +1,15 @@ -// mbed DNS client for Enc28J60-based Ethernet shield +// Arduino DNS client for Enc28J60-based Ethernet shield // (c) Copyright 2009-2010 MCQN Ltd. // Released under Apache License, version 2.0 -#include "utility/Udp.h" -#include "utility/util.h" +#include "Udp.h" +#include "utility/util.h" +#include "utility/millis.h" #include "Dns.h" #include <string.h> //#include <stdlib.h> -#include "mbed.h" -#include "utility/uip_clock.h" +#include <mbed.h> #define SOCKET_NONE 255 // Various flags and header field values for a DNS message @@ -44,11 +44,11 @@ // Possible return codes from ProcessResponse -#define SUCCESS 1 -#define TIMED_OUT - 1 -#define INVALID_SERVER - 2 -#define TRUNCATED - 3 -#define INVALID_RESPONSE - 4 +#define SUCCESS 1 +#define TIMED_OUT -1 +#define INVALID_SERVER -2 +#define TRUNCATED -3 +#define INVALID_RESPONSE -4 /** * @brief @@ -56,6 +56,7 @@ * @param * @retval */ + void DNSClient::begin(const IPAddress& aDNSServer) { iDNSServer = aDNSServer; iRequestId = 0; @@ -147,7 +148,7 @@ } // Find a socket to use - if(iUdp.begin(1024 + (clock_time() & 0xF)) == 1) { + if(iUdp.begin(1024 + (millis() & 0xF)) == 1) { // Try up to three times int retries = 0; @@ -213,7 +214,7 @@ // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ // As we only support one request at a time at present, we can simplify // some of this header - iRequestId = clock_time(); // generate a random ID + iRequestId = millis(); // generate a random ID uint16_t twoByteBuffer; // FIXME We should also check that there's enough space available to write to, rather @@ -285,12 +286,12 @@ * @retval */ uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) { - uint32_t startTime = clock_time(); + uint32_t startTime = millis(); // Wait for a response packet while(iUdp.parsePacket() <= 0) { - if((clock_time() - startTime) > aTimeout) + if((millis() - startTime) > aTimeout) return TIMED_OUT; wait(0.050); } @@ -451,4 +452,3 @@ // If we get here then we haven't found an answer return -10; //INVALID_RESPONSE; } -
--- a/Dns.h Sat Dec 20 11:10:40 2014 +0000 +++ b/Dns.h Sun Mar 08 20:26:56 2015 +0000 @@ -1,39 +1,41 @@ -// mbed DNS client for Enc28J60-based Ethernet shield -// (c) Copyright 2009-2010 MCQN Ltd. -// Released under Apache License, version 2.0 -#ifndef DNSClient_h - #define DNSClient_h - - #include <UIPUdp.h> - -class DNSClient -{ -public: - // ctor - void begin(const IPAddress& aDNSServer); - - /** Convert a numeric IP address string into a four-byte IP address. - @param aIPAddrString IP address to convert - @param aResult IPAddress structure to store the returned IP address - @result 1 if aIPAddrString was successfully converted to an IP address, - else error code - */ - int inet_aton(const char* aIPAddrString, IPAddress& aResult); - - /** Resolve the given hostname to an IP address. - @param aHostname Name to be resolved - @param aResult IPAddress structure to store the returned IP address - @result 1 if aIPAddrString was successfully converted to an IP address, - else error code - */ - int getHostByName(const char* aHostname, IPAddress& aResult); -protected: - uint16_t BuildRequest(const char* aName); - uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); - - IPAddress iDNSServer; - uint16_t iRequestId; - UIPUDP iUdp; -}; -#endif +// Arduino DNS client for Enc28J60-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#ifndef DNSClient_h +#define DNSClient_h + +#include <UIPUdp.h> + +class DNSClient +{ +public: + // ctor + void begin(const IPAddress& aDNSServer); + /** Convert a numeric IP address string into a four-byte IP address. + @param aIPAddrString IP address to convert + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int inet_aton(const char *aIPAddrString, IPAddress& aResult); + + /** Resolve the given hostname to an IP address. + @param aHostname Name to be resolved + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int getHostByName(const char* aHostname, IPAddress& aResult); + +protected: + uint16_t BuildRequest(const char* aName); + uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); + + IPAddress iDNSServer; + uint16_t iRequestId; + UIPUDP iUdp; +}; + +#endif
--- a/Readme.txt Sat Dec 20 11:10:40 2014 +0000 +++ b/Readme.txt Sun Mar 08 20:26:56 2015 +0000 @@ -1,7 +1,7 @@ -This is UIPEthernet version 1.07 +This is UIPEthernet version 1.09 -Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS. -Just include 'UIPEthernet.h' and create one IUPEthernet object initialized with the SPI pins of your ENC28J60 board. +An plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS. +Just include 'UIPEthernet.h' instead of 'Ethernet.h' and use all your code written for the stock Arduino Ethernet lib! UIPEthernet is written as a wrapper around the mature uIP Stack by Adam Dunkels, which provides the low-level implementation for all supported protocols. To overcome the memory-constrains (a 'regular' uIP-application does all processing in RAM) the ENC28J60 internal memory is used for all stream buffers (in and out). Only 400-600 Bytes of Arduinos RAM are used (depending on the number of concurrently open connections). As of Flash-memory a ATmega368-based Arduino is the minimum requirenment. @@ -11,12 +11,28 @@ This library was inspired by the SerialIP implementation by Adam Nielsen <malvineous@shikadi.net>, actually I took this code as a starting point, but in the latest versions there are very few lines left. +This library was ported to mbed by Zoltan Hudak <hudakz@inbox.com> + Installation ------------ -Import into your project as any other mbed library. +To install the libraries, you need to place them into your "libraries" folder. You can find it within your Arduino IDE distribution within the "hardware" folder. + + C:\> cd [path to Arduino distribution]\libraries + C:\> git clone https://github.com/ntruchsess/arduino_uip UIPEthernet + +Be sure to restart the IDE if it was running. + +On a Mac, you will want to create a folder named "libraries" in in the "Documents" -> "Arduino" folder within your home directory. Clone the project there (and restart the IDE, if it was running during this process). -Additional information can be found on the mbed website: https://mbed.org/handbook/mbed-Compiler + $ cd ~/Documents/Arduino/libraries + $ git clone https://github.com/ntruchsess/arduino_uip UIPEthernet + +Or you download the zipped version of the library from https://github.com/ntruchsess/arduino_uip/releases, and copy the contained directory UIPEthernet to [path to Arduino distribution]\libraries\UIPEthernet. + +If you are running Arduino-IDE 1.5.x use release-version 1.59 or checkout branch 'Arduino_1.5.x' + +Additional information can be found on the Arduino website: http://www.arduino.cc/en/Hacking/Libraries Documentation ------------- @@ -33,6 +49,9 @@ - uIP API reference: http://www.sics.se/~adam/uip/uip-1.0-refman/ + - Arduino forums + http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl + - uIP homepage: http://www.sics.se/~adam/uip/index.php/Main_Page @@ -41,6 +60,8 @@ UIPEthernet.h UIPEthernet.cpp +UIPUdp.h +UIPClient.cpp Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> All rights reserved. @@ -50,8 +71,6 @@ UIPServer.h UIPServer.cpp UIPClient.h -UIPClient.cpp -UIPUdp.h UIPUdp.cpp utility/mempool.h utility/mempool.cpp @@ -203,8 +222,6 @@ Copyright (c) 2010 Adam Nielsen <malvineous@shikadi.net> All rights reserved. -Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -243,3 +260,23 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +-------------- + +utility/millis.h +utility/millis.cpp + +Copyright (c) 2015 Zoltan Hudak <hudakz@inbox.com>. +All right reserved. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>.
--- a/UIPClient.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPClient.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -3,6 +3,8 @@ Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> All rights reserved. + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -18,9 +20,10 @@ */ extern "C" { -#include "utility/uip-conf.h" -#include "utility/uip.h" -#include "utility/uip_arp.h" +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +#include "utility/millis.h" #include "string.h" } #include "UIPEthernet.h" @@ -32,7 +35,7 @@ #endif #define UIP_TCP_PHYH_LEN UIP_LLH_LEN + UIP_IPTCPH_LEN -uip_userdata_closed_t* UIPClient:: closed_conns[UIP_CONNS]; +uip_userdata_t UIPClient:: all_data[UIP_CONNS]; /** * @brief @@ -41,20 +44,7 @@ * @retval */ UIPClient::UIPClient(void) : - _uip_conn(NULL), - data(NULL) { - UIPEthernet.set_uip_callback(&UIPClient::uip_callback); -} - -/** - * @brief - * @note - * @param - * @retval - */ -UIPClient::UIPClient(struct uip_conn* conn) : - _uip_conn(conn), - data(conn ? (uip_userdata_t*)conn->appstate.user : NULL) + data(NULL) { } /** @@ -63,9 +53,8 @@ * @param * @retval */ -UIPClient::UIPClient(uip_userdata_closed_t* conn_data) : - _uip_conn(NULL), - data((uip_userdata_t*)conn_data) +UIPClient::UIPClient(uip_userdata_t* conn_data) : + data(conn_data) { } /** @@ -75,22 +64,36 @@ * @retval */ int UIPClient::connect(IPAddress ip, uint16_t port) { + stop(); + uip_ipaddr_t ipaddr; uip_ip_addr(ipaddr, ip); - _uip_conn = uip_connect(&ipaddr, htons(port)); - if(_uip_conn) { - while((_uip_conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) { + + struct uip_conn* conn = uip_connect(&ipaddr, htons(port)); + if(conn) + { +#if UIP_CONNECT_TIMEOUT > 0 + int32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT; +#endif + while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) { UIPEthernet.tick(); - if((_uip_conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) - { + if((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { + data = (uip_userdata_t*)conn->appstate; #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("connected, state: "); - Serial.print(((uip_userdata_t*)_uip_conn->appstate.user)->state); - Serial.print(", first packet in: "); - Serial.println(((uip_userdata_t*)_uip_conn->appstate.user)->packets_in[0]); + Serial.print(F("connected, state: ")); + Serial.print(data->state); + Serial.print(F(", first packet in: ")); + Serial.println(data->packets_in[0]); #endif return 1; } + +#if UIP_CONNECT_TIMEOUT > 0 + if(((int32_t) (millis() - timeout)) > 0) { + conn->tcpstateflags = UIP_CLOSED; + break; + } +#endif } } @@ -111,7 +114,7 @@ DNSClient dns; IPAddress remote_addr; - dns.begin(UIPEthernet.dnsServerIP()); + dns.begin(UIPEthernetClass::_dnsServerAddress); ret = dns.getHostByName(host, remote_addr); if(ret == 1) { return connect(remote_addr, port); @@ -127,29 +130,32 @@ * @retval */ void UIPClient::stop(void) { - if(data) { + if(data && data->state) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("before stop(), with data")); + _dumpAllData(); +#endif _flushBlocks(&data->packets_in[0]); - if(data->state & UIP_CLIENT_CLOSED) { - uip_userdata_closed_t ** cc = &UIPClient::closed_conns[0]; - for(uint8_t i = 0; i < UIP_CONNS; i++) { - if(*cc == (void*)data) { - *cc = NULL; - break; - } - - cc++; - } - - free(data); + if(data->state & UIP_CLIENT_REMOTECLOSED) { + data->state = 0; } else { data->state |= UIP_CLIENT_CLOSE; } - data = NULL; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("after stop()")); + _dumpAllData(); +#endif } - _uip_conn = NULL; +#ifdef UIPETHERNET_DEBUG_CLIENT + else { + Serial.println(F("stop(), data: NULL")); + } +#endif + data = NULL; UIPEthernet.tick(); } @@ -160,7 +166,7 @@ * @retval */ uint8_t UIPClient::connected(void) { - return((_uip_conn && (_uip_conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) || available() > 0) ? 1 : 0; + return(data && (data->packets_in[0] != NOBLOCK || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0; } /** @@ -170,7 +176,7 @@ * @retval */ bool UIPClient::operator==(const UIPClient& rhs) { - return _uip_conn && rhs._uip_conn && _uip_conn == rhs._uip_conn; + return data && rhs.data && (data == rhs.data); } /** @@ -181,8 +187,7 @@ */ UIPClient::operator bool(void) { UIPEthernet.tick(); - return(data || (_uip_conn && (data = (uip_userdata_t*)_uip_conn->appstate.user))) -&& (!(data->state & UIP_CLIENT_CLOSED) || data->packets_in[0] != NOBLOCK); + return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in[0] != NOBLOCK); } /** @@ -192,7 +197,7 @@ * @retval */ size_t UIPClient::write(uint8_t c) { - return _write(_uip_conn, &c, 1); + return _write(data, &c, 1); } /** @@ -202,7 +207,7 @@ * @retval */ size_t UIPClient::write(const uint8_t* buf, size_t size) { - return _write(_uip_conn, buf, size); + return _write(data, buf, size); } /** @@ -211,21 +216,20 @@ * @param * @retval */ -size_t UIPClient::_write(struct uip_conn* conn, const uint8_t* buf, size_t size) { - uip_userdata_t* u; - int remain = size; - uint16_t written; +size_t UIPClient::_write(uip_userdata_t* u, const uint8_t* buf, size_t size) { + int remain = size; + uint16_t written; #if UIP_ATTEMPTS_ON_WRITE > 0 - uint16_t attempts = UIP_ATTEMPTS_ON_WRITE; + uint16_t attempts = UIP_ATTEMPTS_ON_WRITE; #endif repeat : UIPEthernet.tick(); - if(conn && (u = (uip_userdata_t*)conn->appstate.user) && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) { - memhandle* p = _currentBlock(&u->packets_out[0]); - if(*p == NOBLOCK) + if(u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) { + uint8_t p = _currentBlock(&u->packets_out[0]); + if(u->packets_out[p] == NOBLOCK) { newpacket: - *p = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN); - if(*p == NOBLOCK) + u->packets_out[p] = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN); + if(u->packets_out[p] == NOBLOCK) { #if UIP_ATTEMPTS_ON_WRITE > 0 if((--attempts) > 0) @@ -240,23 +244,29 @@ } #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("UIPClient.write: writePacket("); - Serial.print(*p); - Serial.print(") pos: "); + Serial.print(F("UIPClient.write: writePacket(")); + Serial.print(u->packets_out[p]); + Serial.print(F(") pos: ")); Serial.print(u->out_pos); - Serial.print(", buf["); + Serial.print(F(", buf[")); Serial.print(size - remain); - Serial.print("-"); + Serial.print(F("-")); Serial.print(remain); - Serial.print("]: '"); + Serial.print(F("]: '")); Serial.write((uint8_t*)buf + size - remain, remain); - Serial.println("'"); + Serial.println(F("'")); #endif - written = UIPEthernet.network.writePacket(*p, u->out_pos, (uint8_t*)buf + size - remain, remain); + written = UIPEthernet.network.writePacket + ( + u->packets_out[p], + u->out_pos, + (uint8_t*)buf + size - remain, + remain + ); remain -= written; u->out_pos += written; if(remain > 0) { - if(p == &u->packets_out[UIP_SOCKET_NUMPACKETS - 1]) + if(p == UIP_SOCKET_NUMPACKETS - 1) { #if UIP_ATTEMPTS_ON_WRITE > 0 if((--attempts) > 0) @@ -272,6 +282,9 @@ } ready: +#if UIP_CLIENT_TIMER >= 0 + u->timer = millis() + UIP_CLIENT_TIMER; +#endif return size - remain; } @@ -287,7 +300,7 @@ int UIPClient::available(void) { if(*this) return _available(data); - return -1; + return 0; } /** @@ -297,15 +310,9 @@ * @retval */ int UIPClient::_available(uip_userdata_t* u) { - memhandle* p = &u->packets_in[0]; - if(*p == NOBLOCK) - return 0; - int len = 0; - for(memhandle * end = p + UIP_SOCKET_NUMPACKETS; p < end; p++) { - if(*p == NOBLOCK) - break; - len += UIPEthernet.network.blockSize(*p); + for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { + len += UIPEthernet.network.blockSize(u->packets_in[i]); } return len; @@ -319,25 +326,33 @@ */ int UIPClient::read(uint8_t* buf, size_t size) { if(*this) { - int remain = size; - memhandle* p = &data->packets_in[0]; - if(*p == NOBLOCK) + uint16_t remain = size; + if(data->packets_in[0] == NOBLOCK) return 0; - int read; + uint16_t read; do { - read = UIPEthernet.network.readPacket(*p, 0, buf + size - remain, remain); - if(read == UIPEthernet.network.blockSize(*p)) { + read = UIPEthernet.network.readPacket(data->packets_in[0], 0, buf + size - remain, remain); + if(read == UIPEthernet.network.blockSize(data->packets_in[0])) { remain -= read; - _eatBlock(p); - if(_uip_conn && uip_stopped(_uip_conn) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) - data->state |= UIP_CLIENT_RESTART; - if(*p == NOBLOCK) + _eatBlock(&data->packets_in[0]); + if + ( + uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) + && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)) + ) data->state |= UIP_CLIENT_RESTART; + if(data->packets_in[0] == NOBLOCK) { + if(data->state & UIP_CLIENT_REMOTECLOSED) { + data->state = 0; + data = NULL; + } + return size - remain; + } } else { - UIPEthernet.network.resizeBlock(*p, read); + UIPEthernet.network.resizeBlock(data->packets_in[0], read); break; } } while(remain > 0); @@ -368,10 +383,9 @@ */ int UIPClient::peek(void) { if(*this) { - memhandle p = data->packets_in[0]; - if(p != NOBLOCK) { + if(data->packets_in[0] != NOBLOCK) { uint8_t c; - UIPEthernet.network.readPacket(p, 0, &c, 1); + UIPEthernet.network.readPacket(data->packets_in[0], 0, &c, 1); return c; } } @@ -397,67 +411,58 @@ * @param * @retval */ -void UIPClient::uip_callback(uip_tcp_appstate_t* s) { - uip_userdata_t* u = (uip_userdata_t*)s->user; +void uipclient_appcall(void) { + uint16_t send_len = 0; + uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate; if(!u && uip_connected()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.println("UIPClient uip_connected"); + Serial.println(F("UIPClient uip_connected")); + UIPClient::_dumpAllData(); #endif - // We want to store some data in our connections, so allocate some space + u = (uip_userdata_t*)UIPClient::_allocateData(); + if(u) { + uip_conn->appstate = u; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("UIPClient allocated state: ")); + Serial.println(u->state, BIN); +#endif + } - // for it. The connection_data struct is defined in a separate .h file, - // due to the way the Arduino IDE works. (typedefs come after function - // definitions.) - u = (uip_userdata_t*)malloc(sizeof(uip_userdata_t)); - if(u) { - memset(u, 0, sizeof(uip_userdata_t)); - s->user = u; - } +#ifdef UIPETHERNET_DEBUG_CLIENT + else + Serial.println(F("UIPClient allocation failed")); +#endif } if(u) { if(uip_newdata()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("UIPClient uip_newdata, uip_len:"); + Serial.print(F("UIPClient uip_newdata, uip_len:")); Serial.println(uip_len); #endif - if(uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) { - memhandle newPacket = UIPEthernet.network.allocBlock(uip_len); - if(newPacket != NOBLOCK) { - memhandle* p = _currentBlock(&u->packets_in[0]); - //if it's not the first packet - - if(*p != NOBLOCK) { - uint8_t slot = p - &u->packets_in[0]; - if(slot < UIP_SOCKET_NUMPACKETS - 1) - p++; - - //if this is the last slot stop this connection - if(slot >= UIP_SOCKET_NUMPACKETS - 2) { - uip_stop(); - - //if there's no free slot left omit loosing this packet and (again) stop this connection - if(slot == UIP_SOCKET_NUMPACKETS - 1) - goto reject_newdata; + if(uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) { + for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { + if(u->packets_in[i] == NOBLOCK) { + u->packets_in[i] = UIPEthernet.network.allocBlock(uip_len); + if(u->packets_in[i] != NOBLOCK) { + UIPEthernet.network.copyPacket + ( + u->packets_in[i], + 0, + UIPEthernetClass::in_packet, + ((uint8_t*)uip_appdata) - uip_buf, + uip_len + ); + if(i == UIP_SOCKET_NUMPACKETS - 1) + uip_stop(); + goto finish_newdata; } } - - UIPEthernet.network.copyPacket - ( - newPacket, - 0, - UIPEthernet.in_packet, - ((uint8_t*)uip_appdata) - uip_buf, - uip_len - ); - *p = newPacket; - goto finish_newdata; } -reject_newdata: - UIPEthernet.packetstate &= ~UIPETHERNET_FREEPACKET; + UIPEthernetClass::packetstate &= ~UIPETHERNET_FREEPACKET; uip_stop(); } } @@ -472,66 +477,67 @@ if(uip_closed() || uip_timedout()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.println("UIPClient uip_closed"); + Serial.println(F("UIPClient uip_closed")); + UIPClient::_dumpAllData(); #endif // drop outgoing packets not sent yet: - _flushBlocks(&u->packets_out[0]); + UIPClient::_flushBlocks(&u->packets_out[0]); if(u->packets_in[0] != NOBLOCK) { - uip_userdata_closed_t ** closed_conn_data = &UIPClient::closed_conns[0]; - for(uip_socket_ptr i = 0; i < UIP_CONNS; i++) { - if(!*closed_conn_data) { - *closed_conn_data = (uip_userdata_closed_t*)u; - (*closed_conn_data)->lport = uip_conn->lport; - break; - } - - closed_conn_data++; - } + ((uip_userdata_closed_t*)u)->lport = uip_conn->lport; + u->state |= UIP_CLIENT_REMOTECLOSED; } - - u->state |= UIP_CLIENT_CLOSED; + else + u->state = 0; // disassociate appdata. - s->user = NULL; - goto nodata; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("after UIPClient uip_closed")); + UIPClient::_dumpAllData(); +#endif + uip_conn->appstate = NULL; + goto finish; } if(uip_acked()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.println("UIPClient uip_acked"); + Serial.println(F("UIPClient uip_acked")); #endif - _eatBlock(&u->packets_out[0]); + UIPClient::_eatBlock(&u->packets_out[0]); } if(uip_poll() || uip_rexmit()) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.println("UIPClient uip_poll"); + //Serial.println(F("UIPClient uip_poll")); #endif - - memhandle p = u->packets_out[0]; - if(p != NOBLOCK) { + if(u->packets_out[0] != NOBLOCK) { if(u->packets_out[1] == NOBLOCK) { - uip_len = u->out_pos; - if(uip_len > 0) { - UIPEthernet.network.resizeBlock(p, 0, uip_len); + send_len = u->out_pos; + if(send_len > 0) { + UIPEthernet.network.resizeBlock(u->packets_out[0], 0, send_len); } } else - uip_len = UIPEthernet.network.blockSize(p); - if(uip_len > 0) { - UIPEthernet.uip_hdrlen = ((uint8_t*)uip_appdata) - uip_buf; - UIPEthernet.uip_packet = UIPEthernet.network.allocBlock(UIPEthernet.uip_hdrlen + uip_len); - if(UIPEthernet.uip_packet != NOBLOCK) { - UIPEthernet.network.copyPacket(UIPEthernet.uip_packet, UIPEthernet.uip_hdrlen, p, 0, uip_len); - UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET; - uip_send(uip_appdata, uip_len); + send_len = UIPEthernet.network.blockSize(u->packets_out[0]); + if(send_len > 0) { + UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata) - uip_buf; + UIPEthernetClass::uip_packet = UIPEthernet.network.allocBlock(UIPEthernetClass::uip_hdrlen + send_len); + if(UIPEthernetClass::uip_packet != NOBLOCK) { + UIPEthernet.network.copyPacket + ( + UIPEthernetClass::uip_packet, + UIPEthernetClass::uip_hdrlen, + u->packets_out[0], + 0, + send_len + ); + UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; } + } - return; - } + goto finish; } } @@ -539,25 +545,30 @@ if(u->state & UIP_CLIENT_CLOSE) { #ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("UIPClient state UIP_CLIENT_CLOSE"); -#endif - if(u->packets_out[0] == NOBLOCK) - { -#ifdef UIPETHERNET_DEBUG_CLIENT - Serial.print("UIPClient state UIP_CLIENT_CLOSE -> free userdata"); + Serial.println(F("UIPClient state UIP_CLIENT_CLOSE")); + UIPClient::_dumpAllData(); #endif - free(u); - s->user = NULL; + if(u->packets_out[0] == NOBLOCK) { + u->state = 0; + uip_conn->appstate = NULL; uip_close(); +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("no blocks out -> free userdata")); + UIPClient::_dumpAllData(); +#endif } - else + else { uip_stop(); +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("blocks outstanding transfer -> uip_stop()")); +#endif + } } } -nodata: - UIPEthernet.uip_packet = NOBLOCK; - uip_len = 0; +finish: + uip_send(uip_appdata, send_len); + uip_len = send_len; } /** @@ -566,11 +577,32 @@ * @param * @retval */ -memhandle* UIPClient::_currentBlock(memhandle* block) { - for(memhandle * end = block + UIP_SOCKET_NUMPACKETS - 1; block < end; block++) - if(*(block + 1) == NOBLOCK) - break; - return block; +uip_userdata_t* UIPClient::_allocateData(void) { + for(uint8_t sock = 0; sock < UIP_CONNS; sock++) { + uip_userdata_t* data = &UIPClient::all_data[sock]; + if(!data->state) { + data->state = sock | UIP_CLIENT_CONNECTED; + memset(&data->packets_in[0], 0, sizeof(uip_userdata_t) - sizeof(data->state)); + return data; + } + } + + return NULL; +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint8_t UIPClient::_currentBlock(memhandle* block) { + for(uint8_t i = 1; i < UIP_SOCKET_NUMPACKETS; i++) { + if(block[i] == NOBLOCK) + return i - 1; + } + + return UIP_SOCKET_NUMPACKETS - 1; } /** @@ -583,26 +615,26 @@ { #ifdef UIPETHERNET_DEBUG_CLIENT memhandle* start = block; - Serial.print("eatblock("); + Serial.print(F("eatblock(")); Serial.print(*block); - Serial.print("): "); + Serial.print(F("): ")); for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { Serial.print(start[i]); - Serial.print(" "); + Serial.print(F(" ")); } - Serial.print("-> "); + Serial.print(F("-> ")); #endif + UIPEthernet.network.freeBlock(block[0]); + for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS - 1; i++) { + block[i] = block[i + 1]; + } - memhandle* end = block + (UIP_SOCKET_NUMPACKETS - 1); - UIPEthernet.network.freeBlock(*block); - while(block < end) - *block = *((block++) + 1); - *end = NOBLOCK; + block[UIP_SOCKET_NUMPACKETS - 1] = NOBLOCK; #ifdef UIPETHERNET_DEBUG_CLIENT for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { Serial.print(start[i]); - Serial.print(" "); + Serial.print(F(" ")); } Serial.println(); @@ -616,13 +648,48 @@ * @retval */ void UIPClient::_flushBlocks(memhandle* block) { - for(memhandle * end = block + UIP_SOCKET_NUMPACKETS; block < end; block++) { - if(*block != NOBLOCK) { - UIPEthernet.network.freeBlock(*block); - *block = NOBLOCK; - } - else - break; + for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) { + UIPEthernet.network.freeBlock(block[i]); + block[i] = NOBLOCK; } } +#ifdef UIPETHERNET_DEBUG_CLIENT + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPClient::_dumpAllData(void) { + for(uint8_t i = 0; i < UIP_CONNS; i++) { + Serial.print(F("UIPClient::all_data[")); + Serial.print(i); + Serial.print(F("], state:")); + Serial.println(all_data[i].state, BIN); + Serial.print(F("packets_in: ")); + for(uint8_t j = 0; j < UIP_SOCKET_NUMPACKETS; j++) { + Serial.print(all_data[i].packets_in[j]); + Serial.print(F(" ")); + } + + Serial.println(); + if(all_data[i].state & UIP_CLIENT_REMOTECLOSED) { + Serial.print(F("state remote closed, local port: ")); + Serial.println(htons(((uip_userdata_closed_t *) (&all_data[i]))->lport)); + } + else { + Serial.print(F("packets_out: ")); + for(uint8_t j = 0; j < UIP_SOCKET_NUMPACKETS; j++) { + Serial.print(all_data[i].packets_out[j]); + Serial.print(F(" ")); + } + + Serial.println(); + Serial.print(F("out_pos: ")); + Serial.println(all_data[i].out_pos); + } + } +} +#endif
--- a/UIPClient.h Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPClient.h Sun Mar 08 20:26:56 2015 +0000 @@ -16,83 +16,97 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ + #ifndef UIPCLIENT_H - #define UIPCLIENT_H +#define UIPCLIENT_H - #include "ethernet_comp.h" - #include "Client.h" - #include "utility/mempool.h" +#include "ethernet_comp.h" +//#include "Print.h" +#include "Client.h" +#include "utility/mempool.h" + +extern "C" { + #include "utility/uip.h" +} -extern "C" -{ - #include "utility/uip.h" -} - #define UIP_SOCKET_DATALEN UIP_TCP_MSS +#define UIP_SOCKET_DATALEN UIP_TCP_MSS //#define UIP_SOCKET_NUMPACKETS UIP_RECEIVE_WINDOW/UIP_TCP_MSS+1 +#ifndef UIP_SOCKET_NUMPACKETS +#define UIP_SOCKET_NUMPACKETS 5 +#endif - #ifndef UIP_SOCKET_NUMPACKETS - #define UIP_SOCKET_NUMPACKETS 5 - #endif - #define UIP_CLIENT_CLOSE 1 - #define UIP_CLIENT_CLOSED 2 - #define UIP_CLIENT_RESTART 4 +#define UIP_CLIENT_CONNECTED 0x10 +#define UIP_CLIENT_CLOSE 0x20 +#define UIP_CLIENT_REMOTECLOSED 0x40 +#define UIP_CLIENT_RESTART 0x80 +#define UIP_CLIENT_STATEFLAGS (UIP_CLIENT_CONNECTED | UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED | UIP_CLIENT_RESTART) +#define UIP_CLIENT_SOCKETS ~UIP_CLIENT_STATEFLAGS typedef uint8_t uip_socket_ptr; -typedef struct -{ - uint8_t state; - memhandle packets_in[UIP_SOCKET_NUMPACKETS]; - uint16_t lport; /**< The local TCP port, in network byte order. */ +typedef struct { + uint8_t state; + memhandle packets_in[UIP_SOCKET_NUMPACKETS]; + uint16_t lport; /**< The local TCP port, in network byte order. */ } uip_userdata_closed_t; -typedef struct -{ - uint8_t state; - memhandle packets_in[UIP_SOCKET_NUMPACKETS]; - memhandle packets_out[UIP_SOCKET_NUMPACKETS]; - memaddress out_pos; +typedef struct { + uint8_t state; + memhandle packets_in[UIP_SOCKET_NUMPACKETS]; + memhandle packets_out[UIP_SOCKET_NUMPACKETS]; + memaddress out_pos; +#if UIP_CLIENT_TIMER >= 0 + unsigned long timer; +#endif } uip_userdata_t; -class UIPClient : - public Client -{ +class UIPClient : public Client { + public: - UIPClient(void); - int connect(IPAddress ip, uint16_t port); - int connect(const char* host, uint16_t port); - int read(uint8_t* buf, size_t size); - void stop(void); - uint8_t connected(void); - operator bool(void); - virtual bool operator ==(const EthernetClient& ); - virtual bool operator !=(const EthernetClient& rhs) { return !this->operator ==(rhs); }; + UIPClient(); + int connect(IPAddress ip, uint16_t port); + int connect(const char *host, uint16_t port); + int read(uint8_t *buf, size_t size); + void stop(); + uint8_t connected(); + operator bool(); + virtual bool operator==(const EthernetClient&); + virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; - size_t write(uint8_t); - size_t write(const uint8_t* buf, size_t size); - int available(void); - int read(void); - int peek(void); - void flush(void); + size_t write(uint8_t); + size_t write(const uint8_t *buf, size_t size); + int available(); + int read(); + int peek(); + void flush(); + +// using Print::write; + private: - UIPClient(struct uip_conn* _conn); - UIPClient(uip_userdata_closed_t* closed_conn); + UIPClient(struct uip_conn *_conn); + UIPClient(uip_userdata_t* conn_data); + + uip_userdata_t* data; - struct uip_conn* _uip_conn; + static uip_userdata_t all_data[UIP_CONNS]; + static uip_userdata_t* _allocateData(); - uip_userdata_t* data; - - static uip_userdata_closed_t* closed_conns[UIP_CONNS]; + static size_t _write(uip_userdata_t *,const uint8_t *buf, size_t size); + static int _available(uip_userdata_t *); - static size_t _write(struct uip_conn* , const uint8_t* buf, size_t size); - static int _available(uip_userdata_t* ); + static uint8_t _currentBlock(memhandle* blocks); + static void _eatBlock(memhandle* blocks); + static void _flushBlocks(memhandle* blocks); + +#ifdef UIPETHERNET_DEBUG_CLIENT + static void _dumpAllData(); +#endif - static memhandle* _currentBlock(memhandle* blocks); - static void _eatBlock(memhandle* blocks); - static void _flushBlocks(memhandle* blocks); + friend class UIPEthernetClass; + friend class UIPServer; - friend class UIPEthernetClass; - friend class UIPServer; - static void uip_callback(uip_tcp_appstate_t* s); + friend void uipclient_appcall(void); + }; + #endif
--- a/UIPEthernet.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPEthernet.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -1,591 +1,621 @@ -/* - UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#pragma once -#include <mbed.h> -#include "UIPEthernet.h" -#include "utility/Enc28J60Network.h" - -#if (defined UIPETHERNET_DEBUG || defined UIPETHERNET_DEBUG_CHKSUM) - #include "HardwareSerial.h" -#endif -extern "C" -{ -#include "utility/uip-conf.h" -#include "utility/uip.h" -#include "utility/uip_arp.h" -#include "utility/uip_timer.h" -} -#define ETH_HDR ((struct uip_eth_hdr*) &uip_buf[0]) - -// Because uIP isn't encapsulated within a class we have to use global - -// variables, so we can only have one TCP/IP stack per program. -UIPEthernetClass::UIPEthernetClass(PinName mosi, PinName miso, PinName sck, PinName cs) : - network(mosi, miso, sck, cs), - fn_uip_cb(NULL), - fn_uip_udp_cb(NULL), - in_packet(NOBLOCK), - uip_packet(NOBLOCK), - uip_hdrlen(0), - packetstate(0), - _dhcp(NULL) -{ } - -/** - * @brief - * @note - * @param - * @retval - */ -int UIPEthernetClass::begin(const uint8_t* mac) { - static DhcpClass s_dhcp; - _dhcp = &s_dhcp; - - // Initialise the basic info - init(mac); - - // Now try to get our config info from a DHCP server - int ret = _dhcp->beginWithDHCP((uint8_t*)mac); - if(ret == 1) { - - // We've successfully found a DHCP server and got our configuration info, so set things - // accordingly - configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); - } - - return ret; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) { - IPAddress dns = ip; - dns[3] = 1; - begin(mac, ip, dns); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) { - IPAddress gateway = ip; - gateway[3] = 1; - begin(mac, ip, dns, gateway); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) { - IPAddress subnet(255, 255, 255, 0); - begin(mac, ip, dns, gateway, subnet); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { - init(mac); - configure(ip, dns, gateway, subnet); -} - -/** - * @brief - * @note - * @param - * @retval - */ -int UIPEthernetClass::maintain(void) { - tick(); - - int rc = DHCP_CHECK_NONE; - if(_dhcp != NULL) { - - //we have a pointer to dhcp, use it - rc = _dhcp->checkLease(); - switch(rc) { - case DHCP_CHECK_NONE: - //nothing done - break; - - case DHCP_CHECK_RENEW_OK: - case DHCP_CHECK_REBIND_OK: - //we might have got a new IP. - configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); - break; - - default: - //this is actually a error, it will retry though - break; - } - } - - return rc; -} - -/** - * @brief - * @note - * @param - * @retval - */ -IPAddress UIPEthernetClass::localIP(void) { - IPAddress ret; - uip_ipaddr_t a; - uip_gethostaddr(a); - return ip_addr_uip(a); -} - -/** - * @brief - * @note - * @param - * @retval - */ -IPAddress UIPEthernetClass::subnetMask(void) { - IPAddress ret; - uip_ipaddr_t a; - uip_getnetmask(a); - return ip_addr_uip(a); -} - -/** - * @brief - * @note - * @param - * @retval - */ -IPAddress UIPEthernetClass::gatewayIP(void) { - IPAddress ret; - uip_ipaddr_t a; - uip_getdraddr(a); - return ip_addr_uip(a); -} - -/** - * @brief - * @note - * @param - * @retval - */ -IPAddress UIPEthernetClass::dnsServerIP(void) { - return _dnsServerAddress; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::tick(void) { - if(in_packet == NOBLOCK) { - in_packet = network.receivePacket(); -#ifdef UIPETHERNET_DEBUG - if(in_packet != NOBLOCK) { - Serial.print("--------------\nreceivePacket: "); - Serial.println(in_packet); - } -#endif - } - - if(in_packet != NOBLOCK) { - packetstate = UIPETHERNET_FREEPACKET; - uip_len = network.blockSize(in_packet); - if(uip_len > 0) { - network.readPacket(in_packet, 0, (uint8_t*)uip_buf, UIP_BUFSIZE); - if(ETH_HDR->type == HTONS(UIP_ETHTYPE_IP)) { - uip_packet = in_packet; -#ifdef UIPETHERNET_DEBUG - Serial.print("readPacket type IP, uip_len: "); - Serial.println(uip_len); -#endif - uip_arp_ipin(); - uip_input(); - if(uip_len > 0) { - uip_arp_out(); - network_send(); - } - } - else - if(ETH_HDR->type == HTONS(UIP_ETHTYPE_ARP)) - { -#ifdef UIPETHERNET_DEBUG - Serial.print("readPacket type ARP, uip_len: "); - Serial.println(uip_len); -#endif - uip_arp_arpin(); - if(uip_len > 0) { - network_send(); - } - } - } - - if(in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) - { -#ifdef UIPETHERNET_DEBUG - Serial.print("freeing packet: "); - Serial.println(in_packet); -#endif - network.freePacket(); - in_packet = NOBLOCK; - } - } - - if(uip_timer_expired(&periodic_timer)) { - uip_timer_restart(&periodic_timer); - for(int i = 0; i < UIP_CONNS; i++) { - uip_periodic(i); - - // If the above function invocation resulted in data that - // should be sent out on the network, the global variable - // uip_len is set to a value > 0. - if(uip_len > 0) { - uip_arp_out(); - network_send(); - } - } - -#if UIP_UDP - for(int i = 0; i < UIP_UDP_CONNS; i++) { - uip_udp_periodic(i); - - // If the above function invocation resulted in data that - // should be sent out on the network, the global variable - // uip_len is set to a value > 0. */ - if(uip_len > 0) { - network_send(); - } - } -#endif /* UIP_UDP */ - } -} - -/** - * @brief - * @note - * @param - * @retval - */ -bool UIPEthernetClass::network_send(void) { - if(packetstate & UIPETHERNET_SENDPACKET) - { -#ifdef UIPETHERNET_DEBUG - Serial.print("network_send uip_packet: "); - Serial.print(uip_packet); - Serial.print(", hdrlen: "); - Serial.println(uip_hdrlen); -#endif - network.writePacket(uip_packet, 0, uip_buf, uip_hdrlen); - goto sendandfree; - } - - uip_packet = network.allocBlock(uip_len); - if(uip_packet != NOBLOCK) - { -#ifdef UIPETHERNET_DEBUG - Serial.print("network_send uip_buf (uip_len): "); - Serial.print(uip_len); - Serial.print(", packet: "); - Serial.println(uip_packet); -#endif - network.writePacket(uip_packet, 0, uip_buf, uip_len); - goto sendandfree; - } - - return false; -sendandfree: - network.sendPacket(uip_packet); - network.freeBlock(uip_packet); - uip_packet = NOBLOCK; - return true; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::init(const uint8_t* mac) { - uip_timer_set(&this->periodic_timer, CLOCK_SECOND / 4); - - network.init((uint8_t*)mac); - uip_seteth_addr(mac); - - uip_init(); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { - uip_ipaddr_t ipaddr; - - uip_ip_addr(ipaddr, ip); - uip_sethostaddr(ipaddr); - - uip_ip_addr(ipaddr, gateway); - uip_setdraddr(ipaddr); - - uip_ip_addr(ipaddr, subnet); - uip_setnetmask(ipaddr); - - _dnsServerAddress = dns; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::set_uip_callback(fn_uip_cb_t fn) { - this->fn_uip_cb = fn; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::uip_callback(void) { - struct uipethernet_state* s = &(uip_conn->appstate); - - if(this->fn_uip_cb) { - - // The sketch wants to handle all uIP events itself, using uIP functions. - this->fn_uip_cb(s); //->p, &s->user); - } -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::set_uip_udp_callback(fn_uip_udp_cb_t fn) { - this->fn_uip_udp_cb = fn; -} - -#if UIP_UDP - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPEthernetClass::uip_udp_callback(void) { - struct uipudp_state* s = &(uip_udp_conn->appstate); - - if(this->fn_uip_udp_cb) { - - // The sketch wants to handle all uIP events itself, using uIP functions. - this->fn_uip_udp_cb(s); //->p, &s->user); - } -} -#endif -//UIPEthernetClass UIPEthernet; - -// uIP callback function -void uipethernet_appcall(void) { - UIPEthernet.uip_callback(); -} - -#if UIP_UDP - -/** - * @brief - * @note - * @param - * @retval - */ -void uipudp_appcall(void) { - UIPEthernet.uip_udp_callback(); -} -#endif - -/*---------------------------------------------------------------------------*/ -uint16_t UIPEthernetClass::chksum(uint16_t sum, const uint8_t* data, uint16_t len) { - uint16_t t; - const uint8_t* dataptr; - const uint8_t* last_byte; - - dataptr = data; - last_byte = data + len - 1; - - while(dataptr < last_byte) { - - /* At least two more bytes */ - t = (dataptr[0] << 8) + dataptr[1]; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - - dataptr += 2; - } - - if(dataptr == last_byte) { - t = (dataptr[0] << 8) + 0; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - } - - /* Return sum in host byte order. */ - return sum; -} - -/*---------------------------------------------------------------------------*/ -uint16_t UIPEthernetClass::ipchksum(void) { - uint16_t sum; - - sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); - return(sum == 0) ? 0xffff : htons(sum); -} - -/*---------------------------------------------------------------------------*/ -uint16_t UIPEthernetClass::upper_layer_chksum(uint8_t proto) { - uint16_t upper_layer_len; - uint16_t sum; - -#if UIP_CONF_IPV6 - upper_layer_len = (((u16_t) (BUF->len[0]) << 8) + BUF->len[1]); -#else /* UIP_CONF_IPV6 */ - upper_layer_len = (((u16_t) (BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; -#endif /* UIP_CONF_IPV6 */ - - /* First sum pseudoheader. */ - - /* IP protocol and length fields. This addition cannot carry. */ - sum = upper_layer_len + proto; - - /* Sum IP source and destination addresses. */ - sum = chksum(sum, (u8_t*) &BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); - - uint8_t upper_layer_memlen; - switch(proto) { - case UIP_PROTO_ICMP: - case UIP_PROTO_ICMP6: - upper_layer_memlen = upper_layer_len; - break; - - case UIP_PROTO_TCP: - upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; - break; -#if UIP_UDP - - case UIP_PROTO_UDP: - upper_layer_memlen = UIP_UDPH_LEN; - break; -#endif - } - - sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); -#ifdef UIPETHERNET_DEBUG_CHKSUM - Serial.print("chksum uip_buf["); - Serial.print(UIP_IPH_LEN + UIP_LLH_LEN); - Serial.print("-"); - Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); - Serial.print("]: "); - Serial.println(htons(sum), HEX); -#endif - if(upper_layer_memlen < upper_layer_len) { - sum = network.chksum - ( - sum, - uip_packet, - UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, - upper_layer_len - upper_layer_memlen - ); -#ifdef UIPETHERNET_DEBUG_CHKSUM - Serial.print("chksum uip_packet("); - Serial.print(uip_packet); - Serial.print(")["); - Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); - Serial.print("-"); - Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); - Serial.print("]: "); - Serial.println(htons(sum), HEX); -#endif - } - - return(sum == 0) ? 0xffff : htons(sum); -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t uip_ipchksum(void) { - return UIPEthernet.ipchksum(); -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t uip_tcpchksum(void) { - uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); - return sum; -} - -#if UIP_UDP - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t uip_udpchksum(void) { - uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); - return sum; -} -#endif - - - +/* + UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <mbed.h> +#include "UIPEthernet.h" +#include "utility/Enc28J60Network.h" + +#if (defined UIPETHERNET_DEBUG || defined UIPETHERNET_DEBUG_CHKSUM) + #include "HardwareSerial.h" +#endif +#include "UIPUdp.h" + +extern "C" +{ +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +#include "utility/uip_timer.h" +#include "utility/millis.h" +} +#define ETH_HDR ((struct uip_eth_hdr*) &uip_buf[0]) + +memhandle UIPEthernetClass:: in_packet(NOBLOCK); +memhandle UIPEthernetClass:: uip_packet(NOBLOCK); +uint8_t UIPEthernetClass:: uip_hdrlen(0); +uint8_t UIPEthernetClass:: packetstate(0); + +IPAddress UIPEthernetClass:: _dnsServerAddress; +DhcpClass* UIPEthernetClass:: _dhcp(NULL); + +unsigned long UIPEthernetClass:: periodic_timer; + +/** + * @brief + * @note + * @param + * @retval + */ +void enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) { + + //void + + //Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len) + //{ + //as ENC28J60 DMA is unable to copy single bytes: + if(len == 1) { + UIPEthernet.network.writeByte(dest, UIPEthernet.network.readByte(src)); + } + else { + + // calculate address of last byte + len += src - 1; + + /* 1. Appropriately program the EDMAST, EDMAND + and EDMADST register pairs. The EDMAST + registers should point to the first byte to copy + from, the EDMAND registers should point to the + last byte to copy and the EDMADST registers + should point to the first byte in the destination + range. The destination range will always be + linear, never wrapping at any values except from + 8191 to 0 (the 8-Kbyte memory boundary). + Extreme care should be taken when + programming the start and end pointers to + prevent a never ending DMA operation which + would overwrite the entire 8-Kbyte buffer. + */ + UIPEthernet.network.writeRegPair(EDMASTL, src); + UIPEthernet.network.writeRegPair(EDMADSTL, dest); + + if((src <= RXSTOP_INIT) && (len > RXSTOP_INIT)) + len -= (RXSTOP_INIT - RXSTART_INIT); + UIPEthernet.network.writeRegPair(EDMANDL, len); + + /* + 2. If an interrupt at the end of the copy process is + desired, set EIE.DMAIE and EIE.INTIE and + clear EIR.DMAIF. + + 3. Verify that ECON1.CSUMEN is clear. */ + UIPEthernet.network.writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); + + /* 4. Start the DMA copy by setting ECON1.DMAST. */ + UIPEthernet.network.writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); + + // wait until runnig DMA is completed + while(UIPEthernet.network.readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST); + } +} + +// Because uIP isn't encapsulated within a class we have to use global + +// variables, so we can only have one TCP/IP stack per program. +UIPEthernetClass::UIPEthernetClass(PinName mosi, PinName miso, PinName sck, PinName cs) : + network(mosi, miso, sck, cs) { + millis_start(); +} + +#if UIP_UDP + +/** + * @brief + * @note + * @param + * @retval + */ +int UIPEthernetClass::begin(const uint8_t* mac) { + static DhcpClass s_dhcp; + _dhcp = &s_dhcp; + + // Initialise the basic info + init(mac); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP((uint8_t*)mac); + if(ret == 1) { + + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); + } + + return ret; +} +#endif + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) { + IPAddress dns = ip; + dns[3] = 1; + begin(mac, ip, dns); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) { + IPAddress gateway = ip; + gateway[3] = 1; + begin(mac, ip, dns, gateway); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) { + IPAddress subnet(255, 255, 255, 0); + begin(mac, ip, dns, gateway, subnet); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + init(mac); + configure(ip, dns, gateway, subnet); +} + +/** + * @brief + * @note + * @param + * @retval + */ +int UIPEthernetClass::maintain(void) { + tick(); + + int rc = DHCP_CHECK_NONE; +#if UIP_UDP + if(_dhcp != NULL) { + + //we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + switch(rc) { + case DHCP_CHECK_NONE: + //nothing done + break; + + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); + break; + + default: + //this is actually a error, it will retry though + break; + } + } + + return rc; +#endif +} + +/** + * @brief + * @note + * @param + * @retval + */ +IPAddress UIPEthernetClass::localIP(void) { + IPAddress ret; + uip_ipaddr_t a; + uip_gethostaddr(a); + return ip_addr_uip(a); +} + +/** + * @brief + * @note + * @param + * @retval + */ +IPAddress UIPEthernetClass::subnetMask(void) { + IPAddress ret; + uip_ipaddr_t a; + uip_getnetmask(a); + return ip_addr_uip(a); +} + +/** + * @brief + * @note + * @param + * @retval + */ +IPAddress UIPEthernetClass::gatewayIP(void) { + IPAddress ret; + uip_ipaddr_t a; + uip_getdraddr(a); + return ip_addr_uip(a); +} + +/** + * @brief + * @note + * @param + * @retval + */ +IPAddress UIPEthernetClass::dnsServerIP(void) { + return _dnsServerAddress; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPEthernetClass::tick(void) +{ + if(in_packet == NOBLOCK) { + in_packet = network.receivePacket(); +#ifdef UIPETHERNET_DEBUG + if(in_packet != NOBLOCK) { + Serial.print(F("--------------\nreceivePacket: ")); + Serial.println(in_packet); + } +#endif + } + if(in_packet != NOBLOCK) { + packetstate = UIPETHERNET_FREEPACKET; + uip_len = network.blockSize(in_packet); + if(uip_len > 0) { + network.readPacket(in_packet, 0, (uint8_t*)uip_buf, UIP_BUFSIZE); + if(ETH_HDR->type == HTONS(UIP_ETHTYPE_IP)) { + uip_packet = in_packet; //required for upper_layer_checksum of in_packet! +#ifdef UIPETHERNET_DEBUG + Serial.print(F("readPacket type IP, uip_len: ")); + Serial.println(uip_len); +#endif + uip_arp_ipin(); + uip_input(); + if(uip_len > 0) { + uip_arp_out(); + network_send(); + } + } + else + if(ETH_HDR->type == HTONS(UIP_ETHTYPE_ARP)) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("readPacket type ARP, uip_len: ")); + Serial.println(uip_len); +#endif + uip_arp_arpin(); + if(uip_len > 0) { + network_send(); + } + } + } + if(in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("freeing packet: ")); + Serial.println(in_packet); +#endif + network.freePacket(); + in_packet = NOBLOCK; + } + } + unsigned long now = millis(); + +#if UIP_CLIENT_TIMER >= 0 + bool periodic = (long)(now - periodic_timer) >= 0; + for(int i = 0; i < UIP_CONNS; i++) + { +#else + if((long)(now - periodic_timer) >= 0) { + periodic_timer = now + UIP_PERIODIC_TIMER; + + for(int i = 0; i < UIP_CONNS; i++) + { +#endif + uip_conn = &uip_conns[i]; +#if UIP_CLIENT_TIMER >= 0 + if(periodic) + { +#endif + uip_process(UIP_TIMER); +#if UIP_CLIENT_TIMER >= 0 + } + else { + if((long)(now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) + uip_process(UIP_POLL_REQUEST); + else + continue; + } +#endif + // If the above function invocation resulted in data that + + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. + if(uip_len > 0) { + uip_arp_out(); + network_send(); + } + } +#if UIP_CLIENT_TIMER >= 0 + if(periodic) { + periodic_timer = now + UIP_PERIODIC_TIMER; +#endif +#if UIP_UDP + for(int i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. */ + if(uip_len > 0) { + UIPUDP::_send((uip_udp_userdata_t *) (uip_udp_conns[i].appstate)); + } + } +#endif /* UIP_UDP */ + } + } + + /** + * @brief + * @note + * @param + * @retval + */ + bool UIPEthernetClass::network_send(void) { + if(packetstate & UIPETHERNET_SENDPACKET) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("Enc28J60Network_send uip_packet: ")); + Serial.print(uip_packet); + Serial.print(F(", hdrlen: ")); + Serial.println(uip_hdrlen); +#endif + UIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_hdrlen); + packetstate &= ~UIPETHERNET_SENDPACKET; + goto sendandfree; + } + + uip_packet = Enc28J60Network::allocBlock(uip_len); + if(uip_packet != NOBLOCK) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("Enc28J60Network_send uip_buf (uip_len): ")); + Serial.print(uip_len); + Serial.print(F(", packet: ")); + Serial.println(uip_packet); +#endif + UIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_len); + goto sendandfree; + } + + return false; +sendandfree: + network.sendPacket(uip_packet); + Enc28J60Network::freeBlock(uip_packet); + uip_packet = NOBLOCK; + return true; + } + + /** + * @brief + * @note + * @param + * @retval + */ + void UIPEthernetClass::init(const uint8_t* mac) { + periodic_timer = millis() + UIP_PERIODIC_TIMER; + + network.init((uint8_t*)mac); + uip_seteth_addr(mac); + + uip_init(); + uip_arp_init(); + } + + /** + * @brief + * @note + * @param + * @retval + */ + void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + uip_ipaddr_t ipaddr; + + uip_ip_addr(ipaddr, ip); + uip_sethostaddr(ipaddr); + + uip_ip_addr(ipaddr, gateway); + uip_setdraddr(ipaddr); + + uip_ip_addr(ipaddr, subnet); + uip_setnetmask(ipaddr); + + _dnsServerAddress = dns; + } + + //UIPEthernetClass UIPEthernet; + + /*---------------------------------------------------------------------------*/ + uint16_t UIPEthernetClass::chksum(uint16_t sum, const uint8_t* data, uint16_t len) { + uint16_t t; + const uint8_t* dataptr; + const uint8_t* last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while(dataptr < last_byte) { + + /* At least two more bytes */ + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + + dataptr += 2; + } + + if(dataptr == last_byte) { + t = (dataptr[0] << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; + } + + /*---------------------------------------------------------------------------*/ + uint16_t UIPEthernetClass::ipchksum(void) { + uint16_t sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + return(sum == 0) ? 0xffff : htons(sum); + } + + /*---------------------------------------------------------------------------*/ + uint16_t +#if UIP_UDP + UIPEthernetClass::upper_layer_chksum(uint8_t proto) +#else + uip_tcpchksum (void) +#endif + { + uint16_t upper_layer_len; + uint16_t sum; + +#if UIP_CONF_IPV6 + upper_layer_len = (((u16_t) (BUF->len[0]) << 8) + BUF->len[1]); +#else /* UIP_CONF_IPV6 */ + upper_layer_len = (((u16_t) (BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* UIP_CONF_IPV6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ +#if UIP_UDP + sum = upper_layer_len + proto; +#else + sum = upper_layer_len + UIP_PROTO_TCP; +#endif + /* Sum IP source and destination addresses. */ + + sum = UIPEthernetClass::chksum(sum, (u8_t*) &BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + uint8_t upper_layer_memlen; +#if UIP_UDP + switch(proto) { + // case UIP_PROTO_ICMP: + // case UIP_PROTO_ICMP6: + // upper_layer_memlen = upper_layer_len; + // break; + case UIP_PROTO_UDP: + upper_layer_memlen = UIP_UDPH_LEN; + break; + + default: + // case UIP_PROTO_TCP: +#endif + upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; +#if UIP_UDP + break; + } +#endif + sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); +#ifdef UIPETHERNET_DEBUG_CHKSUM + Serial.print(F("chksum uip_buf[")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN); + Serial.print(F("-")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + Serial.print(F("]: ")); + Serial.println(htons(sum), HEX); +#endif + if(upper_layer_memlen < upper_layer_len) { + sum = network.chksum + ( + sum, UIPEthernetClass::uip_packet, UIP_IPH_LEN + + UIP_LLH_LEN + + upper_layer_memlen, upper_layer_len - + upper_layer_memlen + ); +#ifdef UIPETHERNET_DEBUG_CHKSUM + Serial.print(F("chksum uip_packet(")); + Serial.print(uip_packet); + Serial.print(F(")[")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + Serial.print(F("-")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); + Serial.print(F("]: ")); + Serial.println(htons(sum), HEX); +#endif + } + return(sum == 0) ? 0xffff : htons(sum); + } + + /** + * @brief + * @note + * @param + * @retval + */ + uint16_t uip_ipchksum(void) { + return UIPEthernet.ipchksum(); + } + +#if UIP_UDP + /** + * @brief + * @note + * @param + * @retval + */ + uint16_t uip_tcpchksum(void) { + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); + return sum; + } + + /** + * @brief + * @note + * @param + * @retval + */ + uint16_t uip_udpchksum(void) { + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); + return sum; + } +#endif
--- a/UIPEthernet.h Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPEthernet.h Sun Mar 08 20:26:56 2015 +0000 @@ -1,140 +1,130 @@ -/* - UIPEthernet.h - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#pragma once -#ifndef UIPETHERNET_H - #define UIPETHERNET_H - - #include "ethernet_comp.h" - #include <mbed.h> - #include "Dhcp.h" - #include "utility/IPAddress.h" - #include "utility/Enc28J60Network.h" - #include "UIPClient.h" - #include "UIPServer.h" - #include "UIPUdp.h" - -extern "C" -{ - #include "utility/uip_timer.h" - #include "utility/uip.h" -} -//#define UIPETHERNET_DEBUG -//#define UIPETHERNET_DEBUG_CHKSUM -//#define UIPETHERNET_DEBUG_UDP -//#define UIPETHERNET_DEBUG_CLIENT - #define UIPETHERNET_FREEPACKET 1 - #define UIPETHERNET_SENDPACKET 2 - #define UIPETHERNET_BUFFERREAD 4 - - #define uip_ip_addr(addr, ip) \ - do \ - { \ - ((u16_t *) (addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ - ((u16_t *) (addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ - } while(0) - #define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8, a[1] & 0xFF, a[1] >> 8); //TODO this is not IPV6 capable - - #define uip_seteth_addr(eaddr) \ - do \ - { \ - uip_ethaddr.addr[0] = eaddr[0]; \ - uip_ethaddr.addr[1] = eaddr[1]; \ - uip_ethaddr.addr[2] = eaddr[2]; \ - uip_ethaddr.addr[3] = eaddr[3]; \ - uip_ethaddr.addr[4] = eaddr[4]; \ - uip_ethaddr.addr[5] = eaddr[5]; \ - } while(0) - - typedef void (*fn_uip_cb_t) (uip_tcp_appstate_t * conn); - -typedef void (*fn_uip_udp_cb_t) (uip_udp_appstate_t * conn); - - #define BUF ((struct uip_tcpip_hdr*) &uip_buf[UIP_LLH_LEN]) - -class UIPEthernetClass -{ -public: - UIPEthernetClass(PinName mosi, PinName miso, PinName sck, PinName cs); - - int begin(const uint8_t* mac); - void begin(const uint8_t* mac, IPAddress ip); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - - // maintain() must be called at regular intervals to process the incoming serial - // data and issue IP events to the sketch. It does not return until all IP - // events have been processed. Renews dhcp-lease if required. - int maintain(void); - - IPAddress localIP(void); - IPAddress subnetMask(void); - IPAddress gatewayIP(void); - IPAddress dnsServerIP(void); - - // Set a user function to handle raw uIP events as they happen. The - // callback function can only use uIP functions, but it can also use uIP's - // protosockets. - void set_uip_callback(fn_uip_cb_t fn); - void set_uip_udp_callback(fn_uip_udp_cb_t fn); -private: - IPAddress _dnsServerAddress; - DhcpClass* _dhcp; - - struct uip_timer periodic_timer; - fn_uip_cb_t fn_uip_cb; - fn_uip_udp_cb_t fn_uip_udp_cb; - - memhandle in_packet; - memhandle uip_packet; - uint8_t uip_hdrlen; - uint8_t packetstate; - - Enc28J60Network network; - - void init(const uint8_t* mac); - void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - void tick(void); - bool network_send(void); - void uip_callback(void); - friend void uipethernet_appcall(void); - void uip_udp_callback(void); - friend void uipudp_appcall(void); - friend class UIPServer; - friend class UIPClient; - friend class UIPUDP; - - static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); - static uint16_t ipchksum(void); - uint16_t upper_layer_chksum(uint8_t proto); - - friend uint16_t uip_ipchksum(void); - friend uint16_t uip_tcpchksum(void); - friend uint16_t uip_udpchksum(void); - - #if UIP_CONF_IPV6 - uint16_t uip_icmp6chksum(void); - #endif /* UIP_CONF_IPV6 */ -}; - -extern UIPEthernetClass UIPEthernet; -#endif - +/* + UIPEthernet.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef UIPETHERNET_H + #define UIPETHERNET_H + +//#define UIPETHERNET_DEBUG + +//#define UIPETHERNET_DEBUG_CHKSUM +//#define UIPETHERNET_DEBUG_UDP +//#define UIPETHERNET_DEBUG_CLIENT + #include "ethernet_comp.h" + #include <mbed.h> + #include "Dhcp.h" + #include "IPAddress.h" + #include "utility/Enc28J60Network.h" + #include "UIPClient.h" + #include "UIPServer.h" + #include "UIPUdp.h" + +extern "C" +{ + #include "utility/uip_timer.h" + #include "utility/uip.h" +} + #define UIPETHERNET_FREEPACKET 1 + #define UIPETHERNET_SENDPACKET 2 + #define UIPETHERNET_BUFFERREAD 4 + + #define uip_ip_addr(addr, ip) \ + do \ + { \ + ((u16_t *) (addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ + ((u16_t *) (addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ + } while(0) + #define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8, a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable + + #define uip_seteth_addr(eaddr) \ + do \ + { \ + uip_ethaddr.addr[0] = eaddr[0]; \ + uip_ethaddr.addr[1] = eaddr[1]; \ + uip_ethaddr.addr[2] = eaddr[2]; \ + uip_ethaddr.addr[3] = eaddr[3]; \ + uip_ethaddr.addr[4] = eaddr[4]; \ + uip_ethaddr.addr[5] = eaddr[5]; \ + } while(0) + #define BUF ((struct uip_tcpip_hdr*) &uip_buf[UIP_LLH_LEN]) + class UIPEthernetClass + { + public: + Enc28J60Network network; + + UIPEthernetClass(PinName mosi, PinName miso, PinName sck, PinName cs); + + int begin(const uint8_t* mac); + void begin(const uint8_t* mac, IPAddress ip); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + // maintain() must be called at regular intervals to process the incoming serial + // data and issue IP events to the sketch. It does not return until all IP + // events have been processed. Renews dhcp-lease if required. + int maintain(void); + + IPAddress localIP(void); + IPAddress subnetMask(void); + IPAddress gatewayIP(void); + IPAddress dnsServerIP(void); + private: + static memhandle in_packet; + static memhandle uip_packet; + static uint8_t uip_hdrlen; + static uint8_t packetstate; + + static IPAddress _dnsServerAddress; + static DhcpClass* _dhcp; + + static unsigned long periodic_timer; + + void init(const uint8_t* mac); + static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + void tick(void); + + bool network_send(void); + + friend class UIPServer; + + friend class UIPClient; + + friend class UIPUDP; + + static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); + static uint16_t ipchksum(void); + #if UIP_UDP + uint16_t upper_layer_chksum(uint8_t proto); + #endif + friend uint16_t uip_ipchksum(void); + friend uint16_t uip_tcpchksum(void); + friend uint16_t uip_udpchksum(void); + + friend void uipclient_appcall(void); + friend void uipudp_appcall(void); + + #if UIP_CONF_IPV6 + uint16_t uip_icmp6chksum(void); + #endif /* UIP_CONF_IPV6 */ + }; + +extern UIPEthernetClass UIPEthernet; +#endif
--- a/UIPServer.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPServer.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -1,109 +1,92 @@ -/* - UIPServer.cpp - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#include "UIPEthernet.h" -#include "UIPServer.h" -extern "C" -{ -#include "utility/uip-conf.h" -} -/** - * @brief - * @note - * @param - * @retval - */ -UIPServer::UIPServer(uint16_t port) : - _port(htons(port)) { - UIPEthernet.set_uip_callback(&UIPClient::uip_callback); -} - -/** - * @brief - * @note - * @param - * @retval - */ -UIPClient UIPServer::available(void) { - UIPEthernet.tick(); - - uip_userdata_t* u; - for(uint8_t sock = 0; sock < UIP_CONNS; sock++) { - struct uip_conn* conn = &uip_conns[sock]; - if(conn->lport == _port && (u = (uip_userdata_t*)conn->appstate.user)) { - if(UIPClient::_available(u)) - return UIPClient(conn); - } - } - - uip_userdata_closed_t ** cc = &UIPClient::closed_conns[0]; - for(uint8_t i = 0; i < UIP_CONNS; i++) { - if(*cc && (*cc)->lport == _port) { - if((*cc)->packets_in[0] == NOBLOCK) { - free(*cc); - *cc = NULL; - } - else - return UIPClient(*cc); - } - - cc++; - } - - return UIPClient(); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPServer::begin(void) { - uip_listen(_port); - UIPEthernet.tick(); -} - -/** - * @brief - * @note - * @param - * @retval - */ -size_t UIPServer::write(uint8_t c) { - return write(&c, 1); -} - -/** - * @brief - * @note - * @param - * @retval - */ -size_t UIPServer::write(const uint8_t* buf, size_t size) { - size_t ret = 0; - for(int sock = 0; sock < UIP_CONNS; sock++) { - struct uip_conn* conn = &uip_conns[sock]; - if(conn->lport == _port && (conn->tcpstateflags != UIP_CLOSE)) - ret = UIPClient::_write(conn, buf, size); - } - - return ret; -} - - +/* + UIPServer.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "UIPEthernet.h" +#include "UIPServer.h" +extern "C" +{ +#include "utility/uip-conf.h" +} +/** + * @brief + * @note + * @param + * @retval + */ +UIPServer::UIPServer(uint16_t port) : + _port(htons(port)) +{ } + +/** + * @brief + * @note + * @param + * @retval + */ +UIPClient UIPServer::available(void) { + UIPEthernet.tick(); + for(uip_userdata_t * data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++) { + if + ( + data->packets_in[0] != NOBLOCK + && ( + ((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport == _port) + || ((data->state & UIP_CLIENT_REMOTECLOSED) && ((uip_userdata_closed_t*)data)->lport == _port) + ) + ) return UIPClient(data); + } + + return UIPClient(); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPServer::begin(void) { + uip_listen(_port); + UIPEthernet.tick(); +} + +/** + * @brief + * @note + * @param + * @retval + */ +size_t UIPServer::write(uint8_t c) { + return write(&c, 1); +} + +/** + * @brief + * @note + * @param + * @retval + */ +size_t UIPServer::write(const uint8_t* buf, size_t size) { + size_t ret = 0; + for(uip_userdata_t * data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++) { + if((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport == _port) + ret += UIPClient::_write(data, buf, size); + } + + return ret; +}
--- a/UIPServer.h Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPServer.h Sun Mar 08 20:26:56 2015 +0000 @@ -1,43 +1,41 @@ -/* - UIPServer.h - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef UIPSERVER_H - #define UIPSERVER_H - - #include "ethernet_comp.h" - #include "utility/Server.h" - #include "UIPClient.h" - -class UIPServer : - Server -{ -public: - UIPServer(uint16_t); - UIPClient available(void); - void begin(void); - size_t write(uint8_t); - size_t write(const uint8_t* buf, size_t size); - -// using Print::write; - -private: - uint16_t _port; -}; -#endif - - +/* + UIPServer.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef UIPSERVER_H + #define UIPSERVER_H + + #include "ethernet_comp.h" + #include "Server.h" + #include "UIPClient.h" + +class UIPServer : + public Server +{ +public: + UIPServer(uint16_t); + UIPClient available(void); + void begin(void); + size_t write(uint8_t); + size_t write(const uint8_t* buf, size_t size); + +// using Print::write; + +private: + uint16_t _port; +}; +#endif
--- a/UIPUdp.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPUdp.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -1,406 +1,359 @@ -/* - UIPUdp.cpp - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#include "UIPEthernet.h" -#include "UIPUdp.h" -#include "Dns.h" - -#ifdef UIPETHERNET_DEBUG_UDP - #include "mbed.h" -#endif -extern "C" -{ -#include "utility/uip-conf.h" -#include "utility/uip.h" -#include "utility/uip_arp.h" -} -#if UIP_UDP - #define UIP_ARPHDRSIZE 42 - #define UDPBUF ((struct uip_udpip_hdr*) &uip_buf[UIP_LLH_LEN]) - -// Constructor -UIPUDP::UIPUDP(void) { - _uip_udp_conn = NULL; - memset(&appdata, 0, sizeof(appdata)); - UIPEthernet.set_uip_udp_callback(&UIPUDP::uip_callback); -} - -// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use -uint8_t UIPUDP::begin(uint16_t port) { - if(!_uip_udp_conn) { - _uip_udp_conn = uip_udp_new(NULL, 0); - } - - if(_uip_udp_conn) { - uip_udp_bind(_uip_udp_conn, htons(port)); - _uip_udp_conn->appstate.user = &appdata; - return 1; - } - - return 0; -} - -// Finish with the UDP socket -void UIPUDP::stop(void) { - if(_uip_udp_conn) { - flush(); - uip_udp_remove(_uip_udp_conn); - _uip_udp_conn->appstate.user = NULL; - _uip_udp_conn = NULL; - if(appdata.packet_in != NOBLOCK) { - UIPEthernet.network.freeBlock(appdata.packet_in); - appdata.packet_in = NOBLOCK; - } - - uint8_t i = 0; - memhandle* packet = &appdata.packets_in[0]; - while(*packet != NOBLOCK && i < UIP_UDP_NUMPACKETS) { - UIPEthernet.network.freeBlock(*packet); - *packet++ = NOBLOCK; - i++; - } - - if(appdata.packet_out != NOBLOCK) { - UIPEthernet.network.freeBlock(appdata.packet_out); - appdata.packet_out = NOBLOCK; - } - } -} - -// Sending UDP packets -// Start building up a packet to send to the remote host specific in ip and port - -// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port -int UIPUDP::beginPacket(IPAddress ip, uint16_t port) { - UIPEthernet.tick(); - if(ip && port) { - uip_ipaddr_t ripaddr; - uip_ip_addr(&ripaddr, ip); - #ifdef UIPETHERNET_DEBUG_UDP - pc.print("udp beginPacket, "); - #endif - if(_uip_udp_conn) { - _uip_udp_conn->rport = htons(port); - uip_ipaddr_copy(_uip_udp_conn->ripaddr, &ripaddr); - } - else { - _uip_udp_conn = uip_udp_new(&ripaddr, htons(port)); - if(_uip_udp_conn) - { - #ifdef UIPETHERNET_DEBUG_UDP - pc.print("new connection, "); - #endif - _uip_udp_conn->appstate.user = &appdata; - } - else - { - #ifdef UIPETHERNET_DEBUG_UDP - pc.println("failed to allocate new connection"); - #endif - return 0; - } - } - - #ifdef UIPETHERNET_DEBUG_UDP - pc.print("rip: "); - pc.print(ip); - pc.print(", port: "); - pc.println(port); - #endif - } - - if(_uip_udp_conn) { - if(appdata.packet_out == NOBLOCK) { - appdata.packet_out = UIPEthernet.network.allocBlock(UIP_UDP_MAXPACKETSIZE); - appdata.out_pos = UIP_UDP_PHYH_LEN; - if(appdata.packet_out != NOBLOCK) - return 1; - #ifdef UIPETHERNET_DEBUG_UDP - else - pc.println("failed to allocate memory for packet"); - #endif - } - - #ifdef UIPETHERNET_DEBUG_UDP - else - pc.println("previous packet on that connection not sent yet"); - #endif - } - - return 0; -} - -// Start building up a packet to send to the remote host specific in host and port - -// Returns 1 if successful, 0 if there was a problem resolving the hostname or port -int UIPUDP::beginPacket(const char* host, uint16_t port) { - - // Look up the host first - int ret = 0; - DNSClient dns; - IPAddress remote_addr; - - dns.begin(UIPEthernet.dnsServerIP()); - ret = dns.getHostByName(host, remote_addr); - if(ret == 1) { - return beginPacket(remote_addr, port); - } - else { - return ret; - } -} - -// Finish off this packet and send it - -// Returns 1 if the packet was sent successfully, 0 if there was an error -int UIPUDP::endPacket(void) { - if(_uip_udp_conn && appdata.packet_out != NOBLOCK) { - appdata.send = true; - UIPEthernet.network.resizeBlock(appdata.packet_out, 0, appdata.out_pos); - uip_udp_periodic_conn(_uip_udp_conn); - if(uip_len > 0) { - UIPEthernet.network_send(); - return 1; - } - } - - return 0; -} - -// Write a single byte into the packet -size_t UIPUDP::write(uint8_t c) { - return write(&c, 1); -} - -// Write size bytes from buffer into the packet -size_t UIPUDP::write(const uint8_t* buffer, size_t size) { - if(appdata.packet_out != NOBLOCK) { - size_t ret = UIPEthernet.network.writePacket(appdata.packet_out, appdata.out_pos, (uint8_t*)buffer, size); - appdata.out_pos += ret; - return ret; - } - - return 0; -} - -// Start processing the next available incoming packet - -// Returns the size of the packet in bytes, or 0 if no packets are available -int UIPUDP::parsePacket(void) { - UIPEthernet.tick(); - if(appdata.packet_in != NOBLOCK) - { - #ifdef UIPETHERNET_DEBUG_UDP - pc.print("udp parsePacket freeing previous packet: "); - pc.println(appdata.packet_in); - #endif ; - UIPEthernet.network.freeBlock(appdata.packet_in); - } - - memhandle* packet = &appdata.packets_in[0]; - appdata.packet_in = *packet; - if(appdata.packet_in != NOBLOCK) - { - #ifdef UIPETHERNET_DEBUG_UDP - pc.print("udp parsePacket received packet: "); - pc.print(appdata.packet_in); - #endif - if(UIP_UDP_NUMPACKETS > 1) { - uint8_t i = 1; - memhandle* p = packet + 1; -freeloop: - *packet = *p; - if(*packet == NOBLOCK) - goto freeready; - packet++; - if(i < UIP_UDP_NUMPACKETS - 1) { - i++; - p++; - goto freeloop; - } - } - - *packet = NOBLOCK; -freeready: - int size = UIPEthernet.network.blockSize(appdata.packet_in); - #ifdef UIPETHERNET_DEBUG_UDP - pc.print(", size: "); - pc.println(size); - #endif - return size; - } - - return 0; -} - -// Number of bytes remaining in the current packet -int UIPUDP::available(void) { - UIPEthernet.tick(); - if(appdata.packet_in != NOBLOCK) { - return UIPEthernet.network.blockSize(appdata.packet_in); - } - - return 0; -} - -// Read a single byte from the current packet -int UIPUDP::read(void) { - unsigned char c; - if(read(&c, 1) > 0) { - return c; - } - - return -1; -} - -// Read up to len bytes from the current packet and place them into buffer - -// Returns the number of bytes read, or 0 if none are available -int UIPUDP::read(unsigned char* buffer, size_t len) { - UIPEthernet.tick(); - if(appdata.packet_in != NOBLOCK) { - int read = UIPEthernet.network.readPacket(appdata.packet_in, 0, buffer, len); - UIPEthernet.network.resizeBlock(appdata.packet_in, read); - return read; - } - - return 0; -} - -//int -//UIPUDP::read(char* buffer, size_t len) -//{ -// return read((unsigned char*) buffer, size_t len) -//} - -// Return the next byte from the current packet without moving on to the next byte -int UIPUDP::peek(void) { - UIPEthernet.tick(); - if(appdata.packet_in != NOBLOCK) { - unsigned char c; - if(UIPEthernet.network.readPacket(appdata.packet_in, 0, &c, 1) == 1) - return c; - } - - return -1; -} - -// Finish reading the current packet -void UIPUDP::flush(void) { - UIPEthernet.tick(); - if(appdata.packet_in != NOBLOCK) { - UIPEthernet.network.freeBlock(appdata.packet_in); - appdata.packet_in = NOBLOCK; - } -} - -// Return the IP address of the host who sent the current incoming packet -IPAddress UIPUDP::remoteIP(void) { - return appdata.ripaddr; -} - -// Return the port of the host who sent the current incoming packet -uint16_t UIPUDP::remotePort(void) { - return appdata.rport; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void UIPUDP::uip_callback(uip_udp_appstate_t* s) { - if(appdata_t * data = (appdata_t*)s->user) { - if(uip_newdata()) { - data->rport = ntohs(UDPBUF->srcport); - data->ripaddr = ip_addr_uip(UDPBUF->srcipaddr); - - memhandle* packet = &data->packets_in[0]; - uint8_t i = 0; - do - { - if(*packet == NOBLOCK) { - *packet = UIPEthernet.network.allocBlock(ntohs(UDPBUF->udplen) - UIP_UDPH_LEN); - - //if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery - if(*packet != NOBLOCK) { - - //discard Linklevel and IP and udp-header and any trailing bytes: - UIPEthernet.network.copyPacket - ( - *packet, - 0, - UIPEthernet.in_packet, - UIP_UDP_PHYH_LEN, - UIPEthernet.network.blockSize(*packet) - ); - #ifdef UIPETHERNET_DEBUG_UDP - pc.print("udp, uip_newdata received packet: "); - pc.print(*packet); - pc.print(", slot: "); - pc.print(i); - pc.print(", size: "); - pc.println(UIPEthernet.network.blockSize(*packet)); - #endif - break; - } - } - - packet++; - i++; - } while(i < UIP_UDP_NUMPACKETS); - } - - if(uip_poll() && data->send) - { - //set uip_slen (uip private) by calling uip_udp_send - #ifdef UIPETHERNET_DEBUG_UDP - pc.print("udp, uip_poll preparing packet to send: "); - pc.print(data->packet_out); - pc.print(", size: "); - pc.println(UIPEthernet.network.blockSize(data->packet_out)); - #endif - UIPEthernet.uip_packet = data->packet_out; - data->packet_out = NOBLOCK; - UIPEthernet.uip_hdrlen = UIP_UDP_PHYH_LEN; - UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET; - uip_udp_send(data->out_pos - (UIP_UDP_PHYH_LEN)); - uip_process(UIP_UDP_SEND_CONN); //generate udp + ip headers - uip_arp_out(); //add arp - if(uip_len == UIP_ARPHDRSIZE) { - UIPEthernet.packetstate &= ~UIPETHERNET_SENDPACKET; - #ifdef UIPETHERNET_DEBUG_UDP - pc.println("udp, uip_poll results in ARP-packet"); - #endif - } - else { - - //arp found ethaddr for ip (otherwise packet is replaced by arp-request) - data->send = false; - #ifdef UIPETHERNET_DEBUG_UDP - pc.print("udp, uip_packet to send: "); - pc.println(UIPEthernet.uip_packet); - #endif - } - } - } -} -#endif - - +/* + UIPUdp.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "UIPEthernet.h" +#include "UIPUdp.h" +#include "Dns.h" + +#ifdef UIPETHERNET_DEBUG_UDP + #include "HardwareSerial.h" +#endif +extern "C" +{ +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +} +#if UIP_UDP + #define UIP_ARPHDRSIZE 42 + #define UDPBUF ((struct uip_udpip_hdr*) &uip_buf[UIP_LLH_LEN]) + +// Constructor +UIPUDP::UIPUDP(void) : + _uip_udp_conn(NULL) { + memset(&appdata, 0, sizeof(appdata)); +} + +// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use +uint8_t UIPUDP::begin(uint16_t port) { + if(!_uip_udp_conn) { + _uip_udp_conn = uip_udp_new(NULL, 0); + } + + if(_uip_udp_conn) { + uip_udp_bind(_uip_udp_conn, htons(port)); + _uip_udp_conn->appstate = &appdata; + return 1; + } + + return 0; +} + +// Finish with the UDP socket +void UIPUDP::stop(void) { + if(_uip_udp_conn) { + uip_udp_remove(_uip_udp_conn); + _uip_udp_conn->appstate = NULL; + _uip_udp_conn = NULL; + UIPEthernet.network.freeBlock(appdata.packet_in); + UIPEthernet.network.freeBlock(appdata.packet_next); + UIPEthernet.network.freeBlock(appdata.packet_out); + memset(&appdata, 0, sizeof(appdata)); + } +} + +// Sending UDP packets +// Start building up a packet to send to the remote host specific in ip and port + +// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port +int UIPUDP::beginPacket(IPAddress ip, uint16_t port) { + UIPEthernet.tick(); + if(ip && port) { + uip_ipaddr_t ripaddr; + uip_ip_addr(&ripaddr, ip); + #ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp beginPacket, ")); + #endif + if(_uip_udp_conn) { + _uip_udp_conn->rport = htons(port); + uip_ipaddr_copy(_uip_udp_conn->ripaddr, &ripaddr); + } + else { + _uip_udp_conn = uip_udp_new(&ripaddr, htons(port)); + if(_uip_udp_conn) + { + #ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("new connection, ")); + #endif + _uip_udp_conn->appstate = &appdata; + } + else + { + #ifdef UIPETHERNET_DEBUG_UDP + Serial.println(F("failed to allocate new connection")); + #endif + return 0; + } + } + + #ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("rip: ")); + Serial.print(ip); + Serial.print(F(", port: ")); + Serial.println(port); + #endif + } + + if(_uip_udp_conn) { + if(appdata.packet_out == NOBLOCK) { + appdata.packet_out = UIPEthernet.network.allocBlock(UIP_UDP_MAXPACKETSIZE); + appdata.out_pos = UIP_UDP_PHYH_LEN; + if(appdata.packet_out != NOBLOCK) + return 1; + #ifdef UIPETHERNET_DEBUG_UDP + else + Serial.println(F("failed to allocate memory for packet")); + #endif + } + + #ifdef UIPETHERNET_DEBUG_UDP + else + Serial.println(F("previous packet on that connection not sent yet")); + #endif + } + + return 0; +} + +// Start building up a packet to send to the remote host specific in host and port + +// Returns 1 if successful, 0 if there was a problem resolving the hostname or port +int UIPUDP::beginPacket(const char* host, uint16_t port) { + + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(UIPEthernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if(ret == 1) { + return beginPacket(remote_addr, port); + } + else { + return ret; + } +} + +// Finish off this packet and send it + +// Returns 1 if the packet was sent successfully, 0 if there was an error +int UIPUDP::endPacket(void) { + if(_uip_udp_conn && appdata.packet_out != NOBLOCK) { + appdata.send = true; + UIPEthernet.network.resizeBlock(appdata.packet_out, 0, appdata.out_pos); + uip_udp_periodic_conn(_uip_udp_conn); + if(uip_len > 0) { + _send(&appdata); + return 1; + } + } + + return 0; +} + +// Write a single byte into the packet +size_t UIPUDP::write(uint8_t c) { + return write(&c, 1); +} + +// Write size bytes from buffer into the packet +size_t UIPUDP::write(const uint8_t* buffer, size_t size) { + if(appdata.packet_out != NOBLOCK) { + size_t ret = UIPEthernet.network.writePacket(appdata.packet_out, appdata.out_pos, (uint8_t*)buffer, size); + appdata.out_pos += ret; + return ret; + } + + return 0; +} + +// Start processing the next available incoming packet + +// Returns the size of the packet in bytes, or 0 if no packets are available +int UIPUDP::parsePacket(void) { + UIPEthernet.tick(); + #ifdef UIPETHERNET_DEBUG_UDP + if(appdata.packet_in != NOBLOCK) { + Serial.print(F("udp parsePacket freeing previous packet: ")); + Serial.println(appdata.packet_in); + } + #endif + UIPEthernet.network.freeBlock(appdata.packet_in); + + appdata.packet_in = appdata.packet_next; + appdata.packet_next = NOBLOCK; + + #ifdef UIPETHERNET_DEBUG_UDP + if(appdata.packet_in != NOBLOCK) { + Serial.print(F("udp parsePacket received packet: ")); + Serial.print(appdata.packet_in); + } + #endif + + int size = UIPEthernet.network.blockSize(appdata.packet_in); + #ifdef UIPETHERNET_DEBUG_UDP + if(appdata.packet_in != NOBLOCK) { + Serial.print(F(", size: ")); + Serial.println(size); + } + #endif + return size; +} + +// Number of bytes remaining in the current packet +int UIPUDP::available(void) { + UIPEthernet.tick(); + return UIPEthernet.network.blockSize(appdata.packet_in); +} + +// Read a single byte from the current packet +int UIPUDP::read(void) { + unsigned char c; + if(read(&c, 1) > 0) { + return c; + } + + return -1; +} + +// Read up to len bytes from the current packet and place them into buffer + +// Returns the number of bytes read, or 0 if none are available +int UIPUDP::read(unsigned char* buffer, size_t len) { + UIPEthernet.tick(); + if(appdata.packet_in != NOBLOCK) { + memaddress read = UIPEthernet.network.readPacket(appdata.packet_in, 0, buffer, len); + if(read == UIPEthernet.network.blockSize(appdata.packet_in)) { + UIPEthernet.network.freeBlock(appdata.packet_in); + appdata.packet_in = NOBLOCK; + } + else + UIPEthernet.network.resizeBlock(appdata.packet_in, read); + return read; + } + + return 0; +} + +// Return the next byte from the current packet without moving on to the next byte +int UIPUDP::peek(void) { + UIPEthernet.tick(); + if(appdata.packet_in != NOBLOCK) { + unsigned char c; + if(UIPEthernet.network.readPacket(appdata.packet_in, 0, &c, 1) == 1) + return c; + } + + return -1; +} + +// Finish reading the current packet +void UIPUDP::flush(void) { + UIPEthernet.tick(); + UIPEthernet.network.freeBlock(appdata.packet_in); + appdata.packet_in = NOBLOCK; +} + +// Return the IP address of the host who sent the current incoming packet +IPAddress UIPUDP::remoteIP(void) { + return _uip_udp_conn ? ip_addr_uip(_uip_udp_conn->ripaddr) : IPAddress(); +} + +// Return the port of the host who sent the current incoming packet +uint16_t UIPUDP::remotePort(void) { + return _uip_udp_conn ? ntohs(_uip_udp_conn->rport) : 0; +} + +// uIP callback function +void uipudp_appcall(void) { + if(uip_udp_userdata_t * data = (uip_udp_userdata_t *) (uip_udp_conn->appstate)) { + if(uip_newdata()) { + if(data->packet_next == NOBLOCK) { + uip_udp_conn->rport = UDPBUF->srcport; + uip_ipaddr_copy(uip_udp_conn->ripaddr, UDPBUF->srcipaddr); + data->packet_next = UIPEthernet.network.allocBlock(ntohs(UDPBUF->udplen) - UIP_UDPH_LEN); + + //if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery + if(data->packet_next != NOBLOCK) { + + //discard Linklevel and IP and udp-header and any trailing bytes: + UIPEthernet.network.copyPacket + ( + data->packet_next, + 0, + UIPEthernetClass::in_packet, + UIP_UDP_PHYH_LEN, + UIPEthernet.network.blockSize(data->packet_next) + ); + #ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_newdata received packet: ")); + Serial.print(data->packet_next); + Serial.print(F(", size: ")); + Serial.println(UIPEthernet.network.blockSize(data->packet_next)); + #endif + } + } + } + + if(uip_poll() && data->send) + { + //set uip_slen (uip private) by calling uip_udp_send + #ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_poll preparing packet to send: ")); + Serial.print(data->packet_out); + Serial.print(F(", size: ")); + Serial.println(UIPEthernet.network.blockSize(data->packet_out)); + #endif + UIPEthernetClass::uip_packet = data->packet_out; + UIPEthernetClass::uip_hdrlen = UIP_UDP_PHYH_LEN; + uip_udp_send(data->out_pos - (UIP_UDP_PHYH_LEN)); + } + } +} + +/** + * @brief + * @note + * @param + * @retval + */ +void UIPUDP::_send(uip_udp_userdata_t* data) { + uip_arp_out(); //add arp + if(uip_len == UIP_ARPHDRSIZE) { + UIPEthernetClass::uip_packet = NOBLOCK; + UIPEthernetClass::packetstate &= ~UIPETHERNET_SENDPACKET; + #ifdef UIPETHERNET_DEBUG_UDP + Serial.println(F("udp, uip_poll results in ARP-packet")); + #endif + } + else { + + //arp found ethaddr for ip (otherwise packet is replaced by arp-request) + data->send = false; + data->packet_out = NOBLOCK; + UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; + #ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_packet to send: ")); + Serial.println(UIPEthernetClass::uip_packet); + #endif + } + + UIPEthernet.network_send(); +} +#endif
--- a/UIPUdp.h Sat Dec 20 11:10:40 2014 +0000 +++ b/UIPUdp.h Sun Mar 08 20:26:56 2015 +0000 @@ -3,6 +3,8 @@ Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> All rights reserved. + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -20,35 +22,33 @@ #define UIPUDP_H #include "ethernet_comp.h" - #include "mbed.h" + #include <mbed.h> #include <Udp.h> - #include "utility/mempool.h" + #include "utility/mempool.h" extern "C" { - #include "utility/uip.h" + #include "utility/uip.h" } #define UIP_UDP_MAXDATALEN 1500 #define UIP_UDP_PHYH_LEN UIP_LLH_LEN + UIP_IPUDPH_LEN #define UIP_UDP_MAXPACKETSIZE UIP_UDP_MAXDATALEN + UIP_UDP_PHYH_LEN - #ifndef UIP_UDP_NUMPACKETS - #define UIP_UDP_NUMPACKETS 5 - #endif + +typedef struct +{ + memaddress out_pos; + memhandle packet_next; + memhandle packet_in; + memhandle packet_out; + bool send; +} uip_udp_userdata_t; + class UIPUDP : public UDP { private: struct uip_udp_conn* _uip_udp_conn; - struct appdata_t - { - uint16_t rport; - IPAddress ripaddr; - memaddress out_pos; - memhandle packets_in[UIP_UDP_NUMPACKETS]; - memhandle packet_in; - memhandle packet_out; - bool send; - } appdata; + uip_udp_userdata_t appdata; public: UIPUDP(void); // Constructor uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use @@ -73,7 +73,7 @@ // Write size bytes from buffer into the packet size_t write(const uint8_t* buffer, size_t size); - // using Print::write; + // using Print::write; // Start processing the next available incoming packet // Returns the size of the packet in bytes, or 0 if no packets are available int parsePacket(void); @@ -90,11 +90,11 @@ // Read up to len characters from the current packet and place them into buffer // Returns the number of characters read, or 0 if none are available - int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; + int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); } + ; // Return the next byte from the current packet without moving on to the next byte int peek(void); - void flush(void); // Finish reading the current packet // Return the IP address of the host who sent the current incoming packet @@ -103,6 +103,9 @@ // Return the port of the host who sent the current incoming packet uint16_t remotePort(void); private: - static void uip_callback(uip_udp_appstate_t* s); + friend void uipudp_appcall(void); + + friend class UIPEthernetClass; + static void _send(uip_udp_userdata_t* data); }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Udp.h Sun Mar 08 20:26:56 2015 +0000 @@ -0,0 +1,96 @@ +/* + * Udp.cpp: Library to send/receive UDP packets. + * + * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) + * 1) UDP does not guarantee the order in which assembled UDP packets are received. This + * might not happen often in practice, but in larger network topologies, a UDP + * packet can be received out of sequence. + * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being + * aware of it. Again, this may not be a concern in practice on small local networks. + * For more information, see http://www.cafeaulait.org/course/week12/35.html + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * 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. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ +#ifndef udp_h + #define udp_h + + #include <mbed.h> + #include <IPAddress.h> + +//class UDP : public Stream { +class UDP +{ +public: + virtual uint8_t begin(uint16_t) = 0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop(void) = 0; // Finish with the UDP socket + + // Sending UDP packets + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port) = 0; + + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char* host, uint16_t port) = 0; + + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(void) = 0; + + // Write a single byte into the packet + virtual size_t write(uint8_t) = 0; + + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t* buffer, size_t size) = 0; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(void) = 0; + + // Number of bytes remaining in the current packet + virtual int available(void) = 0; + + // Read a single byte from the current packet + virtual int read(void) = 0; + + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len) = 0; + + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) = 0; + + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(void) = 0; + virtual void flush(void) = 0; // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP(void) = 0; + + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort(void) = 0; +protected: + uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; +}; +#endif
--- a/ethernet_comp.h Sat Dec 20 11:10:40 2014 +0000 +++ b/ethernet_comp.h Sun Mar 08 20:26:56 2015 +0000 @@ -1,7 +1,7 @@ #ifndef ETHERNET_COMP_H #define ETHERNET_COMP_H -// #define Ethernet UIPEthernet + //#define Ethernet UIPEthernet #define EthernetClient UIPClient #define EthernetServer UIPServer #define EthernetUDP UIPUDP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keywords.txt Sun Mar 08 20:26:56 2015 +0000 @@ -0,0 +1,58 @@ +####################################### +# Syntax Coloring Map for SerialIP +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +UIPEthernet KEYWORD1 +UIPServer KEYWORD1 +UIPClient KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +PSOCK_BEGIN KEYWORD2 +PSOCK_CLOSE KEYWORD2 +PSOCK_END KEYWORD2 +PSOCK_EXIT KEYWORD2 +PSOCK_INIT KEYWORD2 +PSOCK_READBUF KEYWORD2 +PSOCK_READTO KEYWORD2 +PSOCK_SEND KEYWORD2 +PSOCK_SEND_STR KEYWORD2 + +uip_listen KEYWORD2 +uip_unlisten KEYWORD2 +uip_connect KEYWORD2 +uip_outstanding KEYWORD2 +uip_send KEYWORD2 +uip_datalen KEYWORD2 +uip_close KEYWORD2 +uip_abort KEYWORD2 +uip_stop KEYWORD2 +uip_stopped KEYWORD2 +uip_restart KEYWORD2 +uip_acked KEYWORD2 +uip_connected KEYWORD2 +uip_closed KEYWORD2 +uip_aborted KEYWORD2 +uip_timedout KEYWORD2 +uip_rexmit KEYWORD2 +uip_poll KEYWORD2 +uip_initialmss KEYWORD2 +uip_mss KEYWORD2 +uip_ipaddr KEYWORD2 +uip_ipaddr_maskcmp KEYWORD2 +uip_ipaddr_mask KEYWORD2 +HTONS KEYWORD2 +htons KEYWORD2 + +use_device KEYWORD2 +set_uip_callback KEYWORD2 +set_gateway KEYWORD2 + +####################################### +# Constants (LITERAL1) +#######################################
--- a/utility/Client.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/Client.h Sun Mar 08 20:26:56 2015 +0000 @@ -1,48 +1,43 @@ -/* - Client.h - Base class that provides Client - Copyright (c) 2011 Adrian McEwen. All right reserved. - - Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef client_h - #define client_h - //#include "Print.h" - //#include "Stream.h" - #include "IPAddress.h" - -//class Client : public Stream { -class Client -{ -public: - virtual int connect(IPAddress ip, uint16_t port) = 0; - virtual int connect(const char* host, uint16_t port) = 0; - virtual size_t write(uint8_t) = 0; - virtual size_t write(const uint8_t* buf, size_t size) = 0; - virtual int available(void) = 0; - virtual int read(void) = 0; - virtual int read(uint8_t* buf, size_t size) = 0; - virtual int peek(void) = 0; - virtual void flush(void) = 0; - virtual void stop(void) = 0; - virtual uint8_t connected(void) = 0; - virtual operator bool(void) = 0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; -#endif - - +/* + Client.h - Base class that provides Client + Copyright (c) 2011 Adrian McEwen. All right reserved. + + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef client_h + #define client_h + #include "IPAddress.h" + +class Client +{ +public: + virtual int connect(IPAddress ip, uint16_t port) = 0; + virtual int connect(const char* host, uint16_t port) = 0; + virtual size_t write(uint8_t) = 0; + virtual size_t write(const uint8_t* buf, size_t size) = 0; + virtual int available(void) = 0; + virtual int read(void) = 0; + virtual int read(uint8_t* buf, size_t size) = 0; + virtual int peek(void) = 0; + virtual void flush(void) = 0; + virtual void stop(void) = 0; + virtual uint8_t connected(void) = 0; + virtual operator bool(void) = 0; +protected: + uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; +}; +#endif
--- a/utility/Enc28J60Network.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/Enc28J60Network.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -1,695 +1,733 @@ -/* - Enc28J60Network.h - UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. - - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - based on enc28j60.c file from the AVRlib library by Pascal Stang. - For AVRlib See http://www.procyonengineering.com/ - - Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#include "Enc28J60Network.h" -#include "mbed.h" - -extern "C" -{ -#include "enc28j60.h" -#include "uip.h" -} -#define DMARUNNING 1 -#define DMANEWPACKET 2 - -#define waitspi() while(!(SPSR & (1 << SPIF))) - Enc28J60Network::Enc28J60Network(PinName mosi, PinName miso, PinName sclk, PinName cs) : - MemoryPool(TXSTART_INIT + 1, TXSTOP_INIT - TXSTART_INIT), - - // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte - bank(0xff), - _spi(mosi, miso, sclk), - _cs(cs) { } - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::init(uint8_t* macaddr) { - - // initialize SPI interface - - _spi.format(8, 0); // 8bit, mode 0 - _spi.frequency(7000000); // 7MHz - wait(1); // 1 second for stable state - - // initialize I/O - _cs = 1; // ss=0 - - // initialize SPI interface - // master mode and Fosc/2 clock: - //SPCR = (1<<SPE)|(1<<MSTR); - //SPSR |= (1<<SPI2X); - // perform system reset - writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); - wait(0.020); // 20ms - - // check CLKRDY bit to see if reset is complete - // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. - //while(!(readReg(ESTAT) & ESTAT_CLKRDY)); - // do bank 0 stuff - // initialize receive buffer - // 16-bit transfers, must write low byte first - // set receive buffer start address - nextPacketPtr = RXSTART_INIT; - - // Rx start - writeRegPair(ERXSTL, RXSTART_INIT); - - // set receive pointer address - writeRegPair(ERXRDPTL, RXSTART_INIT); - - // RX end - writeRegPair(ERXNDL, RXSTOP_INIT); - - // TX start - //writeRegPair(ETXSTL, TXSTART_INIT); - // TX end - //writeRegPair(ETXNDL, TXSTOP_INIT); - // do bank 1 stuff, packet filter: - // For broadcast packets we allow only ARP packtets - // All other packets should be unicast only for our mac (MAADR) - // - // The pattern to match on is therefore - // Type ETH.DST - // ARP BROADCAST - // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 - // in binary these poitions are:11 0000 0011 1111 - // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 - //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! - writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN); - writeRegPair(EPMM0, 0x303f); - writeRegPair(EPMCSL, 0xf7f9); - - // - // - // do bank 2 stuff - // enable MAC receive - // and bring MAC out of reset (writes 0x00 to MACON2) - writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); - - // enable automatic padding to 60bytes and CRC operations - writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); - - // set inter-frame gap (non-back-to-back) - writeRegPair(MAIPGL, 0x0C12); - - // set inter-frame gap (back-to-back) - writeReg(MABBIPG, 0x12); - - // Set the maximum packet size which the controller will accept - // Do not send packets longer than MAX_FRAMELEN: - writeRegPair(MAMXFLL, MAX_FRAMELEN); - - // do bank 3 stuff - // write MAC address - // NOTE: MAC address in ENC28J60 is byte-backward - writeReg(MAADR5, macaddr[0]); - writeReg(MAADR4, macaddr[1]); - writeReg(MAADR3, macaddr[2]); - writeReg(MAADR2, macaddr[3]); - writeReg(MAADR1, macaddr[4]); - writeReg(MAADR0, macaddr[5]); - - // no loopback of transmitted frames - phyWrite(PHCON2, PHCON2_HDLDIS); - - // switch to bank 0 - setBank(ECON1); - - // enable interrutps - writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE); - - // enable packet reception - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); - clkout(2); // change clkout from 6.25MHz to 12.5MHz - wait(0.000060); // 60us - - //Configure leds - phyWrite(PHLCON, 0x476); -} - -/** - * @brief - * @note - * @param - * @retval - */ -memhandle Enc28J60Network::receivePacket(void) { - uint16_t rxstat; - uint16_t len; - // check if a packet has been received and buffered - - //if( !(readReg(EIR) & EIR_PKTIF) ){ - // The above does not work. See Rev. B4 Silicon Errata point 6. - if(readReg(EPKTCNT) != 0) { - uint16_t readPtr = nextPacketPtr + 6; - // Set the read pointer to the start of the received packet - - writeRegPair(ERDPTL, nextPacketPtr); - - // read the next packet pointer - nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); - nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - - // read the packet length (see datasheet page 43) - len = readOp(ENC28J60_READ_BUF_MEM, 0); - len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - len -= 4; //remove the CRC count - - // read the receive status (see datasheet page 43) - rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); - rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - - // decrement the packet counter indicate we are done with this packet - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); - - // check CRC and symbol errors (see datasheet page 44, table 7-3): - // The ERXFCON.CRCEN is set by default. Normally we should not - // need to check this. - if((rxstat & 0x80) != 0) { - receivePkt.begin = readPtr; - receivePkt.size = len; - return UIP_RECEIVEBUFFERHANDLE; - } - - // Move the RX read pointer to the start of the next received packet - // This frees the memory we just read out - setERXRDPT(); - } - - return(NOBLOCK); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::setERXRDPT(void) { - writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr - 1); -} - -/** - * @brief - * @note - * @param - * @retval - */ -memaddress Enc28J60Network::blockSize(memhandle handle) { - return handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::sendPacket(memhandle handle) { - memblock* packet = &blocks[handle]; - uint16_t start = packet->begin - 1; - uint16_t end = start + packet->size; - - // backup data at control-byte position - uint8_t data = readByte(start); - // write control-byte (if not 0 anyway) - - if(data) - writeByte(start, 0); - -#ifdef ENC28J60DEBUG - pc.print("sendPacket("); - pc.print(handle); - pc.print(") ["); - pc.print(start); - pc.print("-"); - pc.print(end); - pc.println("]:"); - for(uint16_t i = start; i <= end; i++) { - pc.print(readByte(i), HEX); - pc.print(" "); - } - - pc.println(); -#endif - // TX start - - writeRegPair(ETXSTL, start); - - // Set the TXND pointer to correspond to the packet size given - writeRegPair(ETXNDL, end); - - // send the contents of the transmit buffer onto the network - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); - - // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. - if((readReg(EIR) & EIR_TXERIF)) { - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); - } - - //restore data on control-byte position - if(data) - writeByte(start, data); -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) { - memblock* packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; - memaddress start = packet->begin + position; - - writeRegPair(ERDPTL, start); - - if(len > packet->size - position) - len = packet->size - position; - return len; -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) { - len = setReadPtr(handle, position, len); - readBuffer(len, buffer); - return len; -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) { - memblock* packet = &blocks[handle]; - uint16_t start = packet->begin + position; - - writeRegPair(EWRPTL, start); - - if(len > packet->size - position) - len = packet->size - position; - writeBuffer(len, buffer); - return len; -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint8_t Enc28J60Network::readByte(uint16_t addr) { - uint8_t result; - - writeRegPair(ERDPTL, addr); - - _cs = 0; - - // issue read command - _spi.write(ENC28J60_READ_BUF_MEM); - - // read data - result = _spi.write(0x00); - _cs = 1; - return(result); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) { - writeRegPair(EWRPTL, addr); - - _cs = 0; - - // issue write command - _spi.write(ENC28J60_WRITE_BUF_MEM); - - // write data - _spi.write(data); - _cs = 1; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::copyPacket -( - memhandle dest_pkt, - memaddress dest_pos, - memhandle src_pkt, - memaddress src_pos, - uint16_t len -) { - memblock* dest = &blocks[dest_pkt]; - memblock* src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; - memblock_mv_cb(dest->begin + dest_pos, src->begin + src_pos, len); - - // Move the RX read pointer to the start of the next received packet - // This frees the memory we just read out - setERXRDPT(); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len) { - - //as ENC28J60 DMA is unable to copy single bytes: - - if(len == 1) { - writeByte(dest, readByte(src)); - } - else { - - // calculate address of last byte - len += src - 1; - - /* 1. Appropriately program the EDMAST, EDMAND - and EDMADST register pairs. The EDMAST - registers should point to the first byte to copy - from, the EDMAND registers should point to the - last byte to copy and the EDMADST registers - should point to the first byte in the destination - range. The destination range will always be - linear, never wrapping at any values except from - 8191 to 0 (the 8-Kbyte memory boundary). - Extreme care should be taken when - programming the start and end pointers to - prevent a never ending DMA operation which - would overwrite the entire 8-Kbyte buffer. - */ - writeRegPair(EDMASTL, src); - writeRegPair(EDMADSTL, dest); - - if((src <= RXSTOP_INIT) && (len > RXSTOP_INIT)) - len -= (RXSTOP_INIT - RXSTART_INIT); - writeRegPair(EDMANDL, len); - - /* - 2. If an interrupt at the end of the copy process is - desired, set EIE.DMAIE and EIE.INTIE and - clear EIR.DMAIF. - - 3. Verify that ECON1.CSUMEN is clear. */ - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); - - /* 4. Start the DMA copy by setting ECON1.DMAST. */ - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); - - // wait until runnig DMA is completed - while(readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST); - } -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::freePacket(void) { - setERXRDPT(); -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint8_t Enc28J60Network::readOp(uint8_t op, uint8_t address) { - uint8_t result; - - _cs = 0; - - // issue read command - _spi.write(op | (address & ADDR_MASK)); - - // read data - result = _spi.write(0x00); - - // do dummy read if needed (for mac and mii, see datasheet page 29) - if(address & 0x80) - result = _spi.write(0x00); - - // release CS - _cs = 1; - return(result); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) { - _cs = 0; - - // issue write command - _spi.write(op | (address & ADDR_MASK)); - - // write data - _spi.write(data); - _cs = 1; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) { - _cs = 0; - - // issue read command - _spi.write(ENC28J60_READ_BUF_MEM); - while(len) { - len--; - - // read data - *data = _spi.write(0x00); - data++; - } - - *data = '\0'; - _cs = 1; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) { - _cs = 0; - - // issue write command - _spi.write(ENC28J60_WRITE_BUF_MEM); - while(len) { - len--; - - // write data - _spi.write(*data); - data++; - } - - _cs = 1; -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::setBank(uint8_t address) { - - // set the bank (if needed) - - if((address & BANK_MASK) != bank) { - - // set the bank - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0)); - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5); - bank = (address & BANK_MASK); - } -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint8_t Enc28J60Network::readReg(uint8_t address) { - - // set the bank - - setBank(address); - - // do the read - return readOp(ENC28J60_READ_CTRL_REG, address); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::writeReg(uint8_t address, uint8_t data) { - - // set the bank - - setBank(address); - - // do the write - writeOp(ENC28J60_WRITE_CTRL_REG, address, data); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) { - - // set the bank - - setBank(address); - - // do the write - writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF)); - writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8); -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::phyWrite(uint8_t address, uint16_t data) { - - // set the PHY register address - - writeReg(MIREGADR, address); - - // write the PHY data - writeRegPair(MIWRL, data); - - // wait until the PHY write completes - while(readReg(MISTAT) & MISTAT_BUSY) { - wait(0.000015); - } -} - -/** - * @brief - * @note - * @param - * @retval - */ -void Enc28J60Network::clkout(uint8_t clk) { - - //setup clkout: 2 is 12.5MHz: - - writeReg(ECOCON, clk & 0x7); -} - -// read the revision of the chip: -uint8_t Enc28J60Network::getRev(void) { - return(readReg(EREVID)); -} - -/** - * @brief - * @note - * @param - * @retval - */ -uint16_t Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) { - uint8_t spdr; - uint16_t t; - uint16_t i; - - len = setReadPtr(handle, pos, len) - 1; - _cs = 0; - - // issue read command - spdr = _spi.write(ENC28J60_READ_BUF_MEM); - for(i = 0; i < len; i += 2) { - - // read data - spdr = _spi.write(0x00); - t = spdr << 8; - spdr = _spi.write(0x00); - t += spdr; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - } - - if(i == len) { - spdr = _spi.write(0x00); - t = (spdr << 8) + 0; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - } - - _cs = 1; - - /* Return sum in host byte order. */ - return sum; -} - +/* + Enc28J60Network.cpp + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + based on enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "Enc28J60Network.h" +#include <mbed.h> + +extern "C" +{ +#include "enc28j60.h" +#include "uip.h" +} +#ifdef ENC28J60DEBUG + #include "HardwareSerial.h" +#endif +uint16_t Enc28J60Network:: nextPacketPtr; +uint8_t Enc28J60Network:: bank = 0xff; + +struct memblock Enc28J60Network:: receivePkt; + +/** + * @brief + * @note + * @param + * @retval + */ +Enc28J60Network::Enc28J60Network(PinName mosi, PinName miso, PinName sclk, PinName cs) : + MemoryPool(), + _spi(mosi, miso, sclk), + _cs(cs) +{ } + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::init(uint8_t* macaddr) { + MemoryPool::init(); // 1 byte in between RX_STOP_INIT and pool to allow prepending of controlbyte + + // initialize SPI interface + _spi.format(8, 0); // 8bit, mode 0 + _spi.frequency(7000000); // 7MHz + wait(1); // 1 second for stable state + + // initialize I/O + _cs = 1; // ss=0 + + // perform system reset + writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); + wait_ms(50); + + // check CLKRDY bit to see if reset is complete + // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. + //while(!(readReg(ESTAT) & ESTAT_CLKRDY)); + // do bank 0 stuff + // initialize receive buffer + // 16-bit transfers, must write low byte first + // set receive buffer start address + nextPacketPtr = RXSTART_INIT; + + // Rx start + writeRegPair(ERXSTL, RXSTART_INIT); + + // set receive pointer address + writeRegPair(ERXRDPTL, RXSTART_INIT); + + // RX end + writeRegPair(ERXNDL, RXSTOP_INIT); + + // TX start + //writeRegPair(ETXSTL, TXSTART_INIT); + // TX end + //writeRegPair(ETXNDL, TXSTOP_INIT); + // do bank 1 stuff, packet filter: + // For broadcast packets we allow only ARP packtets + // All other packets should be unicast only for our mac (MAADR) + // + // The pattern to match on is therefore + // Type ETH.DST + // ARP BROADCAST + // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 + // in binary these poitions are:11 0000 0011 1111 + // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 + //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! + writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN); + writeRegPair(EPMM0, 0x303f); + writeRegPair(EPMCSL, 0xf7f9); + + // + // + // do bank 2 stuff + // enable MAC receive + // and bring MAC out of reset (writes 0x00 to MACON2) + writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); + + // enable automatic padding to 60bytes and CRC operations + writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); + + // set inter-frame gap (non-back-to-back) + writeRegPair(MAIPGL, 0x0C12); + + // set inter-frame gap (back-to-back) + writeReg(MABBIPG, 0x12); + + // Set the maximum packet size which the controller will accept + // Do not send packets longer than MAX_FRAMELEN: + writeRegPair(MAMXFLL, MAX_FRAMELEN); + + // do bank 3 stuff + // write MAC address + // NOTE: MAC address in ENC28J60 is byte-backward + writeReg(MAADR5, macaddr[0]); + writeReg(MAADR4, macaddr[1]); + writeReg(MAADR3, macaddr[2]); + writeReg(MAADR2, macaddr[3]); + writeReg(MAADR1, macaddr[4]); + writeReg(MAADR0, macaddr[5]); + + // no loopback of transmitted frames + phyWrite(PHCON2, PHCON2_HDLDIS); + + // switch to bank 0 + setBank(ECON1); + + // enable interrutps + writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE); + + // enable packet reception + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + + clkout(2); // change clkout from 6.25MHz to 12.5MHz + wait_us(60); // 60us + + //Configure leds + phyWrite(PHLCON, 0x476); +} + +/** + * @brief + * @note + * @param + * @retval + */ +memhandle Enc28J60Network::receivePacket(void) { + uint8_t rxstat; + uint16_t len; + // check if a packet has been received and buffered + + //if( !(readReg(EIR) & EIR_PKTIF) ){ + // The above does not work. See Rev. B4 Silicon Errata point 6. + if(readReg(EPKTCNT) != 0) { + uint16_t readPtr = nextPacketPtr + + 6 > RXSTOP_INIT ? nextPacketPtr + + 6 - + RXSTOP_INIT + + RXSTART_INIT : nextPacketPtr + + 6; + // Set the read pointer to the start of the received packet + + writeRegPair(ERDPTL, nextPacketPtr); + + // read the next packet pointer + nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); + nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + + // read the packet length (see datasheet page 43) + len = readOp(ENC28J60_READ_BUF_MEM, 0); + len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + len -= 4; //remove the CRC count + + // read the receive status (see datasheet page 43) + rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); + + //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; +#ifdef ENC28J60DEBUG + Serial.print("receivePacket ["); + Serial.print(readPtr, HEX); + Serial.print("-"); + Serial.print((readPtr + len) % (RXSTOP_INIT + 1), HEX); + Serial.print("], next: "); + Serial.print(nextPacketPtr, HEX); + Serial.print(", stat: "); + Serial.print(rxstat, HEX); + Serial.print(", count: "); + Serial.print(readReg(EPKTCNT)); + Serial.print(" -> "); + Serial.println((rxstat & 0x80) != 0 ? "OK" : "failed"); +#endif + // decrement the packet counter indicate we are done with this packet + + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); + + // check CRC and symbol errors (see datasheet page 44, table 7-3): + // The ERXFCON.CRCEN is set by default. Normally we should not + // need to check this. + if((rxstat & 0x80) != 0) { + receivePkt.begin = readPtr; + receivePkt.size = len; + return UIP_RECEIVEBUFFERHANDLE; + } + + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); + } + + return(NOBLOCK); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::setERXRDPT(void) { + writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr - 1); +} + +/** + * @brief + * @note + * @param + * @retval + */ +memaddress Enc28J60Network::blockSize(memhandle handle) { + return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::sendPacket(memhandle handle) { + memblock* packet = &blocks[handle]; + uint16_t start = packet->begin - 1; + uint16_t end = start + packet->size; + + // backup data at control-byte position + uint8_t data = readByte(start); + // write control-byte (if not 0 anyway) + + if(data) + writeByte(start, 0); + +#ifdef ENC28J60DEBUG + Serial.print("sendPacket("); + Serial.print(handle); + Serial.print(") ["); + Serial.print(start, HEX); + Serial.print("-"); + Serial.print(end, HEX); + Serial.print("]: "); + for(uint16_t i = start; i <= end; i++) { + Serial.print(readByte(i), HEX); + Serial.print(" "); + } + + Serial.println(); +#endif + // TX start + + writeRegPair(ETXSTL, start); + + // Set the TXND pointer to correspond to the packet size given + writeRegPair(ETXNDL, end); + + // send the contents of the transmit buffer onto the network + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); + + // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. + if((readReg(EIR) & EIR_TXERIF)) { + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); + } + + //restore data on control-byte position + if(data) + writeByte(start, data); +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) { + memblock* packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; + memaddress start = handle == UIP_RECEIVEBUFFERHANDLE + && packet->begin + + position > RXSTOP_INIT ? packet->begin + + position - + RXSTOP_INIT + + RXSTART_INIT : packet->begin + + position; + + writeRegPair(ERDPTL, start); + + if(len > packet->size - position) + len = packet->size - position; + return len; +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) { + len = setReadPtr(handle, position, len); + readBuffer(len, buffer); + return len; +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) { + memblock* packet = &blocks[handle]; + uint16_t start = packet->begin + position; + + writeRegPair(EWRPTL, start); + + if(len > packet->size - position) + len = packet->size - position; + writeBuffer(len, buffer); + return len; +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint8_t Enc28J60Network::readByte(uint16_t addr) { + uint8_t result; + + writeRegPair(ERDPTL, addr); + + _cs = 0; + + // issue read command + _spi.write(ENC28J60_READ_BUF_MEM); + + // read data + result = _spi.write(0x00); + _cs = 1; + return(result); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) { + writeRegPair(EWRPTL, addr); + + _cs = 0; + + // issue write command + _spi.write(ENC28J60_WRITE_BUF_MEM); + + // write data + _spi.write(data); + _cs = 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::copyPacket +( + memhandle dest_pkt, + memaddress dest_pos, + memhandle src_pkt, + memaddress src_pos, + uint16_t len +) { + memblock* dest = &blocks[dest_pkt]; + memblock* src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; + memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE + && src->begin + + src_pos > RXSTOP_INIT ? src->begin + + src_pos - + RXSTOP_INIT + + RXSTART_INIT : src->begin + + src_pos; + enc28J60_mempool_block_move_callback(dest->begin + dest_pos, start, len); + + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::freePacket(void) { + setERXRDPT(); +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint8_t Enc28J60Network::readOp(uint8_t op, uint8_t address) { + uint8_t result; + + _cs = 0; + + // issue read command + _spi.write(op | (address & ADDR_MASK)); + + // read data + result = _spi.write(0x00); + + // do dummy read if needed (for mac and mii, see datasheet page 29) + if(address & 0x80) + result = _spi.write(0x00); + + // release CS + _cs = 1; + return(result); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) { + _cs = 0; + + // issue write command + _spi.write(op | (address & ADDR_MASK)); + + // write data + _spi.write(data); + _cs = 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) { + _cs = 0; + + // issue read command + _spi.write(ENC28J60_READ_BUF_MEM); + while(len) { + len--; + + // read data + *data = _spi.write(0x00); + data++; + } + + *data = '\0'; + _cs = 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) { + _cs = 0; + + // issue write command + _spi.write(ENC28J60_WRITE_BUF_MEM); + while(len) { + len--; + + // write data + _spi.write(*data); + data++; + } + + _cs = 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::setBank(uint8_t address) { + + // set the bank (if needed) + + if((address & BANK_MASK) != bank) { + + // set the bank + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0)); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5); + bank = (address & BANK_MASK); + } +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint8_t Enc28J60Network::readReg(uint8_t address) { + + // set the bank + + setBank(address); + + // do the read + return readOp(ENC28J60_READ_CTRL_REG, address); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::writeReg(uint8_t address, uint8_t data) { + + // set the bank + + setBank(address); + + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) { + + // set the bank + + setBank(address); + + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF)); + writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::phyWrite(uint8_t address, uint16_t data) { + + // set the PHY register address + + writeReg(MIREGADR, address); + + // write the PHY data + writeRegPair(MIWRL, data); + + // wait until the PHY write completes + while(readReg(MISTAT) & MISTAT_BUSY) { + wait_us(15); + } +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28J60Network::phyRead(uint8_t address) { + writeReg(MIREGADR, address); + writeReg(MICMD, MICMD_MIIRD); + + // wait until the PHY read completes + while(readReg(MISTAT) & MISTAT_BUSY) { + wait_us(15); + } //and MIRDH + + writeReg(MICMD, 0); + return(readReg(MIRDL) | readReg(MIRDH) << 8); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::clkout(uint8_t clk) { + + //setup clkout: 2 is 12.5MHz: + + writeReg(ECOCON, clk & 0x7); +} + +// read the revision of the chip: +uint8_t Enc28J60Network::getrev(void) { + return(readReg(EREVID)); +} + +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) { + uint8_t spdr; + uint16_t t; + uint16_t i; + + len = setReadPtr(handle, pos, len) - 1; + _cs = 0; + + // issue read command + spdr = _spi.write(ENC28J60_READ_BUF_MEM); + for(i = 0; i < len; i += 2) { + + // read data + spdr = _spi.write(0x00); + t = spdr << 8; + spdr = _spi.write(0x00); + t += spdr; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + + if(i == len) { + spdr = _spi.write(0x00); + t = (spdr << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + + _cs = 1; + + /* Return sum in host byte order. */ + return sum; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::powerOff(void) { + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); + wait_ms(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); + wait_ms(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void Enc28J60Network::powerOn(void) { + writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); + wait_ms(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + wait_ms(50); +} + +/** + * @brief + * @note + * @param + * @retval + */ +bool Enc28J60Network::linkStatus(void) { + return(phyRead(PHSTAT2) & 0x0400) > 0; +}
--- a/utility/Enc28J60Network.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/Enc28J60Network.h Sun Mar 08 20:26:56 2015 +0000 @@ -1,81 +1,85 @@ -/* - Enc28J60Network.h - UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. - - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> - All rights reserved. - - inspired by enc28j60.c file from the AVRlib library by Pascal Stang. - For AVRlib See http://www.procyonengineering.com/ - - Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef ENC28J60NETWORK_H_ - #define ENC28J60NETWORK_H_ - - #include "mbed.h" - #include "mempool.h" - - #define UIP_RECEIVEBUFFERHANDLE 0xff - -//#define ENC28J60DEBUG - -/* - * Received from ip-header, arp etc... - * when tcp/udp -> tcp/udp-callback -> assign new packet to connection - */ -class Enc28J60Network : - public MemoryPool -{ -private: - SPI _spi; - DigitalOut _cs; - uint16_t nextPacketPtr; - uint8_t bank; - - struct memblock receivePkt; - - uint8_t readOp(uint8_t op, uint8_t address); - void writeOp(uint8_t op, uint8_t address, uint8_t data); - uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); - void setERXRDPT(void); - void readBuffer(uint16_t len, uint8_t* data); - void writeBuffer(uint16_t len, uint8_t* data); - uint8_t readByte(uint16_t addr); - void writeByte(uint16_t addr, uint8_t data); - void setBank(uint8_t address); - uint8_t readReg(uint8_t address); - void writeReg(uint8_t address, uint8_t data); - void writeRegPair(uint8_t address, uint16_t data); - void phyWrite(uint8_t address, uint16_t data); - void clkout(uint8_t clk); - uint8_t getRev(void); -protected: - void memblock_mv_cb(memaddress dest, memaddress src, memaddress size); -public: - Enc28J60Network(PinName mosi, PinName miso, PinName sclk, PinName cs); - void init(uint8_t* macaddr); - memhandle receivePacket(void); - void freePacket(void); - memaddress blockSize(memhandle handle); - void sendPacket(memhandle handle); - uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); - uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); - void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); - uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); -}; -#endif /* ENC28J60NETWORK_H_ */ - +/* + Enc28J60Network.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + based on enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef Enc28J60Network_H_ + #define Enc28J60Network_H_ + + #include <mbed.h> + #include "mempool.h" + + #define UIP_RECEIVEBUFFERHANDLE 0xff + +//#define ENC28J60DEBUG + +/* + * Empfangen von ip-header, arp etc... + * wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection + */ +class Enc28J60Network : + public MemoryPool +{ +private: + SPI _spi; + DigitalOut _cs; + static uint16_t nextPacketPtr; + static uint8_t bank; + + static struct memblock receivePkt; + + uint8_t readOp(uint8_t op, uint8_t address); + void writeOp(uint8_t op, uint8_t address, uint8_t data); + uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); + void setERXRDPT(void); + void readBuffer(uint16_t len, uint8_t* data); + void writeBuffer(uint16_t len, uint8_t* data); + uint8_t readByte(uint16_t addr); + void writeByte(uint16_t addr, uint8_t data); + void setBank(uint8_t address); + uint8_t readReg(uint8_t address); + void writeReg(uint8_t address, uint8_t data); + void writeRegPair(uint8_t address, uint16_t data); + void phyWrite(uint8_t address, uint16_t data); + uint16_t phyRead(uint8_t address); + void clkout(uint8_t clk); + + friend void enc28J60_mempool_block_move_callback(memaddress, memaddress, memaddress); +public: + Enc28J60Network(PinName mosi, PinName miso, PinName sclk, PinName cs); + uint8_t getrev(void); + void powerOn(void); + void powerOff(void); + bool linkStatus(void); + + void init(uint8_t* macaddr); + memhandle receivePacket(void); + void freePacket(void); + memaddress blockSize(memhandle handle); + void sendPacket(memhandle handle); + uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); + uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); +}; +#endif /* Enc28J60NetworkClass_H_ */
--- a/utility/Server.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/Server.h Sun Mar 08 20:26:56 2015 +0000 @@ -3,7 +3,7 @@ Copyright (c) 2011 Adrian McEwen. All right reserved. Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -21,7 +21,6 @@ #ifndef server_h #define server_h -//class Server : public Print { class Server { public:
--- a/utility/Udp.h Sat Dec 20 11:10:40 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * Udp.cpp: Library to send/receive UDP packets. - * - * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) - * 1) UDP does not guarantee the order in which assembled UDP packets are received. This - * might not happen often in practice, but in larger network topologies, a UDP - * packet can be received out of sequence. - * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being - * aware of it. Again, this may not be a concern in practice on small local networks. - * For more information, see http://www.cafeaulait.org/course/week12/35.html - * - * MIT License: - * Copyright (c) 2008 Bjoern Hartmann - * 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. - * - * bjoern@cs.stanford.edu 12/30/2008 - */ -#ifndef udp_h - #define udp_h - - #include <mbed.h> - #include <IPAddress.h> - -//class UDP : public Stream { -class UDP -{ -public: - virtual uint8_t begin(uint16_t) = 0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual void stop(void) = 0; // Finish with the UDP socket - - // Sending UDP packets - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port) = 0; - - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char* host, uint16_t port) = 0; - - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket(void) = 0; - - // Write a single byte into the packet - virtual size_t write(uint8_t) = 0; - - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t* buffer, size_t size) = 0; - - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket(void) = 0; - - // Number of bytes remaining in the current packet - virtual int available(void) = 0; - - // Read a single byte from the current packet - virtual int read(void) = 0; - - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len) = 0; - - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) = 0; - - // Return the next byte from the current packet without moving on to the next byte - virtual int peek(void) = 0; - virtual void flush(void) = 0; // Finish reading the current packet - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP(void) = 0; - - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort(void) = 0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; -#endif
--- a/utility/clock-arch.c Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/clock-arch.c Sun Mar 08 20:26:56 2015 +0000 @@ -1,35 +1,33 @@ -/* - clock-arch.c - mbed implementation of uIP clock device. - Copyright (c) 2010 Adam Nielsen <malvineous@shikadi.net> - All rights reserved. - - Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include <time.h> -#include "clock-arch.h" - -/** - * @brief - * @note - * @param - * @retval - */ -clock_time_t clock_time(void) { - return(clock_time_t) time(NULL); -} - - +/* + clock-arch.c - mbed implementation of uIP clock device. + Copyright (c) 2010 Adam Nielsen <malvineous@shikadi.net> + All rights reserved. + + Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <time.h> +#include "clock-arch.h" + +/** + * @brief + * @note + * @param + * @retval + */ +clock_time_t clock_time(void) { + return(clock_time_t) time(NULL); +}
--- a/utility/enc28j60.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/enc28j60.h Sun Mar 08 20:26:56 2015 +0000 @@ -12,272 +12,246 @@ * * *****************************************************************************/ + #ifndef ENC28J60_H - #define ENC28J60_H - #include <inttypes.h> +#define ENC28J60_H +#include <inttypes.h> // ENC28J60 Control Registers - // Control register definitions are a combination of address, // bank number, and Ethernet/MAC/PHY indicator bits. // - Register address (bits 0-4) // - Bank number (bits 5-6) // - MAC/PHY indicator (bit 7) - #define ADDR_MASK 0x1F - #define BANK_MASK 0x60 - #define SPRD_MASK 0x80 +#define ADDR_MASK 0x1F +#define BANK_MASK 0x60 +#define SPRD_MASK 0x80 // All-bank registers - - #define EIE 0x1B - #define EIR 0x1C - #define ESTAT 0x1D - #define ECON2 0x1E - #define ECON1 0x1F +#define EIE 0x1B +#define EIR 0x1C +#define ESTAT 0x1D +#define ECON2 0x1E +#define ECON1 0x1F // Bank 0 registers - - #define ERDPTL (0x00 | 0x00) - #define ERDPTH (0x01 | 0x00) - #define EWRPTL (0x02 | 0x00) - #define EWRPTH (0x03 | 0x00) - #define ETXSTL (0x04 | 0x00) - #define ETXSTH (0x05 | 0x00) - #define ETXNDL (0x06 | 0x00) - #define ETXNDH (0x07 | 0x00) - #define ERXSTL (0x08 | 0x00) - #define ERXSTH (0x09 | 0x00) - #define ERXNDL (0x0A | 0x00) - #define ERXNDH (0x0B | 0x00) - #define ERXRDPTL (0x0C | 0x00) - #define ERXRDPTH (0x0D | 0x00) - #define ERXWRPTL (0x0E | 0x00) - #define ERXWRPTH (0x0F | 0x00) - #define EDMASTL (0x10 | 0x00) - #define EDMASTH (0x11 | 0x00) - #define EDMANDL (0x12 | 0x00) - #define EDMANDH (0x13 | 0x00) - #define EDMADSTL (0x14 | 0x00) - #define EDMADSTH (0x15 | 0x00) - #define EDMACSL (0x16 | 0x00) - #define EDMACSH (0x17 | 0x00) +#define ERDPTL (0x00|0x00) +#define ERDPTH (0x01|0x00) +#define EWRPTL (0x02|0x00) +#define EWRPTH (0x03|0x00) +#define ETXSTL (0x04|0x00) +#define ETXSTH (0x05|0x00) +#define ETXNDL (0x06|0x00) +#define ETXNDH (0x07|0x00) +#define ERXSTL (0x08|0x00) +#define ERXSTH (0x09|0x00) +#define ERXNDL (0x0A|0x00) +#define ERXNDH (0x0B|0x00) +#define ERXRDPTL (0x0C|0x00) +#define ERXRDPTH (0x0D|0x00) +#define ERXWRPTL (0x0E|0x00) +#define ERXWRPTH (0x0F|0x00) +#define EDMASTL (0x10|0x00) +#define EDMASTH (0x11|0x00) +#define EDMANDL (0x12|0x00) +#define EDMANDH (0x13|0x00) +#define EDMADSTL (0x14|0x00) +#define EDMADSTH (0x15|0x00) +#define EDMACSL (0x16|0x00) +#define EDMACSH (0x17|0x00) // Bank 1 registers - - #define EHT0 (0x00 | 0x20) - #define EHT1 (0x01 | 0x20) - #define EHT2 (0x02 | 0x20) - #define EHT3 (0x03 | 0x20) - #define EHT4 (0x04 | 0x20) - #define EHT5 (0x05 | 0x20) - #define EHT6 (0x06 | 0x20) - #define EHT7 (0x07 | 0x20) - #define EPMM0 (0x08 | 0x20) - #define EPMM1 (0x09 | 0x20) - #define EPMM2 (0x0A | 0x20) - #define EPMM3 (0x0B | 0x20) - #define EPMM4 (0x0C | 0x20) - #define EPMM5 (0x0D | 0x20) - #define EPMM6 (0x0E | 0x20) - #define EPMM7 (0x0F | 0x20) - #define EPMCSL (0x10 | 0x20) - #define EPMCSH (0x11 | 0x20) - #define EPMOL (0x14 | 0x20) - #define EPMOH (0x15 | 0x20) - #define EWOLIE (0x16 | 0x20) - #define EWOLIR (0x17 | 0x20) - #define ERXFCON (0x18 | 0x20) - #define EPKTCNT (0x19 | 0x20) +#define EHT0 (0x00|0x20) +#define EHT1 (0x01|0x20) +#define EHT2 (0x02|0x20) +#define EHT3 (0x03|0x20) +#define EHT4 (0x04|0x20) +#define EHT5 (0x05|0x20) +#define EHT6 (0x06|0x20) +#define EHT7 (0x07|0x20) +#define EPMM0 (0x08|0x20) +#define EPMM1 (0x09|0x20) +#define EPMM2 (0x0A|0x20) +#define EPMM3 (0x0B|0x20) +#define EPMM4 (0x0C|0x20) +#define EPMM5 (0x0D|0x20) +#define EPMM6 (0x0E|0x20) +#define EPMM7 (0x0F|0x20) +#define EPMCSL (0x10|0x20) +#define EPMCSH (0x11|0x20) +#define EPMOL (0x14|0x20) +#define EPMOH (0x15|0x20) +#define EWOLIE (0x16|0x20) +#define EWOLIR (0x17|0x20) +#define ERXFCON (0x18|0x20) +#define EPKTCNT (0x19|0x20) // Bank 2 registers - - #define MACON1 (0x00 | 0x40 | 0x80) - #define MACON2 (0x01 | 0x40 | 0x80) - #define MACON3 (0x02 | 0x40 | 0x80) - #define MACON4 (0x03 | 0x40 | 0x80) - #define MABBIPG (0x04 | 0x40 | 0x80) - #define MAIPGL (0x06 | 0x40 | 0x80) - #define MAIPGH (0x07 | 0x40 | 0x80) - #define MACLCON1 (0x08 | 0x40 | 0x80) - #define MACLCON2 (0x09 | 0x40 | 0x80) - #define MAMXFLL (0x0A | 0x40 | 0x80) - #define MAMXFLH (0x0B | 0x40 | 0x80) - #define MAPHSUP (0x0D | 0x40 | 0x80) - #define MICON (0x11 | 0x40 | 0x80) - #define MICMD (0x12 | 0x40 | 0x80) - #define MIREGADR (0x14 | 0x40 | 0x80) - #define MIWRL (0x16 | 0x40 | 0x80) - #define MIWRH (0x17 | 0x40 | 0x80) - #define MIRDL (0x18 | 0x40 | 0x80) - #define MIRDH (0x19 | 0x40 | 0x80) +#define MACON1 (0x00|0x40|0x80) +#define MACON2 (0x01|0x40|0x80) +#define MACON3 (0x02|0x40|0x80) +#define MACON4 (0x03|0x40|0x80) +#define MABBIPG (0x04|0x40|0x80) +#define MAIPGL (0x06|0x40|0x80) +#define MAIPGH (0x07|0x40|0x80) +#define MACLCON1 (0x08|0x40|0x80) +#define MACLCON2 (0x09|0x40|0x80) +#define MAMXFLL (0x0A|0x40|0x80) +#define MAMXFLH (0x0B|0x40|0x80) +#define MAPHSUP (0x0D|0x40|0x80) +#define MICON (0x11|0x40|0x80) +#define MICMD (0x12|0x40|0x80) +#define MIREGADR (0x14|0x40|0x80) +#define MIWRL (0x16|0x40|0x80) +#define MIWRH (0x17|0x40|0x80) +#define MIRDL (0x18|0x40|0x80) +#define MIRDH (0x19|0x40|0x80) // Bank 3 registers - - #define MAADR1 (0x00 | 0x60 | 0x80) - #define MAADR0 (0x01 | 0x60 | 0x80) - #define MAADR3 (0x02 | 0x60 | 0x80) - #define MAADR2 (0x03 | 0x60 | 0x80) - #define MAADR5 (0x04 | 0x60 | 0x80) - #define MAADR4 (0x05 | 0x60 | 0x80) - #define EBSTSD (0x06 | 0x60) - #define EBSTCON (0x07 | 0x60) - #define EBSTCSL (0x08 | 0x60) - #define EBSTCSH (0x09 | 0x60) - #define MISTAT (0x0A | 0x60 | 0x80) - #define EREVID (0x12 | 0x60) - #define ECOCON (0x15 | 0x60) - #define EFLOCON (0x17 | 0x60) - #define EPAUSL (0x18 | 0x60) - #define EPAUSH (0x19 | 0x60) +#define MAADR1 (0x00|0x60|0x80) +#define MAADR0 (0x01|0x60|0x80) +#define MAADR3 (0x02|0x60|0x80) +#define MAADR2 (0x03|0x60|0x80) +#define MAADR5 (0x04|0x60|0x80) +#define MAADR4 (0x05|0x60|0x80) +#define EBSTSD (0x06|0x60) +#define EBSTCON (0x07|0x60) +#define EBSTCSL (0x08|0x60) +#define EBSTCSH (0x09|0x60) +#define MISTAT (0x0A|0x60|0x80) +#define EREVID (0x12|0x60) +#define ECOCON (0x15|0x60) +#define EFLOCON (0x17|0x60) +#define EPAUSL (0x18|0x60) +#define EPAUSH (0x19|0x60) // PHY registers - - #define PHCON1 0x00 - #define PHSTAT1 0x01 - #define PHHID1 0x02 - #define PHHID2 0x03 - #define PHCON2 0x10 - #define PHSTAT2 0x11 - #define PHIE 0x12 - #define PHIR 0x13 - #define PHLCON 0x14 +#define PHCON1 0x00 +#define PHSTAT1 0x01 +#define PHHID1 0x02 +#define PHHID2 0x03 +#define PHCON2 0x10 +#define PHSTAT2 0x11 +#define PHIE 0x12 +#define PHIR 0x13 +#define PHLCON 0x14 // ENC28J60 ERXFCON Register Bit Definitions - - #define ERXFCON_UCEN 0x80 - #define ERXFCON_ANDOR 0x40 - #define ERXFCON_CRCEN 0x20 - #define ERXFCON_PMEN 0x10 - #define ERXFCON_MPEN 0x08 - #define ERXFCON_HTEN 0x04 - #define ERXFCON_MCEN 0x02 - #define ERXFCON_BCEN 0x01 +#define ERXFCON_UCEN 0x80 +#define ERXFCON_ANDOR 0x40 +#define ERXFCON_CRCEN 0x20 +#define ERXFCON_PMEN 0x10 +#define ERXFCON_MPEN 0x08 +#define ERXFCON_HTEN 0x04 +#define ERXFCON_MCEN 0x02 +#define ERXFCON_BCEN 0x01 // ENC28J60 EIE Register Bit Definitions - - #define EIE_INTIE 0x80 - #define EIE_PKTIE 0x40 - #define EIE_DMAIE 0x20 - #define EIE_LINKIE 0x10 - #define EIE_TXIE 0x08 - #define EIE_WOLIE 0x04 - #define EIE_TXERIE 0x02 - #define EIE_RXERIE 0x01 +#define EIE_INTIE 0x80 +#define EIE_PKTIE 0x40 +#define EIE_DMAIE 0x20 +#define EIE_LINKIE 0x10 +#define EIE_TXIE 0x08 +#define EIE_WOLIE 0x04 +#define EIE_TXERIE 0x02 +#define EIE_RXERIE 0x01 // ENC28J60 EIR Register Bit Definitions - - #define EIR_PKTIF 0x40 - #define EIR_DMAIF 0x20 - #define EIR_LINKIF 0x10 - #define EIR_TXIF 0x08 - #define EIR_WOLIF 0x04 - #define EIR_TXERIF 0x02 - #define EIR_RXERIF 0x01 +#define EIR_PKTIF 0x40 +#define EIR_DMAIF 0x20 +#define EIR_LINKIF 0x10 +#define EIR_TXIF 0x08 +#define EIR_WOLIF 0x04 +#define EIR_TXERIF 0x02 +#define EIR_RXERIF 0x01 // ENC28J60 ESTAT Register Bit Definitions - - #define ESTAT_INT 0x80 - #define ESTAT_LATECOL 0x10 - #define ESTAT_RXBUSY 0x04 - #define ESTAT_TXABRT 0x02 - #define ESTAT_CLKRDY 0x01 +#define ESTAT_INT 0x80 +#define ESTAT_LATECOL 0x10 +#define ESTAT_RXBUSY 0x04 +#define ESTAT_TXABRT 0x02 +#define ESTAT_CLKRDY 0x01 // ENC28J60 ECON2 Register Bit Definitions - - #define ECON2_AUTOINC 0x80 - #define ECON2_PKTDEC 0x40 - #define ECON2_PWRSV 0x20 - #define ECON2_VRPS 0x08 +#define ECON2_AUTOINC 0x80 +#define ECON2_PKTDEC 0x40 +#define ECON2_PWRSV 0x20 +#define ECON2_VRPS 0x08 // ENC28J60 ECON1 Register Bit Definitions - - #define ECON1_TXRST 0x80 - #define ECON1_RXRST 0x40 - #define ECON1_DMAST 0x20 - #define ECON1_CSUMEN 0x10 - #define ECON1_TXRTS 0x08 - #define ECON1_RXEN 0x04 - #define ECON1_BSEL1 0x02 - #define ECON1_BSEL0 0x01 +#define ECON1_TXRST 0x80 +#define ECON1_RXRST 0x40 +#define ECON1_DMAST 0x20 +#define ECON1_CSUMEN 0x10 +#define ECON1_TXRTS 0x08 +#define ECON1_RXEN 0x04 +#define ECON1_BSEL1 0x02 +#define ECON1_BSEL0 0x01 // ENC28J60 MACON1 Register Bit Definitions - - #define MACON1_LOOPBK 0x10 - #define MACON1_TXPAUS 0x08 - #define MACON1_RXPAUS 0x04 - #define MACON1_PASSALL 0x02 - #define MACON1_MARXEN 0x01 +#define MACON1_LOOPBK 0x10 +#define MACON1_TXPAUS 0x08 +#define MACON1_RXPAUS 0x04 +#define MACON1_PASSALL 0x02 +#define MACON1_MARXEN 0x01 // ENC28J60 MACON2 Register Bit Definitions - - #define MACON2_MARST 0x80 - #define MACON2_RNDRST 0x40 - #define MACON2_MARXRST 0x08 - #define MACON2_RFUNRST 0x04 - #define MACON2_MATXRST 0x02 - #define MACON2_TFUNRST 0x01 +#define MACON2_MARST 0x80 +#define MACON2_RNDRST 0x40 +#define MACON2_MARXRST 0x08 +#define MACON2_RFUNRST 0x04 +#define MACON2_MATXRST 0x02 +#define MACON2_TFUNRST 0x01 // ENC28J60 MACON3 Register Bit Definitions - - #define MACON3_PADCFG2 0x80 - #define MACON3_PADCFG1 0x40 - #define MACON3_PADCFG0 0x20 - #define MACON3_TXCRCEN 0x10 - #define MACON3_PHDRLEN 0x08 - #define MACON3_HFRMLEN 0x04 - #define MACON3_FRMLNEN 0x02 - #define MACON3_FULDPX 0x01 +#define MACON3_PADCFG2 0x80 +#define MACON3_PADCFG1 0x40 +#define MACON3_PADCFG0 0x20 +#define MACON3_TXCRCEN 0x10 +#define MACON3_PHDRLEN 0x08 +#define MACON3_HFRMLEN 0x04 +#define MACON3_FRMLNEN 0x02 +#define MACON3_FULDPX 0x01 // ENC28J60 MICMD Register Bit Definitions - - #define MICMD_MIISCAN 0x02 - #define MICMD_MIIRD 0x01 +#define MICMD_MIISCAN 0x02 +#define MICMD_MIIRD 0x01 // ENC28J60 MISTAT Register Bit Definitions - - #define MISTAT_NVALID 0x04 - #define MISTAT_SCAN 0x02 - #define MISTAT_BUSY 0x01 +#define MISTAT_NVALID 0x04 +#define MISTAT_SCAN 0x02 +#define MISTAT_BUSY 0x01 // ENC28J60 PHY PHCON1 Register Bit Definitions - - #define PHCON1_PRST 0x8000 - #define PHCON1_PLOOPBK 0x4000 - #define PHCON1_PPWRSV 0x0800 - #define PHCON1_PDPXMD 0x0100 +#define PHCON1_PRST 0x8000 +#define PHCON1_PLOOPBK 0x4000 +#define PHCON1_PPWRSV 0x0800 +#define PHCON1_PDPXMD 0x0100 // ENC28J60 PHY PHSTAT1 Register Bit Definitions - - #define PHSTAT1_PFDPX 0x1000 - #define PHSTAT1_PHDPX 0x0800 - #define PHSTAT1_LLSTAT 0x0004 - #define PHSTAT1_JBSTAT 0x0002 +#define PHSTAT1_PFDPX 0x1000 +#define PHSTAT1_PHDPX 0x0800 +#define PHSTAT1_LLSTAT 0x0004 +#define PHSTAT1_JBSTAT 0x0002 // ENC28J60 PHY PHCON2 Register Bit Definitions - - #define PHCON2_FRCLINK 0x4000 - #define PHCON2_TXDIS 0x2000 - #define PHCON2_JABBER 0x0400 - #define PHCON2_HDLDIS 0x0100 +#define PHCON2_FRCLINK 0x4000 +#define PHCON2_TXDIS 0x2000 +#define PHCON2_JABBER 0x0400 +#define PHCON2_HDLDIS 0x0100 // ENC28J60 Packet Control Byte Bit Definitions - - #define PKTCTRL_PHUGEEN 0x08 - #define PKTCTRL_PPADEN 0x04 - #define PKTCTRL_PCRCEN 0x02 - #define PKTCTRL_POVERRIDE 0x01 +#define PKTCTRL_PHUGEEN 0x08 +#define PKTCTRL_PPADEN 0x04 +#define PKTCTRL_PCRCEN 0x02 +#define PKTCTRL_POVERRIDE 0x01 // SPI operation codes +#define ENC28J60_READ_CTRL_REG 0x00 +#define ENC28J60_READ_BUF_MEM 0x3A +#define ENC28J60_WRITE_CTRL_REG 0x40 +#define ENC28J60_WRITE_BUF_MEM 0x7A +#define ENC28J60_BIT_FIELD_SET 0x80 +#define ENC28J60_BIT_FIELD_CLR 0xA0 +#define ENC28J60_SOFT_RESET 0xFF - #define ENC28J60_READ_CTRL_REG 0x00 - #define ENC28J60_READ_BUF_MEM 0x3A - #define ENC28J60_WRITE_CTRL_REG 0x40 - #define ENC28J60_WRITE_BUF_MEM 0x7A - #define ENC28J60_BIT_FIELD_SET 0x80 - #define ENC28J60_BIT_FIELD_CLR 0xA0 - #define ENC28J60_SOFT_RESET 0xFF // The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata - // buffer boundaries applied to internal 8K ram // the entire available packet buffer space is allocated // // start with recbuf at 0/ - #define RXSTART_INIT 0x0 +#define RXSTART_INIT 0x0 // receive buffer end. make sure this is an odd value ( See Rev. B1,B4,B5,B7 Silicon Errata 'Memory (Ethernet Buffer)') - - #define RXSTOP_INIT (0x1FFF - 0x1800) +#define RXSTOP_INIT (0x1FFF-0x1800) // start TX buffer RXSTOP_INIT+1 - - #define TXSTART_INIT (RXSTOP_INIT + 1) +#define TXSTART_INIT (RXSTOP_INIT+1) // stp TX buffer at end of mem +#define TXSTOP_INIT 0x1FFF +// +// max frame length which the conroller will accept: +#define MAX_FRAMELEN 1500 // (note: maximum ethernet frame length would be 1518) +//#define MAX_FRAMELEN 600 - #define TXSTOP_INIT 0x1FFF -// - -// max frame length which the conroller will accept: - #define MAX_FRAMELEN 1500 // (note: maximum ethernet frame length would be 1518) - -//#define MAX_FRAMELEN 600 #endif
--- a/utility/mempool.cpp Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/mempool.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -21,18 +21,19 @@ #define POOLOFFSET 1 +struct memblock MemoryPool:: blocks[MEMPOOL_NUM_MEMBLOCKS + 1]; + /** * @brief * @note * @param * @retval */ -MemoryPool::MemoryPool(memaddress start, memaddress size) { +void MemoryPool::init(void) { memset(&blocks[0], 0, sizeof(blocks)); - blocks[POOLSTART].begin = start; + blocks[POOLSTART].begin = MEMPOOL_STARTADDRESS; blocks[POOLSTART].size = 0; blocks[POOLSTART].nextblock = NOBLOCK; - poolsize = size; } /** @@ -45,12 +46,12 @@ memblock* best = NULL; memhandle cur = POOLSTART; memblock* block = &blocks[POOLSTART]; - memaddress bestsize = poolsize + 1; + memaddress bestsize = MEMPOOL_SIZE + 1; do { memhandle next = block->nextblock; - memaddress freesize = (next == NOBLOCK ? blocks[POOLSTART].begin + poolsize : blocks[next].begin) - + memaddress freesize = (next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) - block->begin - block->size; if(freesize == size) { @@ -86,8 +87,8 @@ memaddress* src = &nextblock->begin; if(dest != *src) { -#ifdef MEMBLOCK_MV - memblock_mv_cb(dest, *src, nextblock->size); +#ifdef MEMPOOL_MEMBLOCK_MV + MEMPOOL_MEMBLOCK_MV(dest, *src, nextblock->size); #endif *src = dest; } @@ -95,7 +96,7 @@ block = nextblock; } - if(blocks[POOLSTART].begin + poolsize - block->begin - block->size >= size) + if(blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size) best = block; else goto notfound; @@ -104,7 +105,7 @@ found: { block = &blocks[POOLOFFSET]; - for(cur = POOLOFFSET; cur < NUM_MEMBLOCKS + POOLOFFSET; cur++) { + for(cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++) { if(block->size) { block++; continue; @@ -133,6 +134,9 @@ * @retval */ void MemoryPool::freeBlock(memhandle handle) { + if(handle == NOBLOCK) + return; + memblock* b = &blocks[POOLSTART]; do
--- a/utility/mempool.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/mempool.h Sun Mar 08 20:26:56 2015 +0000 @@ -26,16 +26,6 @@ #include "mempool_conf.h" -//#ifdef MEMBLOCK_MV - -//#define memblock_mv_cb(dest,src,size) MEMBLOCK_MV(dest,src,size) -//#endif - #ifdef MEMBLOCK_ALLOC - #define memblock_alloc_cb(address, size) MEMBLOCK_ALLOC(address, size) - #endif - #ifdef MEMBLOCK_FREE - #define memblock_free_cb(address, size) MEMBLOCK_FREE(address, size) - #endif struct memblock { memaddress begin; @@ -49,17 +39,13 @@ friend class MemoryPoolTest; #endif protected: - memaddress poolsize; - struct memblock blocks[NUM_MEMBLOCKS + 1]; - #ifdef MEMBLOCK_MV - virtual void memblock_mv_cb(memaddress dest, memaddress src, memaddress size) = 0; - #endif + static struct memblock blocks[MEMPOOL_NUM_MEMBLOCKS + 1]; public: - MemoryPool(memaddress start, memaddress size); - memhandle allocBlock(memaddress); - void freeBlock(memhandle); - void resizeBlock(memhandle handle, memaddress position); - void resizeBlock(memhandle handle, memaddress position, memaddress size); - memaddress blockSize(memhandle); + static void init(void); + static memhandle allocBlock(memaddress); + static void freeBlock(memhandle); + static void resizeBlock(memhandle handle, memaddress position); + static void resizeBlock(memhandle handle, memaddress position, memaddress size); + static memaddress blockSize(memhandle); }; #endif
--- a/utility/mempool_conf.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/mempool_conf.h Sun Mar 08 20:26:56 2015 +0000 @@ -4,6 +4,7 @@ extern "C" { #include "uipopt.h" + #include "enc28j60.h" } #include <inttypes.h> @@ -15,11 +16,16 @@ #else #define NUM_TCP_MEMBLOCKS 0 #endif - #if UIP_UDP_NUMPACKETS and UIP_UDP_CONNS - #define NUM_UDP_MEMBLOCKS (UIP_UDP_NUMPACKETS + 1) * UIP_UDP_CONNS + #if UIP_UDP and UIP_UDP_CONNS + #define NUM_UDP_MEMBLOCKS 3 * UIP_UDP_CONNS #else #define NUM_UDP_MEMBLOCKS 0 #endif - #define NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS + NUM_UDP_MEMBLOCKS) - #define MEMBLOCK_MV + #define MEMPOOL_NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS + NUM_UDP_MEMBLOCKS) + #define MEMPOOL_STARTADDRESS TXSTART_INIT + 1 + #define MEMPOOL_SIZE TXSTOP_INIT - TXSTART_INIT + +void enc28J60_mempool_block_move_callback(memaddress, memaddress, memaddress); + + #define MEMPOOL_MEMBLOCK_MV(dest, src, size) enc28J60_mempool_block_move_callback(dest, src, size) #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utility/millis.cpp Sun Mar 08 20:26:56 2015 +0000 @@ -0,0 +1,52 @@ +/* + uip_millis.cpp + Copyright (c) 2015 Zoltan Hudak <hudakz@inbox.com> + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "millis.h" +#include <mbed.h> + +volatile unsigned int _millis; + +/** + * @brief + * @note + * @param + * @retval + */ +void millis_start(void) { + SysTick_Config(SystemCoreClock / 1000); +} + +/** + * @brief + * @note + * @param + * @retval + */ +extern "C" void SysTick_Handler(void) { + _millis += 1; +} + +/** + * @brief + * @note + * @param + * @retval + */ +extern "C" unsigned int millis(void) { + return _millis; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utility/millis.h Sun Mar 08 20:26:56 2015 +0000 @@ -0,0 +1,20 @@ +/* + uip_millis.h + Copyright (c) 2015 Zoltan Hudak <hudakz@inbox.com> + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +extern "C" void millis_start(void); +extern "C" unsigned int millis(void);
--- a/utility/uip-conf.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/uip-conf.h Sun Mar 08 20:26:56 2015 +0000 @@ -166,21 +166,15 @@ // SLIP //#define UIP_CONF_LLH_LEN 0 -typedef struct uipethernet_state -{ - void* user; -} uip_tcp_appstate_t; +typedef void* uip_tcp_appstate_t; -void uipethernet_appcall(void); +void uipclient_appcall(void); - #define UIP_APPCALL uipethernet_appcall + #define UIP_APPCALL uipclient_appcall -typedef struct uipudp_state -{ - void* user; -} uip_udp_appstate_t; +typedef void* uip_udp_appstate_t; -void uipudp_appcall(void); +void uipudp_appcall(void); #define UIP_UDP_APPCALL uipudp_appcall
--- a/utility/uip-neighbor.c Sat Dec 20 11:10:40 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2006, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the uIP TCP/IP stack - * - * $Id: uip-neighbor.c,v 1.2 2006/06/12 08:00:30 adam Exp $ - */ -/** - * \file - * Database of link-local neighbors, used by IPv6 code and - * to be used by a future ARP code rewrite. - * \author - * Adam Dunkels <adam@sics.se> - */ -#include "uip-neighbor.h" - -#include <string.h> - -#define MAX_TIME 128 - -#ifdef UIP_NEIGHBOR_CONF_ENTRIES - #define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES -#else /* UIP_NEIGHBOR_CONF_ENTRIES */ - - #define ENTRIES 8 -#endif /* UIP_NEIGHBOR_CONF_ENTRIES */ - -struct neighbor_entry -{ - uip_ipaddr_t ipaddr; - struct uip_neighbor_addr addr; - u8_t time; -}; -static struct neighbor_entry entries[ENTRIES]; - -/*---------------------------------------------------------------------------*/ -void uip_neighbor_init(void) { - int i; - - for(i = 0; i < ENTRIES; ++i) { - entries[i].time = MAX_TIME; - } -} - -/*---------------------------------------------------------------------------*/ -void uip_neighbor_periodic(void) { - int i; - - for(i = 0; i < ENTRIES; ++i) { - if(entries[i].time < MAX_TIME) { - entries[i].time++; - } - } -} - -/*---------------------------------------------------------------------------*/ -void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr* addr) { - int i, oldest; - u8_t oldest_time; - - printf - ( - "Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", - addr->addr.addr[0], - addr->addr.addr[1], - addr->addr.addr[2], - addr->addr.addr[3], - addr->addr.addr[4], - addr->addr.addr[5] - ); - - /* Find the first unused entry or the oldest used entry. */ - oldest_time = 0; - oldest = 0; - for(i = 0; i < ENTRIES; ++i) { - if(entries[i].time == MAX_TIME) { - oldest = i; - break; - } - - if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) { - oldest = i; - break; - } - - if(entries[i].time > oldest_time) { - oldest = i; - oldest_time = entries[i].time; - } - } - - /* Use the oldest or first free entry (either pointed to by the - "oldest" variable). */ - entries[oldest].time = 0; - uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr); - memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr)); -} - -/*---------------------------------------------------------------------------*/ -static struct neighbor_entry* find_entry(uip_ipaddr_t ipaddr) { - int i; - - for(i = 0; i < ENTRIES; ++i) { - if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) { - return &entries[i]; - } - } - - return NULL; -} - -/*---------------------------------------------------------------------------*/ -void uip_neighbor_update(uip_ipaddr_t ipaddr) { - struct neighbor_entry* e; - - e = find_entry(ipaddr); - if(e != NULL) { - e->time = 0; - } -} - -/*---------------------------------------------------------------------------*/ -struct uip_neighbor_addr* uip_neighbor_lookup(uip_ipaddr_t ipaddr) { - struct neighbor_entry* e; - - e = find_entry(ipaddr); - if(e != NULL) { - - /* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", - e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3], - e->addr.addr.addr[4], e->addr.addr.addr[5]);*/ - return &e->addr; - } - - return NULL; -} - -/*---------------------------------------------------------------------------*/
--- a/utility/uip-neighbor.h Sat Dec 20 11:10:40 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2006, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the uIP TCP/IP stack - * - * $Id: uip-neighbor.h,v 1.2 2006/06/12 08:00:30 adam Exp $ - */ -/** - * \file - * Header file for database of link-local neighbors, used by - * IPv6 code and to be used by future ARP code. - * \author - * Adam Dunkels <adam@sics.se> - */ -#ifndef __UIP_NEIGHBOR_H__ - #define __UIP_NEIGHBOR_H__ - - #include "uip.h" - -struct uip_neighbor_addr -{ - #if UIP_NEIGHBOR_CONF_ADDRTYPE - UIP_NEIGHBOR_CONF_ADDRTYPE addr; - #else - struct uip_eth_addr addr; - #endif -}; - -void uip_neighbor_init(void); -void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr* addr); -void uip_neighbor_update(uip_ipaddr_t ipaddr); -struct uip_neighbor_addr* uip_neighbor_lookup(uip_ipaddr_t ipaddr); -void uip_neighbor_periodic(void); -#endif /* __UIP-NEIGHBOR_H__ */
--- a/utility/uip.c Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/uip.c Sun Mar 08 20:26:56 2015 +0000 @@ -136,48 +136,48 @@ #endif #ifndef UIP_CONF_EXTERNAL_BUFFER u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains - incoming packets. */ + incoming packets. */ #endif /* UIP_CONF_EXTERNAL_BUFFER */ void* uip_appdata; /* The uip_appdata pointer points to - application data. */ + application data. */ void* uip_sappdata; /* The uip_appdata pointer points to - the application data which is to - be sent. */ + the application data which is to + be sent. */ #if UIP_URGDATA > 0 void* uip_urgdata; /* The uip_urgdata pointer points to - urgent data (out-of-band data), if - present. */ + urgent data (out-of-band data), if + present. */ u16_t uip_urglen, uip_surglen; #endif /* UIP_URGDATA > 0 */ u16_t uip_len, uip_slen; /* The uip_len is either 8 or 16 bits, - depending on the maximum packet - size. */ + depending on the maximum packet + size. */ u8_t uip_flags; /* The uip_flags variable is used for - communication between the TCP/IP stack - and the application program. */ + communication between the TCP/IP stack + and the application program. */ struct uip_conn* uip_conn; /* uip_conn always points to the current - connection. */ + connection. */ struct uip_conn uip_conns[UIP_CONNS]; /* The uip_conns array holds all TCP - connections. */ + connections. */ u16_t uip_listenports[UIP_LISTENPORTS]; /* The uip_listenports list all currently - listning ports. */ + listning ports. */ #if UIP_UDP struct uip_udp_conn* uip_udp_conn; struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; #endif /* UIP_UDP */ static u16_t ipid; /* Ths ipid variable is an increasing - number that is used for the IP ID - field. */ + number that is used for the IP ID + field. */ /** * @brief @@ -185,16 +185,17 @@ * @param * @retval */ + void uip_setipid(u16_t id) { ipid = id; } static u8_t iss[4]; /* The iss variable is used for the TCP - initial sequence number. */ + initial sequence number. */ #if UIP_ACTIVE_OPEN static u16_t lastport; /* Keeps track of the last port used for - a new connection. */ + a new connection. */ #endif /* UIP_ACTIVE_OPEN */ /* Temporary variables. */ @@ -598,6 +599,7 @@ * @param * @retval */ + static u8_t uip_reass(void) { u16_t offset, len; u16_t i; @@ -645,14 +647,14 @@ if(offset / (8 * 8) == (offset + len) / (8 * 8)) { /* If the two endpoints are in the same byte, we only update - that byte. */ + that byte. */ uip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7] &~bitmap_bits[((offset + len) / 8) & 7]; } else { /* If the two endpoints are in different bytes, we update the - bytes in the endpoints and fill the stuff inbetween with - 0xff. */ + bytes in the endpoints and fill the stuff inbetween with + 0xff. */ uip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7]; for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { uip_reassbitmap[i] = 0xff; @@ -677,7 +679,7 @@ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { /* Check all bytes up to and including all but the last byte in - the bitmap. */ + the bitmap. */ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { if(uip_reassbitmap[i] != 0xff) { goto nullreturn; @@ -685,19 +687,19 @@ } /* Check the last byte in the bitmap. It should contain just the - right amount of bits. */ + right amount of bits. */ if(uip_reassbitmap[uip_reasslen / (8 * 8)] != (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { goto nullreturn; } /* If we have come this far, we have a full packet in the - buffer, so we allocate a pbuf and copy the packet into it. We - also reset the timer. */ + buffer, so we allocate a pbuf and copy the packet into it. We + also reset the timer. */ uip_reasstmr = 0; memcpy(BUF, FBUF, uip_reasslen); /* Pretend to be a "normal" (i.e., not fragmented) IP packet - from now on. */ + from now on. */ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; BUF->len[0] = uip_reasslen >> 8; BUF->len[1] = uip_reasslen & 0xff; @@ -784,8 +786,8 @@ if(uip_connr->tcpstateflags != UIP_CLOSED) { /* If the connection has outstanding data, we increase the - connection's timer and see if it has reached the RTO value - in which case we retransmit. */ + connection's timer and see if it has reached the RTO value + in which case we retransmit. */ if(uip_outstanding(uip_connr)) { if(uip_connr->timer-- == 0) { if @@ -799,8 +801,8 @@ uip_connr->tcpstateflags = UIP_CLOSED; /* We call UIP_APPCALL() with uip_flags set to - UIP_TIMEDOUT to inform the application that the - connection has timed out. */ + UIP_TIMEDOUT to inform the application that the + connection has timed out. */ uip_flags = UIP_TIMEDOUT; UIP_APPCALL(); @@ -814,11 +816,11 @@ ++(uip_connr->nrtx); /* Ok, so we need to retransmit. We do this differently - depending on which state we are in. In ESTABLISHED, we - call upon the application so that it may prepare the - data for the retransmit. In SYN_RCVD, we resend the - SYNACK that we sent earlier and in LAST_ACK we have to - retransmit our FINACK. */ + depending on which state we are in. In ESTABLISHED, we + call upon the application so that it may prepare the + data for the retransmit. In SYN_RCVD, we resend the + SYNACK that we sent earlier and in LAST_ACK we have to + retransmit our FINACK. */ UIP_STAT(++uip_stat.tcp.rexmit); switch(uip_connr->tcpstateflags & UIP_TS_MASK) { case UIP_SYN_RCVD: @@ -921,14 +923,14 @@ uip_len = (BUF->len[0] << 8) + BUF->len[1]; #if UIP_CONF_IPV6 uip_len += 40; /* The length reported in the IPv6 header is the - length of the payload that follows the - header. However, uIP uses the uip_len variable - for holding the size of the entire packet, - including the IP header. For IPv4 this is not a - problem as the length field in the IPv4 header - contains the length of the entire packet. But - for IPv6 we need to add the size of the IPv6 - header (40 bytes). */ + length of the payload that follows the + header. However, uIP uses the uip_len variable + for holding the size of the entire packet, + including the IP header. For IPv4 this is not a + problem as the length field in the IPv4 header + contains the length of the entire packet. But + for IPv6 we need to add the size of the IPv6 + header (40 bytes). */ #endif /* UIP_CONF_IPV6 */ } else { @@ -982,7 +984,7 @@ ( BUF->proto == UIP_PROTO_UDP && uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) /*&& - uip_ipchksum() == 0xffff*/ + uip_ipchksum() == 0xffff*/ ) { goto udp_input; } @@ -1014,7 +1016,7 @@ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header - checksum. */ + checksum. */ UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.chkerr); UIP_LOG("ip: bad checksum."); @@ -1025,8 +1027,8 @@ if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so, - proceed with TCP input - processing. */ + proceed with TCP input + processing. */ goto tcp_input; } @@ -1042,7 +1044,7 @@ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from - here. */ + here. */ UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.protoerr); UIP_LOG("ip: neither tcp nor icmp."); @@ -1100,7 +1102,7 @@ if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from - here. */ + here. */ UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.protoerr); UIP_LOG("ip: neither tcp nor icmp6."); @@ -1120,7 +1122,7 @@ } /* We should now send a neighbor advertisement back to where the - neighbor solicication came from. */ + neighbor solicication came from. */ ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ @@ -1274,7 +1276,7 @@ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP - checksum. */ + checksum. */ UIP_STAT(++uip_stat.tcp.drop); UIP_STAT(++uip_stat.tcp.chkerr); UIP_LOG("tcp: bad checksum."); @@ -1452,11 +1454,11 @@ else { /* All other options have a length field, so that we easily - can skip past them. */ + can skip past them. */ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { /* If the length field is zero, the options are malformed - and we don't process them further. */ + and we don't process them further. */ break; } @@ -1582,9 +1584,9 @@ /* Do different things depending on in what state the connection is. */ switch(uip_connr->tcpstateflags & UIP_TS_MASK) { /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not - implemented, since we force the application to close when the - peer sends a FIN (hence the application goes directly from - ESTABLISHED to LAST_ACK). */ + implemented, since we force the application to close when the + peer sends a FIN (hence the application goes directly from + ESTABLISHED to LAST_ACK). */ case UIP_SYN_RCVD: /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and we are waiting for an ACK that acknowledges the data we sent @@ -1642,11 +1644,11 @@ else { /* All other options have a length field, so that we easily - can skip past them. */ + can skip past them. */ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { /* If the length field is zero, the options are malformed - and we don't process them further. */ + and we don't process them further. */ break; } @@ -1804,32 +1806,32 @@ if(uip_slen > 0) { /* If the connection has acknowledged data, the contents of - the ->len variable should be discarded. */ + the ->len variable should be discarded. */ if((uip_flags & UIP_ACKDATA) != 0) { uip_connr->len = 0; } /* If the ->len variable is non-zero the connection has - already data in transit and cannot send anymore right - now. */ + already data in transit and cannot send anymore right + now. */ if(uip_connr->len == 0) { /* The application cannot send more than what is allowed by - the mss (the minumum of the MSS and the available - window). */ + the mss (the minumum of the MSS and the available + window). */ if(uip_slen > uip_connr->mss) { uip_slen = uip_connr->mss; } /* Remember how much data we send out now so that we know - when everything has been acknowledged. */ + when everything has been acknowledged. */ uip_connr->len = uip_slen; } else { /* If the application already had unacknowledged data, we - make sure that the application does not send (i.e., - retransmit) out more than it previously sent out. */ + make sure that the application does not send (i.e., + retransmit) out more than it previously sent out. */ uip_slen = uip_connr->len; } } @@ -1853,7 +1855,7 @@ } /* If there is no data to send, just send out a pure ACK if - there is newdata. */ + there is newdata. */ if(uip_flags & UIP_NEWDATA) { uip_len = UIP_TCPIP_HLEN; BUF->flags = TCP_ACK;
--- a/utility/uip.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/uip.h Sun Mar 08 20:26:56 2015 +0000 @@ -14,6 +14,8 @@ * structures, TCP/IP header structures and function declarations. * */ + + /* * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. @@ -47,31 +49,30 @@ * $Id: uip.h,v 1.40 2006/06/08 07:12:07 adam Exp $ * */ + #ifndef __UIP_H__ - #define __UIP_H__ +#define __UIP_H__ - #include "uipopt.h" +#include "uipopt.h" /** * Repressentation of an IP address. * */ - typedef u16_t uip_ip4addr_t[2]; -typedef u16_t uip_ip6addr_t[8]; - #if UIP_CONF_IPV6 -typedef uip_ip6addr_t uip_ipaddr_t; - #else /* UIP_CONF_IPV6 */ - -typedef uip_ip4addr_t uip_ipaddr_t; - #endif /* UIP_CONF_IPV6 */ +typedef u16_t uip_ip6addr_t[8]; +#if UIP_CONF_IPV6 +typedef uip_ip6addr_t uip_ipaddr_t; +#else /* UIP_CONF_IPV6 */ +typedef uip_ip4addr_t uip_ipaddr_t; +#endif /* UIP_CONF_IPV6 */ /*---------------------------------------------------------------------------*/ - /* First, the functions that should be called from the * system. Initialization, the periodic timer and incoming packets are * handled by the following three functions. */ + /** * \defgroup uipconffunc uIP configuration functions * @{ @@ -94,7 +95,7 @@ uip_ipaddr(&addr, 192,168,1,2); uip_sethostaddr(&addr); - + \endcode * \param addr A pointer to an IP address of type uip_ipaddr_t; * @@ -102,7 +103,7 @@ * * \hideinitializer */ - #define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr)) +#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr)) /** * Get the IP address of this host. @@ -122,8 +123,7 @@ * * \hideinitializer */ - - #define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr) +#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr) /** * Set the default router's IP address. @@ -135,8 +135,7 @@ * * \hideinitializer */ - - #define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr)) +#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr)) /** * Set the netmask. @@ -148,8 +147,8 @@ * * \hideinitializer */ +#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr)) - #define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr)) /** * Get the default router's IP address. @@ -159,8 +158,7 @@ * * \hideinitializer */ - - #define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr) +#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr) /** * Get the netmask. @@ -170,8 +168,7 @@ * * \hideinitializer */ - - #define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask) +#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask) /** @} */ @@ -181,20 +178,21 @@ * * The uIP initialization functions are used for booting uIP. */ + /** * uIP initialization function. * * This function should be called at boot up to initilize the uIP * TCP/IP stack. */ -void uip_init(void); +void uip_init(void); /** * uIP initialization function. * * This function may be used at boot time to set the initial ip_id. */ -void uip_setipid(u16_t id); +void uip_setipid(u16_t id); /** @} */ @@ -244,19 +242,19 @@ uip_input(); if(uip_len > 0) { uip_arp_out(); - ethernet_devicedriver_send(); + ethernet_devicedriver_send(); } } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { uip_arp_arpin(); if(uip_len > 0) { - ethernet_devicedriver_send(); + ethernet_devicedriver_send(); } } \endcode * * \hideinitializer */ - #define uip_input() uip_process(UIP_DATA) +#define uip_input() uip_process(UIP_DATA) /** * Periodic processing for a connection identified by its number. @@ -300,20 +298,14 @@ * * \hideinitializer */ - - #define uip_periodic(conn) \ - do \ - { \ - uip_conn = &uip_conns[conn]; \ - uip_process(UIP_TIMER); \ - } while(0) +#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ + uip_process(UIP_TIMER); } while (0) /** * * */ - - #define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED) +#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED) /** * Perform periodic processing for a connection identified by a pointer @@ -328,13 +320,8 @@ * * \hideinitializer */ - - #define uip_periodic_conn(conn) \ - do \ - { \ - uip_conn = conn; \ - uip_process(UIP_TIMER); \ - } while(0) +#define uip_periodic_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_TIMER); } while (0) /** * Reuqest that a particular connection should be polled. @@ -347,15 +334,11 @@ * * \hideinitializer */ +#define uip_poll_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_POLL_REQUEST); } while (0) - #define uip_poll_conn(conn) \ - do \ - { \ - uip_conn = conn; \ - uip_process(UIP_POLL_REQUEST); \ - } while(0) - #if UIP_UDP +#if UIP_UDP /** * Periodic processing for a UDP connection identified by its number. * @@ -387,13 +370,8 @@ * * \hideinitializer */ - - #define uip_udp_periodic(conn) \ - do \ - { \ - uip_udp_conn = &uip_udp_conns[conn]; \ - uip_process(UIP_UDP_TIMER); \ - } while(0) +#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ + uip_process(UIP_UDP_TIMER); } while (0) /** * Periodic processing for a UDP connection identified by a pointer to @@ -409,16 +387,13 @@ * * \hideinitializer */ +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ + uip_process(UIP_UDP_TIMER); } while (0) - #define uip_udp_periodic_conn(conn) \ - do \ - { \ - uip_udp_conn = conn; \ - uip_process(UIP_UDP_TIMER); \ - } while(0) - #endif /* UIP_UDP */ - /** +#endif /* UIP_UDP */ + +/** * The uIP packet buffer. * * The uip_buf array is used to hold incoming and outgoing @@ -444,7 +419,7 @@ } \endcode */ - extern u8_t uip_buf[UIP_BUFSIZE + 2]; +extern u8_t uip_buf[UIP_BUFSIZE+2]; /** @} */ @@ -459,6 +434,7 @@ * * Functions used by an application running of top of uIP. */ + /** * Start listening to the specified port. * @@ -471,7 +447,7 @@ * * \param port A 16-bit port number in network byte order. */ -void uip_listen(u16_t port); +void uip_listen(u16_t port); /** * Stop listening to the specified port. @@ -485,7 +461,7 @@ * * \param port A 16-bit port number in network byte order. */ -void uip_unlisten(u16_t port); +void uip_unlisten(u16_t port); /** * Connect to a remote host using TCP. @@ -519,7 +495,9 @@ * or NULL if no connection could be allocated. * */ -struct uip_conn* uip_connect(uip_ipaddr_t* ripaddr, u16_t port); +struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t port); + + /** * \internal @@ -530,8 +508,7 @@ * * \hideinitializer */ - - #define uip_outstanding(conn) ((conn)->len) +#define uip_outstanding(conn) ((conn)->len) /** * Send data on the current connection. @@ -558,7 +535,7 @@ * * \hideinitializer */ -void uip_send(const void* data, int len); +void uip_send(const void *data, int len); /** * The length of any incoming data that is currently avaliable (if avaliable) @@ -569,9 +546,8 @@ * * \hideinitializer */ - /*void uip_datalen(void);*/ - #define uip_datalen() uip_len +#define uip_datalen() uip_len /** * The length of any out-of-band data (urgent data) that has arrived @@ -582,8 +558,7 @@ * * \hideinitializer */ - - #define uip_urgdatalen() uip_urglen +#define uip_urgdatalen() uip_urglen /** * Close the current connection. @@ -592,8 +567,7 @@ * * \hideinitializer */ - - #define uip_close() (uip_flags = UIP_CLOSE) +#define uip_close() (uip_flags = UIP_CLOSE) /** * Abort the current connection. @@ -604,8 +578,7 @@ * * \hideinitializer */ - - #define uip_abort() (uip_flags = UIP_ABORT) +#define uip_abort() (uip_flags = UIP_ABORT) /** * Tell the sending host to stop sending data. @@ -615,8 +588,7 @@ * * \hideinitializer */ - - #define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) +#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) /** * Find out if the current connection has been previously stopped with @@ -624,8 +596,7 @@ * * \hideinitializer */ - - #define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) /** * Restart the current connection, if is has previously been stopped @@ -636,15 +607,12 @@ * * \hideinitializer */ +#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ + uip_conn->tcpstateflags &= ~UIP_STOPPED; \ + } while(0) - #define uip_restart() \ - do \ - { \ - uip_flags |= UIP_NEWDATA; \ - uip_conn->tcpstateflags &= ~UIP_STOPPED; \ - } while(0) - /* uIP tests that can be made to determine in what state the current +/* uIP tests that can be made to determine in what state the current connection is, and what the application function should do. */ /** @@ -655,7 +623,7 @@ * \hideinitializer * */ - #define uip_udpconnection() (uip_conn == NULL) +#define uip_udpconnection() (uip_conn == NULL) /** * Is new incoming data available? @@ -666,8 +634,7 @@ * * \hideinitializer */ - - #define uip_newdata() (uip_flags & UIP_NEWDATA) +#define uip_newdata() (uip_flags & UIP_NEWDATA) /** * Has previously sent data been acknowledged? @@ -678,8 +645,7 @@ * * \hideinitializer */ - - #define uip_acked() (uip_flags & UIP_ACKDATA) +#define uip_acked() (uip_flags & UIP_ACKDATA) /** * Has the connection just been connected? @@ -691,8 +657,7 @@ * * \hideinitializer */ - - #define uip_connected() (uip_flags & UIP_CONNECTED) +#define uip_connected() (uip_flags & UIP_CONNECTED) /** * Has the connection been closed by the other end? @@ -702,8 +667,7 @@ * * \hideinitializer */ - - #define uip_closed() (uip_flags & UIP_CLOSE) +#define uip_closed() (uip_flags & UIP_CLOSE) /** * Has the connection been aborted by the other end? @@ -713,8 +677,7 @@ * * \hideinitializer */ - - #define uip_aborted() (uip_flags & UIP_ABORT) +#define uip_aborted() (uip_flags & UIP_ABORT) /** * Has the connection timed out? @@ -724,8 +687,7 @@ * * \hideinitializer */ - - #define uip_timedout() (uip_flags & UIP_TIMEDOUT) +#define uip_timedout() (uip_flags & UIP_TIMEDOUT) /** * Do we need to retransmit previously data? @@ -737,8 +699,7 @@ * * \hideinitializer */ - - #define uip_rexmit() (uip_flags & UIP_REXMIT) +#define uip_rexmit() (uip_flags & UIP_REXMIT) /** * Is the connection being polled by uIP? @@ -752,8 +713,7 @@ * * \hideinitializer */ - - #define uip_poll() (uip_flags & UIP_POLL) +#define uip_poll() (uip_flags & UIP_POLL) /** * Get the initial maxium segment size (MSS) of the current @@ -761,8 +721,7 @@ * * \hideinitializer */ - - #define uip_initialmss() (uip_conn->initialmss) +#define uip_initialmss() (uip_conn->initialmss) /** * Get the current maxium segment size that can be sent on the current @@ -775,9 +734,9 @@ * * \hideinitializer */ +#define uip_mss() (uip_conn->mss) - #define uip_mss() (uip_conn->mss) - /** +/** * Set up a new UDP connection. * * This function sets up a new UDP connection. The function will @@ -790,7 +749,7 @@ \code uip_ipaddr_t addr; struct uip_udp_conn *c; - + uip_ipaddr(&addr, 192,168,2,1); c = uip_udp_new(&addr, HTONS(12345)); if(c != NULL) { @@ -804,7 +763,7 @@ * \return The uip_udp_conn structure for the new connection or NULL * if no connection could be allocated. */ - struct uip_udp_conn* uip_udp_new(uip_ipaddr_t* ripaddr, u16_t rport); +struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport); /** * Removed a UDP connection. @@ -813,8 +772,7 @@ * * \hideinitializer */ - - #define uip_udp_remove(conn) (conn)->lport = 0 +#define uip_udp_remove(conn) (conn)->lport = 0 /** * Bind a UDP connection to a local port. @@ -826,8 +784,7 @@ * * \hideinitializer */ - - #define uip_udp_bind(conn, port) (conn)->lport = port +#define uip_udp_bind(conn, port) (conn)->lport = port /** * Send a UDP datagram of length len on the current connection. @@ -840,12 +797,12 @@ * * \hideinitializer */ - - #define uip_udp_send(len) uip_send((char*)uip_appdata, len) +#define uip_udp_send(len) uip_send((char *)uip_appdata, len) /** @} */ /* uIP convenience and converting functions. */ + /** * \defgroup uipconvfunc uIP conversion functions * @{ @@ -853,7 +810,7 @@ * These functions can be used for converting between different data * formats used by uIP. */ - + /** * Construct an IP address from four bytes. * @@ -865,7 +822,7 @@ \code uip_ipaddr_t ipaddr; struct uip_conn *c; - + uip_ipaddr(&ipaddr, 192,168,1,2); c = uip_connect(&ipaddr, HTONS(80)); \endcode @@ -880,12 +837,10 @@ * * \hideinitializer */ - #define uip_ipaddr(addr, addr0, addr1, addr2, addr3) \ - do \ - { \ - ((u16_t *) (addr))[0] = HTONS(((addr0) << 8) | (addr1)); \ - ((u16_t *) (addr))[1] = HTONS(((addr2) << 8) | (addr3)); \ - } while(0) +#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ + ((u16_t *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \ + ((u16_t *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \ + } while(0) /** * Construct an IPv6 address from eight 16-bit words. @@ -894,19 +849,18 @@ * * \hideinitializer */ +#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \ + ((u16_t *)(addr))[0] = HTONS((addr0)); \ + ((u16_t *)(addr))[1] = HTONS((addr1)); \ + ((u16_t *)(addr))[2] = HTONS((addr2)); \ + ((u16_t *)(addr))[3] = HTONS((addr3)); \ + ((u16_t *)(addr))[4] = HTONS((addr4)); \ + ((u16_t *)(addr))[5] = HTONS((addr5)); \ + ((u16_t *)(addr))[6] = HTONS((addr6)); \ + ((u16_t *)(addr))[7] = HTONS((addr7)); \ + } while(0) - #define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7) \ - do \ - { \ - ((u16_t *) (addr))[0] = HTONS((addr0)); \ - ((u16_t *) (addr))[1] = HTONS((addr1)); \ - ((u16_t *) (addr))[2] = HTONS((addr2)); \ - ((u16_t *) (addr))[3] = HTONS((addr3)); \ - ((u16_t *) (addr))[4] = HTONS((addr4)); \ - ((u16_t *) (addr))[5] = HTONS((addr5)); \ - ((u16_t *) (addr))[6] = HTONS((addr6)); \ - ((u16_t *) (addr))[7] = HTONS((addr7)); \ - } while(0) /** +/** * Copy an IP address to another IP address. * * Copies an IP address from one place to another. @@ -924,20 +878,16 @@ * * \hideinitializer */ +#if !UIP_CONF_IPV6 +#define uip_ipaddr_copy(dest, src) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1]; \ + } while(0) +#else /* !UIP_CONF_IPV6 */ +#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t)) +#endif /* !UIP_CONF_IPV6 */ - #if !UIP_CONF_IPV6 - #define uip_ipaddr_copy(dest, src) \ - do \ - { \ - ((u16_t*)dest)[0] = ((u16_t*)src)[0]; \ - ((u16_t*)dest)[1] = ((u16_t*)src)[1]; \ - } while(0) - #else /* !UIP_CONF_IPV6 */ - - #define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t)) - #endif /* !UIP_CONF_IPV6 */ - - /** +/** * Compare two IP addresses * * Compares two IP addresses. @@ -957,14 +907,12 @@ * * \hideinitializer */ - - #if !UIP_CONF_IPV6 - #define uip_ipaddr_cmp(addr1, addr2) \ - (((u16_t*)addr1)[0] == ((u16_t*)addr2)[0] && ((u16_t*)addr1)[1] == ((u16_t*)addr2)[1]) - #else /* !UIP_CONF_IPV6 */ - - #define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0) - #endif /* !UIP_CONF_IPV6 */ +#if !UIP_CONF_IPV6 +#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \ + ((u16_t *)addr1)[1] == ((u16_t *)addr2)[1]) +#else /* !UIP_CONF_IPV6 */ +#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0) +#endif /* !UIP_CONF_IPV6 */ /** * Compare two IP addresses with netmasks @@ -990,12 +938,12 @@ * * \hideinitializer */ +#define uip_ipaddr_maskcmp(addr1, addr2, mask) \ + (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \ + (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \ + ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \ + (((u16_t *)addr2)[1] & ((u16_t *)mask)[1]))) - #define uip_ipaddr_maskcmp(addr1, addr2, mask) \ - ( \ - ((((u16_t*)addr1)[0] & ((u16_t*)mask)[0]) == (((u16_t*)addr2)[0] & ((u16_t*)mask)[0])) \ - && ((((u16_t*)addr1)[1] & ((u16_t*)mask)[1]) == (((u16_t*)addr2)[1] & ((u16_t*)mask)[1])) \ - ) /** * Mask out the network part of an IP address. @@ -1021,13 +969,10 @@ * * \hideinitializer */ - - #define uip_ipaddr_mask(dest, src, mask) \ - do \ - { \ - ((u16_t*)dest)[0] = ((u16_t*)src)[0] & ((u16_t*)mask)[0]; \ - ((u16_t*)dest)[1] = ((u16_t*)src)[1] & ((u16_t*)mask)[1]; \ - } while(0) +#define uip_ipaddr_mask(dest, src, mask) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \ + } while(0) /** * Pick the first octet of an IP address. @@ -1047,8 +992,7 @@ * * \hideinitializer */ - - #define uip_ipaddr1(addr) (htons(((u16_t *) (addr))[0]) >> 8) +#define uip_ipaddr1(addr) (htons(((u16_t *)(addr))[0]) >> 8) /** * Pick the second octet of an IP address. @@ -1068,8 +1012,7 @@ * * \hideinitializer */ - - #define uip_ipaddr2(addr) (htons(((u16_t *) (addr))[0]) & 0xff) +#define uip_ipaddr2(addr) (htons(((u16_t *)(addr))[0]) & 0xff) /** * Pick the third octet of an IP address. @@ -1089,8 +1032,7 @@ * * \hideinitializer */ - - #define uip_ipaddr3(addr) (htons(((u16_t *) (addr))[1]) >> 8) +#define uip_ipaddr3(addr) (htons(((u16_t *)(addr))[1]) >> 8) /** * Pick the fourth octet of an IP address. @@ -1110,9 +1052,9 @@ * * \hideinitializer */ +#define uip_ipaddr4(addr) (htons(((u16_t *)(addr))[1]) & 0xff) - #define uip_ipaddr4(addr) (htons(((u16_t *) (addr))[1]) & 0xff) - /** +/** * Convert 16-bit quantity from host byte order to network byte order. * * This macro is primarily used for converting constants from host @@ -1121,34 +1063,30 @@ * * \hideinitializer */ - - #ifndef HTONS - #if UIP_BYTE_ORDER == UIP_BIG_ENDIAN - #define HTONS(n) (n) - #else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +#ifndef HTONS +# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN +# define HTONS(n) (n) +# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +# define HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8)) +# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +#else +#error "HTONS already defined!" +#endif /* HTONS */ - #define HTONS(n) (u16_t) ((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8)) - #endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ - - #else - #error "HTONS already defined!" - #endif /* HTONS */ - - /** +/** * Convert 16-bit quantity from host byte order to network byte order. * * This function is primarily used for converting variables from host * byte order to network byte order. For converting constants to * network byte order, use the HTONS() macro instead. */ +#ifndef htons +u16_t htons(u16_t val); +#endif /* htons */ +#ifndef ntohs +#define ntohs htons +#endif - #ifndef htons - u16_t htons(u16_t val); - #endif /* htons */ - - #ifndef ntohs - #define ntohs htons - #endif /** @} */ /** @@ -1158,16 +1096,17 @@ * called. If the application wishes to send data, the application may * use this space to write the data into before calling uip_send(). */ -extern void* uip_appdata; +extern void *uip_appdata; - #if UIP_URGDATA > 0 +#if UIP_URGDATA > 0 /* u8_t *uip_urgdata: * * This pointer points to any urgent data that has been received. Only * present if compiled with support for urgent data (UIP_URGDATA). */ -extern void* uip_urgdata; - #endif /* UIP_URGDATA > 0 */ +extern void *uip_urgdata; +#endif /* UIP_URGDATA > 0 */ + /** * \defgroup uipdrivervars Variables used in uIP device drivers @@ -1192,12 +1131,14 @@ * packet. * */ -extern u16_t uip_len; +extern u16_t uip_len; /** @} */ - #if UIP_URGDATA > 0 -extern u16_t uip_urglen, uip_surglen; - #endif /* UIP_URGDATA > 0 */ + +#if UIP_URGDATA > 0 +extern u16_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + /** * Representation of a uIP TCP connection. @@ -1209,146 +1150,137 @@ * file pointers) for the connection. The type of this field is * configured in the "uipopt.h" header file. */ - -struct uip_conn -{ - uip_ipaddr_t ripaddr; /**< The IP address of the remote host. */ - - u16_t lport; /**< The local TCP port, in network byte order. */ - u16_t rport; /**< The local remote TCP port, in network byte - order. */ - - u8_t rcv_nxt[4]; /**< The sequence number that we expect to - receive next. */ - u8_t snd_nxt[4]; /**< The sequence number that was last sent by +struct uip_conn { + uip_ipaddr_t ripaddr; /**< The IP address of the remote host. */ + + u16_t lport; /**< The local TCP port, in network byte order. */ + u16_t rport; /**< The local remote TCP port, in network byte + order. */ + + u8_t rcv_nxt[4]; /**< The sequence number that we expect to + receive next. */ + u8_t snd_nxt[4]; /**< The sequence number that was last sent by us. */ - u16_t len; /**< Length of the data that was previously sent. */ - u16_t mss; /**< Current maximum segment size for the - connection. */ - u16_t initialmss; /**< Initial maximum segment size for the - connection. */ - u8_t sa; /**< Retransmission time-out calculation state - variable. */ - u8_t sv; /**< Retransmission time-out calculation state - variable. */ - u8_t rto; /**< Retransmission time-out. */ - u8_t tcpstateflags; /**< TCP state and flags. */ - u8_t timer; /**< The retransmission timer. */ - u8_t nrtx; /**< The number of retransmissions for the last - segment sent. */ + u16_t len; /**< Length of the data that was previously sent. */ + u16_t mss; /**< Current maximum segment size for the + connection. */ + u16_t initialmss; /**< Initial maximum segment size for the + connection. */ + u8_t sa; /**< Retransmission time-out calculation state + variable. */ + u8_t sv; /**< Retransmission time-out calculation state + variable. */ + u8_t rto; /**< Retransmission time-out. */ + u8_t tcpstateflags; /**< TCP state and flags. */ + u8_t timer; /**< The retransmission timer. */ + u8_t nrtx; /**< The number of retransmissions for the last + segment sent. */ - /** The application state. */ - uip_tcp_appstate_t appstate; + /** The application state. */ + uip_tcp_appstate_t appstate; }; + /** * Pointer to the current TCP connection. * * The uip_conn pointer can be used to access the current TCP * connection. */ -extern struct uip_conn* uip_conn; - +extern struct uip_conn *uip_conn; /* The array containing all uIP connections. */ -extern struct uip_conn uip_conns[UIP_CONNS]; - +extern struct uip_conn uip_conns[UIP_CONNS]; /** * \addtogroup uiparch * @{ */ + /** * 4-byte array used for the 32-bit sequence number calculations. */ -extern u8_t uip_acc32[4]; +extern u8_t uip_acc32[4]; /** @} */ - #if UIP_UDP +#if UIP_UDP /** * Representation of a uIP UDP connection. */ -struct uip_udp_conn -{ - uip_ipaddr_t ripaddr; /**< The IP address of the remote peer. */ - u16_t lport; /**< The local port number in network byte order. */ - u16_t rport; /**< The remote port number in network byte order. */ - u8_t ttl; /**< Default time-to-live. */ +struct uip_udp_conn { + uip_ipaddr_t ripaddr; /**< The IP address of the remote peer. */ + u16_t lport; /**< The local port number in network byte order. */ + u16_t rport; /**< The remote port number in network byte order. */ + u8_t ttl; /**< Default time-to-live. */ - /** The application state. */ - uip_udp_appstate_t appstate; + /** The application state. */ + uip_udp_appstate_t appstate; }; /** * The current UDP connection. */ -extern struct uip_udp_conn* uip_udp_conn; -extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; - #endif /* UIP_UDP */ +extern struct uip_udp_conn *uip_udp_conn; +extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ /** * The structure holding the TCP/IP statistics that are gathered if * UIP_STATISTICS is set to 1. * */ - -struct uip_stats -{ - struct - { - uip_stats_t drop; /**< Number of dropped packets at the IP - layer. */ - uip_stats_t recv; /**< Number of received packets at the IP - layer. */ - uip_stats_t sent; /**< Number of sent packets at the IP - layer. */ - uip_stats_t vhlerr; /**< Number of packets dropped due to wrong - IP version or header length. */ - uip_stats_t hblenerr; /**< Number of packets dropped due to wrong - IP length, high byte. */ - uip_stats_t lblenerr; /**< Number of packets dropped due to wrong - IP length, low byte. */ - uip_stats_t fragerr; /**< Number of packets dropped since they - were IP fragments. */ - uip_stats_t chkerr; /**< Number of packets dropped due to IP - checksum errors. */ - uip_stats_t protoerr; /**< Number of packets dropped since they - were neither ICMP, UDP nor TCP. */ - } ip; /**< IP statistics. */ - struct - { - uip_stats_t drop; /**< Number of dropped ICMP packets. */ - uip_stats_t recv; /**< Number of received ICMP packets. */ - uip_stats_t sent; /**< Number of sent ICMP packets. */ - uip_stats_t typeerr; /**< Number of ICMP packets with a wrong - type. */ - } icmp; /**< ICMP statistics. */ - struct - { - uip_stats_t drop; /**< Number of dropped TCP segments. */ - uip_stats_t recv; /**< Number of recived TCP segments. */ - uip_stats_t sent; /**< Number of sent TCP segments. */ - uip_stats_t chkerr; /**< Number of TCP segments with a bad - checksum. */ - uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK - number. */ - uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ - uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ - uip_stats_t syndrop; /**< Number of dropped SYNs due to too few - connections was avaliable. */ - uip_stats_t synrst; /**< Number of SYNs for closed ports, - triggering a RST. */ - } tcp; /**< TCP statistics. */ - #if UIP_UDP - struct - { - uip_stats_t drop; /**< Number of dropped UDP segments. */ - uip_stats_t recv; /**< Number of recived UDP segments. */ - uip_stats_t sent; /**< Number of sent UDP segments. */ - uip_stats_t chkerr; /**< Number of UDP segments with a bad - checksum. */ - } udp; /**< UDP statistics. */ - #endif /* UIP_UDP */ +struct uip_stats { + struct { + uip_stats_t drop; /**< Number of dropped packets at the IP + layer. */ + uip_stats_t recv; /**< Number of received packets at the IP + layer. */ + uip_stats_t sent; /**< Number of sent packets at the IP + layer. */ + uip_stats_t vhlerr; /**< Number of packets dropped due to wrong + IP version or header length. */ + uip_stats_t hblenerr; /**< Number of packets dropped due to wrong + IP length, high byte. */ + uip_stats_t lblenerr; /**< Number of packets dropped due to wrong + IP length, low byte. */ + uip_stats_t fragerr; /**< Number of packets dropped since they + were IP fragments. */ + uip_stats_t chkerr; /**< Number of packets dropped due to IP + checksum errors. */ + uip_stats_t protoerr; /**< Number of packets dropped since they + were neither ICMP, UDP nor TCP. */ + } ip; /**< IP statistics. */ + struct { + uip_stats_t drop; /**< Number of dropped ICMP packets. */ + uip_stats_t recv; /**< Number of received ICMP packets. */ + uip_stats_t sent; /**< Number of sent ICMP packets. */ + uip_stats_t typeerr; /**< Number of ICMP packets with a wrong + type. */ + } icmp; /**< ICMP statistics. */ + struct { + uip_stats_t drop; /**< Number of dropped TCP segments. */ + uip_stats_t recv; /**< Number of recived TCP segments. */ + uip_stats_t sent; /**< Number of sent TCP segments. */ + uip_stats_t chkerr; /**< Number of TCP segments with a bad + checksum. */ + uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK + number. */ + uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ + uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ + uip_stats_t syndrop; /**< Number of dropped SYNs due to too few + connections was avaliable. */ + uip_stats_t synrst; /**< Number of SYNs for closed ports, + triggering a RST. */ + } tcp; /**< TCP statistics. */ +#if UIP_UDP + struct { + uip_stats_t drop; /**< Number of dropped UDP segments. */ + uip_stats_t recv; /**< Number of recived UDP segments. */ + uip_stats_t sent; /**< Number of sent UDP segments. */ + uip_stats_t chkerr; /**< Number of UDP segments with a bad + checksum. */ + } udp; /**< UDP statistics. */ +#endif /* UIP_UDP */ }; /** @@ -1358,6 +1290,7 @@ */ extern struct uip_stats uip_stat; + /*---------------------------------------------------------------------------*/ /* All the stuff below this point is internal to uIP and should not be * used directly by an application or by a device driver. @@ -1369,7 +1302,7 @@ * that are defined in this file. Please read below for more * infomation. */ -extern u8_t uip_flags; +extern u8_t uip_flags; /* The following flags may be set in the global variable uip_flags before calling the application callback. The UIP_ACKDATA, @@ -1378,46 +1311,40 @@ should *NOT* be accessed directly, but only through the uIP functions/macros. */ - #define UIP_ACKDATA 1 /* Signifies that the outstanding data was - acked and the application should send - out new data instead of retransmitting - the last data. */ - - #define UIP_NEWDATA 2 /* Flags the fact that the peer has sent - us new data. */ - - #define UIP_REXMIT 4 /* Tells the application to retransmit the - data that was last sent. */ - - #define UIP_POLL 8 /* Used for polling the application, to - check if the application has data that - it wants to send. */ - - #define UIP_CLOSE 16 /* The remote host has closed the - connection, thus the connection has - gone away. Or the application signals - that it wants to close the - connection. */ - - #define UIP_ABORT 32 /* The remote host has aborted the - connection, thus the connection has - gone away. Or the application signals - that it wants to abort the - connection. */ - - #define UIP_CONNECTED 64 /* We have got a connection from a remote +#define UIP_ACKDATA 1 /* Signifies that the outstanding data was + acked and the application should send + out new data instead of retransmitting + the last data. */ +#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent + us new data. */ +#define UIP_REXMIT 4 /* Tells the application to retransmit the + data that was last sent. */ +#define UIP_POLL 8 /* Used for polling the application, to + check if the application has data that + it wants to send. */ +#define UIP_CLOSE 16 /* The remote host has closed the + connection, thus the connection has + gone away. Or the application signals + that it wants to close the + connection. */ +#define UIP_ABORT 32 /* The remote host has aborted the + connection, thus the connection has + gone away. Or the application signals + that it wants to abort the + connection. */ +#define UIP_CONNECTED 64 /* We have got a connection from a remote host and have set up a new connection for it, or an active connection has been successfully established. */ - #define UIP_TIMEDOUT 128 /* The connection has been aborted due to - too many retransmissions. */ +#define UIP_TIMEDOUT 128 /* The connection has been aborted due to + too many retransmissions. */ /* uip_process(flag): * * The actual uIP function which does all the work. */ -void uip_process(u8_t flag); +void uip_process(u8_t flag); /* The following flags are passed as an argument to the uip_process() function. They are used to distinguish between the two cases where @@ -1425,123 +1352,142 @@ incoming data that should be processed, or because the periodic timer has fired. These values are never used directly, but only in the macrose defined in this file. */ - - #define UIP_DATA 1 /* Tells uIP that there is incoming - data in the uip_buf buffer. The - length of the data is stored in the - global variable uip_len. */ - - #define UIP_TIMER 2 /* Tells uIP that the periodic timer - has fired. */ - - #define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should - be polled. */ - - #define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram - should be constructed in the - uip_buf buffer. */ - - #if UIP_UDP - #define UIP_UDP_TIMER 5 - #endif /* UIP_UDP */ + +#define UIP_DATA 1 /* Tells uIP that there is incoming + data in the uip_buf buffer. The + length of the data is stored in the + global variable uip_len. */ +#define UIP_TIMER 2 /* Tells uIP that the periodic timer + has fired. */ +#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should + be polled. */ +#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram + should be constructed in the + uip_buf buffer. */ +#if UIP_UDP +#define UIP_UDP_TIMER 5 +#endif /* UIP_UDP */ /* The TCP states used in the uip_conn->tcpstateflags. */ - - #define UIP_CLOSED 0 - #define UIP_SYN_RCVD 1 - #define UIP_SYN_SENT 2 - #define UIP_ESTABLISHED 3 - #define UIP_FIN_WAIT_1 4 - #define UIP_FIN_WAIT_2 5 - #define UIP_CLOSING 6 - #define UIP_TIME_WAIT 7 - #define UIP_LAST_ACK 8 - #define UIP_TS_MASK 15 - - #define UIP_STOPPED 16 +#define UIP_CLOSED 0 +#define UIP_SYN_RCVD 1 +#define UIP_SYN_SENT 2 +#define UIP_ESTABLISHED 3 +#define UIP_FIN_WAIT_1 4 +#define UIP_FIN_WAIT_2 5 +#define UIP_CLOSING 6 +#define UIP_TIME_WAIT 7 +#define UIP_LAST_ACK 8 +#define UIP_TS_MASK 15 + +#define UIP_STOPPED 16 /* The TCP and IP headers. */ -struct uip_tcpip_hdr -{ - #if UIP_CONF_IPV6 - /* IPv6 header. */ - u8_t vtc, tcflow; - u16_t flow; - u8_t len[2]; - u8_t proto, ttl; - uip_ip6addr_t srcipaddr, destipaddr; - #else /* UIP_CONF_IPV6 */ - /* IPv4 header. */ - - u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto; - u16_t ipchksum; - u16_t srcipaddr[2], destipaddr[2]; - #endif /* UIP_CONF_IPV6 */ - - /* TCP header. */ - - u16_t srcport, destport; - u8_t seqno[4], ackno[4], tcpoffset, flags, wnd[2]; - u16_t tcpchksum; - u8_t urgp[2]; - u8_t optdata[4]; +struct uip_tcpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcflow; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPv4 header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* TCP header. */ + u16_t srcport, + destport; + u8_t seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + u16_t tcpchksum; + u8_t urgp[2]; + u8_t optdata[4]; }; /* The ICMP and IP headers. */ -struct uip_icmpip_hdr -{ - #if UIP_CONF_IPV6 - /* IPv6 header. */ - u8_t vtc, tcf; - u16_t flow; - u8_t len[2]; - u8_t proto, ttl; - uip_ip6addr_t srcipaddr, destipaddr; - #else /* UIP_CONF_IPV6 */ - /* IPv4 header. */ - - u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto; - u16_t ipchksum; - u16_t srcipaddr[2], destipaddr[2]; - #endif /* UIP_CONF_IPV6 */ - - /* ICMP (echo) header. */ - - u8_t type, icode; - u16_t icmpchksum; - #if !UIP_CONF_IPV6 - u16_t id, seqno; - #else /* !UIP_CONF_IPV6 */ - u8_t flags, reserved1, reserved2, reserved3; - u8_t icmp6data[16]; - u8_t options[1]; - #endif /* !UIP_CONF_IPV6 */ +struct uip_icmpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcf; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPv4 header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* ICMP (echo) header. */ + u8_t type, icode; + u16_t icmpchksum; +#if !UIP_CONF_IPV6 + u16_t id, seqno; +#else /* !UIP_CONF_IPV6 */ + u8_t flags, reserved1, reserved2, reserved3; + u8_t icmp6data[16]; + u8_t options[1]; +#endif /* !UIP_CONF_IPV6 */ }; + /* The UDP and IP headers. */ -struct uip_udpip_hdr -{ - #if UIP_CONF_IPV6 - /* IPv6 header. */ - u8_t vtc, tcf; - u16_t flow; - u8_t len[2]; - u8_t proto, ttl; - uip_ip6addr_t srcipaddr, destipaddr; - #else /* UIP_CONF_IPV6 */ - /* IP header. */ +struct uip_udpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcf; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* UDP header. */ + u16_t srcport, + destport; + u16_t udplen; + u16_t udpchksum; +}; - u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto; - u16_t ipchksum; - u16_t srcipaddr[2], destipaddr[2]; - #endif /* UIP_CONF_IPV6 */ - /* UDP header. */ - - u16_t srcport, destport; - u16_t udplen; - u16_t udpchksum; -}; /** * The buffer size available for user data in the \ref uip_buf buffer. @@ -1557,49 +1503,44 @@ * * \hideinitializer */ - #define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) - #define UIP_PROTO_ICMP 1 - #define UIP_PROTO_TCP 6 - #define UIP_PROTO_UDP 17 - #define UIP_PROTO_ICMP6 58 +#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + + +#define UIP_PROTO_ICMP 1 +#define UIP_PROTO_TCP 6 +#define UIP_PROTO_UDP 17 +#define UIP_PROTO_ICMP6 58 /* Header sizes. */ - - #if UIP_CONF_IPV6 - #define UIP_IPH_LEN 40 - #else /* UIP_CONF_IPV6 */ - - #define UIP_IPH_LEN 20 /* Size of IP header */ - #endif /* UIP_CONF_IPV6 */ - - #define UIP_UDPH_LEN 8 /* Size of UDP header */ - - #define UIP_TCPH_LEN 20 /* Size of TCP header */ +#if UIP_CONF_IPV6 +#define UIP_IPH_LEN 40 +#else /* UIP_CONF_IPV6 */ +#define UIP_IPH_LEN 20 /* Size of IP header */ +#endif /* UIP_CONF_IPV6 */ +#define UIP_UDPH_LEN 8 /* Size of UDP header */ +#define UIP_TCPH_LEN 20 /* Size of TCP header */ +#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + + UDP + header */ +#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + + TCP + header */ +#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN - #define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + - UDP - header */ - - #define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + - TCP - header */ - #define UIP_TCPIP_HLEN UIP_IPTCPH_LEN +#if UIP_FIXEDADDR +extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#else /* UIP_FIXEDADDR */ +extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#endif /* UIP_FIXEDADDR */ - #if UIP_FIXEDADDR -extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; - #else /* UIP_FIXEDADDR */ -extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; - #endif /* UIP_FIXEDADDR */ /** * Representation of a 48-bit Ethernet address. */ - -struct uip_eth_addr -{ - u8_t addr[6]; +struct uip_eth_addr { + u8_t addr[6]; }; /** @@ -1618,7 +1559,7 @@ * * \return The Internet checksum of the buffer. */ -u16_t uip_chksum(u16_t* buf, u16_t len); +u16_t uip_chksum(u16_t *buf, u16_t len); /** * Calculate the IP header checksum of the packet header in uip_buf. @@ -1629,7 +1570,7 @@ * \return The IP header checksum of the IP header in the uip_buf * buffer. */ -u16_t uip_ipchksum(void); +u16_t uip_ipchksum(void); /** * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. @@ -1640,7 +1581,7 @@ * \return The TCP checksum of the TCP segment in uip_buf and pointed * to by uip_appdata. */ -u16_t uip_tcpchksum(void); +u16_t uip_tcpchksum(void); /** * Calculate the UDP checksum of the packet in uip_buf and uip_appdata. @@ -1651,7 +1592,10 @@ * \return The UDP checksum of the UDP segment in uip_buf and pointed * to by uip_appdata. */ -u16_t uip_udpchksum(void); +u16_t uip_udpchksum(void); + + #endif /* __UIP_H__ */ + /** @} */
--- a/utility/uip_clock.cpp Sat Dec 20 11:10:40 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -#include <time.h> -#include "uip_clock.h" - -/** - * @brief - * @note - * @param - * @retval - */ -clock_time_t clock_time(void) { - return(clock_time_t) time(NULL); -}
--- a/utility/uip_debug.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/uip_debug.h Sun Mar 08 20:26:56 2015 +0000 @@ -2,7 +2,7 @@ #define UIP_DEBUG_H extern "C" { - #include "uip.h" + #import "utility/uip.h" } class UIPDebug {
--- a/utility/uipethernet-conf.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/uipethernet-conf.h Sun Mar 08 20:26:56 2015 +0000 @@ -6,15 +6,29 @@ #define UIP_SOCKET_NUMPACKETS 5 #define UIP_CONF_MAX_CONNECTIONS 4 -/* for UDP */ +/* for UDP + * set UIP_CONF_UDP to 0 to disable UDP (saves aprox. 5kb flash) */ #define UIP_CONF_UDP 1 #define UIP_CONF_BROADCAST 1 #define UIP_CONF_UDP_CONNS 4 - #define UIP_UDP_NUMPACKETS 5 /* number of attempts on write before returning number of bytes sent so far * set to -1 to block until connection is closed by timeout */ - #define UIP_ATTEMPTS_ON_WRITE - 1 + #define UIP_ATTEMPTS_ON_WRITE -1 + +/* timeout after which UIPClient::connect gives up. The timeout is specified in seconds. + * if set to a number <= 0 connect will timeout when uIP does (which might be longer than you expect...) */ + + #define UIP_CONNECT_TIMEOUT -1 + +/* periodic timer for uip (in ms) */ + + #define UIP_PERIODIC_TIMER 250 + +/* timer to poll client for data after last write (in ms) + * set to -1 to disable fast polling and rely on periodic only (saves 100 bytes flash) */ + + #define UIP_CLIENT_TIMER 20 #endif
--- a/utility/util.h Sat Dec 20 11:10:40 2014 +0000 +++ b/utility/util.h Sun Mar 08 20:26:56 2015 +0000 @@ -1,13 +1,9 @@ #ifndef UTIL_H -#define UTIL_H - -#define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) ) -#define ntohs(x) htons(x) + #define UTIL_H -#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ - ((x)<< 8 & 0x00FF0000UL) | \ - ((x)>> 8 & 0x0000FF00UL) | \ - ((x)>>24 & 0x000000FFUL) ) -#define ntohl(x) htonl(x) - + #define htons(x) (((x) << 8) | (((x) >> 8) & 0xFF)) + #define ntohs(x) htons(x) + #define htonl(x) \ + (((x) << 24 & 0xFF000000UL) | ((x) << 8 & 0x00FF0000UL) | ((x) >> 8 & 0x0000FF00UL) | ((x) >> 24 & 0x000000FFUL)) + #define ntohl(x) htonl(x) #endif