arduino stuffs
Diffstat (limited to 'libraries/Ethernet/src/socket.cpp')
| -rw-r--r-- | libraries/Ethernet/src/socket.cpp | 539 |
1 files changed, 0 insertions, 539 deletions
diff --git a/libraries/Ethernet/src/socket.cpp b/libraries/Ethernet/src/socket.cpp deleted file mode 100644 index f059dc9..0000000 --- a/libraries/Ethernet/src/socket.cpp +++ /dev/null @@ -1,539 +0,0 @@ -/* Copyright 2018 Paul Stoffregen - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this - * software and associated documentation files (the "Software"), to deal in the Software - * without restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include <Arduino.h> -#include "Ethernet.h" -#include "utility/w5100.h" - -#if ARDUINO >= 156 && !defined(ARDUINO_ARCH_PIC32) -extern void yield(void); -#else -#define yield() -#endif - -// TODO: randomize this when not using DHCP, but how? -static uint16_t local_port = 49152; // 49152 to 65535 - -typedef struct { - uint16_t RX_RSR; // Number of bytes received - uint16_t RX_RD; // Address to read - uint16_t TX_FSR; // Free space ready for transmit - uint8_t RX_inc; // how much have we advanced RX_RD -} socketstate_t; - -static socketstate_t state[MAX_SOCK_NUM]; - - -static uint16_t getSnTX_FSR(uint8_t s); -static uint16_t getSnRX_RSR(uint8_t s); -static void write_data(uint8_t s, uint16_t offset, const uint8_t *data, uint16_t len); -static void read_data(uint8_t s, uint16_t src, uint8_t *dst, uint16_t len); - - - -/*****************************************/ -/* Socket management */ -/*****************************************/ - - -void EthernetClass::socketPortRand(uint16_t n) -{ - n &= 0x3FFF; - local_port ^= n; - //Serial.printf("socketPortRand %d, srcport=%d\n", n, local_port); -} - -uint8_t EthernetClass::socketBegin(uint8_t protocol, uint16_t port) -{ - uint8_t s, status[MAX_SOCK_NUM], chip, maxindex=MAX_SOCK_NUM; - - // first check hardware compatibility - chip = W5100.getChip(); - if (!chip) return MAX_SOCK_NUM; // immediate error if no hardware detected -#if MAX_SOCK_NUM > 4 - if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets -#endif - //Serial.printf("W5000socket begin, protocol=%d, port=%d\n", protocol, port); - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - // look at all the hardware sockets, use any that are closed (unused) - for (s=0; s < maxindex; s++) { - status[s] = W5100.readSnSR(s); - if (status[s] == SnSR::CLOSED) goto makesocket; - } - //Serial.printf("W5000socket step2\n"); - // as a last resort, forcibly close any already closing - for (s=0; s < maxindex; s++) { - uint8_t stat = status[s]; - if (stat == SnSR::LAST_ACK) goto closemakesocket; - if (stat == SnSR::TIME_WAIT) goto closemakesocket; - if (stat == SnSR::FIN_WAIT) goto closemakesocket; - if (stat == SnSR::CLOSING) goto closemakesocket; - } -#if 0 - Serial.printf("W5000socket step3\n"); - // next, use any that are effectively closed - for (s=0; s < MAX_SOCK_NUM; s++) { - uint8_t stat = status[s]; - // TODO: this also needs to check if no more data - if (stat == SnSR::CLOSE_WAIT) goto closemakesocket; - } -#endif - SPI.endTransaction(); - return MAX_SOCK_NUM; // all sockets are in use -closemakesocket: - //Serial.printf("W5000socket close\n"); - W5100.execCmdSn(s, Sock_CLOSE); -makesocket: - //Serial.printf("W5000socket %d\n", s); - EthernetServer::server_port[s] = 0; - delayMicroseconds(250); // TODO: is this needed?? - W5100.writeSnMR(s, protocol); - W5100.writeSnIR(s, 0xFF); - if (port > 0) { - W5100.writeSnPORT(s, port); - } else { - // if don't set the source port, set local_port number. - if (++local_port < 49152) local_port = 49152; - W5100.writeSnPORT(s, local_port); - } - W5100.execCmdSn(s, Sock_OPEN); - state[s].RX_RSR = 0; - state[s].RX_RD = W5100.readSnRX_RD(s); // always zero? - state[s].RX_inc = 0; - state[s].TX_FSR = 0; - //Serial.printf("W5000socket prot=%d, RX_RD=%d\n", W5100.readSnMR(s), state[s].RX_RD); - SPI.endTransaction(); - return s; -} - -// multicast version to set fields before open thd -uint8_t EthernetClass::socketBeginMulticast(uint8_t protocol, IPAddress ip, uint16_t port) -{ - uint8_t s, status[MAX_SOCK_NUM], chip, maxindex=MAX_SOCK_NUM; - - // first check hardware compatibility - chip = W5100.getChip(); - if (!chip) return MAX_SOCK_NUM; // immediate error if no hardware detected -#if MAX_SOCK_NUM > 4 - if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets -#endif - //Serial.printf("W5000socket begin, protocol=%d, port=%d\n", protocol, port); - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - // look at all the hardware sockets, use any that are closed (unused) - for (s=0; s < maxindex; s++) { - status[s] = W5100.readSnSR(s); - if (status[s] == SnSR::CLOSED) goto makesocket; - } - //Serial.printf("W5000socket step2\n"); - // as a last resort, forcibly close any already closing - for (s=0; s < maxindex; s++) { - uint8_t stat = status[s]; - if (stat == SnSR::LAST_ACK) goto closemakesocket; - if (stat == SnSR::TIME_WAIT) goto closemakesocket; - if (stat == SnSR::FIN_WAIT) goto closemakesocket; - if (stat == SnSR::CLOSING) goto closemakesocket; - } -#if 0 - Serial.printf("W5000socket step3\n"); - // next, use any that are effectively closed - for (s=0; s < MAX_SOCK_NUM; s++) { - uint8_t stat = status[s]; - // TODO: this also needs to check if no more data - if (stat == SnSR::CLOSE_WAIT) goto closemakesocket; - } -#endif - SPI.endTransaction(); - return MAX_SOCK_NUM; // all sockets are in use -closemakesocket: - //Serial.printf("W5000socket close\n"); - W5100.execCmdSn(s, Sock_CLOSE); -makesocket: - //Serial.printf("W5000socket %d\n", s); - EthernetServer::server_port[s] = 0; - delayMicroseconds(250); // TODO: is this needed?? - W5100.writeSnMR(s, protocol); - W5100.writeSnIR(s, 0xFF); - if (port > 0) { - W5100.writeSnPORT(s, port); - } else { - // if don't set the source port, set local_port number. - if (++local_port < 49152) local_port = 49152; - W5100.writeSnPORT(s, local_port); - } - // Calculate MAC address from Multicast IP Address - byte mac[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; - mac[3] = ip[1] & 0x7F; - mac[4] = ip[2]; - mac[5] = ip[3]; - W5100.writeSnDIPR(s, ip.raw_address()); //239.255.0.1 - W5100.writeSnDPORT(s, port); - W5100.writeSnDHAR(s, mac); - W5100.execCmdSn(s, Sock_OPEN); - state[s].RX_RSR = 0; - state[s].RX_RD = W5100.readSnRX_RD(s); // always zero? - state[s].RX_inc = 0; - state[s].TX_FSR = 0; - //Serial.printf("W5000socket prot=%d, RX_RD=%d\n", W5100.readSnMR(s), state[s].RX_RD); - SPI.endTransaction(); - return s; -} -// Return the socket's status -// -uint8_t EthernetClass::socketStatus(uint8_t s) -{ - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - uint8_t status = W5100.readSnSR(s); - SPI.endTransaction(); - return status; -} - -// Immediately close. If a TCP connection is established, the -// remote host is left unaware we closed. -// -void EthernetClass::socketClose(uint8_t s) -{ - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.execCmdSn(s, Sock_CLOSE); - SPI.endTransaction(); -} - - -// Place the socket in listening (server) mode -// -uint8_t EthernetClass::socketListen(uint8_t s) -{ - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - if (W5100.readSnSR(s) != SnSR::INIT) { - SPI.endTransaction(); - return 0; - } - W5100.execCmdSn(s, Sock_LISTEN); - SPI.endTransaction(); - return 1; -} - - -// establish a TCP connection in Active (client) mode. -// -void EthernetClass::socketConnect(uint8_t s, uint8_t * addr, uint16_t port) -{ - // set destination IP - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.writeSnDIPR(s, addr); - W5100.writeSnDPORT(s, port); - W5100.execCmdSn(s, Sock_CONNECT); - SPI.endTransaction(); -} - - - -// Gracefully disconnect a TCP connection. -// -void EthernetClass::socketDisconnect(uint8_t s) -{ - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.execCmdSn(s, Sock_DISCON); - SPI.endTransaction(); -} - - - -/*****************************************/ -/* Socket Data Receive Functions */ -/*****************************************/ - - -static uint16_t getSnRX_RSR(uint8_t s) -{ -#if 1 - uint16_t val, prev; - - prev = W5100.readSnRX_RSR(s); - while (1) { - val = W5100.readSnRX_RSR(s); - if (val == prev) { - return val; - } - prev = val; - } -#else - uint16_t val = W5100.readSnRX_RSR(s); - return val; -#endif -} - -static void read_data(uint8_t s, uint16_t src, uint8_t *dst, uint16_t len) -{ - uint16_t size; - uint16_t src_mask; - uint16_t src_ptr; - - //Serial.printf("read_data, len=%d, at:%d\n", len, src); - src_mask = (uint16_t)src & W5100.SMASK; - src_ptr = W5100.RBASE(s) + src_mask; - - if (W5100.hasOffsetAddressMapping() || src_mask + len <= W5100.SSIZE) { - W5100.read(src_ptr, dst, len); - } else { - size = W5100.SSIZE - src_mask; - W5100.read(src_ptr, dst, size); - dst += size; - W5100.read(W5100.RBASE(s), dst, len - size); - } -} - -// Receive data. Returns size, or -1 for no data, or 0 if connection closed -// -int EthernetClass::socketRecv(uint8_t s, uint8_t *buf, int16_t len) -{ - // Check how much data is available - int ret = state[s].RX_RSR; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - if (ret < len) { - uint16_t rsr = getSnRX_RSR(s); - ret = rsr - state[s].RX_inc; - state[s].RX_RSR = ret; - //Serial.printf("Sock_RECV, RX_RSR=%d, RX_inc=%d\n", ret, state[s].RX_inc); - } - if (ret == 0) { - // No data available. - uint8_t status = W5100.readSnSR(s); - if ( status == SnSR::LISTEN || status == SnSR::CLOSED || - status == SnSR::CLOSE_WAIT ) { - // The remote end has closed its side of the connection, - // so this is the eof state - ret = 0; - } else { - // The connection is still up, but there's no data waiting to be read - ret = -1; - } - } else { - if (ret > len) ret = len; // more data available than buffer length - uint16_t ptr = state[s].RX_RD; - if (buf) read_data(s, ptr, buf, ret); - ptr += ret; - state[s].RX_RD = ptr; - state[s].RX_RSR -= ret; - uint16_t inc = state[s].RX_inc + ret; - if (inc >= 250 || state[s].RX_RSR == 0) { - state[s].RX_inc = 0; - W5100.writeSnRX_RD(s, ptr); - W5100.execCmdSn(s, Sock_RECV); - //Serial.printf("Sock_RECV cmd, RX_RD=%d, RX_RSR=%d\n", - // state[s].RX_RD, state[s].RX_RSR); - } else { - state[s].RX_inc = inc; - } - } - SPI.endTransaction(); - //Serial.printf("socketRecv, ret=%d\n", ret); - return ret; -} - -uint16_t EthernetClass::socketRecvAvailable(uint8_t s) -{ - uint16_t ret = state[s].RX_RSR; - if (ret == 0) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - uint16_t rsr = getSnRX_RSR(s); - SPI.endTransaction(); - ret = rsr - state[s].RX_inc; - state[s].RX_RSR = ret; - //Serial.printf("sockRecvAvailable s=%d, RX_RSR=%d\n", s, ret); - } - return ret; -} - -// get the first byte in the receive queue (no checking) -// -uint8_t EthernetClass::socketPeek(uint8_t s) -{ - uint8_t b; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - uint16_t ptr = state[s].RX_RD; - W5100.read((ptr & W5100.SMASK) + W5100.RBASE(s), &b, 1); - SPI.endTransaction(); - return b; -} - - - -/*****************************************/ -/* Socket Data Transmit Functions */ -/*****************************************/ - -static uint16_t getSnTX_FSR(uint8_t s) -{ - uint16_t val, prev; - - prev = W5100.readSnTX_FSR(s); - while (1) { - val = W5100.readSnTX_FSR(s); - if (val == prev) { - state[s].TX_FSR = val; - return val; - } - prev = val; - } -} - - -static void write_data(uint8_t s, uint16_t data_offset, const uint8_t *data, uint16_t len) -{ - uint16_t ptr = W5100.readSnTX_WR(s); - ptr += data_offset; - uint16_t offset = ptr & W5100.SMASK; - uint16_t dstAddr = offset + W5100.SBASE(s); - - if (W5100.hasOffsetAddressMapping() || offset + len <= W5100.SSIZE) { - W5100.write(dstAddr, data, len); - } else { - // Wrap around circular buffer - uint16_t size = W5100.SSIZE - offset; - W5100.write(dstAddr, data, size); - W5100.write(W5100.SBASE(s), data + size, len - size); - } - ptr += len; - W5100.writeSnTX_WR(s, ptr); -} - - -/** - * @brief This function used to send the data in TCP mode - * @return 1 for success else 0. - */ -uint16_t EthernetClass::socketSend(uint8_t s, const uint8_t * buf, uint16_t len) -{ - uint8_t status=0; - uint16_t ret=0; - uint16_t freesize=0; - - if (len > W5100.SSIZE) { - ret = W5100.SSIZE; // check size not to exceed MAX size. - } else { - ret = len; - } - - // if freebuf is available, start. - do { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - freesize = getSnTX_FSR(s); - status = W5100.readSnSR(s); - SPI.endTransaction(); - if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT)) { - ret = 0; - break; - } - yield(); - } while (freesize < ret); - - // copy data - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - write_data(s, 0, (uint8_t *)buf, ret); - W5100.execCmdSn(s, Sock_SEND); - - /* +2008.01 bj */ - while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) { - /* m2008.01 [bj] : reduce code */ - if ( W5100.readSnSR(s) == SnSR::CLOSED ) { - SPI.endTransaction(); - return 0; - } - SPI.endTransaction(); - yield(); - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - } - /* +2008.01 bj */ - W5100.writeSnIR(s, SnIR::SEND_OK); - SPI.endTransaction(); - return ret; -} - -uint16_t EthernetClass::socketSendAvailable(uint8_t s) -{ - uint8_t status=0; - uint16_t freesize=0; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - freesize = getSnTX_FSR(s); - status = W5100.readSnSR(s); - SPI.endTransaction(); - if ((status == SnSR::ESTABLISHED) || (status == SnSR::CLOSE_WAIT)) { - return freesize; - } - return 0; -} - -uint16_t EthernetClass::socketBufferData(uint8_t s, uint16_t offset, const uint8_t* buf, uint16_t len) -{ - //Serial.printf(" bufferData, offset=%d, len=%d\n", offset, len); - uint16_t ret =0; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - uint16_t txfree = getSnTX_FSR(s); - if (len > txfree) { - ret = txfree; // check size not to exceed MAX size. - } else { - ret = len; - } - write_data(s, offset, buf, ret); - SPI.endTransaction(); - return ret; -} - -bool EthernetClass::socketStartUDP(uint8_t s, uint8_t* addr, uint16_t port) -{ - if ( ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || - ((port == 0x00)) ) { - return false; - } - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.writeSnDIPR(s, addr); - W5100.writeSnDPORT(s, port); - SPI.endTransaction(); - return true; -} - -bool EthernetClass::socketSendUDP(uint8_t s) -{ - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.execCmdSn(s, Sock_SEND); - - /* +2008.01 bj */ - while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) { - if (W5100.readSnIR(s) & SnIR::TIMEOUT) { - /* +2008.01 [bj]: clear interrupt */ - W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT)); - SPI.endTransaction(); - //Serial.printf("sendUDP timeout\n"); - return false; - } - SPI.endTransaction(); - yield(); - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - } - - /* +2008.01 bj */ - W5100.writeSnIR(s, SnIR::SEND_OK); - SPI.endTransaction(); - - //Serial.printf("sendUDP ok\n"); - /* Sent ok */ - return true; -} - |