Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of UIPEthernet by
UIPEthernet.cpp@8:4acb22344932, 2017-06-30 (annotated)
- Committer:
- hudakz
- Date:
- Fri Jun 30 19:51:28 2017 +0000
- Revision:
- 8:4acb22344932
- Parent:
- 4:d774541a34da
'UIPEthernet' renamed to 'uIPEthernet'; 'UIPEthernetClass' renamed to 'UIPEthernet'; added IPAddress::toString() to support printing; added print support for debugging; bugs preventing offline build with GCC ARM toolchain fixed.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| hudakz | 4:d774541a34da | 1 | /* |
| hudakz | 8:4acb22344932 | 2 | UIPEthernet.cpp - Arduino implementation of a UIP wrapper class. |
| hudakz | 4:d774541a34da | 3 | Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> |
| hudakz | 4:d774541a34da | 4 | All rights reserved. |
| hudakz | 4:d774541a34da | 5 | |
| hudakz | 4:d774541a34da | 6 | Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com> |
| hudakz | 4:d774541a34da | 7 | |
| hudakz | 4:d774541a34da | 8 | This program is free software: you can redistribute it and/or modify |
| hudakz | 4:d774541a34da | 9 | it under the terms of the GNU General Public License as published by |
| hudakz | 4:d774541a34da | 10 | the Free Software Foundation, either version 3 of the License, or |
| hudakz | 4:d774541a34da | 11 | (at your option) any later version. |
| hudakz | 4:d774541a34da | 12 | |
| hudakz | 4:d774541a34da | 13 | This program is distributed in the hope that it will be useful, |
| hudakz | 4:d774541a34da | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| hudakz | 4:d774541a34da | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| hudakz | 4:d774541a34da | 16 | GNU General Public License for more details. |
| hudakz | 4:d774541a34da | 17 | |
| hudakz | 4:d774541a34da | 18 | You should have received a copy of the GNU General Public License |
| hudakz | 4:d774541a34da | 19 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| hudakz | 4:d774541a34da | 20 | */ |
| hudakz | 8:4acb22344932 | 21 | #include "mbed.h" |
| hudakz | 4:d774541a34da | 22 | #include "UIPEthernet.h" |
| hudakz | 4:d774541a34da | 23 | #include "utility/Enc28J60Network.h" |
| hudakz | 4:d774541a34da | 24 | #include "UIPUdp.h" |
| hudakz | 4:d774541a34da | 25 | |
| hudakz | 4:d774541a34da | 26 | extern "C" |
| hudakz | 4:d774541a34da | 27 | { |
| hudakz | 4:d774541a34da | 28 | #include "utility/uip-conf.h" |
| hudakz | 4:d774541a34da | 29 | #include "utility/uip.h" |
| hudakz | 4:d774541a34da | 30 | #include "utility/uip_arp.h" |
| hudakz | 4:d774541a34da | 31 | #include "utility/uip_timer.h" |
| hudakz | 4:d774541a34da | 32 | #include "utility/millis.h" |
| hudakz | 4:d774541a34da | 33 | } |
| hudakz | 4:d774541a34da | 34 | #define ETH_HDR ((struct uip_eth_hdr*) &uip_buf[0]) |
| hudakz | 4:d774541a34da | 35 | |
| hudakz | 8:4acb22344932 | 36 | memhandle UIPEthernet::in_packet(NOBLOCK); |
| hudakz | 8:4acb22344932 | 37 | memhandle UIPEthernet::uip_packet(NOBLOCK); |
| hudakz | 8:4acb22344932 | 38 | uint8_t UIPEthernet::uip_hdrlen(0); |
| hudakz | 8:4acb22344932 | 39 | uint8_t UIPEthernet::packetstate(0); |
| hudakz | 4:d774541a34da | 40 | |
| hudakz | 8:4acb22344932 | 41 | IPAddress UIPEthernet::_dnsServerAddress; |
| hudakz | 8:4acb22344932 | 42 | DhcpClass* UIPEthernet::_dhcp(NULL); |
| hudakz | 4:d774541a34da | 43 | |
| hudakz | 8:4acb22344932 | 44 | unsigned long UIPEthernet::periodic_timer; |
| hudakz | 4:d774541a34da | 45 | |
| hudakz | 4:d774541a34da | 46 | /** |
| hudakz | 4:d774541a34da | 47 | * @brief |
| hudakz | 4:d774541a34da | 48 | * @note |
| hudakz | 4:d774541a34da | 49 | * @param |
| hudakz | 4:d774541a34da | 50 | * @retval |
| hudakz | 4:d774541a34da | 51 | */ |
| hudakz | 4:d774541a34da | 52 | void enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) { |
| hudakz | 4:d774541a34da | 53 | |
| hudakz | 8:4acb22344932 | 54 | //as ENC28J60 DMA is unable to copy single bytes: |
| hudakz | 4:d774541a34da | 55 | |
| hudakz | 8:4acb22344932 | 56 | if (len == 1) { |
| hudakz | 8:4acb22344932 | 57 | uIPEthernet.network.writeByte(dest, uIPEthernet.network.readByte(src)); |
| hudakz | 4:d774541a34da | 58 | } |
| hudakz | 4:d774541a34da | 59 | else { |
| hudakz | 4:d774541a34da | 60 | |
| hudakz | 4:d774541a34da | 61 | // calculate address of last byte |
| hudakz | 4:d774541a34da | 62 | len += src - 1; |
| hudakz | 4:d774541a34da | 63 | |
| hudakz | 8:4acb22344932 | 64 | /* 1. Appropriately program the EDMAST, EDMAND |
| hudakz | 8:4acb22344932 | 65 | and EDMADST register pairs. The EDMAST |
| hudakz | 8:4acb22344932 | 66 | registers should point to the first byte to copy |
| hudakz | 8:4acb22344932 | 67 | from, the EDMAND registers should point to the |
| hudakz | 8:4acb22344932 | 68 | last byte to copy and the EDMADST registers |
| hudakz | 8:4acb22344932 | 69 | should point to the first byte in the destination |
| hudakz | 8:4acb22344932 | 70 | range. The destination range will always be |
| hudakz | 8:4acb22344932 | 71 | linear, never wrapping at any values except from |
| hudakz | 8:4acb22344932 | 72 | 8191 to 0 (the 8-Kbyte memory boundary). |
| hudakz | 8:4acb22344932 | 73 | Extreme care should be taken when |
| hudakz | 8:4acb22344932 | 74 | programming the start and end pointers to |
| hudakz | 8:4acb22344932 | 75 | prevent a never ending DMA operation which |
| hudakz | 8:4acb22344932 | 76 | would overwrite the entire 8-Kbyte buffer. |
| hudakz | 4:d774541a34da | 77 | */ |
| hudakz | 8:4acb22344932 | 78 | uIPEthernet.network.writeRegPair(EDMASTL, src); |
| hudakz | 8:4acb22344932 | 79 | uIPEthernet.network.writeRegPair(EDMADSTL, dest); |
| hudakz | 4:d774541a34da | 80 | |
| hudakz | 8:4acb22344932 | 81 | if ((src <= RXSTOP_INIT) && (len > RXSTOP_INIT)) |
| hudakz | 4:d774541a34da | 82 | len -= (RXSTOP_INIT - RXSTART_INIT); |
| hudakz | 8:4acb22344932 | 83 | uIPEthernet.network.writeRegPair(EDMANDL, len); |
| hudakz | 4:d774541a34da | 84 | |
| hudakz | 8:4acb22344932 | 85 | /* 2. If an interrupt at the end of the copy process is |
| hudakz | 8:4acb22344932 | 86 | desired, set EIE.DMAIE and EIE.INTIE and |
| hudakz | 8:4acb22344932 | 87 | clear EIR.DMAIF. |
| hudakz | 4:d774541a34da | 88 | |
| hudakz | 8:4acb22344932 | 89 | 3. Verify that ECON1.CSUMEN is clear. */ |
| hudakz | 8:4acb22344932 | 90 | uIPEthernet.network.writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); |
| hudakz | 4:d774541a34da | 91 | |
| hudakz | 4:d774541a34da | 92 | /* 4. Start the DMA copy by setting ECON1.DMAST. */ |
| hudakz | 8:4acb22344932 | 93 | uIPEthernet.network.writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); |
| hudakz | 4:d774541a34da | 94 | |
| hudakz | 8:4acb22344932 | 95 | // wait until runnig DMA is completed |
| hudakz | 8:4acb22344932 | 96 | while (uIPEthernet.network.readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST); |
| hudakz | 4:d774541a34da | 97 | } |
| hudakz | 4:d774541a34da | 98 | } |
| hudakz | 4:d774541a34da | 99 | |
| hudakz | 8:4acb22344932 | 100 | /* |
| hudakz | 8:4acb22344932 | 101 | * Because UIP isn't encapsulated within a class we have to use global |
| hudakz | 8:4acb22344932 | 102 | * variables, so we can only have one TCP/IP stack per program. |
| hudakz | 8:4acb22344932 | 103 | */ |
| hudakz | 8:4acb22344932 | 104 | UIPEthernet::UIPEthernet(PinName mosi, PinName miso, PinName sck, PinName cs) : |
| hudakz | 4:d774541a34da | 105 | network(mosi, miso, sck, cs) { |
| hudakz | 4:d774541a34da | 106 | millis_start(); |
| hudakz | 4:d774541a34da | 107 | } |
| hudakz | 4:d774541a34da | 108 | |
| hudakz | 4:d774541a34da | 109 | #if UIP_UDP |
| hudakz | 4:d774541a34da | 110 | |
| hudakz | 4:d774541a34da | 111 | /** |
| hudakz | 4:d774541a34da | 112 | * @brief |
| hudakz | 4:d774541a34da | 113 | * @note |
| hudakz | 4:d774541a34da | 114 | * @param |
| hudakz | 4:d774541a34da | 115 | * @retval |
| hudakz | 4:d774541a34da | 116 | */ |
| hudakz | 8:4acb22344932 | 117 | int UIPEthernet::begin(const uint8_t* mac) { |
| hudakz | 4:d774541a34da | 118 | static DhcpClass s_dhcp; |
| hudakz | 8:4acb22344932 | 119 | |
| hudakz | 4:d774541a34da | 120 | _dhcp = &s_dhcp; |
| hudakz | 4:d774541a34da | 121 | |
| hudakz | 4:d774541a34da | 122 | // Initialise the basic info |
| hudakz | 4:d774541a34da | 123 | init(mac); |
| hudakz | 4:d774541a34da | 124 | |
| hudakz | 4:d774541a34da | 125 | // Now try to get our config info from a DHCP server |
| hudakz | 4:d774541a34da | 126 | int ret = _dhcp->beginWithDHCP((uint8_t*)mac); |
| hudakz | 8:4acb22344932 | 127 | |
| hudakz | 8:4acb22344932 | 128 | if (ret == 1) { |
| hudakz | 4:d774541a34da | 129 | |
| hudakz | 4:d774541a34da | 130 | // We've successfully found a DHCP server and got our configuration info, so set things |
| hudakz | 4:d774541a34da | 131 | // accordingly |
| hudakz | 4:d774541a34da | 132 | configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); |
| hudakz | 4:d774541a34da | 133 | } |
| hudakz | 4:d774541a34da | 134 | |
| hudakz | 4:d774541a34da | 135 | return ret; |
| hudakz | 4:d774541a34da | 136 | } |
| hudakz | 4:d774541a34da | 137 | #endif |
| hudakz | 4:d774541a34da | 138 | |
| hudakz | 4:d774541a34da | 139 | /** |
| hudakz | 4:d774541a34da | 140 | * @brief |
| hudakz | 4:d774541a34da | 141 | * @note |
| hudakz | 4:d774541a34da | 142 | * @param |
| hudakz | 4:d774541a34da | 143 | * @retval |
| hudakz | 4:d774541a34da | 144 | */ |
| hudakz | 8:4acb22344932 | 145 | void UIPEthernet::begin(const uint8_t* mac, IPAddress ip) { |
| hudakz | 4:d774541a34da | 146 | IPAddress dns = ip; |
| hudakz | 8:4acb22344932 | 147 | |
| hudakz | 4:d774541a34da | 148 | dns[3] = 1; |
| hudakz | 4:d774541a34da | 149 | begin(mac, ip, dns); |
| hudakz | 4:d774541a34da | 150 | } |
| hudakz | 4:d774541a34da | 151 | |
| hudakz | 4:d774541a34da | 152 | /** |
| hudakz | 4:d774541a34da | 153 | * @brief |
| hudakz | 4:d774541a34da | 154 | * @note |
| hudakz | 4:d774541a34da | 155 | * @param |
| hudakz | 4:d774541a34da | 156 | * @retval |
| hudakz | 4:d774541a34da | 157 | */ |
| hudakz | 8:4acb22344932 | 158 | void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) { |
| hudakz | 4:d774541a34da | 159 | IPAddress gateway = ip; |
| hudakz | 8:4acb22344932 | 160 | |
| hudakz | 4:d774541a34da | 161 | gateway[3] = 1; |
| hudakz | 4:d774541a34da | 162 | begin(mac, ip, dns, gateway); |
| hudakz | 4:d774541a34da | 163 | } |
| hudakz | 4:d774541a34da | 164 | |
| hudakz | 4:d774541a34da | 165 | /** |
| hudakz | 4:d774541a34da | 166 | * @brief |
| hudakz | 4:d774541a34da | 167 | * @note |
| hudakz | 4:d774541a34da | 168 | * @param |
| hudakz | 4:d774541a34da | 169 | * @retval |
| hudakz | 4:d774541a34da | 170 | */ |
| hudakz | 8:4acb22344932 | 171 | void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) { |
| hudakz | 4:d774541a34da | 172 | IPAddress subnet(255, 255, 255, 0); |
| hudakz | 8:4acb22344932 | 173 | |
| hudakz | 4:d774541a34da | 174 | begin(mac, ip, dns, gateway, subnet); |
| hudakz | 4:d774541a34da | 175 | } |
| hudakz | 4:d774541a34da | 176 | |
| hudakz | 4:d774541a34da | 177 | /** |
| hudakz | 4:d774541a34da | 178 | * @brief |
| hudakz | 4:d774541a34da | 179 | * @note |
| hudakz | 4:d774541a34da | 180 | * @param |
| hudakz | 4:d774541a34da | 181 | * @retval |
| hudakz | 4:d774541a34da | 182 | */ |
| hudakz | 8:4acb22344932 | 183 | void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { |
| hudakz | 4:d774541a34da | 184 | init(mac); |
| hudakz | 4:d774541a34da | 185 | configure(ip, dns, gateway, subnet); |
| hudakz | 4:d774541a34da | 186 | } |
| hudakz | 4:d774541a34da | 187 | |
| hudakz | 4:d774541a34da | 188 | /** |
| hudakz | 4:d774541a34da | 189 | * @brief |
| hudakz | 4:d774541a34da | 190 | * @note |
| hudakz | 4:d774541a34da | 191 | * @param |
| hudakz | 4:d774541a34da | 192 | * @retval |
| hudakz | 4:d774541a34da | 193 | */ |
| hudakz | 8:4acb22344932 | 194 | int UIPEthernet::maintain(void) { |
| hudakz | 4:d774541a34da | 195 | tick(); |
| hudakz | 4:d774541a34da | 196 | |
| hudakz | 4:d774541a34da | 197 | int rc = DHCP_CHECK_NONE; |
| hudakz | 8:4acb22344932 | 198 | |
| hudakz | 4:d774541a34da | 199 | #if UIP_UDP |
| hudakz | 8:4acb22344932 | 200 | if (_dhcp != NULL) { |
| hudakz | 4:d774541a34da | 201 | |
| hudakz | 4:d774541a34da | 202 | //we have a pointer to dhcp, use it |
| hudakz | 4:d774541a34da | 203 | rc = _dhcp->checkLease(); |
| hudakz | 8:4acb22344932 | 204 | switch (rc) { |
| hudakz | 8:4acb22344932 | 205 | case DHCP_CHECK_NONE: |
| hudakz | 8:4acb22344932 | 206 | //nothing done |
| hudakz | 8:4acb22344932 | 207 | break; |
| hudakz | 4:d774541a34da | 208 | |
| hudakz | 8:4acb22344932 | 209 | case DHCP_CHECK_RENEW_OK: |
| hudakz | 8:4acb22344932 | 210 | case DHCP_CHECK_REBIND_OK: |
| hudakz | 8:4acb22344932 | 211 | //we might have got a new IP. |
| hudakz | 8:4acb22344932 | 212 | configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); |
| hudakz | 8:4acb22344932 | 213 | break; |
| hudakz | 4:d774541a34da | 214 | |
| hudakz | 8:4acb22344932 | 215 | default: |
| hudakz | 8:4acb22344932 | 216 | //this is actually an error, it will retry though |
| hudakz | 8:4acb22344932 | 217 | break; |
| hudakz | 4:d774541a34da | 218 | } |
| hudakz | 4:d774541a34da | 219 | } |
| hudakz | 4:d774541a34da | 220 | |
| hudakz | 4:d774541a34da | 221 | return rc; |
| hudakz | 4:d774541a34da | 222 | #endif |
| hudakz | 4:d774541a34da | 223 | } |
| hudakz | 4:d774541a34da | 224 | |
| hudakz | 4:d774541a34da | 225 | /** |
| hudakz | 4:d774541a34da | 226 | * @brief |
| hudakz | 4:d774541a34da | 227 | * @note |
| hudakz | 4:d774541a34da | 228 | * @param |
| hudakz | 4:d774541a34da | 229 | * @retval |
| hudakz | 4:d774541a34da | 230 | */ |
| hudakz | 8:4acb22344932 | 231 | IPAddress UIPEthernet::localIP(void) { |
| hudakz | 4:d774541a34da | 232 | uip_ipaddr_t a; |
| hudakz | 8:4acb22344932 | 233 | |
| hudakz | 4:d774541a34da | 234 | uip_gethostaddr(a); |
| hudakz | 4:d774541a34da | 235 | return ip_addr_uip(a); |
| hudakz | 4:d774541a34da | 236 | } |
| hudakz | 4:d774541a34da | 237 | |
| hudakz | 4:d774541a34da | 238 | /** |
| hudakz | 4:d774541a34da | 239 | * @brief |
| hudakz | 4:d774541a34da | 240 | * @note |
| hudakz | 4:d774541a34da | 241 | * @param |
| hudakz | 4:d774541a34da | 242 | * @retval |
| hudakz | 4:d774541a34da | 243 | */ |
| hudakz | 8:4acb22344932 | 244 | IPAddress UIPEthernet::subnetMask(void) { |
| hudakz | 4:d774541a34da | 245 | uip_ipaddr_t a; |
| hudakz | 8:4acb22344932 | 246 | |
| hudakz | 4:d774541a34da | 247 | uip_getnetmask(a); |
| hudakz | 4:d774541a34da | 248 | return ip_addr_uip(a); |
| hudakz | 4:d774541a34da | 249 | } |
| hudakz | 4:d774541a34da | 250 | |
| hudakz | 4:d774541a34da | 251 | /** |
| hudakz | 4:d774541a34da | 252 | * @brief |
| hudakz | 4:d774541a34da | 253 | * @note |
| hudakz | 4:d774541a34da | 254 | * @param |
| hudakz | 4:d774541a34da | 255 | * @retval |
| hudakz | 4:d774541a34da | 256 | */ |
| hudakz | 8:4acb22344932 | 257 | IPAddress UIPEthernet::gatewayIP(void) { |
| hudakz | 4:d774541a34da | 258 | uip_ipaddr_t a; |
| hudakz | 8:4acb22344932 | 259 | |
| hudakz | 4:d774541a34da | 260 | uip_getdraddr(a); |
| hudakz | 4:d774541a34da | 261 | return ip_addr_uip(a); |
| hudakz | 4:d774541a34da | 262 | } |
| hudakz | 4:d774541a34da | 263 | |
| hudakz | 4:d774541a34da | 264 | /** |
| hudakz | 4:d774541a34da | 265 | * @brief |
| hudakz | 4:d774541a34da | 266 | * @note |
| hudakz | 4:d774541a34da | 267 | * @param |
| hudakz | 4:d774541a34da | 268 | * @retval |
| hudakz | 4:d774541a34da | 269 | */ |
| hudakz | 8:4acb22344932 | 270 | IPAddress UIPEthernet::dnsServerIP(void) { |
| hudakz | 4:d774541a34da | 271 | return _dnsServerAddress; |
| hudakz | 4:d774541a34da | 272 | } |
| hudakz | 4:d774541a34da | 273 | |
| hudakz | 4:d774541a34da | 274 | /** |
| hudakz | 4:d774541a34da | 275 | * @brief |
| hudakz | 4:d774541a34da | 276 | * @note |
| hudakz | 4:d774541a34da | 277 | * @param |
| hudakz | 4:d774541a34da | 278 | * @retval |
| hudakz | 4:d774541a34da | 279 | */ |
| hudakz | 8:4acb22344932 | 280 | void UIPEthernet::tick(void) { |
| hudakz | 8:4acb22344932 | 281 | if (in_packet == NOBLOCK) { |
| hudakz | 4:d774541a34da | 282 | in_packet = network.receivePacket(); |
| hudakz | 4:d774541a34da | 283 | #ifdef UIPETHERNET_DEBUG |
| hudakz | 8:4acb22344932 | 284 | if (in_packet != NOBLOCK) { |
| hudakz | 8:4acb22344932 | 285 | printf("--------------\r\nreceivePacket: %d\r\n", in_packet); |
| hudakz | 4:d774541a34da | 286 | } |
| hudakz | 4:d774541a34da | 287 | #endif |
| hudakz | 4:d774541a34da | 288 | } |
| hudakz | 8:4acb22344932 | 289 | |
| hudakz | 8:4acb22344932 | 290 | if (in_packet != NOBLOCK) { |
| hudakz | 4:d774541a34da | 291 | packetstate = UIPETHERNET_FREEPACKET; |
| hudakz | 4:d774541a34da | 292 | uip_len = network.blockSize(in_packet); |
| hudakz | 8:4acb22344932 | 293 | if (uip_len > 0) { |
| hudakz | 4:d774541a34da | 294 | network.readPacket(in_packet, 0, (uint8_t*)uip_buf, UIP_BUFSIZE); |
| hudakz | 8:4acb22344932 | 295 | if (ETH_HDR->type == HTONS(UIP_ETHTYPE_IP)) { |
| hudakz | 4:d774541a34da | 296 | uip_packet = in_packet; //required for upper_layer_checksum of in_packet! |
| hudakz | 4:d774541a34da | 297 | #ifdef UIPETHERNET_DEBUG |
| hudakz | 8:4acb22344932 | 298 | printf("readPacket type IP, uip_len: %d\r\n", uip_len); |
| hudakz | 4:d774541a34da | 299 | #endif |
| hudakz | 4:d774541a34da | 300 | uip_arp_ipin(); |
| hudakz | 4:d774541a34da | 301 | uip_input(); |
| hudakz | 8:4acb22344932 | 302 | if (uip_len > 0) { |
| hudakz | 4:d774541a34da | 303 | uip_arp_out(); |
| hudakz | 4:d774541a34da | 304 | network_send(); |
| hudakz | 4:d774541a34da | 305 | } |
| hudakz | 4:d774541a34da | 306 | } |
| hudakz | 4:d774541a34da | 307 | else |
| hudakz | 8:4acb22344932 | 308 | if (ETH_HDR->type == HTONS(UIP_ETHTYPE_ARP)) |
| hudakz | 4:d774541a34da | 309 | { |
| hudakz | 4:d774541a34da | 310 | #ifdef UIPETHERNET_DEBUG |
| hudakz | 8:4acb22344932 | 311 | printf("readPacket type ARP, uip_len: %d\r\n", uip_len); |
| hudakz | 4:d774541a34da | 312 | #endif |
| hudakz | 4:d774541a34da | 313 | uip_arp_arpin(); |
| hudakz | 8:4acb22344932 | 314 | if (uip_len > 0) { |
| hudakz | 4:d774541a34da | 315 | network_send(); |
| hudakz | 4:d774541a34da | 316 | } |
| hudakz | 4:d774541a34da | 317 | } |
| hudakz | 4:d774541a34da | 318 | } |
| hudakz | 8:4acb22344932 | 319 | |
| hudakz | 8:4acb22344932 | 320 | if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) |
| hudakz | 4:d774541a34da | 321 | { |
| hudakz | 4:d774541a34da | 322 | #ifdef UIPETHERNET_DEBUG |
| hudakz | 8:4acb22344932 | 323 | printf("freeing packet: %d\r\n", in_packet); |
| hudakz | 4:d774541a34da | 324 | #endif |
| hudakz | 4:d774541a34da | 325 | network.freePacket(); |
| hudakz | 4:d774541a34da | 326 | in_packet = NOBLOCK; |
| hudakz | 4:d774541a34da | 327 | } |
| hudakz | 4:d774541a34da | 328 | } |
| hudakz | 8:4acb22344932 | 329 | |
| hudakz | 4:d774541a34da | 330 | unsigned long now = millis(); |
| hudakz | 4:d774541a34da | 331 | bool periodic = (long)(now - periodic_timer) >= 0; |
| hudakz | 8:4acb22344932 | 332 | |
| hudakz | 8:4acb22344932 | 333 | for (int i = 0; i < UIP_CONNS; i++) { |
| hudakz | 8:4acb22344932 | 334 | uip_conn = &uip_conns[i]; |
| hudakz | 8:4acb22344932 | 335 | if (periodic) { |
| hudakz | 8:4acb22344932 | 336 | uip_process(UIP_TIMER); |
| hudakz | 8:4acb22344932 | 337 | } |
| hudakz | 8:4acb22344932 | 338 | else { |
| hudakz | 8:4acb22344932 | 339 | if ((long)(now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) |
| hudakz | 8:4acb22344932 | 340 | uip_process(UIP_POLL_REQUEST); |
| hudakz | 8:4acb22344932 | 341 | else |
| hudakz | 8:4acb22344932 | 342 | continue; |
| hudakz | 8:4acb22344932 | 343 | } |
| hudakz | 4:d774541a34da | 344 | |
| hudakz | 8:4acb22344932 | 345 | // If the above function invocation resulted in data that |
| hudakz | 8:4acb22344932 | 346 | // should be sent out on the Enc28J60Network, the global variable |
| hudakz | 8:4acb22344932 | 347 | // uip_len is set to a value > 0. |
| hudakz | 8:4acb22344932 | 348 | if (uip_len > 0) { |
| hudakz | 8:4acb22344932 | 349 | uip_arp_out(); |
| hudakz | 8:4acb22344932 | 350 | network_send(); |
| hudakz | 8:4acb22344932 | 351 | } |
| hudakz | 8:4acb22344932 | 352 | } |
| hudakz | 4:d774541a34da | 353 | |
| hudakz | 8:4acb22344932 | 354 | if (periodic) { |
| hudakz | 8:4acb22344932 | 355 | periodic_timer = now + UIP_PERIODIC_TIMER; |
| hudakz | 4:d774541a34da | 356 | #if UIP_UDP |
| hudakz | 8:4acb22344932 | 357 | for (int i = 0; i < UIP_UDP_CONNS; i++) { |
| hudakz | 8:4acb22344932 | 358 | uip_udp_periodic(i); |
| hudakz | 4:d774541a34da | 359 | |
| hudakz | 8:4acb22344932 | 360 | // If the above function invocation resulted in data that |
| hudakz | 8:4acb22344932 | 361 | // should be sent out on the Enc28J60Network, the global variable |
| hudakz | 8:4acb22344932 | 362 | // uip_len is set to a value > 0. |
| hudakz | 8:4acb22344932 | 363 | if (uip_len > 0) { |
| hudakz | 8:4acb22344932 | 364 | UIPUDP::_send((uip_udp_userdata_t *) (uip_udp_conns[i].appstate)); |
| hudakz | 4:d774541a34da | 365 | } |
| hudakz | 4:d774541a34da | 366 | } |
| hudakz | 8:4acb22344932 | 367 | #endif // UIP_UDP |
| hudakz | 8:4acb22344932 | 368 | } |
| hudakz | 8:4acb22344932 | 369 | } |
| hudakz | 4:d774541a34da | 370 | |
| hudakz | 8:4acb22344932 | 371 | /** |
| hudakz | 4:d774541a34da | 372 | * @brief |
| hudakz | 4:d774541a34da | 373 | * @note |
| hudakz | 4:d774541a34da | 374 | * @param |
| hudakz | 4:d774541a34da | 375 | * @retval |
| hudakz | 4:d774541a34da | 376 | */ |
| hudakz | 8:4acb22344932 | 377 | bool UIPEthernet::network_send(void) { |
| hudakz | 8:4acb22344932 | 378 | if (packetstate & UIPETHERNET_SENDPACKET) |
| hudakz | 8:4acb22344932 | 379 | { |
| hudakz | 4:d774541a34da | 380 | #ifdef UIPETHERNET_DEBUG |
| hudakz | 8:4acb22344932 | 381 | printf("Enc28J60Network_send uip_packet: %d, hdrlen: %d\r\n", uip_packet, uip_hdrlen); |
| hudakz | 4:d774541a34da | 382 | #endif |
| hudakz | 8:4acb22344932 | 383 | uIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_hdrlen); |
| hudakz | 8:4acb22344932 | 384 | packetstate &= ~UIPETHERNET_SENDPACKET; |
| hudakz | 8:4acb22344932 | 385 | goto sendandfree; |
| hudakz | 8:4acb22344932 | 386 | } |
| hudakz | 4:d774541a34da | 387 | |
| hudakz | 8:4acb22344932 | 388 | uip_packet = Enc28J60Network::allocBlock(uip_len); |
| hudakz | 8:4acb22344932 | 389 | if (uip_packet != NOBLOCK) |
| hudakz | 8:4acb22344932 | 390 | { |
| hudakz | 4:d774541a34da | 391 | #ifdef UIPETHERNET_DEBUG |
| hudakz | 8:4acb22344932 | 392 | printf("Enc28J60Network_send uip_buf (uip_len): %d, packet: %d\r\n", uip_len, uip_packet); |
| hudakz | 4:d774541a34da | 393 | #endif |
| hudakz | 8:4acb22344932 | 394 | uIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_len); |
| hudakz | 8:4acb22344932 | 395 | goto sendandfree; |
| hudakz | 8:4acb22344932 | 396 | } |
| hudakz | 4:d774541a34da | 397 | |
| hudakz | 8:4acb22344932 | 398 | return false; |
| hudakz | 4:d774541a34da | 399 | sendandfree: |
| hudakz | 8:4acb22344932 | 400 | network.sendPacket(uip_packet); |
| hudakz | 8:4acb22344932 | 401 | Enc28J60Network::freeBlock(uip_packet); |
| hudakz | 8:4acb22344932 | 402 | uip_packet = NOBLOCK; |
| hudakz | 8:4acb22344932 | 403 | return true; |
| hudakz | 8:4acb22344932 | 404 | } |
| hudakz | 4:d774541a34da | 405 | |
| hudakz | 8:4acb22344932 | 406 | /** |
| hudakz | 4:d774541a34da | 407 | * @brief |
| hudakz | 4:d774541a34da | 408 | * @note |
| hudakz | 4:d774541a34da | 409 | * @param |
| hudakz | 4:d774541a34da | 410 | * @retval |
| hudakz | 4:d774541a34da | 411 | */ |
| hudakz | 8:4acb22344932 | 412 | void UIPEthernet::init(const uint8_t* mac) { |
| hudakz | 8:4acb22344932 | 413 | periodic_timer = millis() + UIP_PERIODIC_TIMER; |
| hudakz | 4:d774541a34da | 414 | |
| hudakz | 8:4acb22344932 | 415 | network.init((uint8_t*)mac); |
| hudakz | 8:4acb22344932 | 416 | uip_seteth_addr(mac); |
| hudakz | 4:d774541a34da | 417 | |
| hudakz | 8:4acb22344932 | 418 | uip_init(); |
| hudakz | 8:4acb22344932 | 419 | uip_arp_init(); |
| hudakz | 8:4acb22344932 | 420 | } |
| hudakz | 4:d774541a34da | 421 | |
| hudakz | 8:4acb22344932 | 422 | /** |
| hudakz | 4:d774541a34da | 423 | * @brief |
| hudakz | 4:d774541a34da | 424 | * @note |
| hudakz | 4:d774541a34da | 425 | * @param |
| hudakz | 4:d774541a34da | 426 | * @retval |
| hudakz | 4:d774541a34da | 427 | */ |
| hudakz | 8:4acb22344932 | 428 | void UIPEthernet::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { |
| hudakz | 8:4acb22344932 | 429 | uip_ipaddr_t ipaddr; |
| hudakz | 4:d774541a34da | 430 | |
| hudakz | 8:4acb22344932 | 431 | uip_ip_addr(ipaddr, ip); |
| hudakz | 8:4acb22344932 | 432 | uip_sethostaddr(ipaddr); |
| hudakz | 4:d774541a34da | 433 | |
| hudakz | 8:4acb22344932 | 434 | uip_ip_addr(ipaddr, gateway); |
| hudakz | 8:4acb22344932 | 435 | uip_setdraddr(ipaddr); |
| hudakz | 4:d774541a34da | 436 | |
| hudakz | 8:4acb22344932 | 437 | uip_ip_addr(ipaddr, subnet); |
| hudakz | 8:4acb22344932 | 438 | uip_setnetmask(ipaddr); |
| hudakz | 4:d774541a34da | 439 | |
| hudakz | 8:4acb22344932 | 440 | _dnsServerAddress = dns; |
| hudakz | 8:4acb22344932 | 441 | } |
| hudakz | 4:d774541a34da | 442 | |
| hudakz | 8:4acb22344932 | 443 | /** |
| hudakz | 8:4acb22344932 | 444 | * @brief |
| hudakz | 8:4acb22344932 | 445 | * @note |
| hudakz | 8:4acb22344932 | 446 | * @param |
| hudakz | 8:4acb22344932 | 447 | * @retval |
| hudakz | 8:4acb22344932 | 448 | */ |
| hudakz | 8:4acb22344932 | 449 | uint16_t UIPEthernet::chksum(uint16_t sum, const uint8_t* data, uint16_t len) { |
| hudakz | 8:4acb22344932 | 450 | uint16_t t; |
| hudakz | 8:4acb22344932 | 451 | const uint8_t* dataptr; |
| hudakz | 8:4acb22344932 | 452 | const uint8_t* last_byte; |
| hudakz | 4:d774541a34da | 453 | |
| hudakz | 8:4acb22344932 | 454 | dataptr = data; |
| hudakz | 8:4acb22344932 | 455 | last_byte = data + len - 1; |
| hudakz | 8:4acb22344932 | 456 | |
| hudakz | 8:4acb22344932 | 457 | while (dataptr < last_byte) { |
| hudakz | 4:d774541a34da | 458 | |
| hudakz | 8:4acb22344932 | 459 | /* At least two more bytes */ |
| hudakz | 8:4acb22344932 | 460 | t = (dataptr[0] << 8) + dataptr[1]; |
| hudakz | 8:4acb22344932 | 461 | sum += t; |
| hudakz | 8:4acb22344932 | 462 | if (sum < t) { |
| hudakz | 8:4acb22344932 | 463 | sum++; /* carry */ |
| hudakz | 4:d774541a34da | 464 | } |
| hudakz | 4:d774541a34da | 465 | |
| hudakz | 8:4acb22344932 | 466 | dataptr += 2; |
| hudakz | 8:4acb22344932 | 467 | } |
| hudakz | 4:d774541a34da | 468 | |
| hudakz | 8:4acb22344932 | 469 | if (dataptr == last_byte) { |
| hudakz | 8:4acb22344932 | 470 | t = (dataptr[0] << 8) + 0; |
| hudakz | 8:4acb22344932 | 471 | sum += t; |
| hudakz | 8:4acb22344932 | 472 | if (sum < t) { |
| hudakz | 8:4acb22344932 | 473 | sum++; /* carry */ |
| hudakz | 4:d774541a34da | 474 | } |
| hudakz | 8:4acb22344932 | 475 | } |
| hudakz | 4:d774541a34da | 476 | |
| hudakz | 8:4acb22344932 | 477 | /* Return sum in host byte order. */ |
| hudakz | 8:4acb22344932 | 478 | return sum; |
| hudakz | 8:4acb22344932 | 479 | } |
| hudakz | 8:4acb22344932 | 480 | |
| hudakz | 8:4acb22344932 | 481 | /** |
| hudakz | 4:d774541a34da | 482 | * @brief |
| hudakz | 4:d774541a34da | 483 | * @note |
| hudakz | 4:d774541a34da | 484 | * @param |
| hudakz | 4:d774541a34da | 485 | * @retval |
| hudakz | 4:d774541a34da | 486 | */ |
| hudakz | 8:4acb22344932 | 487 | uint16_t UIPEthernet::ipchksum(void) { |
| hudakz | 8:4acb22344932 | 488 | uint16_t sum; |
| hudakz | 8:4acb22344932 | 489 | |
| hudakz | 8:4acb22344932 | 490 | sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); |
| hudakz | 8:4acb22344932 | 491 | return(sum == 0) ? 0xffff : htons(sum); |
| hudakz | 8:4acb22344932 | 492 | } |
| hudakz | 8:4acb22344932 | 493 | |
| hudakz | 8:4acb22344932 | 494 | uint16_t |
| hudakz | 8:4acb22344932 | 495 | #if UIP_UDP |
| hudakz | 8:4acb22344932 | 496 | UIPEthernet::upper_layer_chksum(uint8_t proto) |
| hudakz | 8:4acb22344932 | 497 | #else |
| hudakz | 8:4acb22344932 | 498 | uip_tcpchksum (void) |
| hudakz | 8:4acb22344932 | 499 | #endif |
| hudakz | 8:4acb22344932 | 500 | { |
| hudakz | 8:4acb22344932 | 501 | uint16_t upper_layer_len; |
| hudakz | 8:4acb22344932 | 502 | uint16_t sum; |
| hudakz | 8:4acb22344932 | 503 | |
| hudakz | 8:4acb22344932 | 504 | #if UIP_CONF_IPV6 |
| hudakz | 8:4acb22344932 | 505 | upper_layer_len = (((u16_t) (BUF->len[0]) << 8) + BUF->len[1]); |
| hudakz | 8:4acb22344932 | 506 | #else /* UIP_CONF_IPV6 */ |
| hudakz | 8:4acb22344932 | 507 | upper_layer_len = (((u16_t) (BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; |
| hudakz | 8:4acb22344932 | 508 | #endif /* UIP_CONF_IPV6 */ |
| hudakz | 8:4acb22344932 | 509 | |
| hudakz | 8:4acb22344932 | 510 | /* First sum pseudoheader. */ |
| hudakz | 8:4acb22344932 | 511 | |
| hudakz | 8:4acb22344932 | 512 | /* IP protocol and length fields. This addition cannot carry. */ |
| hudakz | 8:4acb22344932 | 513 | #if UIP_UDP |
| hudakz | 8:4acb22344932 | 514 | sum = upper_layer_len + proto; |
| hudakz | 8:4acb22344932 | 515 | #else |
| hudakz | 8:4acb22344932 | 516 | sum = upper_layer_len + UIP_PROTO_TCP; |
| hudakz | 8:4acb22344932 | 517 | #endif |
| hudakz | 8:4acb22344932 | 518 | /* Sum IP source and destination addresses. */ |
| hudakz | 8:4acb22344932 | 519 | |
| hudakz | 8:4acb22344932 | 520 | sum = UIPEthernet::chksum(sum, (u8_t*) &BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); |
| hudakz | 4:d774541a34da | 521 | |
| hudakz | 8:4acb22344932 | 522 | uint8_t upper_layer_memlen; |
| hudakz | 4:d774541a34da | 523 | #if UIP_UDP |
| hudakz | 8:4acb22344932 | 524 | switch (proto) { |
| hudakz | 8:4acb22344932 | 525 | // case UIP_PROTO_ICMP: |
| hudakz | 8:4acb22344932 | 526 | // case UIP_PROTO_ICMP6: |
| hudakz | 8:4acb22344932 | 527 | // upper_layer_memlen = upper_layer_len; |
| hudakz | 8:4acb22344932 | 528 | // break; |
| hudakz | 8:4acb22344932 | 529 | case UIP_PROTO_UDP: |
| hudakz | 8:4acb22344932 | 530 | upper_layer_memlen = UIP_UDPH_LEN; |
| hudakz | 8:4acb22344932 | 531 | break; |
| hudakz | 8:4acb22344932 | 532 | |
| hudakz | 8:4acb22344932 | 533 | default: |
| hudakz | 8:4acb22344932 | 534 | // case UIP_PROTO_TCP: |
| hudakz | 8:4acb22344932 | 535 | #endif |
| hudakz | 8:4acb22344932 | 536 | upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; |
| hudakz | 8:4acb22344932 | 537 | #if UIP_UDP |
| hudakz | 8:4acb22344932 | 538 | break; |
| hudakz | 8:4acb22344932 | 539 | } |
| hudakz | 8:4acb22344932 | 540 | #endif |
| hudakz | 8:4acb22344932 | 541 | sum = UIPEthernet::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); |
| hudakz | 8:4acb22344932 | 542 | #ifdef UIPETHERNET_DEBUG_CHKSUM |
| hudakz | 8:4acb22344932 | 543 | 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)); |
| hudakz | 8:4acb22344932 | 544 | #endif |
| hudakz | 8:4acb22344932 | 545 | if (upper_layer_memlen < upper_layer_len) { |
| hudakz | 8:4acb22344932 | 546 | sum = network.chksum |
| hudakz | 8:4acb22344932 | 547 | ( |
| hudakz | 8:4acb22344932 | 548 | sum, UIPEthernet::uip_packet, UIP_IPH_LEN + |
| hudakz | 8:4acb22344932 | 549 | UIP_LLH_LEN + |
| hudakz | 8:4acb22344932 | 550 | upper_layer_memlen, upper_layer_len - |
| hudakz | 8:4acb22344932 | 551 | upper_layer_memlen |
| hudakz | 8:4acb22344932 | 552 | ); |
| hudakz | 8:4acb22344932 | 553 | #ifdef UIPETHERNET_DEBUG_CHKSUM |
| hudakz | 8:4acb22344932 | 554 | 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)); |
| hudakz | 8:4acb22344932 | 555 | #endif |
| hudakz | 8:4acb22344932 | 556 | } |
| hudakz | 8:4acb22344932 | 557 | return(sum == 0) ? 0xffff : htons(sum); |
| hudakz | 8:4acb22344932 | 558 | } |
| hudakz | 8:4acb22344932 | 559 | |
| hudakz | 8:4acb22344932 | 560 | /** |
| hudakz | 4:d774541a34da | 561 | * @brief |
| hudakz | 4:d774541a34da | 562 | * @note |
| hudakz | 4:d774541a34da | 563 | * @param |
| hudakz | 4:d774541a34da | 564 | * @retval |
| hudakz | 4:d774541a34da | 565 | */ |
| hudakz | 8:4acb22344932 | 566 | uint16_t uip_ipchksum(void) { |
| hudakz | 8:4acb22344932 | 567 | return uIPEthernet.ipchksum(); |
| hudakz | 8:4acb22344932 | 568 | } |
| hudakz | 4:d774541a34da | 569 | |
| hudakz | 8:4acb22344932 | 570 | #if UIP_UDP |
| hudakz | 8:4acb22344932 | 571 | |
| hudakz | 8:4acb22344932 | 572 | /** |
| hudakz | 4:d774541a34da | 573 | * @brief |
| hudakz | 4:d774541a34da | 574 | * @note |
| hudakz | 4:d774541a34da | 575 | * @param |
| hudakz | 4:d774541a34da | 576 | * @retval |
| hudakz | 4:d774541a34da | 577 | */ |
| hudakz | 8:4acb22344932 | 578 | uint16_t uip_tcpchksum(void) { |
| hudakz | 8:4acb22344932 | 579 | uint16_t sum = uIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); |
| hudakz | 8:4acb22344932 | 580 | |
| hudakz | 8:4acb22344932 | 581 | return sum; |
| hudakz | 8:4acb22344932 | 582 | } |
| hudakz | 8:4acb22344932 | 583 | |
| hudakz | 8:4acb22344932 | 584 | /** |
| hudakz | 8:4acb22344932 | 585 | * @brief |
| hudakz | 8:4acb22344932 | 586 | * @note |
| hudakz | 8:4acb22344932 | 587 | * @param |
| hudakz | 8:4acb22344932 | 588 | * @retval |
| hudakz | 8:4acb22344932 | 589 | */ |
| hudakz | 8:4acb22344932 | 590 | uint16_t uip_udpchksum(void) { |
| hudakz | 8:4acb22344932 | 591 | uint16_t sum = uIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); |
| hudakz | 8:4acb22344932 | 592 | |
| hudakz | 8:4acb22344932 | 593 | return sum; |
| hudakz | 8:4acb22344932 | 594 | } |
| hudakz | 4:d774541a34da | 595 | #endif |
| hudakz | 8:4acb22344932 | 596 |
