Moved west manifest, zephyr folder, and ports/zephyr folders to another repository bacnet-stack-zephyr (#757)

This commit is contained in:
Steve Karg
2024-08-30 11:01:18 -05:00
committed by GitHub
parent 8ee583a10c
commit 622a9e609e
401 changed files with 0 additions and 13931 deletions
-22
View File
@@ -1,22 +0,0 @@
/**
* @file
* @brief Port specific configuration for BACnet Stack for Zephyr OS
* @author Steve Karg
* @date 2024
* @section LICENSE
*
* Copyright (C) 2024 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*/
#ifndef BACNET_PORTS_ZEPHYR_BACNET_CONFIG_H
#define BACNET_PORTS_ZEPHYR_BACNET_CONFIG_H
#if ! defined BACNET_CONFIG_H || ! BACNET_CONFIG_H
#error bacnet-config.h included outside of BACNET_CONFIG_H control
#endif
/* provides platform specific define for ARRAY_SIZE */
#include <zephyr/sys/util.h>
#endif
-65
View File
@@ -1,65 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
#ifndef BITS_H
#define BITS_H
#include <zephyr/sys/util.h> /* defines BIT(n) */
/********************************************************************
* Bit Masks
*********************************************************************/
#define BIT0 BIT( 0)
#define BIT1 BIT( 1)
#define BIT2 BIT( 2)
#define BIT3 BIT( 3)
#define BIT4 BIT( 4)
#define BIT5 BIT( 5)
#define BIT6 BIT( 6)
#define BIT7 BIT( 7)
#define BIT8 BIT( 8)
#define BIT9 BIT( 9)
#define BIT10 BIT(10)
#define BIT11 BIT(11)
#define BIT12 BIT(12)
#define BIT13 BIT(13)
#define BIT14 BIT(14)
#define BIT15 BIT(15)
#define BIT16 BIT(16)
#define BIT17 BIT(17)
#define BIT18 BIT(18)
#define BIT19 BIT(19)
#define BIT20 BIT(20)
#define BIT21 BIT(21)
#define BIT22 BIT(22)
#define BIT23 BIT(23)
#define BIT24 BIT(24)
#define BIT25 BIT(25)
#define BIT26 BIT(26)
#define BIT27 BIT(27)
#define BIT28 BIT(28)
#define BIT29 BIT(29)
#define BIT30 BIT(30)
#define BIT31 BIT(31)
/* a=register, b=bit number to act upon 0-n */
#define BIT_SET(a,b) ((a) |= (1<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1<<(b)))
#define BIT_CHECK(a,b) ((a) & (1<<(b)))
/* x=target variable, y=mask */
#define BITMASK_SET(x,y) ((x) |= (y))
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK(x,y) (((x) & (y)) == (y))
#ifndef _BV
#define _BV(x) (1<<(x))
#endif
#endif
-95
View File
@@ -1,95 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
#ifndef ETHERNET_H
#define ETHERNET_H
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/npdu.h"
/* specific defines for Ethernet */
#define ETHERNET_HEADER_MAX (6+6+2+1+1+1)
#define ETHERNET_MPDU_MAX (ETHERNET_HEADER_MAX+MAX_PDU)
/* Unless we explicitly need these remaps to be NOT exposed
* (e.g. implementation where we need both bacnet and Zephyr symbols),
* replace the BACnet Ethernet API symbols with non-conflicting ones.
*/
#if !defined(BACNET_ETHERNET_NO_REMAP_DEFINES)
#define ethernet_valid bacnet_ethernet_valid
#define ethernet_cleanup bacnet_ethernet_cleanup
#define ethernet_init bacnet_ethernet_init
#define ethernet_send_pdu bacnet_ethernet_send_pdu
#define ethernet_receive bacnet_ethernet_receive
#define ethernet_set_my_address bacnet_ethernet_set_my_address
#define ethernet_get_my_address bacnet_ethernet_get_my_address
#define ethernet_get_broadcast_address bacnet_ethernet_get_broadcast_address
#define ethernet_debug_address bacnet_ethernet_debug_address
#define ethernet_send bacnet_ethernet_send
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
BACNET_STACK_EXPORT
bool bacnet_ethernet_valid(
void);
BACNET_STACK_EXPORT
void bacnet_ethernet_cleanup(
void);
BACNET_STACK_EXPORT
bool bacnet_ethernet_init(
char *interface_name);
/* function to send a packet out the 802.2 socket */
/* returns number of bytes sent on success, negative on failure */
BACNET_STACK_EXPORT
int bacnet_ethernet_send_pdu(
BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len); /* number of bytes of data */
/* receives an 802.2 framed packet */
/* returns the number of octets in the PDU, or zero on failure */
BACNET_STACK_EXPORT
uint16_t bacnet_ethernet_receive(
BACNET_ADDRESS * src, /* source address */
uint8_t * pdu, /* PDU data */
uint16_t max_pdu, /* amount of space available in the PDU */
unsigned timeout); /* milliseconds to wait for a packet */
BACNET_STACK_EXPORT
void bacnet_ethernet_set_my_address(
const BACNET_ADDRESS * my_address);
BACNET_STACK_EXPORT
void bacnet_ethernet_get_my_address(
BACNET_ADDRESS * my_address);
BACNET_STACK_EXPORT
void bacnet_ethernet_get_broadcast_address(
BACNET_ADDRESS * dest); /* destination address */
/* some functions from Linux driver */
BACNET_STACK_EXPORT
void bacnet_ethernet_debug_address(
const char *info,
BACNET_ADDRESS * dest);
BACNET_STACK_EXPORT
int bacnet_ethernet_send(
uint8_t * mtu,
int mtu_len);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
-64
View File
@@ -1,64 +0,0 @@
/**************************************************************************
*
* Copyright (c) 2020 Legrand North America, LLC.
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
#ifndef NET_H
#define NET_H
#include <zephyr/net/net_ip.h>
#include <zephyr/net/socket.h>
#include <zephyr/kernel.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/basic/object/device.h"
static inline char *inet_ntoa(struct in_addr in) {
return "(inet_ntoa() to be implemented)";
}
/* Local helper functions for this port */
extern int bip_get_local_netmask(
struct in_addr *netmask);
#ifdef CONFIG_BACNET_USE_SECTION_ITERABLE_OBJECT_TABLE
#define BACNET_OBJECT_TABLE(table_name, _type, _init, _count, \
_index_to_instance, _valid_instance, _object_name, \
_read_property, _write_property, _RPM_list, \
_RR_info, _iterator, _value_list, _COV, \
_COV_clear, _intrinsic_reporting) \
STRUCT_SECTION_ITERABLE(object_functions, table_name) = { \
.Object_Type = _type, \
.Object_Init = _init, \
.Object_Count = _count, \
.Object_Index_To_Instance = _index_to_instance, \
.Object_Valid_Instance = _valid_instance, \
.Object_Name = _object_name, \
.Object_Read_Property = _read_property, \
.Object_Write_Property = _write_property, \
.Object_RPM_List = _RPM_list, \
.Object_RR_Info = _RR_info, \
.Object_Iterator = _iterator, \
.Object_Value_List = _value_list, \
.Object_COV = _COV, \
.Object_COV_Clear = _COV_clear, \
.Object_Intrinsic_Reporting = _intrinsic_reporting \
}
#else
#define BACNET_OBJECT_TABLE(table_name, _type, _init, _count, \
_index_to_instance, _valid_instance, _object_name, \
_read_property, _write_property, _RPM_list, \
_RR_info, _iterator, _value_list, _COV, \
_COV_clear, _intrinsic_reporting) \
while{}(0)
#endif
#endif
-613
View File
@@ -1,613 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*
*********************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/socket_select.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bacdcode.h"
#include "bacnet/bacint.h"
#include "bacnet/datalink/bip.h"
#include "bacnet/basic/sys/debug.h"
#include "bacnet/basic/bbmd/h_bbmd.h"
/* Logging module registration is already done in ports/zephyr/main.c */
#include <zephyr/logging/log.h>
#include <zephyr/logging/log_ctrl.h>
LOG_MODULE_DECLARE(bacnet, CONFIG_BACNETSTACK_LOG_LEVEL);
#define THIS_FILE "bip-init.c"
/* zephyr sockets */
static int BIP_Socket = -1;
static int BIP_Broadcast_Socket = -1;
/* NOTE: we store address and port in network byte order
since BACnet/IP uses network byte order for all address byte arrays
*/
/* port to use - stored here in network byte order */
static uint16_t BIP_Port = htons(CONFIG_BACDL_BIP_PORT);
/* IP address - stored here in network byte order */
static struct in_addr BIP_Address;
/* IP broadcast address - stored here in network byte order */
static struct in_addr BIP_Broadcast_Addr;
/* Used by inet_ntoa */
#if CONFIG_BACNETSTACK_LOG_LEVEL
static char ipv4_addr_str[16] = { 0 };
#else
static char ipv4_addr_str[] = "";
#endif
/**
* @brief Return a string representation of an IPv4 address
* @param a - IPv4 address
* @return Pointer to global string
*/
char *inet_ntoa(struct in_addr *a)
{
if (IS_ENABLED(CONFIG_BACNETSTACK_LOG_LEVEL)) {
snprintf(ipv4_addr_str, sizeof(ipv4_addr_str), "%d.%d.%d.%d",
a->s4_addr[0], a->s4_addr[1], a->s4_addr[2], a->s4_addr[3]);
}
return &ipv4_addr_str[0];
}
/**
* @brief Print the IPv4 address with debug info
* @param str - debug info string
* @param addr - IPv4 address
*/
static void debug_print_ipv4(const char *str,
const struct in_addr *addr,
const unsigned int port,
const unsigned int count)
{
LOG_DBG("%s %s:%hu (%u bytes)", str, inet_ntoa((struct in_addr *)&addr),
ntohs(port), count);
}
/**
* @brief Set the BACnet IPv4 UDP port number
* @param port - IPv4 UDP port number - in host byte order
*/
void bip_set_port(uint16_t port)
{
BIP_Port = htons(port);
}
/**
* @brief Get the BACnet IPv4 UDP port number
* @return IPv4 UDP port number - in host byte order
*/
uint16_t bip_get_port(void)
{
return ntohs(BIP_Port);
}
/**
* @brief Get the IPv4 address for my interface. Used for sending src address.
* @param addr - BACnet datalink address
*/
void bip_get_my_address(BACNET_ADDRESS *addr)
{
unsigned int i = 0;
if (addr) {
addr->mac_len = BIP_ADDRESS_MAX; /* 6 */
memcpy(&addr->mac[0], &BIP_Address.s_addr, IP_ADDRESS_MAX); /* 4 */
memcpy(&addr->mac[IP_ADDRESS_MAX], &BIP_Port, sizeof(BIP_Port));
/* local only, no routing */
addr->net = 0;
/* no SLEN */
addr->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) {
/* no SADR */
addr->adr[i] = 0;
}
}
}
/**
* Get the IPv4 broadcast address for my interface.
*
* @param addr - BACnet datalink address
*/
void bip_get_broadcast_address(BACNET_ADDRESS *dest)
{
int i = 0;
if (dest) {
dest->mac_len = BIP_ADDRESS_MAX;
memcpy(&dest->mac[0], &BIP_Broadcast_Addr.s_addr, IP_ADDRESS_MAX);
memcpy(&dest->mac[IP_ADDRESS_MAX], &BIP_Port, sizeof(BIP_Port));
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
}
return;
}
/**
* @brief Set the BACnet/IP address
* @param addr - network IPv4 address
* @return true if the address was set
*/
bool bip_set_addr(const BACNET_IP_ADDRESS *addr)
{
if (addr) {
memcpy(&BIP_Address.s_addr, &addr->address[0], IP_ADDRESS_MAX);
BIP_Port = htons(addr->port);
return true;
}
return false;
}
/**
* @brief Get the BACnet/IP address
* @param addr - network IPv4 address (in network byte order)
* @return true if the address was retrieved
*/
bool bip_get_addr(BACNET_IP_ADDRESS *addr)
{
if (addr) {
memcpy(&addr->address[0], &BIP_Address.s_addr, IP_ADDRESS_MAX);
addr->port = ntohs(BIP_Port);
return true;
}
return false;
}
/**
* @brief Set the BACnet/IP address
* @param addr - network IPv4 address
* @return true if the address was set
*/
bool bip_set_broadcast_addr(const BACNET_IP_ADDRESS *addr)
{
if (addr) {
memcpy(&BIP_Broadcast_Addr.s_addr, &addr->address[0], IP_ADDRESS_MAX);
return true;
}
return false;
}
/**
* Get the BACnet/IP address
*
* @return BACnet/IP address
*/
bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr)
{
if (addr) {
memcpy(&addr->address[0], &BIP_Broadcast_Addr.s_addr, IP_ADDRESS_MAX);
addr->port = ntohs(BIP_Port);
return true;
}
return false;
}
/**
* @brief Set the BACnet/IP subnet mask CIDR prefix
* @return true if the subnet mask CIDR prefix is set
*/
bool bip_set_subnet_prefix(uint8_t prefix)
{
/* not something we do within this driver */
return false;
}
/**
* @brief Get the BACnet/IP subnet mask CIDR prefix
* @return subnet mask CIDR prefix 1..32
*/
uint8_t bip_get_subnet_prefix(void)
{
uint32_t address = 0;
uint32_t broadcast = 0;
uint32_t mask = 0xFFFFFFFE;
uint8_t prefix = 0;
address = BIP_Address.s_addr;
broadcast = BIP_Broadcast_Addr.s_addr;
/* calculate the subnet prefix from the broadcast address */
for (prefix = 1; prefix <= 32; prefix++) {
if ((address | mask) == broadcast) {
break;
}
mask = mask << 1;
}
return prefix;
}
/**
* The send function for BACnet/IP driver layer
*
* @param dest - Points to a BACNET_IP_ADDRESS structure containing the
* destination address.
* @param mtu - the bytes of data to send
* @param mtu_len - the number of bytes of data to send
*
* @return Upon successful completion, returns the number of bytes sent.
* Otherwise, -1 shall be returned and errno set to indicate the error.
*/
int bip_send_mpdu(
const BACNET_IP_ADDRESS *dest, const uint8_t *mtu, uint16_t mtu_len)
{
struct sockaddr_in bip_dest = { 0 };
/* assumes that the driver has already been initialized */
if (BIP_Socket < 0) {
LOG_ERR("%s:%d - Socket not initialized!", THIS_FILE, __LINE__);
return BIP_Socket;
}
/* load destination IP address */
bip_dest.sin_family = AF_INET;
memcpy(&bip_dest.sin_addr.s_addr, &dest->address[0], IP_ADDRESS_MAX);
bip_dest.sin_port = htons(dest->port);
/* Send the packet */
debug_print_ipv4(
"Sending MPDU->", &bip_dest.sin_addr, bip_dest.sin_port, mtu_len);
return zsock_sendto(BIP_Socket, (const char *)mtu, mtu_len, 0,
(struct sockaddr *)&bip_dest, sizeof(struct sockaddr));
}
/**
* BACnet/IP Datalink Receive handler.
*
* @param src - returns the source address
* @param npdu - returns the NPDU buffer
* @param max_npdu -maximum size of the NPDU buffer
* @param timeout - number of milliseconds to wait for a packet
*
* @return Number of bytes received, or 0 if none or timeout.
*/
uint16_t bip_receive(
BACNET_ADDRESS *src, uint8_t *npdu, uint16_t max_npdu, unsigned timeout)
{
uint16_t npdu_len = 0; /* return value */
zsock_fd_set read_fds;
int max = 0;
struct zsock_timeval select_timeout;
struct sockaddr_in sin = { 0 };
BACNET_IP_ADDRESS addr = { 0 };
socklen_t sin_len = sizeof(sin);
int received_bytes = 0;
int offset = 0;
uint16_t i = 0;
int socket;
/* Make sure the socket is open */
if (BIP_Socket < 0) {
return 0;
}
/* we could just use a non-blocking socket, but that consumes all
the CPU time. We can use a timeout; it is only supported as
a select. */
if (timeout >= 1000) {
select_timeout.tv_sec = timeout / 1000;
select_timeout.tv_usec =
1000 * (timeout - select_timeout.tv_sec * 1000);
} else {
select_timeout.tv_sec = 0;
select_timeout.tv_usec = 1000 * timeout;
}
ZSOCK_FD_ZERO(&read_fds);
ZSOCK_FD_SET(BIP_Socket, &read_fds);
ZSOCK_FD_SET(BIP_Broadcast_Socket, &read_fds);
max = BIP_Socket > BIP_Broadcast_Socket ? BIP_Socket : BIP_Broadcast_Socket;
/* see if there is a packet for us */
if (zsock_select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
socket =
FD_ISSET(BIP_Socket, &read_fds) ? BIP_Socket : BIP_Broadcast_Socket;
received_bytes = zsock_recvfrom(socket, (char *)&npdu[0], max_npdu, 0,
(struct sockaddr *)&sin, &sin_len);
} else {
return 0;
}
/* See if there is a problem */
if (received_bytes < 0) {
LOG_WRN("%s:%d - RX zsock_recvfrom() error: %d", THIS_FILE, __LINE__,
received_bytes);
return 0;
}
/* no problem, just no bytes */
if (received_bytes == 0) {
return 0;
}
/* the signature of a BACnet/IP packet */
if (npdu[0] != BVLL_TYPE_BACNET_IP) {
LOG_WRN("%s:%d - RX bad packet", THIS_FILE, __LINE__);
return 0;
}
/* Data link layer addressing between B/IPv4 nodes consists of a 32-bit
IPv4 address followed by a two-octet UDP port number (both of which
shall be transmitted with the most significant octet first). This
address shall be referred to as a B/IPv4 address.
*/
memcpy(&addr.address[0], &sin.sin_addr.s_addr, IP_ADDRESS_MAX);
addr.port = ntohs(sin.sin_port);
debug_print_ipv4(
"Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes);
/* pass the packet into the BBMD handler */
offset = socket == BIP_Socket
? bvlc_handler(&addr, src, npdu, received_bytes)
: bvlc_broadcast_handler(&addr, src, npdu, received_bytes);
if (offset > 0) {
npdu_len = received_bytes - offset;
debug_print_ipv4(
"Received NPDU->", &sin.sin_addr, sin.sin_port, npdu_len);
if (npdu_len <= max_npdu) {
/* shift the buffer to return a valid NPDU */
for (i = 0; i < npdu_len; i++) {
npdu[i] = npdu[offset + i];
}
} else {
LOG_WRN("%s:%d - NPDU dropped!", THIS_FILE, __LINE__);
npdu_len = 0;
}
}
return npdu_len;
}
/**
* The common send function for BACnet/IP application layer
*
* @param dest - Points to a #BACNET_ADDRESS structure containing the
* destination address.
* @param npdu_data - Points to a BACNET_NPDU_DATA structure containing the
* destination network layer control flags and data.
* @param mtu - the bytes of data to send
* @param mtu_len - the number of bytes of data to send
* @return Upon successful completion, returns the number of bytes sent.
* Otherwise, -1 shall be returned and errno set to indicate the error.
*/
int bip_send_pdu(BACNET_ADDRESS *dest,
BACNET_NPDU_DATA *npdu_data,
uint8_t *pdu,
unsigned pdu_len)
{
dest->net = BACNET_BROADCAST_NETWORK;
return bvlc_send_pdu(dest, npdu_data, pdu, pdu_len);
}
/** Gets the local IP address and local broadcast address from the system,
* and saves it into the BACnet/IP data structures.
*
* @param ifname [in] The named interface to use for the network layer.
* Eg, for Linux, ifname is eth0, ath0, arc0, and others.
*/
void bip_set_interface(const char *ifname)
{
struct net_if *iface = 0;
int index = -1;
uint8_t x = 0;
BACNET_IP_ADDRESS unicast = { 0 };
BACNET_IP_ADDRESS broadcast = { 0 };
/* Network byte order */
unicast.port = ntohs(BIP_Port);
broadcast.port = ntohs(BIP_Port);
LOG_INF("bip_set_interface()");
LOG_INF("UDP port: %d", unicast.port);
if (ifname) {
index = atoi(ifname);
/* if index is zero, discern between "0" and a parse error */
if (!index && strcmp(ifname, "0")) {
LOG_ERR("%s:%d - Argument must parse to an integer", THIS_FILE,
__LINE__);
} else {
iface = net_if_get_by_index(index);
if (iface) {
LOG_INF("Using iface %d", index);
} else {
LOG_ERR(
"%s:%d - No iface at index %d", THIS_FILE, __LINE__, index);
}
}
}
if (index == -1) {
LOG_WRN("%s:%d - No valid interface specified - using default ",
THIS_FILE, __LINE__);
iface = net_if_get_default();
}
if (iface) {
LOG_INF("Interface set.");
#if defined(CONFIG_BACDL_BIP_ADDRESS_INDEX)
LOG_INF("Config unicast address %d/%d",
CONFIG_BACDL_BIP_ADDRESS_INDEX, NET_IF_MAX_IPV4_ADDR);
index = CONFIG_BACDL_BIP_ADDRESS_INDEX;
#else
int i;
char hr_addr[NET_IPV4_ADDR_LEN];
index = 0;
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
struct net_if_addr *if_addr = &iface->config.ip.ipv4->unicast[i];
if (!if_addr->is_used) {
continue;
}
index = i;
LOG_INF("IPv4 address: %s",
net_addr_ntop(AF_INET, &if_addr->address.in_addr, hr_addr,
NET_IPV4_ADDR_LEN));
LOG_INF("Subnet: %s",
net_addr_ntop(AF_INET, &iface->config.ip.ipv4->netmask, hr_addr,
NET_IPV4_ADDR_LEN));
LOG_INF("Router: %s",
net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw, hr_addr,
NET_IPV4_ADDR_LEN));
break;
}
#endif
if (index >= NET_IF_MAX_IPV4_ADDR) {
LOG_ERR("%s:%d - IPv4 address index of %d is out of range (0-%d)",
THIS_FILE, __LINE__, index, NET_IF_MAX_IPV4_ADDR - 1);
return;
}
LOG_INF("Using IPv4 address at index %d", index);
/* Build the broadcast address from the unicast and netmask */
struct net_if_addr *if_addr = &iface->config.ip.ipv4->unicast[index];
for (x = 0; x < IP_ADDRESS_MAX; x++) {
unicast.address[x] = if_addr->address.in_addr.s4_addr[x];
broadcast.address[x] = if_addr->address.in_addr.s4_addr[x] |
~iface->config.ip.ipv4->netmask.s4_addr[x];
}
bip_set_addr(&unicast);
bip_set_broadcast_addr(&broadcast);
LOG_INF("BACnet/IP Unicast: %u.%u.%u.%u:%d", unicast.address[0],
unicast.address[1], unicast.address[2], unicast.address[3],
unicast.port);
LOG_INF("BACnet/IP Broadcast: %u.%u.%u.%u", broadcast.address[0],
broadcast.address[1], broadcast.address[2], broadcast.address[3]);
} else {
LOG_ERR("%s:%d - Failed to set iface", THIS_FILE, __LINE__);
}
}
static int createSocket(const struct sockaddr_in *sin)
{
int sock_fd = -1;
const int sockopt = 1;
int status = -1;
/* assumes that the driver has already been initialized */
sock_fd = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock_fd < 0) {
LOG_ERR("%s:%d - Failed to create socket", THIS_FILE, __LINE__);
return sock_fd;
} else {
LOG_DBG("Socket created");
}
/* Allow us to use the same socket for sending and receiving */
/* This makes sure that the src port is correct when sending */
status = zsock_setsockopt(
sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
if (status < 0) {
zsock_close(sock_fd);
return status;
}
/* bind the socket to the local port number and IP address */
status = zsock_bind(
sock_fd, (const struct sockaddr *)sin, sizeof(struct sockaddr));
if (status < 0) {
zsock_close(sock_fd);
LOG_ERR("%s:%d - zsock_bind() failure", THIS_FILE, __LINE__);
return status;
} else {
LOG_DBG("Socket bound");
}
return sock_fd;
}
/** Initialize the BACnet/IP services at the given interface.
* @ingroup DLBIP
* -# Gets the local IP address and local broadcast address from the system,
* and saves it into the BACnet/IP data structures.
* -# Opens a UDP socket
* -# Configures the socket for sending and receiving
* -# Configures the socket so it can send broadcasts
* -# Binds the socket to the local IP address at the specified port for
* BACnet/IP (by default, 0xBAC0 = 47808).
*
* @note For Zephyr, ifname is the index number of the interface as a string.
*
* @param ifname [in] The named interface to use for the network layer.
* If NULL, the default interface is assigned.
* @return True if the socket is successfully opened for BACnet/IP,
* else False if the socket functions fail.
*/
bool bip_init(char *ifname)
{
int sock_fd;
struct sockaddr_in sin = { 0 };
bip_set_interface(ifname);
if (BIP_Address.s_addr == 0) {
LOG_ERR("%s:%d - Failed to get an IP address on interface: %s\n",
THIS_FILE, __LINE__, ifname ? ifname : "[default]");
return false;
}
/* bind the socket to the local port number and IP address */
sin.sin_family = AF_INET;
sin.sin_port = BIP_Port;
sin.sin_addr.s_addr = BIP_Address.s_addr;
sock_fd = createSocket(&sin);
BIP_Socket = sock_fd;
if (sock_fd < 0) {
return false;
}
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sock_fd = createSocket(&sin);
BIP_Broadcast_Socket = sock_fd;
if (sock_fd < 0) {
return false;
}
bvlc_init();
LOG_DBG("bip_init() success");
return true;
}
/**
* @brief Determine if this BACnet/IP datalink is valid
* @return true if the BACnet/IP datalink is valid
*/
bool bip_valid(void)
{
return (BIP_Socket != -1);
}
/** Cleanup and close out the BACnet/IP services by closing the socket.
* @ingroup DLBIP
*/
void bip_cleanup(void)
{
LOG_DBG("bip_cleanup()");
memset(&BIP_Address, 0, sizeof(BIP_Address));
memset(&BIP_Broadcast_Addr, 0, sizeof(BIP_Broadcast_Addr));
if (BIP_Socket != -1) {
zsock_close(BIP_Socket);
}
BIP_Socket = -1;
return;
}
-578
View File
@@ -1,578 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2005-2020 Steve Karg
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*
*********************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/socket_select.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bacdcode.h"
#include "bacnet/bacint.h"
#include "bacnet/datalink/bip6.h"
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/sys/debug.h"
#include "bacnet/basic/bbmd6/h_bbmd6.h"
/* Logging module registration is already done in ports/zephyr/main.c */
#include <zephyr/logging/log.h>
#include <zephyr/logging/log_ctrl.h>
LOG_MODULE_DECLARE(bacnet, CONFIG_BACNETSTACK_LOG_LEVEL);
#define THIS_FILE "bip6-init.c"
/* zephyr socket */
static int BIP6_Socket = -1;
static int BIP6_Socket_Scope_Id;
/* local address - filled by init functions */
static BACNET_IP6_ADDRESS BIP6_Addr;
static BACNET_IP6_ADDRESS BIP6_Broadcast_Addr;
/* Used by inet6_ntoa */
#if CONFIG_BACNETSTACK_LOG_LEVEL
static char ipv6_addr_str[42] = { 0 };
#else
static char ipv6_addr_str[] = "";
#endif
/**
* @brief Return a string representation of an IPv6 address
* @param a - IPv6 address
* @return Pointer to global string
*/
static char *inet6_ntoa(const struct in6_addr *a)
{
#if CONFIG_BACNETSTACK_LOG_LEVEL
uint8_t x = 0;
uint8_t d = 0;
uint8_t non_zero_count = 0;
/* Avoid overwhelming the logging system */
while (log_buffered_cnt()) {
k_sleep(K_MSEC(1));
}
for (x = 0; x < IP6_ADDRESS_MAX; x += 2) {
if (a->s6_addr[x] | a->s6_addr[x + 1]) {
non_zero_count++;
d += snprintf(
&ipv6_addr_str[d], sizeof(ipv6_addr_str), "%02X%02X",
a->s6_addr[x], a->s6_addr[x + 1]);
}
if (x < 14) {
d += snprintf(&ipv6_addr_str[d], sizeof(ipv6_addr_str), ":");
}
}
if (!non_zero_count) {
snprintf(&ipv6_addr_str[0], sizeof(ipv6_addr_str), "undefined");
}
#endif
return &ipv6_addr_str[0];
}
void bip6_set_interface(char *ifname)
{
struct net_if *interface = 0;
int index = -1;
int x = 0;
BACNET_IP6_ADDRESS unicast = { 0 };
BACNET_IP6_ADDRESS multicast = { 0 };
unicast.port = bip6_get_port();
multicast.port = unicast.port;
LOG_DBG("bip6_set_interface()");
LOG_INF("BIP6: UDP port: 0x%04X", (unsigned)unicast.port);
LOG_INF("BIP6: seeking interface: %s", ifname?ifname:"NULL");
if (ifname) {
index = atoi(ifname);
/* if index is zero, discern between "0" and a parse error */
if (!index && strcmp(ifname, "0")) {
LOG_ERR(
"%s:%d - Argument must parse to an integer", THIS_FILE,
__LINE__);
} else {
interface = net_if_get_by_index(index);
if (interface) {
LOG_INF("BIP6: Using interface %d", index);
} else {
LOG_ERR(
"%s:%d - No interface at index %d", THIS_FILE, __LINE__,
index);
}
}
}
if (index == -1) {
LOG_INF("BIP6: No valid interface specified. Using default ");
interface = net_if_get_default();
}
if (interface) {
BIP6_Socket_Scope_Id = net_if_get_by_iface(interface);
LOG_INF("BIP6: Socket Scope ID = %d", BIP6_Socket_Scope_Id);
LOG_INF("BIP6: Interface set - Configured addresses:");
for (x = 0; x < NET_IF_MAX_IPV6_ADDR; x++) {
inet6_ntoa(&interface->config.ip.ipv6->unicast[x].address.in6_addr);
LOG_INF(" unicast[%d]: %s", x, ipv6_addr_str);
}
for (x = 0; x < NET_IF_MAX_IPV6_MADDR; x++) {
inet6_ntoa(&interface->config.ip.ipv6->mcast[x].address.in6_addr);
LOG_INF(" multicast[%d]: %s", x, ipv6_addr_str);
}
if (CONFIG_BACDL_BIP6_ADDRESS_INDEX >= NET_IF_MAX_IPV6_ADDR) {
LOG_ERR(
"%s:%d - IPv6 address index of %d is out of range (0-%d)",
THIS_FILE, __LINE__, CONFIG_BACDL_BIP6_ADDRESS_INDEX,
NET_IF_MAX_IPV6_ADDR - 1);
return;
}
LOG_INF("BIP6: Using configured index %d",
CONFIG_BACDL_BIP6_ADDRESS_INDEX);
memcpy(
&unicast.address,
&interface->config.ip.ipv6->unicast[CONFIG_BACDL_BIP6_ADDRESS_INDEX]
.address.in6_addr,
IP6_ADDRESS_MAX);
if (net_addr_pton(
AF_INET6, CONFIG_BACDL_BIP6_MCAST_ADDRESS,
&multicast.address)) {
LOG_ERR(
"%s:%d - Failed to parse IPv6 multicast address: %s", THIS_FILE,
__LINE__, CONFIG_BACDL_BIP6_MCAST_ADDRESS);
}
bip6_set_addr(&unicast);
bip6_set_broadcast_addr(&multicast);
LOG_INF(
" Unicast: %s", inet6_ntoa((struct in6_addr *)&unicast.address));
LOG_INF(
" Multicast: %s",
inet6_ntoa((struct in6_addr *)&multicast.address));
} else {
LOG_ERR("%s:%d - Failed to set interface", THIS_FILE, __LINE__);
}
}
/**
* Set the BACnet IPv6 UDP port number
*
* @param port - IPv6 UDP port number
*/
void bip6_set_port(uint16_t port)
{
BIP6_Addr.port = port;
BIP6_Broadcast_Addr.port = port;
}
/**
* Get the BACnet IPv6 UDP port number
*
* @return IPv6 UDP port number
*/
uint16_t bip6_get_port(void)
{
return BIP6_Addr.port;
}
/**
* Get the BACnet broadcast address for my interface.
* Used as dest address in messages sent as BROADCAST
*
* @param addr - IPv6 source address
*/
void bip6_get_broadcast_address(BACNET_ADDRESS *addr)
{
if (addr) {
addr->net = BACNET_BROADCAST_NETWORK;
addr->mac_len = 0;
addr->len = 0;
}
}
/**
* Get the IPv6 address for my interface. Used as src address in messages sent.
*
* @param addr - IPv6 source address
*/
void bip6_get_my_address(BACNET_ADDRESS *addr)
{
uint32_t device_id = 0;
if (addr) {
device_id = Device_Object_Instance_Number();
bvlc6_vmac_address_set(addr, device_id);
}
}
/**
* Set the BACnet/IP address
*
* @param addr - network IPv6 address
*/
bool bip6_set_addr(const BACNET_IP6_ADDRESS *addr)
{
return bvlc6_address_copy(&BIP6_Addr, addr);
}
/**
* Get the BACnet/IP address
*
* @return BACnet/IP address
*/
bool bip6_get_addr(BACNET_IP6_ADDRESS *addr)
{
return bvlc6_address_copy(addr, &BIP6_Addr);
}
/**
* Set the BACnet/IP address
*
* @param addr - network IPv6 address
*/
bool bip6_set_broadcast_addr(const BACNET_IP6_ADDRESS *addr)
{
return bvlc6_address_copy(&BIP6_Broadcast_Addr, addr);
}
/**
* Get the BACnet/IP address
*
* @return BACnet/IP address
*/
bool bip6_get_broadcast_addr(BACNET_IP6_ADDRESS *addr)
{
return bvlc6_address_copy(addr, &BIP6_Broadcast_Addr);
}
/**
* The send function for BACnet/IPv6 driver layer
*
* @param dest - Points to a BACNET_IP6_ADDRESS structure containing the
* destination address.
* @param mtu - the bytes of data to send
* @param mtu_len - the number of bytes of data to send
*
* @return Upon successful completion, returns the number of bytes sent.
* Otherwise, -1 shall be returned and errno set to indicate the error.
*/
int bip6_send_mpdu(
const BACNET_IP6_ADDRESS *dest, const uint8_t *mtu, uint16_t mtu_len)
{
struct sockaddr_in6 bvlc_dest = { 0 };
uint16_t addr16[8];
/* assumes that the driver has already been initialized */
if (BIP6_Socket < 0) {
LOG_ERR("%s:%d - Socket not initialized!", THIS_FILE, __LINE__);
return BIP6_Socket;
}
/* load destination IP address */
bvlc_dest.sin6_family = AF_INET6;
bvlc6_address_get(
dest, &addr16[0], &addr16[1], &addr16[2], &addr16[3], &addr16[4],
&addr16[5], &addr16[6], &addr16[7]);
bvlc_dest.sin6_addr.s6_addr16[0] = htons(addr16[0]);
bvlc_dest.sin6_addr.s6_addr16[1] = htons(addr16[1]);
bvlc_dest.sin6_addr.s6_addr16[2] = htons(addr16[2]);
bvlc_dest.sin6_addr.s6_addr16[3] = htons(addr16[3]);
bvlc_dest.sin6_addr.s6_addr16[4] = htons(addr16[4]);
bvlc_dest.sin6_addr.s6_addr16[5] = htons(addr16[5]);
bvlc_dest.sin6_addr.s6_addr16[6] = htons(addr16[6]);
bvlc_dest.sin6_addr.s6_addr16[7] = htons(addr16[7]);
bvlc_dest.sin6_port = htons(dest->port);
bvlc_dest.sin6_scope_id = BIP6_Socket_Scope_Id;
inet6_ntoa(&bvlc_dest.sin6_addr);
LOG_DBG("BIP6: Sending MPDU to %s", ipv6_addr_str);
/* Send the packet */
return zsock_sendto(
BIP6_Socket, (const char *)mtu, mtu_len, 0,
(struct sockaddr *)&bvlc_dest, sizeof(bvlc_dest));
}
/**
* The common send function for BACnet/IPv6 application layer
*
* @param dest - Points to a #BACNET_ADDRESS structure containing the
* destination address.
* @param npdu_data - Points to a BACNET_NPDU_DATA structure containing the
* destination network layer control flags and data.
* @param pdu - the bytes of data to send
* @param pdu_len - the number of bytes of data to send
* @return Upon successful completion, returns the number of bytes sent.
* Otherwise, -1 shall be returned and errno set to indicate the error.
*/
int bip6_send_pdu(
BACNET_ADDRESS *dest,
BACNET_NPDU_DATA *npdu_data,
uint8_t *pdu,
unsigned pdu_len)
{
return bvlc6_send_pdu(dest, npdu_data, pdu, pdu_len);
}
/**
* @brief Generate ASCII address string from BACnet/IPv6 address
* @param s - buffer to store the string
* @param n - size of the buffer
* @param addr - BACnet/IPv6 address
*/
static int bvlc6_snprintf_addr(
char *s, size_t n, const BACNET_IP6_ADDRESS *addr)
{
uint16_t addr16[8];
bvlc6_address_get(
addr, &addr16[0], &addr16[1], &addr16[2], &addr16[3], &addr16[4],
&addr16[5], &addr16[6], &addr16[7]);
return snprintf(s, n, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
addr16[0], addr16[1], addr16[2], addr16[3], addr16[4], addr16[5],
addr16[6], addr16[7]);
}
/**
* BACnet/IP Datalink Receive handler.
*
* @param src - returns the source address
* @param npdu - returns the NPDU buffer
* @param max_npdu -maximum size of the NPDU buffer
* @param timeout - number of milliseconds to wait for a packet
*
* @return Number of bytes received, or 0 if none or timeout.
*/
uint16_t bip6_receive(
BACNET_ADDRESS *src, uint8_t *npdu, uint16_t max_npdu, unsigned timeout)
{
uint16_t npdu_len = 0; /* return value */
zsock_fd_set read_fds;
int max = 0;
struct zsock_timeval select_timeout;
struct sockaddr_in6 sin = { 0 };
BACNET_IP6_ADDRESS addr = { 0 };
socklen_t sin_len = sizeof(sin);
int received_bytes = 0;
int offset = 0;
uint16_t i = 0;
/* Make sure the socket is open */
if (BIP6_Socket < 0) {
return 0;
}
/* we could just use a non-blocking socket, but that consumes all
the CPU time. We can use a timeout; it is only supported as
a select. */
if (timeout >= 1000) {
select_timeout.tv_sec = timeout / 1000;
select_timeout.tv_usec =
1000 * (timeout - select_timeout.tv_sec * 1000);
} else {
select_timeout.tv_sec = 0;
select_timeout.tv_usec = 1000 * timeout;
}
ZSOCK_FD_ZERO(&read_fds);
ZSOCK_FD_SET(BIP6_Socket, &read_fds);
max = BIP6_Socket;
/* see if there is a packet for us */
if (zsock_select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
received_bytes = zsock_recvfrom(
BIP6_Socket, (char *)&npdu[0], max_npdu, 0, (struct sockaddr *)&sin,
&sin_len);
} else {
return 0;
}
/* See if there is a problem */
if (received_bytes < 0) {
LOG_WRN(
"%s:%d - RX zsock_recvfrom() error: %d", THIS_FILE, __LINE__,
received_bytes);
return 0;
}
/* no problem, just no bytes */
if (received_bytes == 0) {
return 0;
}
/* the signature of a BACnet/IPv6 packet */
if (npdu[0] != BVLL_TYPE_BACNET_IP6) {
LOG_DBG("BIP6: not a BACnet packet. Dropped.");
return 0;
}
/* pass the packet into the BBMD handler */
inet6_ntoa(&sin.sin6_addr);
LOG_DBG("BIP6: Received MPDU from %s", ipv6_addr_str);
bvlc6_address_set(
&addr, ntohs(sin.sin6_addr.s6_addr16[0]),
ntohs(sin.sin6_addr.s6_addr16[1]), ntohs(sin.sin6_addr.s6_addr16[2]),
ntohs(sin.sin6_addr.s6_addr16[3]), ntohs(sin.sin6_addr.s6_addr16[4]),
ntohs(sin.sin6_addr.s6_addr16[5]), ntohs(sin.sin6_addr.s6_addr16[6]),
ntohs(sin.sin6_addr.s6_addr16[7]));
addr.port = ntohs(sin.sin6_port);
offset = bvlc6_handler(&addr, src, npdu, received_bytes);
if (offset > 0) {
npdu_len = received_bytes - offset;
if (npdu_len <= max_npdu) {
/* shift the buffer to return a valid NPDU */
for (i = 0; i < npdu_len; i++) {
npdu[i] = npdu[offset + i];
}
} else {
LOG_WRN("%s:%d - NPDU dropped (too long)!", THIS_FILE, __LINE__);
npdu_len = 0;
}
}
return npdu_len;
}
/** Cleanup and close out the BACnet/IP services by closing the socket.
* @ingroup DLBIP6
*/
void bip6_cleanup(void)
{
LOG_DBG("bip6_cleanup();");
bvlc6_cleanup();
if (BIP6_Socket != -1) {
zsock_close(BIP6_Socket);
}
BIP6_Socket = -1;
}
/** Initialize the BACnet/IP services at the given interface.
* @ingroup DLBIP6
* -# Gets the local IP address and local broadcast address from the system,
* and saves it into the BACnet/IPv6 data structures.
* -# Opens a UDP socket
* -# Configures the socket for sending and receiving
* -# Configures the socket so it can send multicasts
* -# Binds the socket to the local IP address at the specified port for
* BACnet/IPv6 (by default, 0xBAC0 = 47808).
*
* @param ifname [in] The named interface to use for the network layer.
* If NULL, the "eth0" interface is assigned.
* @return True if the socket is successfully opened for BACnet/IP,
* else False if the socket functions fail.
*/
bool bip6_init(char *ifname)
{
int status = -1;
struct sockaddr_in6 server = { 0 };
struct in6_addr broadcast_address;
struct ipv6_mreq join_request;
const int sockopt = 1;
char addr6_str[40] = "";
LOG_DBG("bip6_init()");
if (BIP6_Addr.port == 0) {
bip6_set_port(0xBAC0U);
}
bip6_set_interface(ifname);
LOG_INF("BIP6: IPv6 UDP port: 0x%04X", (unsigned)BIP6_Addr.port);
bvlc6_snprintf_addr(addr6_str, sizeof(addr6_str), &BIP6_Addr);
LOG_INF("BIP6: IPv6 unicast addr: %s", addr6_str);
if (BIP6_Broadcast_Addr.address[0] == 0) {
bvlc6_address_set(
&BIP6_Broadcast_Addr, BIP6_MULTICAST_SITE_LOCAL, 0, 0, 0, 0, 0, 0,
BIP6_MULTICAST_GROUP_ID);
LOG_INF("BIP6: IPv6 MULTICAST_SITE_LOCAL");
}
bvlc6_snprintf_addr(addr6_str, sizeof(addr6_str), &BIP6_Broadcast_Addr);
LOG_INF("BIP6: IPv6 multicast addr: %s", addr6_str);
/* assumes that the driver has already been initialized */
BIP6_Socket = zsock_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (BIP6_Socket < 0) {
LOG_ERR("%s:%d - Failed to create socket", THIS_FILE, __LINE__);
return false;
} else {
LOG_INF("Socket created");
}
/* Allow us to use the same socket for sending and receiving */
/* This makes sure that the src port is correct when sending */
status = zsock_setsockopt(
BIP6_Socket, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
if (status < 0) {
LOG_ERR("BIP6: setsockopt(SO_REUSEADDR)");
}
/* allow us to send a broadcast */
status = zsock_setsockopt(
BIP6_Socket, SOL_SOCKET, SO_BROADCAST, &sockopt, sizeof(sockopt));
if (status < 0) {
/* ignored? For compatibility? Really? */
LOG_ERR("BIP6: setsockopt(SO_BROADCAST)");
}
/* subscribe to a multicast address */
memcpy(
&broadcast_address.s6_addr[0], &BIP6_Broadcast_Addr.address[0],
IP6_ADDRESS_MAX);
memcpy(
&join_request.ipv6mr_multiaddr, &broadcast_address,
sizeof(struct in6_addr));
/* Let system not choose the interface */
join_request.ipv6mr_ifindex = BIP6_Socket_Scope_Id;
status = setsockopt(
BIP6_Socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &join_request,
sizeof(join_request));
if (status < 0) {
LOG_ERR("BIP6: setsockopt(IPV6_ADD_MEMBERSHIP)");
return false;
}
/* bind the socket to the local port number and IP address */
server.sin6_family = AF_INET6;
#if 0
uint16_t addr16[8];
bvlc6_address_get(&BIP6_Addr, &addr16[0], &addr16[1], &addr16[2],
&addr16[3], &addr16[4], &addr16[5], &addr16[6], &addr16[7]);
server.sin6_addr.s6_addr16[0] = htons(addr16[0]);
server.sin6_addr.s6_addr16[1] = htons(addr16[1]);
server.sin6_addr.s6_addr16[2] = htons(addr16[2]);
server.sin6_addr.s6_addr16[3] = htons(addr16[3]);
server.sin6_addr.s6_addr16[4] = htons(addr16[4]);
server.sin6_addr.s6_addr16[5] = htons(addr16[5]);
server.sin6_addr.s6_addr16[6] = htons(addr16[6]);
server.sin6_addr.s6_addr16[7] = htons(addr16[7]);
#else
server.sin6_addr = in6addr_any;
#endif
server.sin6_port = htons(BIP6_Addr.port);
LOG_INF("BIP6: Binding to port %d", BIP6_Addr.port);
status =
zsock_bind(BIP6_Socket, (const struct sockaddr *)&server, sizeof(server));
if (status < 0) {
zsock_close(BIP6_Socket);
BIP6_Socket = -1;
LOG_ERR("%s:%d - zsock_bind() failure", THIS_FILE, __LINE__);
return false;
} else {
LOG_INF("BIP6: Socket bound. Success!");
}
bvlc6_init();
return true;
}
/**
* @brief Check if the BACnet/IPv6 socket is valid
* @return True if the socket is valid, else False
*/
bool bip6_valid(void)
{
return (BIP6_Socket != -1);
}
-40
View File
@@ -1,40 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2020 Steve Karg
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*
*********************************************************************/
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/datalink/bvlc.h"
/**
* @brief Encode the BVLC header
*
* @param pdu - buffer to store the encoding
* @param pdu_size - size of the buffer to store encoding
* @param message_type - BVLL Messages
* @param length - number of bytes for this message type
*
* @return number of bytes encoded
*/
void bvlc_file_bdt_write(
void *data,
size_t len)
{
/* TODO: Write BDT data blob into persistent storage */
}
size_t bvlc_file_bdt_read(
void *data,
size_t len)
{
size_t sz = -1;
/* TODO: Read BD data blob from persistent storage */
return sz;
}
-111
View File
@@ -1,111 +0,0 @@
/**
* @file
* @author Steve Karg
* @date 2009
* @brief System time library header file.
*
* @section DESCRIPTION
*
* This library provides functions for getting and setting the system time.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/datetime.h"
/* HACK:
* - Zephyr does not declare timezone in any header file.
* - The gcc-arm-none-eabi-7-2018-q2-update/bin/arm-none-eabi/lib/thumb/v7e-m/
* libc_nano.a 'time' symbol does not resolve '_gettimeofday'
*
* TODO: figure out how to link in the real time() and timezone;
*/
long timezone;
time_t time(time_t *tloc)
{
time_t time = { 0 };
return time;
}
/**
* @brief Get the date, time, timezone, and UTC offset from system
* @param utc_time - the BACnet Date and Time structure to hold UTC time
* @param local_time - the BACnet Date and Time structure to hold local time
* @param utc_offset_minutes - number of minutes offset from UTC
* For example, -6*60 represents 6.00 hours behind UTC/GMT
* @param true if DST is enabled and active
* @return true if local time was retrieved
*/
bool datetime_local(
BACNET_DATE * bdate,
BACNET_TIME * btime,
int16_t * utc_offset_minutes,
bool * dst_active)
{
bool status = false;
struct tm tblock_st = { 0 };
struct tm *tblock = &tblock_st;
struct timeval tv;
if (gettimeofday(&tv, NULL) == 0)
{
tblock = (struct tm *)localtime((const time_t *)&tv.tv_sec);
}
if (tblock) {
status = true;
/** struct tm
* int tm_sec Seconds [0,60].
* int tm_min Minutes [0,59].
* int tm_hour Hour [0,23].
* int tm_mday Day of month [1,31].
* int tm_mon Month of year [0,11].
* int tm_year Years since 1900.
* int tm_wday Day of week [0,6] (Sunday =0).
* int tm_yday Day of year [0,365].
* int tm_isdst Daylight Savings flag.
*/
datetime_set_date(bdate, (uint16_t)tblock->tm_year + 1900,
(uint8_t)tblock->tm_mon + 1,
(uint8_t)tblock->tm_mday);
datetime_set_time(btime, (uint8_t)tblock->tm_hour,
(uint8_t)tblock->tm_min, (uint8_t)tblock->tm_sec,
(uint8_t)(tv.tv_usec / 10000));
if (dst_active) {
/* The value of tm_isdst is:
- positive if Daylight Saving Time is in effect,
- 0 if Daylight Saving Time is not in effect, and
- negative if the information is not available. */
if (tblock->tm_isdst > 0) {
*dst_active = true;
} else {
*dst_active = false;
}
}
/* note: timezone is declared in <time.h> stdlib. */
if (utc_offset_minutes) {
/* timezone is set to the difference, in seconds,
between Coordinated Universal Time (UTC) and
local standard time */
*utc_offset_minutes = timezone / 60;
}
}
return status;
}
/**
* initialize the date time
*/
void datetime_init(void)
{
/* nothing to do */
}
-32
View File
@@ -1,32 +0,0 @@
/*
* Copyright (C) 2020 Legrand North America, Inc.
*
* SPDX-License-Identifier: MIT
*/
/* Standard includes */
#include <stdint.h>
/* Zephyr includes */
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>
#include <zephyr/kernel.h>
#define LOG_LEVEL CONFIG_BACNETSTACK_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bacnet);
/* To do: init()
static int init(struct device *unused)
{
ARG_UNUSED(unused);
return 0;
}
SYS_INIT(init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
*/
-30
View File
@@ -1,30 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
* Multimedia Timer contribution by Cameron Crothers, 2008
*
* SPDX-License-Identifier: MIT
*
*********************************************************************/
#include <zephyr/kernel.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/basic/sys/mstimer.h"
/**
* @brief returns the current millisecond count
* @return millisecond counter
*/
unsigned long mstimer_now(void)
{
return (unsigned long) k_uptime_get_32();
}
/**
* @brief Initialization for timer
*/
void mstimer_init(void)
{
}
-61
View File
@@ -1,61 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2004 Steve Karg
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*
*********************************************************************/
#ifndef RS485_H
#define RS485_H
#include <stdint.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/datalink/mstp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
BACNET_STACK_EXPORT
void RS485_Set_Interface(
char *ifname);
BACNET_STACK_EXPORT
const char *RS485_Interface(
void);
BACNET_STACK_EXPORT
void RS485_Initialize(
void);
BACNET_STACK_EXPORT
void RS485_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
const uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
uint16_t nbytes); /* number of bytes of data (up to 501) */
BACNET_STACK_EXPORT
void RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
BACNET_STACK_EXPORT
uint32_t RS485_Get_Port_Baud_Rate(
volatile struct mstp_port_struct_t *mstp_port);
BACNET_STACK_EXPORT
uint32_t RS485_Get_Baud_Rate(
void);
BACNET_STACK_EXPORT
bool RS485_Set_Baud_Rate(
uint32_t baud);
BACNET_STACK_EXPORT
void RS485_Cleanup(
void);
BACNET_STACK_EXPORT
void RS485_Print_Ports(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif