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.
Diff: UIPEthernet.cpp
- Revision:
- 8:4acb22344932
- Parent:
- 4:d774541a34da
--- a/UIPEthernet.cpp Tue Apr 26 18:37:14 2016 +0000 +++ b/UIPEthernet.cpp Fri Jun 30 19:51:28 2017 +0000 @@ -1,5 +1,5 @@ /* - UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. + UIPEthernet.cpp - Arduino implementation of a UIP wrapper class. Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> All rights reserved. @@ -18,13 +18,9 @@ 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 "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" @@ -37,15 +33,15 @@ } #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); +memhandle UIPEthernet::in_packet(NOBLOCK); +memhandle UIPEthernet::uip_packet(NOBLOCK); +uint8_t UIPEthernet::uip_hdrlen(0); +uint8_t UIPEthernet::packetstate(0); -IPAddress UIPEthernetClass:: _dnsServerAddress; -DhcpClass* UIPEthernetClass:: _dhcp(NULL); +IPAddress UIPEthernet::_dnsServerAddress; +DhcpClass* UIPEthernet::_dhcp(NULL); -unsigned long UIPEthernetClass:: periodic_timer; +unsigned long UIPEthernet::periodic_timer; /** * @brief @@ -55,60 +51,57 @@ */ void enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) { - //void + //as ENC28J60 DMA is unable to copy single bytes: - //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)); + 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. + /* 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); + uIPEthernet.network.writeRegPair(EDMASTL, src); + uIPEthernet.network.writeRegPair(EDMADSTL, dest); - if((src <= RXSTOP_INIT) && (len > RXSTOP_INIT)) + if ((src <= RXSTOP_INIT) && (len > RXSTOP_INIT)) len -= (RXSTOP_INIT - RXSTART_INIT); - UIPEthernet.network.writeRegPair(EDMANDL, len); + 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. + /* 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); + 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); + 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); + // 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) : +/* + * 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. + */ +UIPEthernet::UIPEthernet(PinName mosi, PinName miso, PinName sck, PinName cs) : network(mosi, miso, sck, cs) { millis_start(); } @@ -121,8 +114,9 @@ * @param * @retval */ -int UIPEthernetClass::begin(const uint8_t* mac) { +int UIPEthernet::begin(const uint8_t* mac) { static DhcpClass s_dhcp; + _dhcp = &s_dhcp; // Initialise the basic info @@ -130,7 +124,8 @@ // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP((uint8_t*)mac); - if(ret == 1) { + + if (ret == 1) { // We've successfully found a DHCP server and got our configuration info, so set things // accordingly @@ -147,8 +142,9 @@ * @param * @retval */ -void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) { +void UIPEthernet::begin(const uint8_t* mac, IPAddress ip) { IPAddress dns = ip; + dns[3] = 1; begin(mac, ip, dns); } @@ -159,8 +155,9 @@ * @param * @retval */ -void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) { +void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) { IPAddress gateway = ip; + gateway[3] = 1; begin(mac, ip, dns, gateway); } @@ -171,8 +168,9 @@ * @param * @retval */ -void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) { +void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) { IPAddress subnet(255, 255, 255, 0); + begin(mac, ip, dns, gateway, subnet); } @@ -182,7 +180,7 @@ * @param * @retval */ -void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { +void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { init(mac); configure(ip, dns, gateway, subnet); } @@ -193,29 +191,30 @@ * @param * @retval */ -int UIPEthernetClass::maintain(void) { +int UIPEthernet::maintain(void) { tick(); int rc = DHCP_CHECK_NONE; + #if UIP_UDP - if(_dhcp != NULL) { + if (_dhcp != NULL) { //we have a pointer to dhcp, use it rc = _dhcp->checkLease(); - switch(rc) { - case DHCP_CHECK_NONE: - //nothing done - break; + 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; + 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; + default: + //this is actually an error, it will retry though + break; } } @@ -229,9 +228,9 @@ * @param * @retval */ -IPAddress UIPEthernetClass::localIP(void) { - IPAddress ret; +IPAddress UIPEthernet::localIP(void) { uip_ipaddr_t a; + uip_gethostaddr(a); return ip_addr_uip(a); } @@ -242,9 +241,9 @@ * @param * @retval */ -IPAddress UIPEthernetClass::subnetMask(void) { - IPAddress ret; +IPAddress UIPEthernet::subnetMask(void) { uip_ipaddr_t a; + uip_getnetmask(a); return ip_addr_uip(a); } @@ -255,9 +254,9 @@ * @param * @retval */ -IPAddress UIPEthernetClass::gatewayIP(void) { - IPAddress ret; +IPAddress UIPEthernet::gatewayIP(void) { uip_ipaddr_t a; + uip_getdraddr(a); return ip_addr_uip(a); } @@ -268,7 +267,7 @@ * @param * @retval */ -IPAddress UIPEthernetClass::dnsServerIP(void) { +IPAddress UIPEthernet::dnsServerIP(void) { return _dnsServerAddress; } @@ -278,344 +277,320 @@ * @param * @retval */ -void UIPEthernetClass::tick(void) -{ - if(in_packet == NOBLOCK) { +void UIPEthernet::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); + if (in_packet != NOBLOCK) { + printf("--------------\r\nreceivePacket: %d\r\n", in_packet); } #endif } - if(in_packet != NOBLOCK) { + + if (in_packet != NOBLOCK) { packetstate = UIPETHERNET_FREEPACKET; uip_len = network.blockSize(in_packet); - if(uip_len > 0) { + if (uip_len > 0) { network.readPacket(in_packet, 0, (uint8_t*)uip_buf, UIP_BUFSIZE); - if(ETH_HDR->type == HTONS(UIP_ETHTYPE_IP)) { + 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); + printf("readPacket type IP, uip_len: %d\r\n", uip_len); #endif uip_arp_ipin(); uip_input(); - if(uip_len > 0) { + if (uip_len > 0) { uip_arp_out(); network_send(); } } else - if(ETH_HDR->type == HTONS(UIP_ETHTYPE_ARP)) + if (ETH_HDR->type == HTONS(UIP_ETHTYPE_ARP)) { #ifdef UIPETHERNET_DEBUG - Serial.print(F("readPacket type ARP, uip_len: ")); - Serial.println(uip_len); + printf("readPacket type ARP, uip_len: %d\r\n", uip_len); #endif uip_arp_arpin(); - if(uip_len > 0) { + if (uip_len > 0) { network_send(); } } } - if(in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) + + if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) { #ifdef UIPETHERNET_DEBUG - Serial.print(F("freeing packet: ")); - Serial.println(in_packet); + printf("freeing packet: %d\r\n", 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++) { + uip_conn = &uip_conns[i]; + if (periodic) { + uip_process(UIP_TIMER); + } + else { + if ((long)(now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) + uip_process(UIP_POLL_REQUEST); + else + continue; + } - 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 + // 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(); + } + } - // 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 (periodic) { + periodic_timer = now + UIP_PERIODIC_TIMER; #if UIP_UDP - for(int i = 0; i < UIP_UDP_CONNS; i++) { - uip_udp_periodic(i); + 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 */ + // 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) - { +bool UIPEthernet::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); + printf("Enc28J60Network_send uip_packet: %d, hdrlen: %d\r\n", uip_packet, uip_hdrlen); #endif - UIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_hdrlen); - packetstate &= ~UIPETHERNET_SENDPACKET; - goto sendandfree; - } + 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) - { + 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); + printf("Enc28J60Network_send uip_buf (uip_len): %d, packet: %d\r\n", uip_len, uip_packet); #endif - UIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_len); - goto sendandfree; - } + uIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_len); + goto sendandfree; + } - return false; + return false; sendandfree: - network.sendPacket(uip_packet); - Enc28J60Network::freeBlock(uip_packet); - uip_packet = NOBLOCK; - return true; - } + 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; +void UIPEthernet::init(const uint8_t* mac) { + periodic_timer = millis() + UIP_PERIODIC_TIMER; - network.init((uint8_t*)mac); - uip_seteth_addr(mac); + network.init((uint8_t*)mac); + uip_seteth_addr(mac); - uip_init(); - uip_arp_init(); - } + 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); +void UIPEthernet::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + uip_ipaddr_t ipaddr; - uip_ip_addr(ipaddr, gateway); - uip_setdraddr(ipaddr); - - uip_ip_addr(ipaddr, subnet); - uip_setnetmask(ipaddr); + uip_ip_addr(ipaddr, ip); + uip_sethostaddr(ipaddr); - _dnsServerAddress = dns; - } - - //UIPEthernetClass UIPEthernet; + uip_ip_addr(ipaddr, gateway); + uip_setdraddr(ipaddr); - /*---------------------------------------------------------------------------*/ - 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; + uip_ip_addr(ipaddr, subnet); + uip_setnetmask(ipaddr); - dataptr = data; - last_byte = data + len - 1; - - while(dataptr < last_byte) { + _dnsServerAddress = dns; +} - /* At least two more bytes */ - t = (dataptr[0] << 8) + dataptr[1]; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - - dataptr += 2; - } +/** + * @brief + * @note + * @param + * @retval + */ +uint16_t UIPEthernet::chksum(uint16_t sum, const uint8_t* data, uint16_t len) { + uint16_t t; + const uint8_t* dataptr; + const uint8_t* last_byte; - if(dataptr == last_byte) { - t = (dataptr[0] << 8) + 0; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - } + dataptr = data; + last_byte = data + len - 1; + + while (dataptr < last_byte) { - /* 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); + /* At least two more bytes */ + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if (sum < t) { + sum++; /* carry */ } - /*---------------------------------------------------------------------------*/ - 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; + dataptr += 2; + } - 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); + if (dataptr == last_byte) { + t = (dataptr[0] << 8) + 0; + sum += t; + if (sum < t) { + sum++; /* carry */ } + } - /** + /* Return sum in host byte order. */ + return sum; +} + +/** * @brief * @note * @param * @retval */ - uint16_t uip_ipchksum(void) { - return UIPEthernet.ipchksum(); - } +uint16_t UIPEthernet::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 +UIPEthernet::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 = UIPEthernet::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 = UIPEthernet::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); +#ifdef UIPETHERNET_DEBUG_CHKSUM + printf("chksum uip_buf[%d-%d]: %d\r\n", UIP_IPH_LEN + UIP_LLH_LEN, UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, htons(sum)); +#endif + if (upper_layer_memlen < upper_layer_len) { + sum = network.chksum + ( + sum, UIPEthernet::uip_packet, UIP_IPH_LEN + + UIP_LLH_LEN + + upper_layer_memlen, upper_layer_len - + upper_layer_memlen + ); +#ifdef UIPETHERNET_DEBUG_CHKSUM + printf("chksum uip_packet(%d)[%d-%d]: %d\r\n", uip_packet, UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len, htons(sum)); +#endif + } + return(sum == 0) ? 0xffff : htons(sum); +} + +/** * @brief * @note * @param * @retval */ - uint16_t uip_tcpchksum(void) { - uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); - return sum; - } +uint16_t uip_ipchksum(void) { + return uIPEthernet.ipchksum(); +} - /** +#if UIP_UDP + +/** * @brief * @note * @param * @retval */ - uint16_t uip_udpchksum(void) { - uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); - return sum; - } +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 +