diff --git a/src/WiFiSocket.cpp b/src/WiFiSocket.cpp index 87725bc..51a1f09 100644 --- a/src/WiFiSocket.cpp +++ b/src/WiFiSocket.cpp @@ -55,8 +55,8 @@ WiFiSocket WiFiSocket::accept(arduino::IPAddress & remoteIpAddress, uint16_t & r return WiFiSocket(res); } -bool WiFiSocket::connect(const arduino::IPAddress & remoteIpAddress, uint16_t remotePort) { - return SocketDrv::connect(m_handle, remoteIpAddress, remotePort); +bool WiFiSocket::connect(const arduino::IPAddress & ipAddress, uint16_t port) { + return SocketDrv::connect(m_handle, ipAddress, port); } int32_t WiFiSocket::send(const void * buf, uint16_t size) { @@ -73,6 +73,22 @@ int32_t WiFiSocket::recv(void * buf, uint16_t size) { return ret; } +int32_t WiFiSocket::sendTo(const void * buf, uint16_t size, + const arduino::IPAddress & ipAddress, uint16_t port) { + auto ret = SocketDrv::sendTo(m_handle, buf, size, ipAddress, port); + if (ret == 0 && lastError() != 0) + ret = -1; + return ret; +} + +int32_t WiFiSocket::recvFrom(void * buf, uint16_t size, + arduino::IPAddress & remoteIpAddress, uint16_t & remotePort) { + auto ret = SocketDrv::recvFrom(m_handle, buf, size, remoteIpAddress, remotePort); + if (ret == 0 && lastError() != 0) + ret = -1; + return ret; +} + bool WiFiSocket::setNonBlocking(bool val) { uint32_t value = val; auto size = SocketDrv::ioctl(m_handle, uint32_t(IOControl::NonBlockingIO), diff --git a/src/WiFiSocket.h b/src/WiFiSocket.h index f9feea3..144515f 100644 --- a/src/WiFiSocket.h +++ b/src/WiFiSocket.h @@ -199,10 +199,10 @@ class WiFiSocket { * Connects a socket to remote endpoint * * @returns success flag. Check lastError() for more information about failure - * @param remoteIpAddress host to connect to - * @param remotePort port to connect to + * @param ipAddress host to connect to + * @param port port to connect to */ - bool connect(const arduino::IPAddress & remoteIpAddress, uint16_t remotePort); + bool connect(const arduino::IPAddress & ipAddress, uint16_t port); /** @@ -222,6 +222,24 @@ class WiFiSocket { * to accommodate -1. When non-negative it will never be bigger than the size parameter. */ int32_t recv(void * buf, uint16_t size); + + /** + * Sends data to remote endpoint + * + * @return the amount of data actually sent or -1 on failure. Check lastError() + * for more information about failure. The type of the return value is int32_t + * to accommodate -1. When non-negative it will never be bigger than the size parameter. + */ + int32_t sendTo(const void * buf, uint16_t size, const arduino::IPAddress & ipAddress, uint16_t port); + + /** + * Receives data from remote endpoint + * + * @return the amount of data actually read or -1 on failure. Check lastError() + * for more information about failure. The type of the return value is int32_t + * to accommodate -1. When non-negative it will never be bigger than the size parameter. + */ + int32_t recvFrom(void * buf, uint16_t size, arduino::IPAddress & remoteIpAddress, uint16_t & remotePort); /** * Sets the socket into non-blocking or blocking mode diff --git a/src/utility/socket_drv.cpp b/src/utility/socket_drv.cpp index 15ede07..47c384a 100644 --- a/src/utility/socket_drv.cpp +++ b/src/utility/socket_drv.cpp @@ -306,11 +306,11 @@ uint8_t SocketDrv::accept(uint8_t s, arduino::IPAddress & remoteIpAddress, uint1 // Wait for reply uint8_t resultSocket; uint8_t remoteIpBuf[4]; - uint8_t remotePortBuf[2]; + uint16_t remotePortTmp; tParam params[PARAM_NUMS_3] = { {0, (char*)&resultSocket}, {0, (char*)&remoteIpBuf}, - {0, (char*)&remotePortBuf} + {0, (char*)&remotePortTmp} }; if (!SpiDrv::waitResponseParams(cmd, PARAM_NUMS_3, params)) { WARN("error waitResponse"); @@ -321,7 +321,7 @@ uint8_t SocketDrv::accept(uint8_t s, arduino::IPAddress & remoteIpAddress, uint1 if (resultSocket != 255) { g_lastError = 0; remoteIpAddress = IPAddress(arduino::IPv4, remoteIpBuf); //buf is in network order - remotePort = (uint16_t(remotePortBuf[0]) << 8) | uint16_t(remotePortBuf[1]); + remotePort = remotePortTmp; //port is host order } return resultSocket; } @@ -471,6 +471,125 @@ int32_t SocketDrv::recv(uint8_t s, void * buf, uint16_t size) { } } +int32_t SocketDrv::sendTo(uint8_t s, const void * buf, uint16_t size, + const arduino::IPAddress & ipAddress, uint16_t port) { + + if (ipAddress.type() != arduino::IPv4) { + g_lastError = EINVAL; + return false; + } + auto ipv4Address = uint32_t(ipAddress); + uint8_t portNetOrder[2] = {uint8_t(port >> 8), uint8_t(port)}; + + g_lastError.reset(); + if (!SpiDrv::initialized) + SpiDrv::begin(); + + //keep the size well below 4096 which seems to be SPI_MAX_DMA_LEN + if (size > 4000) + size = 4000; + + uint8_t cmd = SOCKET_SENDTO_CMD; + + { + SelectSlave sel; + + // Send Command + int commandSize = 4; + SpiDrv::sendCmd(cmd, PARAM_NUMS_4); + SpiDrv::sendBuffer(&s, sizeof(s), NO_LAST_PARAM); + commandSize += (2 + sizeof(s)); + SpiDrv::sendBuffer((uint8_t *)&ipv4Address, sizeof(ipv4Address), NO_LAST_PARAM); + commandSize += (2 + sizeof(ipv4Address)); + SpiDrv::sendBuffer(portNetOrder, sizeof(portNetOrder), NO_LAST_PARAM); + commandSize += (2 + sizeof(portNetOrder)); + SpiDrv::sendBuffer((uint8_t *)buf, size, LAST_PARAM); + commandSize += (2 + size); + + // pad to multiple of 4 + while (commandSize % 4) { + SpiDrv::readChar(); + commandSize++; + } + } + { + //Wait the reply elaboration + SelectSlave sel; + + // Wait for reply + uint8_t data[2] = {}; + uint8_t dataLen = 0; + if (!SpiDrv::waitResponseCmd(cmd, PARAM_NUMS_1, data, &dataLen)) { + WARN("error waitResponse"); + g_lastError = SocketDrv::Failure; + return -1; + } + + uint16_t ret = (uint16_t(data[0]) << 8) | uint16_t(data[1]); + if (ret) + g_lastError = 0; + return ret; + } +} + +int32_t SocketDrv::recvFrom(uint8_t s, void * buf, uint16_t size, + arduino::IPAddress & remoteIpAddress, uint16_t & remotePort) { + g_lastError.reset(); + if (!SpiDrv::initialized) + SpiDrv::begin(); + + //keep the size well below 4096 which seems to be SPI_MAX_DMA_LEN + if (size > 4000) + size = 4000; + + uint8_t cmd = SOCKET_RECVFROM_CMD; + + { + SelectSlave sel; + + // Send Command + int commandSize = 4; + SpiDrv::sendCmd(cmd, PARAM_NUMS_2); + SpiDrv::sendParam(&s, sizeof(s), NO_LAST_PARAM); + commandSize += (1 + sizeof(s)); + SpiDrv::sendParam((uint8_t*)&size, sizeof(size), LAST_PARAM); + commandSize += (1 + sizeof(size)); + + // pad to multiple of 4 + while (commandSize % 4) { + SpiDrv::readChar(); + commandSize++; + } + } + { + //Wait the reply elaboration + SelectSlave sel; + + // Wait for reply + uint8_t remoteIpBuf[4]; + uint16_t remotePortTmp; + tDataParam params[PARAM_NUMS_3] = { + {0, (char*)&remoteIpBuf}, + {0, (char*)&remotePortTmp}, + {0, (char*)buf} + }; + if (!SpiDrv::waitResponseParams(cmd, PARAM_NUMS_3, params)) { + WARN("error waitResponse"); + g_lastError = SocketDrv::Failure; + return -1; + } + + if (params[2].dataLen) { + g_lastError = 0; + remoteIpAddress = IPAddress(arduino::IPv4, remoteIpBuf); //buf is in network order + remotePort = remotePortTmp; //port is in host order + } + + return params[2].dataLen; + } +} + + uint8_t SocketDrv::ioctl(uint8_t s, uint32_t code, void * buf, uint8_t bufSize) { g_lastError.reset(); diff --git a/src/utility/socket_drv.h b/src/utility/socket_drv.h index a95c72e..8b79383 100644 --- a/src/utility/socket_drv.h +++ b/src/utility/socket_drv.h @@ -53,6 +53,8 @@ namespace SocketDrv { bool connect(uint8_t s, const arduino::IPAddress & ipAddress, uint16_t port); int32_t send(uint8_t s, const void * buf, uint16_t size); int32_t recv(uint8_t s, void * buf, uint16_t size); + int32_t sendTo(uint8_t s, const void * buf, uint16_t size, const arduino::IPAddress & ipAddress, uint16_t port); + int32_t recvFrom(uint8_t s, void * buf, uint16_t size, arduino::IPAddress & remoteIpAddress, uint16_t & remotePort); uint8_t ioctl(uint8_t s, uint32_t code, void * buf, uint8_t bufSize); SocketState poll(uint8_t s); diff --git a/src/utility/spi_drv.cpp b/src/utility/spi_drv.cpp index 2673112..0dec112 100644 --- a/src/utility/spi_drv.cpp +++ b/src/utility/spi_drv.cpp @@ -378,6 +378,45 @@ int SpiDrv::waitResponseParams(uint8_t cmd, uint8_t numParam, tParam* params) return 1; } +int SpiDrv::waitResponseParams(uint8_t cmd, uint8_t numParam, tDataParam* params) +{ + char _data = 0; + int i =0, ii = 0; + + + IF_CHECK_START_CMD(_data) + { + CHECK_DATA(cmd | REPLY_FLAG, _data){}; + + uint8_t _numParam = readChar(); + if (_numParam != 0) + { + for (i=0; i<_numParam; ++i) + { + params[i].dataLen = readParamLen16(); + for (ii=0; ii