diff --git a/examples/knx-linux/CMakeLists.txt b/examples/knx-linux/CMakeLists.txt
index 470dfaa..3389d64 100644
--- a/examples/knx-linux/CMakeLists.txt
+++ b/examples/knx-linux/CMakeLists.txt
@@ -51,6 +51,8 @@ add_executable(knx-linux
../../src/knx/ip_parameter_object.h
../../src/knx/knx_ip_frame.cpp
../../src/knx/knx_ip_routing_indication.cpp
+ ../../src/knx/knx_ip_search_request.cpp
+ ../../src/knx/ip_host_protocol_address_information.cpp
../../src/knx/knx_value.cpp
../../src/knx/knx_value.h
../../src/knx/memory.cpp
diff --git a/examples/knx-linux/knx-linux.vcxproj b/examples/knx-linux/knx-linux.vcxproj
index b74baa1..aeca3e7 100644
--- a/examples/knx-linux/knx-linux.vcxproj
+++ b/examples/knx-linux/knx-linux.vcxproj
@@ -97,9 +97,13 @@
+
+
+
+
@@ -151,9 +155,13 @@
+
+
+
+
diff --git a/examples/knx-linux/knx-linux.vcxproj.filters b/examples/knx-linux/knx-linux.vcxproj.filters
index fa8dd01..be2aad8 100644
--- a/examples/knx-linux/knx-linux.vcxproj.filters
+++ b/examples/knx-linux/knx-linux.vcxproj.filters
@@ -176,6 +176,18 @@
Header files\knx
+
+ Header files\knx
+
+
+ Header files\knx
+
+
+ Header files\knx
+
+
+ Header files\knx
+
@@ -310,5 +322,17 @@
Source files\knx
+
+ Source files\knx
+
+
+ Source files\knx
+
+
+ Source files\knx
+
+
+ Source files\knx
+
\ No newline at end of file
diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp
index 7cfc22e..e6e842d 100644
--- a/src/knx/bau_systemB.cpp
+++ b/src/knx/bau_systemB.cpp
@@ -232,6 +232,10 @@ void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hop
uint8_t data[size];
if(obj)
obj->readProperty((PropertyID)propertyId, startIndex, elementCount, data);
+
+ if (elementCount == 0)
+ size = 0;
+
_appLayer.propertyValueReadResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, elementCount,
startIndex, data, size);
}
diff --git a/src/knx/ip_data_link_layer.cpp b/src/knx/ip_data_link_layer.cpp
index 2cb2ad2..ccd3e33 100644
--- a/src/knx/ip_data_link_layer.cpp
+++ b/src/knx/ip_data_link_layer.cpp
@@ -7,6 +7,7 @@
#include "device_object.h"
#include "address_table_object.h"
#include "knx_ip_routing_indication.h"
+#include "knx_ip_search_request.h"
#include
#include
@@ -55,9 +56,19 @@ void IpDataLinkLayer::loop()
switch ((KnxIpServiceType)code)
{
case RoutingIndication:
+ {
KnxIpRoutingIndication routingIndication(buffer, len);
frameRecieved(routingIndication.frame());
break;
+ }
+ case SearchRequest:
+ {
+ KnxIpSearchRequest searchRequest(buffer, len);
+ break;
+ }
+ default:
+ print("Unhandled service identifier: ");
+ println(code, HEX);
}
}
diff --git a/src/knx/ip_host_protocol_address_information.cpp b/src/knx/ip_host_protocol_address_information.cpp
new file mode 100644
index 0000000..79a86cd
--- /dev/null
+++ b/src/knx/ip_host_protocol_address_information.cpp
@@ -0,0 +1,31 @@
+#include "ip_host_protocol_address_information.h"
+#include "bits.h"
+#ifdef USE_IP
+IpHostProtocolAddressInformation::IpHostProtocolAddressInformation(uint8_t* data)
+ : _data(data)
+{}
+
+
+uint8_t IpHostProtocolAddressInformation::length()
+{
+ return *_data;
+}
+
+
+HostProtocolCode IpHostProtocolAddressInformation::code()
+{
+ return (HostProtocolCode)_data[1];
+}
+
+
+uint32_t IpHostProtocolAddressInformation::ipAddress()
+{
+ return getInt(_data + 2);
+}
+
+
+uint16_t IpHostProtocolAddressInformation::ipPortNumber()
+{
+ return getWord(_data + 6);
+}
+#endif
\ No newline at end of file
diff --git a/src/knx/ip_host_protocol_address_information.h b/src/knx/ip_host_protocol_address_information.h
new file mode 100644
index 0000000..29df5b7
--- /dev/null
+++ b/src/knx/ip_host_protocol_address_information.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include
+#include "config.h"
+
+enum HostProtocolCode : uint8_t
+{
+ IPV4_UDP = 1,
+ IPV4_TCP = 2
+};
+
+#ifdef USE_IP
+class IpHostProtocolAddressInformation
+{
+ public:
+ IpHostProtocolAddressInformation(uint8_t* data);
+ uint8_t length();
+ HostProtocolCode code();
+ uint32_t ipAddress();
+ uint16_t ipPortNumber();
+ private:
+ uint8_t* _data;
+};
+#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_dib.cpp b/src/knx/knx_ip_dib.cpp
new file mode 100644
index 0000000..fadffeb
--- /dev/null
+++ b/src/knx/knx_ip_dib.cpp
@@ -0,0 +1,15 @@
+#include "knx_ip_dib.h"
+
+DIB::DIB(uint8_t* data) : _data(data)
+{}
+
+DescriptionTypeCode DIB::code()
+{
+ return (DescriptionTypeCode)_data[1];
+}
+
+
+uint8_t DIB::length()
+{
+ return *_data;
+}
diff --git a/src/knx/knx_ip_dib.h b/src/knx/knx_ip_dib.h
new file mode 100644
index 0000000..bafe7e6
--- /dev/null
+++ b/src/knx/knx_ip_dib.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include
+#include "config.h"
+
+#ifdef USE_IP
+
+enum DescriptionTypeCode : uint8_t
+{
+ DEVICE_INFO = 0x01,
+ SUPP_SVC_FAMILIES = 0x02,
+ IP_CONFIG = 0x03,
+ IP_CUR_CONFIG = 0x04,
+ KNX_ADDRESSES = 0x05,
+ MFR_DATA = 0xFE
+};
+
+class DIB
+{
+ public:
+ DIB(uint8_t* data);
+ DescriptionTypeCode code();
+ uint8_t length();
+ private:
+ uint8_t* _data = 0;
+};
+#endif
diff --git a/src/knx/knx_ip_frame.cpp b/src/knx/knx_ip_frame.cpp
index 038a817..df0aa29 100644
--- a/src/knx/knx_ip_frame.cpp
+++ b/src/knx/knx_ip_frame.cpp
@@ -10,6 +10,7 @@ KnxIpFrame::KnxIpFrame(uint8_t* data,
uint16_t length)
{
_data = data;
+ _dataLength = length;
}
uint8_t KnxIpFrame::headerLength() const
@@ -62,13 +63,14 @@ uint8_t* KnxIpFrame::data()
KnxIpFrame::~KnxIpFrame()
{
if (_freeData)
- delete _data;
+ delete[] _data;
}
KnxIpFrame::KnxIpFrame(uint16_t length)
{
_data = new uint8_t[length];
+ _dataLength = length;
_freeData = true;
headerLength(KNXIP_HEADER_LEN);
protocolVersion(KnxIp1_0);
diff --git a/src/knx/knx_ip_frame.h b/src/knx/knx_ip_frame.h
index b5ab6c8..688b2b2 100644
--- a/src/knx/knx_ip_frame.h
+++ b/src/knx/knx_ip_frame.h
@@ -53,5 +53,6 @@ class KnxIpFrame
protected:
bool _freeData = false;
uint8_t* _data = 0;
+ uint16_t _dataLength;
};
#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_search_request.cpp b/src/knx/knx_ip_search_request.cpp
new file mode 100644
index 0000000..ef9cca1
--- /dev/null
+++ b/src/knx/knx_ip_search_request.cpp
@@ -0,0 +1,13 @@
+#include "knx_ip_search_request.h"
+#ifdef USE_IP
+KnxIpSearchRequest::KnxIpSearchRequest(uint8_t* data, uint16_t length)
+ : KnxIpFrame(data, length), _hpai(data + KNXIP_HEADER_LEN)
+{
+}
+
+
+IpHostProtocolAddressInformation& KnxIpSearchRequest::hpai()
+{
+ return _hpai;
+}
+#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_search_request.h b/src/knx/knx_ip_search_request.h
new file mode 100644
index 0000000..e51ae46
--- /dev/null
+++ b/src/knx/knx_ip_search_request.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "knx_ip_frame.h"
+#include "ip_host_protocol_address_information.h"
+#ifdef USE_IP
+class KnxIpSearchRequest : public KnxIpFrame
+{
+ public:
+ KnxIpSearchRequest(uint8_t* data, uint16_t length);
+ IpHostProtocolAddressInformation& hpai();
+ private:
+ IpHostProtocolAddressInformation _hpai;
+};
+#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_search_response.cpp b/src/knx/knx_ip_search_response.cpp
new file mode 100644
index 0000000..54cc32e
--- /dev/null
+++ b/src/knx/knx_ip_search_response.cpp
@@ -0,0 +1,4 @@
+#include "knx_ip_search_response.h"
+#ifdef USE_IP
+
+#endif
\ No newline at end of file
diff --git a/src/knx/knx_ip_search_response.h b/src/knx/knx_ip_search_response.h
new file mode 100644
index 0000000..2bff759
--- /dev/null
+++ b/src/knx/knx_ip_search_response.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "knx_ip_frame.h"
+#include "ip_host_protocol_address_information.h"
+#ifdef USE_IP
+
+class KnxIpSearchResponse : public KnxIpFrame
+{
+ IpHostProtocolAddressInformation& controlEndpoint();
+
+};
+
+#endif
\ No newline at end of file
diff --git a/src/knx/platform.cpp b/src/knx/platform.cpp
index 14e6187..7ed8cfc 100644
--- a/src/knx/platform.cpp
+++ b/src/knx/platform.cpp
@@ -84,6 +84,24 @@ bool Platform::sendBytesMultiCast(uint8_t *buffer, uint16_t len)
}
int Platform::readBytesMultiCast(uint8_t *buffer, uint16_t maxLen)
+{
+ return 0;
+}
+
+void Platform::setupUniCast(uint32_t addr, uint16_t port, uint8_t type)
+{}
+
+
+void Platform::closeUniCast()
+{}
+
+
+bool Platform::sendBytesUniCast(uint8_t* buffer, uint16_t len)
+{
+ return false;
+}
+
+int Platform::readBytesUniCast(uint8_t *buffer, uint16_t maxLen)
{
return 0;
}
\ No newline at end of file
diff --git a/src/knx/platform.h b/src/knx/platform.h
index 62122dd..347e825 100644
--- a/src/knx/platform.h
+++ b/src/knx/platform.h
@@ -29,6 +29,12 @@ class Platform
virtual void closeMultiCast();
virtual bool sendBytesMultiCast(uint8_t* buffer, uint16_t len);
virtual int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen);
+
+ //unicast socket
+ virtual void setupUniCast(uint32_t addr, uint16_t port, uint8_t type);
+ virtual void closeUniCast();
+ virtual bool sendBytesUniCast(uint8_t* buffer, uint16_t len);
+ virtual int readBytesUniCast(uint8_t* buffer, uint16_t maxLen);
//UART
virtual void setupUart();
diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp
index e37d3f8..552cdd6 100644
--- a/src/linux_platform.cpp
+++ b/src/linux_platform.cpp
@@ -15,14 +15,17 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
#include
-#include // Needed for SPI port
-#include // Needed for SPI port
-#include // Needed for GPIO edge detection
-#include // Needed for delayMicroseconds()
+#include // Needed for SPI port
+#include // Needed for SPI port
+#include // Needed for GPIO edge detection
+#include // Needed for delayMicroseconds()
#include "knx/device_object.h"
#include "knx/address_table_object.h"
@@ -31,18 +34,97 @@
#include "knx/application_program_object.h"
#include "knx/ip_parameter_object.h"
#include "knx/bits.h"
+#include "knx/ip_host_protocol_address_information.h"
#define MAX_MEM 4096
LinuxPlatform::LinuxPlatform()
-{}
+{
+ int socketMac = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (socketMac < 0)
+ {
+ printf("Lookup socket creation failed");
+ return;
+ }
+
+ struct ifreq ifr;
+ struct ifconf ifc;
+ char buf[1024];
+
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(socketMac, SIOCGIFCONF, &ifc) < 0)
+ return;
+
+ struct ifreq* it = ifc.ifc_req;
+ const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
+
+ for (; it != end; ++it)
+ {
+ strcpy(ifr.ifr_name, it->ifr_name);
+ if (ioctl(socketMac, SIOCGIFFLAGS, &ifr))
+ continue;
+
+ if (ifr.ifr_flags & IFF_LOOPBACK) // don't count loopback
+ continue;
+
+ if (ioctl(socketMac, SIOCGIFHWADDR, &ifr))
+ continue;
+
+ if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
+ continue;
+
+ memcpy(_macAddress, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
+
+ ioctl(socketMac, SIOCGIFADDR, &ifr);
+
+ struct sockaddr_in* ipaddr = (struct sockaddr_in*)&ifr.ifr_addr;
+ _ipAddress = ntohl(ipaddr->sin_addr.s_addr);
+
+ //printf("IP address: %s\n", inet_ntoa(ipaddr->sin_addr));
+ ioctl(socketMac, SIOCGIFNETMASK, &ifr);
+ struct sockaddr_in* netmask = (struct sockaddr_in*)&ifr.ifr_netmask;
+ _netmask = ntohl(netmask->sin_addr.s_addr);
+ //printf("Netmask: %s\n", inet_ntoa(ipaddr->sin_addr));
+ break;
+ }
+ close(socketMac);
+
+ // default GW
+ FILE* f;
+ char line[100], *p, *c, *g, *saveptr;
+
+ f = fopen("/proc/net/route", "r");
+
+ while (fgets(line, 100, f))
+ {
+ p = strtok_r(line, " \t", &saveptr);
+ c = strtok_r(NULL, " \t", &saveptr);
+ g = strtok_r(NULL, " \t", &saveptr);
+
+ if (p != NULL && c != NULL)
+ {
+ if (strcmp(c, "00000000") == 0)
+ {
+ //printf("Default interface is : %s \n" , p);
+ if (g)
+ {
+ char* pEnd;
+ _defaultGateway = ntohl(strtol(g, &pEnd, 16));
+
+ }
+ break;
+ }
+ }
+ }
+ fclose(f);
+}
LinuxPlatform::~LinuxPlatform()
{
delete[] _args;
}
-
uint32_t millis()
{
struct timespec spec;
@@ -59,8 +141,6 @@ void delay(uint32_t millis)
nanosleep(&ts, NULL);
}
-
-
void LinuxPlatform::restart()
{
execv(_args[0], _args);
@@ -75,8 +155,11 @@ void LinuxPlatform::fatalError()
void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port)
{
+ if (_multicastSocketFd >= 0)
+ closeMultiCast();
+
_multicastAddr = addr;
- _port = port;
+ _multicastPort = port;
struct ip_mreq command;
uint32_t loop = 1;
@@ -87,21 +170,22 @@ void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port)
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
- _socketFd = socket(AF_INET, SOCK_DGRAM, 0);
- if (_socketFd == -1) {
+ _multicastSocketFd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (_multicastSocketFd == -1)
+ {
perror("socket()");
fatalError();
}
/* Mehr Prozessen erlauben, denselben Port zu nutzen */
loop = 1;
- if (setsockopt(_socketFd, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0)
+ if (setsockopt(_multicastSocketFd, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0)
{
perror("setsockopt:SO_REUSEADDR");
fatalError();
}
- if (bind(_socketFd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ if (bind(_multicastSocketFd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
perror("bind");
fatalError();
@@ -109,7 +193,7 @@ void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port)
/* loopback */
loop = 0;
- if (setsockopt(_socketFd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0)
+ if (setsockopt(_multicastSocketFd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0)
{
perror("setsockopt:IP_MULTICAST_LOOP");
fatalError();
@@ -119,15 +203,15 @@ void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port)
command.imr_multiaddr.s_addr = htonl(addr);
command.imr_interface.s_addr = htonl(INADDR_ANY);
- if (setsockopt(_socketFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &command, sizeof(command)) < 0)
+ if (setsockopt(_multicastSocketFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &command, sizeof(command)) < 0)
{
perror("setsockopt:IP_ADD_MEMBERSHIP");
fatalError();
}
- uint32_t flags = fcntl(_socketFd, F_GETFL);
+ uint32_t flags = fcntl(_multicastSocketFd, F_GETFL);
flags |= O_NONBLOCK;
- fcntl(_socketFd, F_SETFL, flags);
+ fcntl(_multicastSocketFd, F_SETFL, flags);
}
void LinuxPlatform::closeMultiCast()
@@ -136,54 +220,56 @@ void LinuxPlatform::closeMultiCast()
command.imr_multiaddr.s_addr = htonl(_multicastAddr);
command.imr_interface.s_addr = htonl(INADDR_ANY);
- if (setsockopt(_socketFd,
- IPPROTO_IP,
- IP_DROP_MEMBERSHIP,
- &command, sizeof(command)) < 0) {
+ if (setsockopt(_multicastSocketFd,
+ IPPROTO_IP,
+ IP_DROP_MEMBERSHIP,
+ &command, sizeof(command)) < 0)
+ {
perror("setsockopt:IP_DROP_MEMBERSHIP");
}
- close(_socketFd);
+ close(_multicastSocketFd);
+ _multicastSocketFd = -1;
}
bool LinuxPlatform::sendBytesMultiCast(uint8_t* buffer, uint16_t len)
{
- struct sockaddr_in address = { 0 };
+ struct sockaddr_in address = {0};
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(_multicastAddr);
- address.sin_port = htons(_port);
+ address.sin_port = htons(_multicastPort);
ssize_t retVal = 0;
do
{
- retVal = sendto(_socketFd, buffer, len, 0, (struct sockaddr *) &address, sizeof(address));
+ retVal = sendto(_multicastSocketFd, buffer, len, 0, (struct sockaddr*)&address, sizeof(address));
if (retVal == -1)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
return false;
}
} while (retVal == -1);
-// printHex("<-", buffer, len);
+ // printHex("<-", buffer, len);
return true;
}
-int LinuxPlatform::readBytesMultiCast(uint8_t * buffer, uint16_t maxLen)
+int LinuxPlatform::readBytesMultiCast(uint8_t* buffer, uint16_t maxLen)
{
uint32_t sin_len;
struct sockaddr_in sin;
sin_len = sizeof(sin);
- ssize_t len = recvfrom(_socketFd, buffer, maxLen, 0, (struct sockaddr *) &sin, &sin_len);
-// if (len > 0)
-// printHex("->", buffer, len);
-
+ ssize_t len = recvfrom(_multicastSocketFd, buffer, maxLen, 0, (struct sockaddr*)&sin, &sin_len);
+ // if (len > 0)
+ // printHex("->", buffer, len);
+
return len;
}
-uint8_t * LinuxPlatform::getEepromBuffer(uint16_t size)
+uint8_t* LinuxPlatform::getEepromBuffer(uint16_t size)
{
if (_fd < 0)
doMemoryMapping();
-
+
return _mappedFile + 2;
}
@@ -191,7 +277,7 @@ void LinuxPlatform::commitToEeprom()
{
if (_fd < 0)
doMemoryMapping();
-
+
fsync(_fd);
}
@@ -242,69 +328,67 @@ void LinuxPlatform::doMemoryMapping()
void LinuxPlatform::closeSpi()
{
close(_spiFd);
- printf ("SPI device closed.\r\n");
+ printf("SPI device closed.\r\n");
}
-int LinuxPlatform::readWriteSpi (uint8_t *data, size_t len)
+int LinuxPlatform::readWriteSpi(uint8_t* data, size_t len)
{
- uint16_t spiDelay = 0 ;
+ uint16_t spiDelay = 0;
uint32_t spiSpeed = 8000000; // 4 MHz SPI speed
- uint8_t spiBPW = 8; // Bits per word
+ uint8_t spiBPW = 8; // Bits per word
- struct spi_ioc_transfer spi ;
+ struct spi_ioc_transfer spi;
// Mentioned in spidev.h but not used in the original kernel documentation
// test program )-:
- memset (&spi, 0, sizeof (spi)) ;
+ memset(&spi, 0, sizeof(spi));
- spi.tx_buf = (uint64_t)data;
- spi.rx_buf = (uint64_t)data;
- spi.len = len;
- spi.delay_usecs = spiDelay;
- spi.speed_hz = spiSpeed;
+ spi.tx_buf = (uint64_t)data;
+ spi.rx_buf = (uint64_t)data;
+ spi.len = len;
+ spi.delay_usecs = spiDelay;
+ spi.speed_hz = spiSpeed;
spi.bits_per_word = spiBPW;
- return ioctl (_spiFd, SPI_IOC_MESSAGE(1), &spi) ;
+ return ioctl(_spiFd, SPI_IOC_MESSAGE(1), &spi);
}
void LinuxPlatform::setupSpi()
{
- if ((_spiFd = open ("/dev/spidev0.0", O_RDWR)) < 0)
+ if ((_spiFd = open("/dev/spidev0.0", O_RDWR)) < 0)
{
- printf ("ERROR: SPI setup failed! Could not open SPI device!\r\n");
+ printf("ERROR: SPI setup failed! Could not open SPI device!\r\n");
return;
}
// Set SPI parameters.
- int mode = 0; // Mode 0
- uint8_t spiBPW = 8; // Bits per word
+ int mode = 0; // Mode 0
+ uint8_t spiBPW = 8; // Bits per word
int speed = 8000000; // 4 MHz SPI speed
- if (ioctl (_spiFd, SPI_IOC_WR_MODE, &mode) < 0)
+ if (ioctl(_spiFd, SPI_IOC_WR_MODE, &mode) < 0)
{
- printf ("ERROR: SPI Mode Change failure: %s\n", strerror (errno)) ;
+ printf("ERROR: SPI Mode Change failure: %s\n", strerror(errno));
close(_spiFd);
return;
}
- if (ioctl (_spiFd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0)
+ if (ioctl(_spiFd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0)
{
- printf ("ERROR: SPI BPW Change failure: %s\n", strerror (errno)) ;
+ printf("ERROR: SPI BPW Change failure: %s\n", strerror(errno));
close(_spiFd);
return;
}
- if (ioctl (_spiFd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
+ if (ioctl(_spiFd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
{
- printf ("ERROR: SPI Speed Change failure: %s\n", strerror (errno)) ;
+ printf("ERROR: SPI Speed Change failure: %s\n", strerror(errno));
close(_spiFd);
return;
}
- printf ("SPI device setup ok.\r\n");
-
-
+ printf("SPI device setup ok.\r\n");
}
void LinuxPlatform::flashFilePath(const std::string path)
@@ -312,7 +396,6 @@ void LinuxPlatform::flashFilePath(const std::string path)
_flashFilePath = path;
}
-
std::string LinuxPlatform::flashFilePath()
{
return _flashFilePath;
@@ -521,13 +604,73 @@ void LinuxPlatform::cmdLineArgs(int argc, char** argv)
#define MAX_STRBUF_SIZE 100
#define MAX_NUM_GPIO 64
-static int gpioFds [MAX_NUM_GPIO] =
-{
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-} ;
+static int gpioFds[MAX_NUM_GPIO] =
+ {
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+};
/* Activate GPIO-Pin
* Write GPIO pin number to /sys/class/gpio/export
@@ -535,10 +678,10 @@ static int gpioFds [MAX_NUM_GPIO] =
*/
int gpio_export(int pin)
{
- char buffer[MAX_STRBUF_SIZE]; /* Output Buffer */
- ssize_t bytes; /* Used Buffer length */
- int fd; /* Filedescriptor */
- int res; /* Result from write() */
+ char buffer[MAX_STRBUF_SIZE]; /* Output Buffer */
+ ssize_t bytes; /* Used Buffer length */
+ int fd; /* Filedescriptor */
+ int res; /* Result from write() */
fprintf(stderr, "Export GPIO pin %d\n", pin);
@@ -546,7 +689,7 @@ int gpio_export(int pin)
if (fd < 0)
{
perror("Could not export GPIO pin(open)!\n");
- return(-1);
+ return (-1);
}
bytes = snprintf(buffer, MAX_STRBUF_SIZE, "%d", pin);
@@ -555,13 +698,13 @@ int gpio_export(int pin)
if (res < 0)
{
perror("Could not export GPIO pin(write)!\n");
- return(-1);
+ return (-1);
}
close(fd);
delay(100);
- return(0);
+ return (0);
}
/* Deactivate GPIO pin
@@ -570,10 +713,10 @@ int gpio_export(int pin)
*/
int gpio_unexport(int pin)
{
- char buffer[MAX_STRBUF_SIZE]; /* Output Buffer */
- ssize_t bytes; /* Used Buffer length */
- int fd; /* Filedescriptor */
- int res; /* Result from write() */
+ char buffer[MAX_STRBUF_SIZE]; /* Output Buffer */
+ ssize_t bytes; /* Used Buffer length */
+ int fd; /* Filedescriptor */
+ int res; /* Result from write() */
fprintf(stderr, "Unexport GPIO pin %d\n", pin);
@@ -583,7 +726,7 @@ int gpio_unexport(int pin)
if (fd < 0)
{
perror("Could not unexport GPIO pin(open)!\n");
- return(-1);
+ return (-1);
}
bytes = snprintf(buffer, MAX_STRBUF_SIZE, "%d", pin);
@@ -592,11 +735,11 @@ int gpio_unexport(int pin)
if (res < 0)
{
perror("Could not unexport GPIO pin(write)!\n");
- return(-1);
+ return (-1);
}
close(fd);
- return(0);
+ return (0);
}
/* Set GPIO pin mode (input/output)
@@ -606,35 +749,41 @@ int gpio_unexport(int pin)
*/
int gpio_direction(int pin, int dir)
{
- char path[MAX_STRBUF_SIZE]; /* Buffer for path */
- int fd; /* Filedescriptor */
- int res; /* Result from write() */
+ char path[MAX_STRBUF_SIZE]; /* Buffer for path */
+ int fd; /* Filedescriptor */
+ int res; /* Result from write() */
- fprintf(stderr, "Set GPIO direction for pin %d to %s\n", pin, (dir==INPUT) ? "INPUT":"OUTPUT");
+ fprintf(stderr, "Set GPIO direction for pin %d to %s\n", pin, (dir == INPUT) ? "INPUT" : "OUTPUT");
snprintf(path, MAX_STRBUF_SIZE, "/sys/class/gpio/gpio%d/direction", pin);
fd = open(path, O_WRONLY);
if (fd < 0)
{
perror("Could not set mode for GPIO pin(open)!\n");
- return(-1);
+ return (-1);
}
switch (dir)
{
- case INPUT : res = write(fd,"in",2); break;
- case OUTPUT: res = write(fd,"out",3); break;
- default: res = -1; break;
+ case INPUT:
+ res = write(fd, "in", 2);
+ break;
+ case OUTPUT:
+ res = write(fd, "out", 3);
+ break;
+ default:
+ res = -1;
+ break;
}
if (res < 0)
{
perror("Could not set mode for GPIO pin(write)!\n");
- return(-1);
+ return (-1);
}
close(fd);
- return(0);
+ return (0);
}
/* Read from GPIO pin
@@ -642,7 +791,7 @@ int gpio_direction(int pin, int dir)
*/
int gpio_read(int pin)
{
- char path[MAX_STRBUF_SIZE]; /* Buffer for path */
+ char path[MAX_STRBUF_SIZE]; /* Buffer for path */
char c;
snprintf(path, MAX_STRBUF_SIZE, "/sys/class/gpio/gpio%d/value", pin);
@@ -651,14 +800,14 @@ int gpio_read(int pin)
if (gpioFds[pin] < 0)
{
perror("Could not read from GPIO(open)!\n");
- return(-1);
+ return (-1);
}
- lseek(gpioFds [pin], 0L, SEEK_SET) ;
+ lseek(gpioFds[pin], 0L, SEEK_SET);
if (read(gpioFds[pin], &c, 1) < 0)
{
perror("Could not read from GPIO(read)!\n");
- return(-1);
+ return (-1);
}
return (c == '0') ? LOW : HIGH;
@@ -669,8 +818,8 @@ int gpio_read(int pin)
*/
int gpio_write(int pin, int value)
{
- char path[MAX_STRBUF_SIZE]; /* Buffer for path */
- int res; /* Result from write()*/
+ char path[MAX_STRBUF_SIZE]; /* Buffer for path */
+ int res; /* Result from write()*/
snprintf(path, MAX_STRBUF_SIZE, "/sys/class/gpio/gpio%d/value", pin);
if (gpioFds[pin] < 0)
@@ -679,23 +828,29 @@ int gpio_write(int pin, int value)
if (gpioFds[pin] < 0)
{
perror("Could not write to GPIO(open)!\n");
- return(-1);
+ return (-1);
}
switch (value)
{
- case LOW : res = write(gpioFds[pin], "0\n", 2); break;
- case HIGH: res = write(gpioFds[pin], "1\n", 2); break;
- default: res = -1; break;
+ case LOW:
+ res = write(gpioFds[pin], "0\n", 2);
+ break;
+ case HIGH:
+ res = write(gpioFds[pin], "1\n", 2);
+ break;
+ default:
+ res = -1;
+ break;
}
if (res < 0)
{
perror("Could not write to GPIO(write)!\n");
- return(-1);
+ return (-1);
}
- return(0);
+ return (0);
}
/* Set GPIO pin edge detection
@@ -705,25 +860,35 @@ int gpio_write(int pin, int value)
*/
int gpio_edge(unsigned int pin, char edge)
{
- char path[MAX_STRBUF_SIZE]; /* Buffer for path */
- int fd; /* Filedescriptor */
+ char path[MAX_STRBUF_SIZE]; /* Buffer for path */
+ int fd; /* Filedescriptor */
snprintf(path, MAX_STRBUF_SIZE, "/sys/class/gpio/gpio%d/edge", pin);
- fd = open(path, O_WRONLY | O_NONBLOCK );
+ fd = open(path, O_WRONLY | O_NONBLOCK);
if (fd < 0)
{
perror("Could not set GPIO edge detection(open)!\n");
- return(-1);
+ return (-1);
}
switch (edge)
{
- case 'r': strncpy(path,"rising",8); break;
- case 'f': strncpy(path,"falling",8); break;
- case 'b': strncpy(path,"both",8); break;
- case 'n': strncpy(path,"none",8); break;
- default: close(fd);return(-2);
+ case 'r':
+ strncpy(path, "rising", 8);
+ break;
+ case 'f':
+ strncpy(path, "falling", 8);
+ break;
+ case 'b':
+ strncpy(path, "both", 8);
+ break;
+ case 'n':
+ strncpy(path, "none", 8);
+ break;
+ default:
+ close(fd);
+ return (-2);
}
write(fd, path, strlen(path) + 1);
@@ -740,19 +905,19 @@ int gpio_edge(unsigned int pin, char edge)
*/
int gpio_wait(unsigned int pin, int timeout)
{
- char path[MAX_STRBUF_SIZE]; /* Buffer for path */
- int fd; /* Filedescriptor */
- struct pollfd polldat[1]; /* Variable for poll() */
- char buf[MAX_STRBUF_SIZE]; /* Read buffer */
- int rc; /* Result */
+ char path[MAX_STRBUF_SIZE]; /* Buffer for path */
+ int fd; /* Filedescriptor */
+ struct pollfd polldat[1]; /* Variable for poll() */
+ char buf[MAX_STRBUF_SIZE]; /* Read buffer */
+ int rc; /* Result */
/* Open GPIO pin */
snprintf(path, MAX_STRBUF_SIZE, "/sys/class/gpio/gpio%d/value", pin);
- fd = open(path, O_RDONLY | O_NONBLOCK );
+ fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd < 0)
{
perror("Could not wait for GPIO edge(open)!\n");
- return(-1);
+ return (-1);
}
/* prepare poll() */
@@ -770,13 +935,13 @@ int gpio_wait(unsigned int pin, int timeout)
{ /* poll() failed! */
perror("Could not wait for GPIO edge(poll)!\n");
close(fd);
- return(-1);
+ return (-1);
}
if (rc == 0)
{ /* poll() timeout! */
close(fd);
- return(0);
+ return (0);
}
if (polldat[0].revents & POLLPRI)
@@ -785,46 +950,159 @@ int gpio_wait(unsigned int pin, int timeout)
{ /* read() failed! */
perror("Could not wait for GPIO edge(read)!\n");
close(fd);
- return(-2);
+ return (-2);
}
/* printf("poll() GPIO %d interrupt occurred: %s\n", pin, buf); */
close(fd);
- return(1 + atoi(buf));
+ return (1 + atoi(buf));
}
close(fd);
- return(-1);
+ return (-1);
}
-void delayMicrosecondsHard (unsigned int howLong)
+void delayMicrosecondsHard(unsigned int howLong)
{
- struct timeval tNow, tLong, tEnd ;
+ struct timeval tNow, tLong, tEnd;
- gettimeofday (&tNow, NULL) ;
- tLong.tv_sec = howLong / 1000000 ;
- tLong.tv_usec = howLong % 1000000 ;
- timeradd (&tNow, &tLong, &tEnd) ;
+ gettimeofday(&tNow, NULL);
+ tLong.tv_sec = howLong / 1000000;
+ tLong.tv_usec = howLong % 1000000;
+ timeradd(&tNow, &tLong, &tEnd);
- while (timercmp (&tNow, &tEnd, <))
- gettimeofday (&tNow, NULL) ;
+ while (timercmp(&tNow, &tEnd, <))
+ gettimeofday(&tNow, NULL);
}
-void delayMicroseconds (unsigned int howLong)
+void delayMicroseconds(unsigned int howLong)
{
- struct timespec sleeper ;
- unsigned int uSecs = howLong % 1000000 ;
- unsigned int wSecs = howLong / 1000000 ;
+ struct timespec sleeper;
+ unsigned int uSecs = howLong % 1000000;
+ unsigned int wSecs = howLong / 1000000;
- /**/ if (howLong == 0)
- return ;
- else if (howLong < 100)
- delayMicrosecondsHard (howLong) ;
- else
- {
- sleeper.tv_sec = wSecs ;
- sleeper.tv_nsec = (long)(uSecs * 1000L) ;
- nanosleep (&sleeper, NULL) ;
- }
+ /**/ if (howLong == 0)
+ return;
+ else if (howLong < 100)
+ delayMicrosecondsHard(howLong);
+ else
+ {
+ sleeper.tv_sec = wSecs;
+ sleeper.tv_nsec = (long)(uSecs * 1000L);
+ nanosleep(&sleeper, NULL);
+ }
}
#endif
+
+void LinuxPlatform::setupUniCast(uint32_t addr, uint16_t port, uint8_t type)
+{
+ if (_unicastSocketFd >= 0)
+ closeUniCast();
+
+ _unicastAddr = addr;
+ _unicastPort = port;
+ _unicastType = type;
+
+ uint32_t loop = 1;
+
+ struct sockaddr_in sin;
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons(port);
+
+ int socketType = 0;
+ if (type == IPV4_UDP)
+ socketType = SOCK_DGRAM;
+ else
+ socketType = SOCK_STREAM;
+
+ _unicastSocketFd = socket(AF_INET, socketType, 0);
+ if (_unicastSocketFd == -1)
+ {
+ perror("socket()");
+ fatalError();
+ }
+
+ /* Mehr Prozessen erlauben, denselben Port zu nutzen */
+ loop = 1;
+ if (setsockopt(_unicastSocketFd, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0)
+ {
+ perror("setsockopt:SO_REUSEADDR");
+ fatalError();
+ }
+
+ if (bind(_unicastSocketFd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
+ {
+ perror("bind");
+ fatalError();
+ }
+
+ uint32_t flags = fcntl(_unicastSocketFd, F_GETFL);
+ flags |= O_NONBLOCK;
+ fcntl(_unicastSocketFd, F_SETFL, flags);
+}
+
+void LinuxPlatform::closeUniCast()
+{
+ close(_unicastSocketFd);
+ _unicastSocketFd = -1;
+}
+
+bool LinuxPlatform::sendBytesUniCast(uint8_t* buffer, uint16_t len)
+{
+ struct sockaddr_in address = {0};
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = htonl(_unicastAddr);
+ address.sin_port = htons(_unicastPort);
+
+ ssize_t retVal = 0;
+ do
+ {
+ retVal = sendto(_unicastSocketFd, buffer, len, 0, (struct sockaddr*)&address, sizeof(address));
+ if (retVal == -1)
+ {
+ if (errno != EAGAIN && errno != EWOULDBLOCK)
+ return false;
+ }
+ } while (retVal == -1);
+ // printHex("<-", buffer, len);
+ return true;
+}
+
+int LinuxPlatform::readBytesUniCast(uint8_t* buffer,
+ uint16_t maxLen)
+{
+ uint32_t sin_len;
+ struct sockaddr_in sin;
+
+ sin_len = sizeof(sin);
+ ssize_t len = recvfrom(_unicastSocketFd, buffer, maxLen, 0, (struct sockaddr*)&sin, &sin_len);
+ // if (len > 0)
+ // printHex("->", buffer, len);
+
+ return len;
+}
+
+void LinuxPlatform::macAddress(uint8_t* mac_address)
+{
+ memcpy(mac_address, _macAddress, IFHWADDRLEN);
+}
+
+
+uint32_t LinuxPlatform::currentIpAddress()
+{
+ return _ipAddress;
+}
+
+
+uint32_t LinuxPlatform::currentSubnetMask()
+{
+ return _netmask;
+}
+
+
+uint32_t LinuxPlatform::currentDefaultGateway()
+{
+ return _defaultGateway;
+}
diff --git a/src/linux_platform.h b/src/linux_platform.h
index bbee364..90250b1 100644
--- a/src/linux_platform.h
+++ b/src/linux_platform.h
@@ -26,11 +26,23 @@ public:
void restart() override;
void fatalError() override;
+ // ip config
+ uint32_t currentIpAddress() override;
+ uint32_t currentSubnetMask() override;
+ uint32_t currentDefaultGateway() override;
+ void macAddress(uint8_t* data) override;
+
+
//multicast
void setupMultiCast(uint32_t addr, uint16_t port) override;
void closeMultiCast() override;
bool sendBytesMultiCast(uint8_t* buffer, uint16_t len) override;
int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen) override;
+
+ void setupUniCast(uint32_t addr, uint16_t port, uint8_t type);
+ void closeUniCast();
+ bool sendBytesUniCast(uint8_t* buffer, uint16_t len);
+ int readBytesUniCast(uint8_t* buffer, uint16_t maxLen);
//spi
void setupSpi() override;
@@ -44,15 +56,25 @@ public:
private:
uint32_t _multicastAddr = -1;
- uint16_t _port = -1;
- int _socketFd = -1;
+ uint16_t _multicastPort = -1;
+ int _multicastSocketFd = -1;
+
+ uint32_t _unicastAddr = -1;
+ uint16_t _unicastPort = -1;
+ int _unicastSocketFd = -1;
+ uint8_t _unicastType = -1;
+
void doMemoryMapping();
uint8_t* _mappedFile = 0;
int _fd = -1;
int _spiFd = -1;
- uint8_t* _currentMaxMem = 0;
std::string _flashFilePath = "flash.bin";
char** _args = 0;
+
+ uint8_t _macAddress[6] = {0, 0, 0, 0, 0, 0};
+ uint32_t _ipAddress = 0;
+ uint32_t _netmask = 0;
+ uint32_t _defaultGateway = 0;
};
#endif
\ No newline at end of file