re-save line endings to LF for git
This commit is contained in:
+1228
-1228
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rdproperty", "rdproperty.vcproj", "{7AC60281-278A-4060-B900-A1343E438701}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7AC60281-278A-4060-B900-A1343E438701}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7AC60281-278A-4060-B900-A1343E438701}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7AC60281-278A-4060-B900-A1343E438701}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7AC60281-278A-4060-B900-A1343E438701}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rdproperty", "rdproperty.vcproj", "{7AC60281-278A-4060-B900-A1343E438701}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7AC60281-278A-4060-B900-A1343E438701}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7AC60281-278A-4060-B900-A1343E438701}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7AC60281-278A-4060-B900-A1343E438701}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7AC60281-278A-4060-B900-A1343E438701}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "readrange", "readrange.vcproj", "{6017A2EA-1296-4E67-995F-6344A3CC27C2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6017A2EA-1296-4E67-995F-6344A3CC27C2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6017A2EA-1296-4E67-995F-6344A3CC27C2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6017A2EA-1296-4E67-995F-6344A3CC27C2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6017A2EA-1296-4E67-995F-6344A3CC27C2}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "readrange", "readrange.vcproj", "{6017A2EA-1296-4E67-995F-6344A3CC27C2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6017A2EA-1296-4E67-995F-6344A3CC27C2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6017A2EA-1296-4E67-995F-6344A3CC27C2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6017A2EA-1296-4E67-995F-6344A3CC27C2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6017A2EA-1296-4E67-995F-6344A3CC27C2}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
+59
-59
@@ -1,59 +1,59 @@
|
||||
#Makefile to build BACnet Application for the GCC port
|
||||
|
||||
# tools - only if you need them.
|
||||
# Most platforms have this already defined
|
||||
# CC = gcc
|
||||
|
||||
# Executable file name
|
||||
TARGET = bacroute
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
CFLAGS += -DPRINT_ENABLED=1
|
||||
|
||||
BACNET_SOURCE_DIR = ../../src
|
||||
BACNET_HANDLER_DIR = ../handler
|
||||
BACNET_OBJECT_DIR = ../object
|
||||
|
||||
SRC = main.c \
|
||||
$(BACNET_OBJECT_DIR)/netport.c \
|
||||
$(BACNET_OBJECT_DIR)/device-client.c
|
||||
|
||||
PORT_BIP6_SRC = \
|
||||
$(BACNET_PORT_DIR)/bip6.c \
|
||||
$(BACNET_SOURCE_DIR)/bvlc6.c \
|
||||
$(BACNET_HANDLER_DIR)/h_bbmd6.c \
|
||||
$(BACNET_SOURCE_DIR)/vmac.c
|
||||
|
||||
PORT_BIP_SRC = \
|
||||
$(BACNET_PORT_DIR)/bip-init.c \
|
||||
$(BACNET_SOURCE_DIR)/bvlc.c \
|
||||
$(BACNET_SOURCE_DIR)/bip.c
|
||||
|
||||
SRCS = ${SRC} ${PORT_BIP6_SRC} ${PORT_BIP_SRC}
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
|
||||
|
||||
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
|
||||
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
|
||||
size $@
|
||||
cp $@ ../../bin
|
||||
|
||||
lib: ${BACNET_LIB_TARGET}
|
||||
|
||||
${BACNET_LIB_TARGET}:
|
||||
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $*.c -o $@
|
||||
|
||||
depend:
|
||||
rm -f .depend
|
||||
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||
|
||||
clean:
|
||||
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
|
||||
|
||||
include: .depend
|
||||
#Makefile to build BACnet Application for the GCC port
|
||||
|
||||
# tools - only if you need them.
|
||||
# Most platforms have this already defined
|
||||
# CC = gcc
|
||||
|
||||
# Executable file name
|
||||
TARGET = bacroute
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
CFLAGS += -DPRINT_ENABLED=1
|
||||
|
||||
BACNET_SOURCE_DIR = ../../src
|
||||
BACNET_HANDLER_DIR = ../handler
|
||||
BACNET_OBJECT_DIR = ../object
|
||||
|
||||
SRC = main.c \
|
||||
$(BACNET_OBJECT_DIR)/netport.c \
|
||||
$(BACNET_OBJECT_DIR)/device-client.c
|
||||
|
||||
PORT_BIP6_SRC = \
|
||||
$(BACNET_PORT_DIR)/bip6.c \
|
||||
$(BACNET_SOURCE_DIR)/bvlc6.c \
|
||||
$(BACNET_HANDLER_DIR)/h_bbmd6.c \
|
||||
$(BACNET_SOURCE_DIR)/vmac.c
|
||||
|
||||
PORT_BIP_SRC = \
|
||||
$(BACNET_PORT_DIR)/bip-init.c \
|
||||
$(BACNET_SOURCE_DIR)/bvlc.c \
|
||||
$(BACNET_SOURCE_DIR)/bip.c
|
||||
|
||||
SRCS = ${SRC} ${PORT_BIP6_SRC} ${PORT_BIP_SRC}
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
|
||||
|
||||
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
|
||||
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
|
||||
size $@
|
||||
cp $@ ../../bin
|
||||
|
||||
lib: ${BACNET_LIB_TARGET}
|
||||
|
||||
${BACNET_LIB_TARGET}:
|
||||
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $*.c -o $@
|
||||
|
||||
depend:
|
||||
rm -f .depend
|
||||
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||
|
||||
clean:
|
||||
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
|
||||
|
||||
include: .depend
|
||||
|
||||
+1253
-1253
File diff suppressed because it is too large
Load Diff
+40
-40
@@ -1,40 +1,40 @@
|
||||
#Makefile to build BACnet Application for the Linux Port
|
||||
|
||||
# tools - only if you need them.
|
||||
# Most platforms have this already defined
|
||||
# CC = gcc
|
||||
|
||||
# Executable file name
|
||||
TARGET = bacwpm
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c \
|
||||
../object/netport.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
|
||||
|
||||
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
|
||||
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
|
||||
size $@
|
||||
cp $@ ../../bin
|
||||
|
||||
lib: ${BACNET_LIB_TARGET}
|
||||
|
||||
${BACNET_LIB_TARGET}:
|
||||
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $*.c -o $@
|
||||
|
||||
depend:
|
||||
rm -f .depend
|
||||
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||
|
||||
clean:
|
||||
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
|
||||
|
||||
include: .depend
|
||||
#Makefile to build BACnet Application for the Linux Port
|
||||
|
||||
# tools - only if you need them.
|
||||
# Most platforms have this already defined
|
||||
# CC = gcc
|
||||
|
||||
# Executable file name
|
||||
TARGET = bacwpm
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c \
|
||||
../object/netport.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
|
||||
|
||||
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
|
||||
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
|
||||
size $@
|
||||
cp $@ ../../bin
|
||||
|
||||
lib: ${BACNET_LIB_TARGET}
|
||||
|
||||
${BACNET_LIB_TARGET}:
|
||||
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $*.c -o $@
|
||||
|
||||
depend:
|
||||
rm -f .depend
|
||||
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||
|
||||
clean:
|
||||
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
|
||||
|
||||
include: .depend
|
||||
|
||||
+522
-522
File diff suppressed because it is too large
Load Diff
+87
-87
@@ -1,87 +1,87 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Steve Karg
|
||||
* @date 2015
|
||||
* @defgroup DLBIP6 BACnet/IPv6 DataLink Network Layer
|
||||
* @ingroup DataLink
|
||||
*
|
||||
* Implementation of the Network Layer using BACnet/IPv6 as the transport, as
|
||||
* described in Annex J.
|
||||
* The functions described here fulfill the roles defined generically at the
|
||||
* DataLink level by serving as the implementation of the function templates.
|
||||
*/
|
||||
#ifndef BIP6_H
|
||||
#define BIP6_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "bacdef.h"
|
||||
#include "npdu.h"
|
||||
#include "bvlc6.h"
|
||||
|
||||
/* specific defines for BACnet/IP over Ethernet */
|
||||
#define BIP6_HEADER_MAX (1 + 1 + 2)
|
||||
#define BIP6_MPDU_MAX (BIP6_HEADER_MAX+MAX_PDU)
|
||||
/* for legacy demo applications */
|
||||
#define MAX_MPDU BIP6_MPDU_MAX
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* 6 datalink functions used by demo handlers and applications:
|
||||
init, send, receive, cleanup, unicast/broadcast address.
|
||||
Note: the addresses used here are VMAC addresses. */
|
||||
bool bip6_init(
|
||||
char *ifname);
|
||||
void bip6_cleanup(
|
||||
void);
|
||||
void bip6_get_broadcast_address(
|
||||
BACNET_ADDRESS * my_address);
|
||||
void bip6_get_my_address(
|
||||
BACNET_ADDRESS * my_address);
|
||||
int bip6_send_pdu(
|
||||
BACNET_ADDRESS * dest,
|
||||
BACNET_NPDU_DATA * npdu_data,
|
||||
uint8_t * pdu,
|
||||
unsigned pdu_len);
|
||||
uint16_t bip6_receive(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * pdu,
|
||||
uint16_t max_pdu,
|
||||
unsigned timeout);
|
||||
|
||||
/* functions that are custom per port */
|
||||
void bip6_set_interface(
|
||||
char *ifname);
|
||||
|
||||
bool bip6_address_match_self(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
|
||||
bool bip6_set_addr(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
bool bip6_get_addr(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
|
||||
void bip6_set_port(
|
||||
uint16_t port);
|
||||
uint16_t bip6_get_port(
|
||||
void);
|
||||
|
||||
bool bip6_set_broadcast_addr(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
/* returns network byte order */
|
||||
bool bip6_get_broadcast_addr(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
|
||||
int bip6_send_mpdu(
|
||||
BACNET_IP6_ADDRESS *addr,
|
||||
uint8_t * mtu,
|
||||
uint16_t mtu_len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @author Steve Karg
|
||||
* @date 2015
|
||||
* @defgroup DLBIP6 BACnet/IPv6 DataLink Network Layer
|
||||
* @ingroup DataLink
|
||||
*
|
||||
* Implementation of the Network Layer using BACnet/IPv6 as the transport, as
|
||||
* described in Annex J.
|
||||
* The functions described here fulfill the roles defined generically at the
|
||||
* DataLink level by serving as the implementation of the function templates.
|
||||
*/
|
||||
#ifndef BIP6_H
|
||||
#define BIP6_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "bacdef.h"
|
||||
#include "npdu.h"
|
||||
#include "bvlc6.h"
|
||||
|
||||
/* specific defines for BACnet/IP over Ethernet */
|
||||
#define BIP6_HEADER_MAX (1 + 1 + 2)
|
||||
#define BIP6_MPDU_MAX (BIP6_HEADER_MAX+MAX_PDU)
|
||||
/* for legacy demo applications */
|
||||
#define MAX_MPDU BIP6_MPDU_MAX
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* 6 datalink functions used by demo handlers and applications:
|
||||
init, send, receive, cleanup, unicast/broadcast address.
|
||||
Note: the addresses used here are VMAC addresses. */
|
||||
bool bip6_init(
|
||||
char *ifname);
|
||||
void bip6_cleanup(
|
||||
void);
|
||||
void bip6_get_broadcast_address(
|
||||
BACNET_ADDRESS * my_address);
|
||||
void bip6_get_my_address(
|
||||
BACNET_ADDRESS * my_address);
|
||||
int bip6_send_pdu(
|
||||
BACNET_ADDRESS * dest,
|
||||
BACNET_NPDU_DATA * npdu_data,
|
||||
uint8_t * pdu,
|
||||
unsigned pdu_len);
|
||||
uint16_t bip6_receive(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * pdu,
|
||||
uint16_t max_pdu,
|
||||
unsigned timeout);
|
||||
|
||||
/* functions that are custom per port */
|
||||
void bip6_set_interface(
|
||||
char *ifname);
|
||||
|
||||
bool bip6_address_match_self(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
|
||||
bool bip6_set_addr(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
bool bip6_get_addr(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
|
||||
void bip6_set_port(
|
||||
uint16_t port);
|
||||
uint16_t bip6_get_port(
|
||||
void);
|
||||
|
||||
bool bip6_set_broadcast_addr(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
/* returns network byte order */
|
||||
bool bip6_get_broadcast_addr(
|
||||
BACNET_IP6_ADDRESS *addr);
|
||||
|
||||
int bip6_send_mpdu(
|
||||
BACNET_IP6_ADDRESS *addr,
|
||||
uint8_t * mtu,
|
||||
uint16_t mtu_len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
+403
-403
@@ -1,403 +1,403 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Steve Karg
|
||||
* @date 2015
|
||||
*
|
||||
* Implementation of the BACnet Virtual Link Layer using IPv6,
|
||||
* as described in Annex J.
|
||||
*/
|
||||
#ifndef BVLC6_H
|
||||
#define BVLC6_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
#include "bacdef.h"
|
||||
#include "npdu.h"
|
||||
|
||||
/**
|
||||
* BVLL for BACnet/IPv6
|
||||
* @{
|
||||
*/
|
||||
#define BVLL_TYPE_BACNET_IP6 (0x82)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* B/IPv6 BVLL Messages
|
||||
* @{
|
||||
*/
|
||||
#define BVLC6_RESULT 0x00
|
||||
#define BVLC6_ORIGINAL_UNICAST_NPDU 0x01
|
||||
#define BVLC6_ORIGINAL_BROADCAST_NPDU 0x02
|
||||
#define BVLC6_ADDRESS_RESOLUTION 0x03
|
||||
#define BVLC6_FORWARDED_ADDRESS_RESOLUTION 0x04
|
||||
#define BVLC6_ADDRESS_RESOLUTION_ACK 0x05
|
||||
#define BVLC6_VIRTUAL_ADDRESS_RESOLUTION 0x06
|
||||
#define BVLC6_VIRTUAL_ADDRESS_RESOLUTION_ACK 0x07
|
||||
#define BVLC6_FORWARDED_NPDU 0x08
|
||||
#define BVLC6_REGISTER_FOREIGN_DEVICE 0x09
|
||||
#define BVLC6_DELETE_FOREIGN_DEVICE 0x0A
|
||||
#define BVLC6_SECURE_BVLL 0x0B
|
||||
#define BVLC6_DISTRIBUTE_BROADCAST_TO_NETWORK 0x0C
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* BVLC Result Code
|
||||
* @{
|
||||
*/
|
||||
#define BVLC6_RESULT_SUCCESSFUL_COMPLETION 0x0000
|
||||
#define BVLC6_RESULT_ADDRESS_RESOLUTION_NAK 0x0030
|
||||
#define BVLC6_RESULT_VIRTUAL_ADDRESS_RESOLUTION_NAK 0x0060
|
||||
#define BVLC6_RESULT_REGISTER_FOREIGN_DEVICE_NAK 0x0090
|
||||
#define BVLC6_RESULT_DELETE_FOREIGN_DEVICE_NAK 0x00A0
|
||||
#define BVLC6_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK 0x00C0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* BACnet IPv6 Multicast Group ID
|
||||
* BACnet broadcast messages shall be delivered by IPv6 multicasts
|
||||
* as opposed to using IP broadcasting. Broadcasting in
|
||||
* IPv6 is subsumed by multicasting to the all-nodes link
|
||||
* group FF02::1; however, the use of the all-nodes group is not
|
||||
* recommended, and BACnet/IPv6 uses an IANA permanently assigned
|
||||
* multicast group identifier to avoid disturbing
|
||||
* every interface in the network.
|
||||
*
|
||||
* The IANA assigned BACnet/IPv6 variable scope multicast address
|
||||
* is FF0X:0:0:0:0:0:0:BAC0 (FF0X::BAC0) which indicates the multicast
|
||||
* group identifier X'BAC0'. The following multicast scopes are
|
||||
* defined for B/IPv6.
|
||||
* @{
|
||||
*/
|
||||
#define BIP6_MULTICAST_GROUP_ID 0xBAC0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* IANA prefixes
|
||||
* @{
|
||||
*/
|
||||
#define BIP6_MULTICAST_reserved_0 0xFF00
|
||||
#define BIP6_MULTICAST_NODE_LOCAL 0xFF01
|
||||
#define BIP6_MULTICAST_LINK_LOCAL 0xFF02
|
||||
#define BIP6_MULTICAST_reserved_3 0xFF03
|
||||
#define BIP6_MULTICAST_ADMIN_LOCAL 0xFF04
|
||||
#define BIP6_MULTICAST_SITE_LOCAL 0xFF05
|
||||
#define BIP6_MULTICAST_ORG_LOCAL 0xFF08
|
||||
#define BIP6_MULTICAST_GLOBAL 0xFF0E
|
||||
/** @} */
|
||||
|
||||
/* number of bytes in the IPv6 address */
|
||||
#define IP6_ADDRESS_MAX 16
|
||||
/* number of bytes in the B/IPv6 address */
|
||||
#define BIP6_ADDRESS_MAX 18
|
||||
|
||||
/**
|
||||
* BACnet IPv6 Address
|
||||
*
|
||||
* Data link layer addressing between B/IPv6 nodes consists of a 128-bit
|
||||
* IPv6 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/IPv6 address.
|
||||
* @{
|
||||
*/
|
||||
typedef struct BACnet_IP6_Address {
|
||||
uint8_t address[IP6_ADDRESS_MAX];
|
||||
uint16_t port;
|
||||
} BACNET_IP6_ADDRESS;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* BACnet /IPv6 Broadcast Distribution Table Format
|
||||
*
|
||||
* The BDT shall consist of either the eighteen-octet B/IPv6 address
|
||||
* of the peer BBMD or the combination of the fully qualified
|
||||
* domain name service (DNS) entry and UDP port that resolves to
|
||||
* the B/IPv6 address of the peer BBMD. The Broadcast
|
||||
* Distribution Table shall not contain an entry for the BBMD in
|
||||
* which the BDT resides.
|
||||
* @{
|
||||
*/
|
||||
struct BACnet_IP6_Broadcast_Distribution_Table_Entry;
|
||||
typedef struct BACnet_IP6_Broadcast_Distribution_Table_Entry {
|
||||
/* true if valid entry - false if not */
|
||||
bool valid;
|
||||
/* BACnet/IPv6 address */
|
||||
BACNET_IP6_ADDRESS bip6_address;
|
||||
struct BACnet_IP6_Broadcast_Distribution_Table_Entry *next;
|
||||
} BACNET_IP6_BROADCAST_DISTRIBUTION_TABLE_ENTRY;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Foreign Device Table (FDT)
|
||||
*
|
||||
* Each entry shall contain the B/IPv6 address and the TTL of the
|
||||
* registered foreign device.
|
||||
*
|
||||
* Each entry shall consist of the eighteen-octet B/IPv6 address of the
|
||||
* registrant; the 2-octet Time-to-Live value supplied at the time of
|
||||
* registration; and a 2-octet value representing the number of seconds
|
||||
* remaining before the BBMD will purge the registrant's FDT entry if no
|
||||
* re-registration occurs. The number of seconds remaining shall be
|
||||
* initialized to the 2-octet Time-to-Live value supplied at the time
|
||||
* of registration plus 30 seconds (see U.4.5.2), with a maximum of 65535.
|
||||
* @{
|
||||
*/
|
||||
struct BACnet_IP6_Foreign_Device_Table_Entry;
|
||||
typedef struct BACnet_IP6_Foreign_Device_Table_Entry {
|
||||
/* true if valid entry - false if not */
|
||||
bool valid;
|
||||
/* BACnet/IPv6 address */
|
||||
BACNET_IP6_ADDRESS bip6_address;
|
||||
/* requested time-to-live value */
|
||||
uint16_t ttl_seconds;
|
||||
/* number of seconds remaining */
|
||||
uint16_t ttl_seconds_remaining;
|
||||
struct BACnet_IP6_Foreign_Device_Table_Entry *next;
|
||||
} BACNET_IP6_FOREIGN_DEVICE_TABLE_ENTRY;
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
#endif /* __cplusplus */
|
||||
int bvlc6_encode_address(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
BACNET_IP6_ADDRESS * ip6_address);
|
||||
int bvlc6_decode_address(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
BACNET_IP6_ADDRESS * ip6_address);
|
||||
bool bvlc6_address_copy(
|
||||
BACNET_IP6_ADDRESS * dst,
|
||||
BACNET_IP6_ADDRESS * src);
|
||||
bool bvlc6_address_different(
|
||||
BACNET_IP6_ADDRESS * dst,
|
||||
BACNET_IP6_ADDRESS * src);
|
||||
|
||||
bool bvlc6_address_set(
|
||||
BACNET_IP6_ADDRESS * addr,
|
||||
uint16_t addr0,
|
||||
uint16_t addr1,
|
||||
uint16_t addr2,
|
||||
uint16_t addr3,
|
||||
uint16_t addr4,
|
||||
uint16_t addr5,
|
||||
uint16_t addr6,
|
||||
uint16_t addr7);
|
||||
bool bvlc6_address_get(
|
||||
BACNET_IP6_ADDRESS * addr,
|
||||
uint16_t *addr0,
|
||||
uint16_t *addr1,
|
||||
uint16_t *addr2,
|
||||
uint16_t *addr3,
|
||||
uint16_t *addr4,
|
||||
uint16_t *addr5,
|
||||
uint16_t *addr6,
|
||||
uint16_t *addr7);
|
||||
|
||||
bool bvlc6_vmac_address_set(
|
||||
BACNET_ADDRESS * addr,
|
||||
uint32_t device_id);
|
||||
bool bvlc6_vmac_address_get(
|
||||
BACNET_ADDRESS * addr,
|
||||
uint32_t *device_id);
|
||||
|
||||
int bvlc6_encode_header(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint8_t message_type,
|
||||
uint16_t length);
|
||||
int bvlc6_decode_header(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint8_t * message_type,
|
||||
uint16_t * length);
|
||||
|
||||
int bvlc6_encode_result(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac,
|
||||
uint16_t result_code);
|
||||
int bvlc6_decode_result(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac,
|
||||
uint16_t * result_code);
|
||||
|
||||
int bvlc6_encode_original_unicast(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_dst,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_decode_original_unicast(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_dst,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_size,
|
||||
uint16_t * npdu_len);
|
||||
|
||||
int bvlc6_encode_original_broadcast(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_decode_original_broadcast(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_size,
|
||||
uint16_t * npdu_len);
|
||||
|
||||
int bvlc6_encode_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_target);
|
||||
int bvlc6_decode_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_target);
|
||||
|
||||
int bvlc6_encode_forwarded_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_target,
|
||||
BACNET_IP6_ADDRESS * bip6_address);
|
||||
int bvlc6_decode_forwarded_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_target,
|
||||
BACNET_IP6_ADDRESS * bip6_address);
|
||||
|
||||
int bvlc6_encode_address_resolution_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_dst);
|
||||
int bvlc6_decode_address_resolution_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_dst);
|
||||
|
||||
int bvlc6_encode_virtual_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src);
|
||||
int bvlc6_decode_virtual_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src);
|
||||
|
||||
int bvlc6_encode_virtual_address_resolution_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_dst);
|
||||
int bvlc6_decode_virtual_address_resolution_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_dst);
|
||||
|
||||
int bvlc6_encode_forwarded_npdu(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
BACNET_IP6_ADDRESS * address,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_decode_forwarded_npdu(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
BACNET_IP6_ADDRESS * address,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_size,
|
||||
uint16_t * npdu_len);
|
||||
|
||||
int bvlc6_encode_register_foreign_device(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint16_t ttl_seconds);
|
||||
int bvlc6_decode_register_foreign_device(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint16_t * ttl_seconds);
|
||||
|
||||
int bvlc6_encode_delete_foreign_device(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
BACNET_IP6_FOREIGN_DEVICE_TABLE_ENTRY * fdt_entry);
|
||||
int bvlc6_decode_delete_foreign_device(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
BACNET_IP6_FOREIGN_DEVICE_TABLE_ENTRY * fdt_entry);
|
||||
|
||||
int bvlc6_encode_secure_bvll(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint8_t * sbuf,
|
||||
uint16_t sbuf_len);
|
||||
int bvlc6_decode_secure_bvll(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint8_t * sbuf,
|
||||
uint16_t sbuf_size,
|
||||
uint16_t * sbuf_len);
|
||||
|
||||
int bvlc6_encode_distribute_broadcast_to_network(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_decode_distribute_broadcast_to_network(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_size,
|
||||
uint16_t * npdu_len);
|
||||
|
||||
/* user application function prototypes */
|
||||
int bvlc6_handler(
|
||||
BACNET_IP6_ADDRESS *addr,
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_register_with_bbmd(
|
||||
BACNET_IP6_ADDRESS *bbmd_addr,
|
||||
uint32_t vmac_src,
|
||||
uint16_t time_to_live_seconds);
|
||||
uint16_t bvlc6_get_last_result(
|
||||
void);
|
||||
uint8_t bvlc6_get_function_code(
|
||||
void);
|
||||
void bvlc6_init(void);
|
||||
|
||||
#ifdef TEST
|
||||
#include "ctest.h"
|
||||
void test_BVLC6(
|
||||
Test * pTest);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* */
|
||||
/**
|
||||
* @file
|
||||
* @author Steve Karg
|
||||
* @date 2015
|
||||
*
|
||||
* Implementation of the BACnet Virtual Link Layer using IPv6,
|
||||
* as described in Annex J.
|
||||
*/
|
||||
#ifndef BVLC6_H
|
||||
#define BVLC6_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
#include "bacdef.h"
|
||||
#include "npdu.h"
|
||||
|
||||
/**
|
||||
* BVLL for BACnet/IPv6
|
||||
* @{
|
||||
*/
|
||||
#define BVLL_TYPE_BACNET_IP6 (0x82)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* B/IPv6 BVLL Messages
|
||||
* @{
|
||||
*/
|
||||
#define BVLC6_RESULT 0x00
|
||||
#define BVLC6_ORIGINAL_UNICAST_NPDU 0x01
|
||||
#define BVLC6_ORIGINAL_BROADCAST_NPDU 0x02
|
||||
#define BVLC6_ADDRESS_RESOLUTION 0x03
|
||||
#define BVLC6_FORWARDED_ADDRESS_RESOLUTION 0x04
|
||||
#define BVLC6_ADDRESS_RESOLUTION_ACK 0x05
|
||||
#define BVLC6_VIRTUAL_ADDRESS_RESOLUTION 0x06
|
||||
#define BVLC6_VIRTUAL_ADDRESS_RESOLUTION_ACK 0x07
|
||||
#define BVLC6_FORWARDED_NPDU 0x08
|
||||
#define BVLC6_REGISTER_FOREIGN_DEVICE 0x09
|
||||
#define BVLC6_DELETE_FOREIGN_DEVICE 0x0A
|
||||
#define BVLC6_SECURE_BVLL 0x0B
|
||||
#define BVLC6_DISTRIBUTE_BROADCAST_TO_NETWORK 0x0C
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* BVLC Result Code
|
||||
* @{
|
||||
*/
|
||||
#define BVLC6_RESULT_SUCCESSFUL_COMPLETION 0x0000
|
||||
#define BVLC6_RESULT_ADDRESS_RESOLUTION_NAK 0x0030
|
||||
#define BVLC6_RESULT_VIRTUAL_ADDRESS_RESOLUTION_NAK 0x0060
|
||||
#define BVLC6_RESULT_REGISTER_FOREIGN_DEVICE_NAK 0x0090
|
||||
#define BVLC6_RESULT_DELETE_FOREIGN_DEVICE_NAK 0x00A0
|
||||
#define BVLC6_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK 0x00C0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* BACnet IPv6 Multicast Group ID
|
||||
* BACnet broadcast messages shall be delivered by IPv6 multicasts
|
||||
* as opposed to using IP broadcasting. Broadcasting in
|
||||
* IPv6 is subsumed by multicasting to the all-nodes link
|
||||
* group FF02::1; however, the use of the all-nodes group is not
|
||||
* recommended, and BACnet/IPv6 uses an IANA permanently assigned
|
||||
* multicast group identifier to avoid disturbing
|
||||
* every interface in the network.
|
||||
*
|
||||
* The IANA assigned BACnet/IPv6 variable scope multicast address
|
||||
* is FF0X:0:0:0:0:0:0:BAC0 (FF0X::BAC0) which indicates the multicast
|
||||
* group identifier X'BAC0'. The following multicast scopes are
|
||||
* defined for B/IPv6.
|
||||
* @{
|
||||
*/
|
||||
#define BIP6_MULTICAST_GROUP_ID 0xBAC0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* IANA prefixes
|
||||
* @{
|
||||
*/
|
||||
#define BIP6_MULTICAST_reserved_0 0xFF00
|
||||
#define BIP6_MULTICAST_NODE_LOCAL 0xFF01
|
||||
#define BIP6_MULTICAST_LINK_LOCAL 0xFF02
|
||||
#define BIP6_MULTICAST_reserved_3 0xFF03
|
||||
#define BIP6_MULTICAST_ADMIN_LOCAL 0xFF04
|
||||
#define BIP6_MULTICAST_SITE_LOCAL 0xFF05
|
||||
#define BIP6_MULTICAST_ORG_LOCAL 0xFF08
|
||||
#define BIP6_MULTICAST_GLOBAL 0xFF0E
|
||||
/** @} */
|
||||
|
||||
/* number of bytes in the IPv6 address */
|
||||
#define IP6_ADDRESS_MAX 16
|
||||
/* number of bytes in the B/IPv6 address */
|
||||
#define BIP6_ADDRESS_MAX 18
|
||||
|
||||
/**
|
||||
* BACnet IPv6 Address
|
||||
*
|
||||
* Data link layer addressing between B/IPv6 nodes consists of a 128-bit
|
||||
* IPv6 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/IPv6 address.
|
||||
* @{
|
||||
*/
|
||||
typedef struct BACnet_IP6_Address {
|
||||
uint8_t address[IP6_ADDRESS_MAX];
|
||||
uint16_t port;
|
||||
} BACNET_IP6_ADDRESS;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* BACnet /IPv6 Broadcast Distribution Table Format
|
||||
*
|
||||
* The BDT shall consist of either the eighteen-octet B/IPv6 address
|
||||
* of the peer BBMD or the combination of the fully qualified
|
||||
* domain name service (DNS) entry and UDP port that resolves to
|
||||
* the B/IPv6 address of the peer BBMD. The Broadcast
|
||||
* Distribution Table shall not contain an entry for the BBMD in
|
||||
* which the BDT resides.
|
||||
* @{
|
||||
*/
|
||||
struct BACnet_IP6_Broadcast_Distribution_Table_Entry;
|
||||
typedef struct BACnet_IP6_Broadcast_Distribution_Table_Entry {
|
||||
/* true if valid entry - false if not */
|
||||
bool valid;
|
||||
/* BACnet/IPv6 address */
|
||||
BACNET_IP6_ADDRESS bip6_address;
|
||||
struct BACnet_IP6_Broadcast_Distribution_Table_Entry *next;
|
||||
} BACNET_IP6_BROADCAST_DISTRIBUTION_TABLE_ENTRY;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Foreign Device Table (FDT)
|
||||
*
|
||||
* Each entry shall contain the B/IPv6 address and the TTL of the
|
||||
* registered foreign device.
|
||||
*
|
||||
* Each entry shall consist of the eighteen-octet B/IPv6 address of the
|
||||
* registrant; the 2-octet Time-to-Live value supplied at the time of
|
||||
* registration; and a 2-octet value representing the number of seconds
|
||||
* remaining before the BBMD will purge the registrant's FDT entry if no
|
||||
* re-registration occurs. The number of seconds remaining shall be
|
||||
* initialized to the 2-octet Time-to-Live value supplied at the time
|
||||
* of registration plus 30 seconds (see U.4.5.2), with a maximum of 65535.
|
||||
* @{
|
||||
*/
|
||||
struct BACnet_IP6_Foreign_Device_Table_Entry;
|
||||
typedef struct BACnet_IP6_Foreign_Device_Table_Entry {
|
||||
/* true if valid entry - false if not */
|
||||
bool valid;
|
||||
/* BACnet/IPv6 address */
|
||||
BACNET_IP6_ADDRESS bip6_address;
|
||||
/* requested time-to-live value */
|
||||
uint16_t ttl_seconds;
|
||||
/* number of seconds remaining */
|
||||
uint16_t ttl_seconds_remaining;
|
||||
struct BACnet_IP6_Foreign_Device_Table_Entry *next;
|
||||
} BACNET_IP6_FOREIGN_DEVICE_TABLE_ENTRY;
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
#endif /* __cplusplus */
|
||||
int bvlc6_encode_address(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
BACNET_IP6_ADDRESS * ip6_address);
|
||||
int bvlc6_decode_address(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
BACNET_IP6_ADDRESS * ip6_address);
|
||||
bool bvlc6_address_copy(
|
||||
BACNET_IP6_ADDRESS * dst,
|
||||
BACNET_IP6_ADDRESS * src);
|
||||
bool bvlc6_address_different(
|
||||
BACNET_IP6_ADDRESS * dst,
|
||||
BACNET_IP6_ADDRESS * src);
|
||||
|
||||
bool bvlc6_address_set(
|
||||
BACNET_IP6_ADDRESS * addr,
|
||||
uint16_t addr0,
|
||||
uint16_t addr1,
|
||||
uint16_t addr2,
|
||||
uint16_t addr3,
|
||||
uint16_t addr4,
|
||||
uint16_t addr5,
|
||||
uint16_t addr6,
|
||||
uint16_t addr7);
|
||||
bool bvlc6_address_get(
|
||||
BACNET_IP6_ADDRESS * addr,
|
||||
uint16_t *addr0,
|
||||
uint16_t *addr1,
|
||||
uint16_t *addr2,
|
||||
uint16_t *addr3,
|
||||
uint16_t *addr4,
|
||||
uint16_t *addr5,
|
||||
uint16_t *addr6,
|
||||
uint16_t *addr7);
|
||||
|
||||
bool bvlc6_vmac_address_set(
|
||||
BACNET_ADDRESS * addr,
|
||||
uint32_t device_id);
|
||||
bool bvlc6_vmac_address_get(
|
||||
BACNET_ADDRESS * addr,
|
||||
uint32_t *device_id);
|
||||
|
||||
int bvlc6_encode_header(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint8_t message_type,
|
||||
uint16_t length);
|
||||
int bvlc6_decode_header(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint8_t * message_type,
|
||||
uint16_t * length);
|
||||
|
||||
int bvlc6_encode_result(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac,
|
||||
uint16_t result_code);
|
||||
int bvlc6_decode_result(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac,
|
||||
uint16_t * result_code);
|
||||
|
||||
int bvlc6_encode_original_unicast(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_dst,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_decode_original_unicast(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_dst,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_size,
|
||||
uint16_t * npdu_len);
|
||||
|
||||
int bvlc6_encode_original_broadcast(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_decode_original_broadcast(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_size,
|
||||
uint16_t * npdu_len);
|
||||
|
||||
int bvlc6_encode_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_target);
|
||||
int bvlc6_decode_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_target);
|
||||
|
||||
int bvlc6_encode_forwarded_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_target,
|
||||
BACNET_IP6_ADDRESS * bip6_address);
|
||||
int bvlc6_decode_forwarded_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_target,
|
||||
BACNET_IP6_ADDRESS * bip6_address);
|
||||
|
||||
int bvlc6_encode_address_resolution_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_dst);
|
||||
int bvlc6_decode_address_resolution_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_dst);
|
||||
|
||||
int bvlc6_encode_virtual_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src);
|
||||
int bvlc6_decode_virtual_address_resolution(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src);
|
||||
|
||||
int bvlc6_encode_virtual_address_resolution_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint32_t vmac_dst);
|
||||
int bvlc6_decode_virtual_address_resolution_ack(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint32_t * vmac_dst);
|
||||
|
||||
int bvlc6_encode_forwarded_npdu(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
BACNET_IP6_ADDRESS * address,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_decode_forwarded_npdu(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
BACNET_IP6_ADDRESS * address,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_size,
|
||||
uint16_t * npdu_len);
|
||||
|
||||
int bvlc6_encode_register_foreign_device(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
uint16_t ttl_seconds);
|
||||
int bvlc6_decode_register_foreign_device(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
uint16_t * ttl_seconds);
|
||||
|
||||
int bvlc6_encode_delete_foreign_device(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac_src,
|
||||
BACNET_IP6_FOREIGN_DEVICE_TABLE_ENTRY * fdt_entry);
|
||||
int bvlc6_decode_delete_foreign_device(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac_src,
|
||||
BACNET_IP6_FOREIGN_DEVICE_TABLE_ENTRY * fdt_entry);
|
||||
|
||||
int bvlc6_encode_secure_bvll(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint8_t * sbuf,
|
||||
uint16_t sbuf_len);
|
||||
int bvlc6_decode_secure_bvll(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint8_t * sbuf,
|
||||
uint16_t sbuf_size,
|
||||
uint16_t * sbuf_len);
|
||||
|
||||
int bvlc6_encode_distribute_broadcast_to_network(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_size,
|
||||
uint32_t vmac,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_decode_distribute_broadcast_to_network(
|
||||
uint8_t * pdu,
|
||||
uint16_t pdu_len,
|
||||
uint32_t * vmac,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_size,
|
||||
uint16_t * npdu_len);
|
||||
|
||||
/* user application function prototypes */
|
||||
int bvlc6_handler(
|
||||
BACNET_IP6_ADDRESS *addr,
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * npdu,
|
||||
uint16_t npdu_len);
|
||||
int bvlc6_register_with_bbmd(
|
||||
BACNET_IP6_ADDRESS *bbmd_addr,
|
||||
uint32_t vmac_src,
|
||||
uint16_t time_to_live_seconds);
|
||||
uint16_t bvlc6_get_last_result(
|
||||
void);
|
||||
uint8_t bvlc6_get_function_code(
|
||||
void);
|
||||
void bvlc6_init(void);
|
||||
|
||||
#ifdef TEST
|
||||
#include "ctest.h"
|
||||
void test_BVLC6(
|
||||
Test * pTest);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* */
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Steve Karg
|
||||
* @date 2016
|
||||
*/
|
||||
#ifndef VMAC_H
|
||||
#define VMAC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* define the max MAC as big as IPv6 + port number */
|
||||
#define VMAC_MAC_MAX 18
|
||||
/**
|
||||
* VMAC data structure
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
struct vmac_data {
|
||||
uint8_t mac[18];
|
||||
uint8_t mac_len;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
unsigned int VMAC_Count(void);
|
||||
struct vmac_data *VMAC_Find_By_Key(uint32_t device_id);
|
||||
bool VMAC_Find_By_Data(struct vmac_data *vmac, uint32_t *device_id);
|
||||
bool VMAC_Add(uint32_t device_id, struct vmac_data *pVMAC);
|
||||
bool VMAC_Delete(uint32_t device_id);
|
||||
bool VMAC_Different(
|
||||
struct vmac_data *vmac1,
|
||||
struct vmac_data *vmac2);
|
||||
bool VMAC_Match(
|
||||
struct vmac_data *vmac1,
|
||||
struct vmac_data *vmac2);
|
||||
void VMAC_Cleanup(void);
|
||||
void VMAC_Init(void);
|
||||
|
||||
#ifdef TEST
|
||||
#include "ctest.h"
|
||||
void testVMAC(
|
||||
Test * pTest);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @author Steve Karg
|
||||
* @date 2016
|
||||
*/
|
||||
#ifndef VMAC_H
|
||||
#define VMAC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* define the max MAC as big as IPv6 + port number */
|
||||
#define VMAC_MAC_MAX 18
|
||||
/**
|
||||
* VMAC data structure
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
struct vmac_data {
|
||||
uint8_t mac[18];
|
||||
uint8_t mac_len;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
unsigned int VMAC_Count(void);
|
||||
struct vmac_data *VMAC_Find_By_Key(uint32_t device_id);
|
||||
bool VMAC_Find_By_Data(struct vmac_data *vmac, uint32_t *device_id);
|
||||
bool VMAC_Add(uint32_t device_id, struct vmac_data *pVMAC);
|
||||
bool VMAC_Delete(uint32_t device_id);
|
||||
bool VMAC_Different(
|
||||
struct vmac_data *vmac1,
|
||||
struct vmac_data *vmac2);
|
||||
bool VMAC_Match(
|
||||
struct vmac_data *vmac1,
|
||||
struct vmac_data *vmac2);
|
||||
void VMAC_Cleanup(void);
|
||||
void VMAC_Init(void);
|
||||
|
||||
#ifdef TEST
|
||||
#include "ctest.h"
|
||||
void testVMAC(
|
||||
Test * pTest);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
+117
-117
@@ -1,117 +1,117 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
#ifndef BIP_H
|
||||
#define BIP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "bacdef.h"
|
||||
#include "npdu.h"
|
||||
|
||||
/* specific defines for BACnet/IP over Ethernet */
|
||||
#define MAX_HEADER (1 + 1 + 2)
|
||||
#define MAX_MPDU (MAX_HEADER+MAX_PDU)
|
||||
|
||||
#define BVLL_TYPE_BACNET_IP (0x81)
|
||||
|
||||
extern bool BIP_Debug;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* note: define init, set_interface, and cleanup in your port */
|
||||
/* on Linux, ifname is eth0, ath0, arc0, and others.
|
||||
on Windows, ifname is the dotted ip address of the interface */
|
||||
bool bip_init(char *ifname);
|
||||
void bip_set_interface(char *ifname);
|
||||
void bip_cleanup(void);
|
||||
|
||||
/* Convert uint8_t IPv4 to uint32 */
|
||||
uint32_t convertBIP_Address2uint32(uint8_t * bip_address);
|
||||
void convertUint32Address_2_uint8Address(uint32_t ip,
|
||||
uint8_t * address);
|
||||
/* common BACnet/IP functions */
|
||||
void bip_set_socket(uint8_t sock_fd);
|
||||
uint8_t bip_socket(void);
|
||||
bool bip_valid(void);
|
||||
void bip_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */
|
||||
void bip_get_my_address(BACNET_ADDRESS * my_address);
|
||||
|
||||
/* function to send a packet out the BACnet/IP socket */
|
||||
/* returns zero on success, non-zero on failure */
|
||||
int bip_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 a BACnet/IP packet */
|
||||
/* returns the number of octets in the PDU, or zero on failure */
|
||||
uint16_t bip_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 */
|
||||
|
||||
/* use network byte order for setting */
|
||||
void bip_set_port(uint16_t port);
|
||||
/* returns network byte order */
|
||||
uint16_t bip_get_port(void);
|
||||
|
||||
/* use network byte order for setting */
|
||||
void bip_set_addr(uint8_t * net_address);
|
||||
/* returns network byte order */
|
||||
uint8_t *bip_get_addr(void);
|
||||
|
||||
/* use network byte order for setting */
|
||||
void bip_set_broadcast_addr(uint8_t * net_address);
|
||||
/* returns network byte order */
|
||||
uint8_t *bip_get_broadcast_addr(void);
|
||||
|
||||
/* gets an IP address by name, where name can be a
|
||||
string that is an IP address in dotted form, or
|
||||
a name that is a domain name
|
||||
returns 0 if not found, or
|
||||
an IP address in network byte order */
|
||||
long bip_getaddrbyname(const char *host_name);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
/** @defgroup DLBIP BACnet/IP DataLink Network Layer
|
||||
* @ingroup DataLink
|
||||
* Implementation of the Network Layer using BACnet/IP as the transport, as
|
||||
* described in Annex J.
|
||||
* The functions described here fulfill the roles defined generically at the
|
||||
* DataLink level by serving as the implementation of the function templates.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
#ifndef BIP_H
|
||||
#define BIP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "bacdef.h"
|
||||
#include "npdu.h"
|
||||
|
||||
/* specific defines for BACnet/IP over Ethernet */
|
||||
#define MAX_HEADER (1 + 1 + 2)
|
||||
#define MAX_MPDU (MAX_HEADER+MAX_PDU)
|
||||
|
||||
#define BVLL_TYPE_BACNET_IP (0x81)
|
||||
|
||||
extern bool BIP_Debug;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* note: define init, set_interface, and cleanup in your port */
|
||||
/* on Linux, ifname is eth0, ath0, arc0, and others.
|
||||
on Windows, ifname is the dotted ip address of the interface */
|
||||
bool bip_init(char *ifname);
|
||||
void bip_set_interface(char *ifname);
|
||||
void bip_cleanup(void);
|
||||
|
||||
/* Convert uint8_t IPv4 to uint32 */
|
||||
uint32_t convertBIP_Address2uint32(uint8_t * bip_address);
|
||||
void convertUint32Address_2_uint8Address(uint32_t ip,
|
||||
uint8_t * address);
|
||||
/* common BACnet/IP functions */
|
||||
void bip_set_socket(uint8_t sock_fd);
|
||||
uint8_t bip_socket(void);
|
||||
bool bip_valid(void);
|
||||
void bip_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */
|
||||
void bip_get_my_address(BACNET_ADDRESS * my_address);
|
||||
|
||||
/* function to send a packet out the BACnet/IP socket */
|
||||
/* returns zero on success, non-zero on failure */
|
||||
int bip_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 a BACnet/IP packet */
|
||||
/* returns the number of octets in the PDU, or zero on failure */
|
||||
uint16_t bip_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 */
|
||||
|
||||
/* use network byte order for setting */
|
||||
void bip_set_port(uint16_t port);
|
||||
/* returns network byte order */
|
||||
uint16_t bip_get_port(void);
|
||||
|
||||
/* use network byte order for setting */
|
||||
void bip_set_addr(uint8_t * net_address);
|
||||
/* returns network byte order */
|
||||
uint8_t *bip_get_addr(void);
|
||||
|
||||
/* use network byte order for setting */
|
||||
void bip_set_broadcast_addr(uint8_t * net_address);
|
||||
/* returns network byte order */
|
||||
uint8_t *bip_get_broadcast_addr(void);
|
||||
|
||||
/* gets an IP address by name, where name can be a
|
||||
string that is an IP address in dotted form, or
|
||||
a name that is a domain name
|
||||
returns 0 if not found, or
|
||||
an IP address in network byte order */
|
||||
long bip_getaddrbyname(const char *host_name);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
/** @defgroup DLBIP BACnet/IP DataLink Network Layer
|
||||
* @ingroup DataLink
|
||||
* Implementation of the Network Layer using BACnet/IP as the transport, as
|
||||
* described in Annex J.
|
||||
* The functions described here fulfill the roles defined generically at the
|
||||
* DataLink level by serving as the implementation of the function templates.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+460
-460
@@ -1,460 +1,460 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacstr.h"
|
||||
#include "bacenum.h"
|
||||
#include "apdu.h"
|
||||
#include "dcc.h"
|
||||
#include "dlmstp.h"
|
||||
#include "version.h"
|
||||
|
||||
/* objects */
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
#include "bv.h"
|
||||
#include "wp.h"
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
The properties that are constant can be hard coded
|
||||
into the read-property encoding. */
|
||||
static uint32_t Object_Instance_Number = 260001;
|
||||
static char Object_Name[20] = "My Device";
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
|
||||
void Device_Init(void)
|
||||
{
|
||||
/* Reinitialize_State = BACNET_REINIT_IDLE; */
|
||||
/* dcc_set_status_duration(COMMUNICATION_ENABLE, 0); */
|
||||
/* FIXME: Get the data from the eeprom */
|
||||
/* I2C_Read_Block(EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&Object_Instance_Number,
|
||||
sizeof(Object_Instance_Number),
|
||||
EEPROM_BACNET_ID_ADDR); */
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
if (object_id <= BACNET_MAX_INSTANCE) {
|
||||
Object_Instance_Number = object_id;
|
||||
/* FIXME: Write the data to the eeprom */
|
||||
/* I2C_Write_Block(
|
||||
EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&Object_Instance_Number,
|
||||
sizeof(Object_Instance_Number),
|
||||
EEPROM_BACNET_ID_ADDR); */
|
||||
} else
|
||||
status = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return ((Object_Instance_Number == object_id) ||
|
||||
(object_id == BACNET_MAX_INSTANCE));
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
|
||||
/* FIXME: add objects as needed */
|
||||
count += Analog_Value_Count();
|
||||
count += Binary_Value_Count();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(uint32_t array_index,
|
||||
int *object_type,
|
||||
uint32_t * instance)
|
||||
{
|
||||
bool status = false;
|
||||
uint32_t object_index = 0;
|
||||
uint32_t object_count = 0;
|
||||
|
||||
/* device object */
|
||||
if (array_index == 1) {
|
||||
*object_type = OBJECT_DEVICE;
|
||||
*instance = Object_Instance_Number;
|
||||
status = true;
|
||||
}
|
||||
/* normalize the index since
|
||||
we know it is not the previous objects */
|
||||
/* array index starts at 1 */
|
||||
object_index = array_index - 1;
|
||||
/* 1 for the device object */
|
||||
object_count = 1;
|
||||
/* FIXME: add objects as needed */
|
||||
/* analog value objects */
|
||||
if (!status) {
|
||||
/* array index starts at 1, and 1 for the device object */
|
||||
object_index -= object_count;
|
||||
object_count = Analog_Value_Count();
|
||||
if (object_index < object_count) {
|
||||
*object_type = OBJECT_ANALOG_VALUE;
|
||||
*instance = Analog_Value_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
/* binary value objects */
|
||||
if (!status) {
|
||||
object_index -= object_count;
|
||||
object_count = Binary_Value_Count();
|
||||
/* is it a valid index for this object? */
|
||||
if (object_index < object_count) {
|
||||
*object_type = OBJECT_BINARY_VALUE;
|
||||
*instance = Binary_Value_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error */
|
||||
int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID property,
|
||||
uint32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint32_t i = 0;
|
||||
int object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
uint32_t count = 0;
|
||||
|
||||
//object_instance = object_instance;
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string, Object_Name);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], System_Status);
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, "GNU Demo");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, BACNET_VERSION_TEXT);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string, "1.0");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], BACNET_PROTOCOL_VERSION);
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
BACNET_PROTOCOL_REVISION);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
|
||||
/* Note: this is the list of objects that can be in this device,
|
||||
not a list of objects that this device can access */
|
||||
bitstring_init(&bit_string);
|
||||
/* must have the bit string as big as it can be */
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_OBJECT_LIST:
|
||||
count = Device_Object_List_Count();
|
||||
/* Array element zero is the number of objects in the list */
|
||||
if (array_index == 0)
|
||||
apdu_len = encode_application_unsigned(&apdu[0], count);
|
||||
/* if no index was specified, then try to encode the entire list */
|
||||
/* into one packet. Note that more than likely you will have */
|
||||
/* to return an error if the number of encoded objects exceeds */
|
||||
/* your maximum APDU size. */
|
||||
else if (array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
Device_Object_List_Identifier(i, &object_type, &instance);
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
if ((apdu_len + len) >= MAX_APDU) {
|
||||
/* Abort response */
|
||||
*error_code =
|
||||
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
|
||||
apdu_len = BACNET_STATUS_ABORT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_MAX_APDU_LENGTH_ACCEPTED:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], SEGMENTATION_NONE);
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 60000);
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
// case PROP_MAX_INFO_FRAMES:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0],
|
||||
// dlmstp_max_info_frames());
|
||||
// break;
|
||||
// case PROP_MAX_MASTER:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
||||
// break;
|
||||
// case 9600:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
|
||||
// break;
|
||||
// case 512:
|
||||
// apdu_len = encode_application_unsigned(&apdu[0], stack_size());
|
||||
// break;
|
||||
// case 513:
|
||||
// apdu_len = encode_application_unsigned(&apdu[0], stack_unused());
|
||||
// break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
/* only array properties can have array options */
|
||||
if ((apdu_len >= 0) && (property != PROP_OBJECT_LIST) &&
|
||||
(array_index != BACNET_ARRAY_ALL)) {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) {
|
||||
*error_class = ERROR_CLASS_OBJECT;
|
||||
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
/* FIXME: len < application_data_len: more data? */
|
||||
if (len < 0) {
|
||||
/* error while decoding - a value larger than we can handle */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
return false;
|
||||
}
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.Object_Id.
|
||||
instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
// case PROP_MAX_INFO_FRAMES:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if (value.type.Unsigned_Int <= 255) {
|
||||
// dlmstp_set_max_info_frames(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
// case PROP_MAX_MASTER:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if ((value.type.Unsigned_Int > 0) &&
|
||||
// (value.type.Unsigned_Int <= 127)) {
|
||||
// dlmstp_set_max_master(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
case PROP_OBJECT_NAME:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
|
||||
uint8_t encoding;
|
||||
|
||||
encoding =
|
||||
characterstring_encoding(&value.type.Character_String);
|
||||
if (encoding == CHARACTER_ANSI_X34) {
|
||||
if (characterstring_ansi_copy(&Object_Name[0],
|
||||
sizeof(Object_Name),
|
||||
&value.type.Character_String)) {
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
// case 9600:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if (value.type.Unsigned_Int > 115200) {
|
||||
// RS485_Set_Baud_Rate(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacstr.h"
|
||||
#include "bacenum.h"
|
||||
#include "apdu.h"
|
||||
#include "dcc.h"
|
||||
#include "dlmstp.h"
|
||||
#include "version.h"
|
||||
|
||||
/* objects */
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
#include "bv.h"
|
||||
#include "wp.h"
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
The properties that are constant can be hard coded
|
||||
into the read-property encoding. */
|
||||
static uint32_t Object_Instance_Number = 260001;
|
||||
static char Object_Name[20] = "My Device";
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
|
||||
void Device_Init(void)
|
||||
{
|
||||
/* Reinitialize_State = BACNET_REINIT_IDLE; */
|
||||
/* dcc_set_status_duration(COMMUNICATION_ENABLE, 0); */
|
||||
/* FIXME: Get the data from the eeprom */
|
||||
/* I2C_Read_Block(EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&Object_Instance_Number,
|
||||
sizeof(Object_Instance_Number),
|
||||
EEPROM_BACNET_ID_ADDR); */
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
if (object_id <= BACNET_MAX_INSTANCE) {
|
||||
Object_Instance_Number = object_id;
|
||||
/* FIXME: Write the data to the eeprom */
|
||||
/* I2C_Write_Block(
|
||||
EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&Object_Instance_Number,
|
||||
sizeof(Object_Instance_Number),
|
||||
EEPROM_BACNET_ID_ADDR); */
|
||||
} else
|
||||
status = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return ((Object_Instance_Number == object_id) ||
|
||||
(object_id == BACNET_MAX_INSTANCE));
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
|
||||
/* FIXME: add objects as needed */
|
||||
count += Analog_Value_Count();
|
||||
count += Binary_Value_Count();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(uint32_t array_index,
|
||||
int *object_type,
|
||||
uint32_t * instance)
|
||||
{
|
||||
bool status = false;
|
||||
uint32_t object_index = 0;
|
||||
uint32_t object_count = 0;
|
||||
|
||||
/* device object */
|
||||
if (array_index == 1) {
|
||||
*object_type = OBJECT_DEVICE;
|
||||
*instance = Object_Instance_Number;
|
||||
status = true;
|
||||
}
|
||||
/* normalize the index since
|
||||
we know it is not the previous objects */
|
||||
/* array index starts at 1 */
|
||||
object_index = array_index - 1;
|
||||
/* 1 for the device object */
|
||||
object_count = 1;
|
||||
/* FIXME: add objects as needed */
|
||||
/* analog value objects */
|
||||
if (!status) {
|
||||
/* array index starts at 1, and 1 for the device object */
|
||||
object_index -= object_count;
|
||||
object_count = Analog_Value_Count();
|
||||
if (object_index < object_count) {
|
||||
*object_type = OBJECT_ANALOG_VALUE;
|
||||
*instance = Analog_Value_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
/* binary value objects */
|
||||
if (!status) {
|
||||
object_index -= object_count;
|
||||
object_count = Binary_Value_Count();
|
||||
/* is it a valid index for this object? */
|
||||
if (object_index < object_count) {
|
||||
*object_type = OBJECT_BINARY_VALUE;
|
||||
*instance = Binary_Value_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error */
|
||||
int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID property,
|
||||
uint32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint32_t i = 0;
|
||||
int object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
uint32_t count = 0;
|
||||
|
||||
//object_instance = object_instance;
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string, Object_Name);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], System_Status);
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, "GNU Demo");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, BACNET_VERSION_TEXT);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string, "1.0");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], BACNET_PROTOCOL_VERSION);
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
BACNET_PROTOCOL_REVISION);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
|
||||
/* Note: this is the list of objects that can be in this device,
|
||||
not a list of objects that this device can access */
|
||||
bitstring_init(&bit_string);
|
||||
/* must have the bit string as big as it can be */
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_OBJECT_LIST:
|
||||
count = Device_Object_List_Count();
|
||||
/* Array element zero is the number of objects in the list */
|
||||
if (array_index == 0)
|
||||
apdu_len = encode_application_unsigned(&apdu[0], count);
|
||||
/* if no index was specified, then try to encode the entire list */
|
||||
/* into one packet. Note that more than likely you will have */
|
||||
/* to return an error if the number of encoded objects exceeds */
|
||||
/* your maximum APDU size. */
|
||||
else if (array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
Device_Object_List_Identifier(i, &object_type, &instance);
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
if ((apdu_len + len) >= MAX_APDU) {
|
||||
/* Abort response */
|
||||
*error_code =
|
||||
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
|
||||
apdu_len = BACNET_STATUS_ABORT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_MAX_APDU_LENGTH_ACCEPTED:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], SEGMENTATION_NONE);
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 60000);
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
// case PROP_MAX_INFO_FRAMES:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0],
|
||||
// dlmstp_max_info_frames());
|
||||
// break;
|
||||
// case PROP_MAX_MASTER:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
||||
// break;
|
||||
// case 9600:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
|
||||
// break;
|
||||
// case 512:
|
||||
// apdu_len = encode_application_unsigned(&apdu[0], stack_size());
|
||||
// break;
|
||||
// case 513:
|
||||
// apdu_len = encode_application_unsigned(&apdu[0], stack_unused());
|
||||
// break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
/* only array properties can have array options */
|
||||
if ((apdu_len >= 0) && (property != PROP_OBJECT_LIST) &&
|
||||
(array_index != BACNET_ARRAY_ALL)) {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) {
|
||||
*error_class = ERROR_CLASS_OBJECT;
|
||||
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
/* FIXME: len < application_data_len: more data? */
|
||||
if (len < 0) {
|
||||
/* error while decoding - a value larger than we can handle */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
return false;
|
||||
}
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.Object_Id.
|
||||
instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
// case PROP_MAX_INFO_FRAMES:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if (value.type.Unsigned_Int <= 255) {
|
||||
// dlmstp_set_max_info_frames(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
// case PROP_MAX_MASTER:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if ((value.type.Unsigned_Int > 0) &&
|
||||
// (value.type.Unsigned_Int <= 127)) {
|
||||
// dlmstp_set_max_master(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
case PROP_OBJECT_NAME:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
|
||||
uint8_t encoding;
|
||||
|
||||
encoding =
|
||||
characterstring_encoding(&value.type.Character_String);
|
||||
if (encoding == CHARACTER_ANSI_X34) {
|
||||
if (characterstring_ansi_copy(&Object_Name[0],
|
||||
sizeof(Object_Name),
|
||||
&value.type.Character_String)) {
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
// case 9600:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if (value.type.Unsigned_Int > 115200) {
|
||||
// RS485_Set_Baud_Rate(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
+161
-161
@@ -1,161 +1,161 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacerror.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
#include "rp.h"
|
||||
/* demo objects */
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
#include "bv.h"
|
||||
|
||||
/* Encodes the property APDU and returns the length,
|
||||
or sets the error, and returns -1 */
|
||||
int Encode_Property_APDU(uint8_t * apdu,
|
||||
BACNET_READ_PROPERTY_DATA * rp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = -1;
|
||||
|
||||
/* handle each object type */
|
||||
switch (rp_data->object_type) {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Valid_Object_Instance_Number(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Device_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Binary_Value_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_OBJECT;
|
||||
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
void handler_read_property(uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
{
|
||||
BACNET_READ_PROPERTY_DATA data;
|
||||
int len = 0;
|
||||
int ack_len = 0;
|
||||
int property_len = 0;
|
||||
int pdu_len = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
BACNET_ADDRESS my_address;
|
||||
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
|
||||
&npdu_data);
|
||||
if (service_data->segmented_message) {
|
||||
/* we don't support segmentation - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
goto RP_ABORT;
|
||||
}
|
||||
len = rp_decode_service_request(service_request, service_len, &data);
|
||||
if (len < 0) {
|
||||
/* bad decoding - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||
goto RP_ABORT;
|
||||
}
|
||||
/* most cases will be error */
|
||||
ack_len =
|
||||
rp_ack_encode_apdu_init(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
/* FIXME: add buffer len as passed into function or use smart buffer */
|
||||
property_len =
|
||||
Encode_Property_APDU(&Handler_Transmit_Buffer[pdu_len + ack_len],
|
||||
&data, &error_class, &error_code);
|
||||
if (property_len >= 0) {
|
||||
len =
|
||||
rp_ack_encode_apdu_object_property_end(&Handler_Transmit_Buffer
|
||||
[pdu_len + property_len + ack_len]);
|
||||
len += ack_len + property_len;
|
||||
} else {
|
||||
switch (property_len) {
|
||||
/* BACnet APDU too small to fit data, so proper response is Abort */
|
||||
case BACNET_STATUS_ABORT:
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RP_ABORT:
|
||||
pdu_len += len;
|
||||
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
|
||||
|
||||
return;
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacerror.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
#include "rp.h"
|
||||
/* demo objects */
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
#include "bv.h"
|
||||
|
||||
/* Encodes the property APDU and returns the length,
|
||||
or sets the error, and returns -1 */
|
||||
int Encode_Property_APDU(uint8_t * apdu,
|
||||
BACNET_READ_PROPERTY_DATA * rp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = -1;
|
||||
|
||||
/* handle each object type */
|
||||
switch (rp_data->object_type) {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Valid_Object_Instance_Number(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Device_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Binary_Value_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_OBJECT;
|
||||
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
void handler_read_property(uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
{
|
||||
BACNET_READ_PROPERTY_DATA data;
|
||||
int len = 0;
|
||||
int ack_len = 0;
|
||||
int property_len = 0;
|
||||
int pdu_len = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
BACNET_ADDRESS my_address;
|
||||
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
|
||||
&npdu_data);
|
||||
if (service_data->segmented_message) {
|
||||
/* we don't support segmentation - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
goto RP_ABORT;
|
||||
}
|
||||
len = rp_decode_service_request(service_request, service_len, &data);
|
||||
if (len < 0) {
|
||||
/* bad decoding - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||
goto RP_ABORT;
|
||||
}
|
||||
/* most cases will be error */
|
||||
ack_len =
|
||||
rp_ack_encode_apdu_init(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
/* FIXME: add buffer len as passed into function or use smart buffer */
|
||||
property_len =
|
||||
Encode_Property_APDU(&Handler_Transmit_Buffer[pdu_len + ack_len],
|
||||
&data, &error_class, &error_code);
|
||||
if (property_len >= 0) {
|
||||
len =
|
||||
rp_ack_encode_apdu_object_property_end(&Handler_Transmit_Buffer
|
||||
[pdu_len + property_len + ack_len]);
|
||||
len += ack_len + property_len;
|
||||
} else {
|
||||
switch (property_len) {
|
||||
/* BACnet APDU too small to fit data, so proper response is Abort */
|
||||
case BACNET_STATUS_ABORT:
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RP_ABORT:
|
||||
pdu_len += len;
|
||||
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+44
-44
@@ -1,44 +1,44 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Miguel Fernandes <miguelandre.fernandes@gmail.com>
|
||||
* @date 6 de Jun de 2013
|
||||
* @brief For redirecting stdout, stdin and stderr
|
||||
* see http://www.appelsiini.net/2011/simple-usart-with-avr-libc
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/setbaud.h>
|
||||
#include "hardware.h"
|
||||
#include "uart.h"
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
UBRR0H = UBRRH_VALUE;
|
||||
UBRR0L = UBRRL_VALUE;
|
||||
|
||||
#if USE_2X
|
||||
UCSR0A |= _BV(U2X0);
|
||||
#else
|
||||
UCSR0A &= ~(_BV(U2X0));
|
||||
#endif
|
||||
|
||||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
|
||||
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
|
||||
}
|
||||
|
||||
void uart_putchar(char c,
|
||||
FILE * stream)
|
||||
{
|
||||
if (c == '\n') {
|
||||
uart_putchar('\r', stream);
|
||||
}
|
||||
loop_until_bit_is_set(UCSR0A, UDRE0);
|
||||
UDR0 = c;
|
||||
}
|
||||
|
||||
char uart_getchar(FILE * stream)
|
||||
{
|
||||
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
|
||||
return UDR0;
|
||||
}
|
||||
/**
|
||||
* @file
|
||||
* @author Miguel Fernandes <miguelandre.fernandes@gmail.com>
|
||||
* @date 6 de Jun de 2013
|
||||
* @brief For redirecting stdout, stdin and stderr
|
||||
* see http://www.appelsiini.net/2011/simple-usart-with-avr-libc
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/setbaud.h>
|
||||
#include "hardware.h"
|
||||
#include "uart.h"
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
UBRR0H = UBRRH_VALUE;
|
||||
UBRR0L = UBRRL_VALUE;
|
||||
|
||||
#if USE_2X
|
||||
UCSR0A |= _BV(U2X0);
|
||||
#else
|
||||
UCSR0A &= ~(_BV(U2X0));
|
||||
#endif
|
||||
|
||||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
|
||||
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
|
||||
}
|
||||
|
||||
void uart_putchar(char c,
|
||||
FILE * stream)
|
||||
{
|
||||
if (c == '\n') {
|
||||
uart_putchar('\r', stream);
|
||||
}
|
||||
loop_until_bit_is_set(UCSR0A, UDRE0);
|
||||
UDR0 = c;
|
||||
}
|
||||
|
||||
char uart_getchar(FILE * stream)
|
||||
{
|
||||
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
|
||||
return UDR0;
|
||||
}
|
||||
|
||||
+27
-27
@@ -1,27 +1,27 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Miguel Fernandes <miguelandre.fernandes@gmail.com>
|
||||
* @date 6 de Jun de 2013
|
||||
* @brief BACnet Virtual Link Control for Wiznet on Arduino-Uno
|
||||
*/
|
||||
#ifndef UART_H_
|
||||
#define UART_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void uart_init(void);
|
||||
void uart_putchar(char c,
|
||||
FILE * stream);
|
||||
char uart_getchar(FILE * stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @author Miguel Fernandes <miguelandre.fernandes@gmail.com>
|
||||
* @date 6 de Jun de 2013
|
||||
* @brief BACnet Virtual Link Control for Wiznet on Arduino-Uno
|
||||
*/
|
||||
#ifndef UART_H_
|
||||
#define UART_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void uart_init(void);
|
||||
void uart_putchar(char c,
|
||||
FILE * stream);
|
||||
char uart_getchar(FILE * stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
+56
-56
@@ -1,57 +1,57 @@
|
||||
//
|
||||
// Copyleft F.Chaxel 2017
|
||||
//
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#include "bip.h"
|
||||
|
||||
long bip_getaddrbyname(
|
||||
const char *host_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bip_set_interface(char *ifname)
|
||||
{
|
||||
}
|
||||
|
||||
void bip_cleanup (void)
|
||||
{
|
||||
close(bip_socket());
|
||||
bip_set_socket(-1);
|
||||
}
|
||||
|
||||
bool bip_init(char *ifname)
|
||||
{
|
||||
|
||||
tcpip_adapter_ip_info_t ip_info = { 0 };
|
||||
|
||||
int value = 1;
|
||||
|
||||
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info);
|
||||
|
||||
bip_set_interface(ifname);
|
||||
bip_set_port(htons(0xBAC0));
|
||||
bip_set_addr(ip_info.ip.addr);
|
||||
bip_set_broadcast_addr((ip_info.ip.addr&ip_info.netmask.addr)|(~ip_info.netmask.addr));
|
||||
|
||||
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
struct sockaddr_in saddr = { 0 };
|
||||
|
||||
saddr.sin_family = PF_INET;
|
||||
saddr.sin_port = htons(0xBAC0);
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &value, sizeof(value));
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &value, sizeof(value));
|
||||
|
||||
bip_set_socket(sock);
|
||||
|
||||
return true;
|
||||
//
|
||||
// Copyleft F.Chaxel 2017
|
||||
//
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#include "bip.h"
|
||||
|
||||
long bip_getaddrbyname(
|
||||
const char *host_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bip_set_interface(char *ifname)
|
||||
{
|
||||
}
|
||||
|
||||
void bip_cleanup (void)
|
||||
{
|
||||
close(bip_socket());
|
||||
bip_set_socket(-1);
|
||||
}
|
||||
|
||||
bool bip_init(char *ifname)
|
||||
{
|
||||
|
||||
tcpip_adapter_ip_info_t ip_info = { 0 };
|
||||
|
||||
int value = 1;
|
||||
|
||||
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info);
|
||||
|
||||
bip_set_interface(ifname);
|
||||
bip_set_port(htons(0xBAC0));
|
||||
bip_set_addr(ip_info.ip.addr);
|
||||
bip_set_broadcast_addr((ip_info.ip.addr&ip_info.netmask.addr)|(~ip_info.netmask.addr));
|
||||
|
||||
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
struct sockaddr_in saddr = { 0 };
|
||||
|
||||
saddr.sin_family = PF_INET;
|
||||
saddr.sin_port = htons(0xBAC0);
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &value, sizeof(value));
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &value, sizeof(value));
|
||||
|
||||
bip_set_socket(sock);
|
||||
|
||||
return true;
|
||||
}
|
||||
+214
-214
@@ -1,215 +1,215 @@
|
||||
//
|
||||
// Copyleft F.Chaxel 2017
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "client.h"
|
||||
|
||||
#include "handlers.h"
|
||||
#include "datalink.h"
|
||||
#include "dcc.h"
|
||||
#include "tsm.h"
|
||||
// conflict filename address.h with another file in default include paths
|
||||
#include "../lib/stack/address.h"
|
||||
#include "bip.h"
|
||||
|
||||
#include "device.h"
|
||||
#include "ai.h"
|
||||
#include "bo.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
// hidden function not in any .h files
|
||||
extern uint8_t temprature_sens_read();
|
||||
extern uint32_t hall_sens_read();
|
||||
|
||||
// Wifi params
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = "myWifi",
|
||||
.password = "myPass",
|
||||
},
|
||||
};
|
||||
|
||||
// GPIO 5 has a Led on Sparkfun ESP32 board
|
||||
#define BACNET_LED 5
|
||||
|
||||
uint8_t Handler_Transmit_Buffer[MAX_PDU] = { 0 };
|
||||
uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
EventGroupHandle_t wifi_event_group;
|
||||
const static int CONNECTED_BIT = BIT0;
|
||||
|
||||
/* BACnet handler, stack init, IAm */
|
||||
void StartBACnet()
|
||||
{
|
||||
/* we need to handle who-is to support dynamic device binding */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
/* set the handler for all the services we don't implement */
|
||||
/* It is required to send the proper reject message... */
|
||||
apdu_set_unrecognized_service_handler_handler
|
||||
(handler_unrecognized_service);
|
||||
/* Set the handlers for any confirmed services that we support. */
|
||||
/* We must implement read property - it's required! */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
handler_read_property);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
|
||||
handler_read_property_multiple);
|
||||
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
handler_write_property);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_SUBSCRIBE_COV,
|
||||
handler_cov_subscribe);
|
||||
|
||||
address_init();
|
||||
bip_init(NULL);
|
||||
Send_I_Am(&Handler_Transmit_Buffer[0]);
|
||||
}
|
||||
|
||||
/* wifi events handler : start & stop bacnet with an event */
|
||||
esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
switch(event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
break ;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
if (xEventGroupGetBits(wifi_event_group)!=CONNECTED_BIT)
|
||||
{
|
||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
||||
StartBACnet();
|
||||
}
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
/* This is a workaround as ESP32 WiFi libs don't currently
|
||||
auto-reassociate. */
|
||||
esp_wifi_connect();
|
||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||
bip_cleanup();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* tcpip & wifi station start */
|
||||
|
||||
void wifi_init_station(void)
|
||||
{
|
||||
tcpip_adapter_init();
|
||||
wifi_event_group = xEventGroupCreate();
|
||||
esp_event_loop_init(wifi_event_handler, NULL);
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
esp_wifi_init(&cfg);
|
||||
|
||||
esp_wifi_set_storage(WIFI_STORAGE_RAM);
|
||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
|
||||
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
|
||||
|
||||
esp_wifi_start() ;
|
||||
}
|
||||
|
||||
/* setup gpio & nv flash, call wifi init code */
|
||||
void setup()
|
||||
{
|
||||
gpio_pad_select_gpio(BACNET_LED);
|
||||
gpio_set_direction(BACNET_LED, GPIO_MODE_OUTPUT);
|
||||
|
||||
gpio_set_level(BACNET_LED,0);
|
||||
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES)
|
||||
{
|
||||
nvs_flash_erase();
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
wifi_init_station();
|
||||
}
|
||||
|
||||
/* Bacnet Task */
|
||||
void BACnetTask(void *pvParameters)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BACNET_ADDRESS src = {
|
||||
0
|
||||
};
|
||||
unsigned timeout = 1;
|
||||
|
||||
// Init Bacnet objets dictionnary
|
||||
Device_Init(NULL);
|
||||
Device_Set_Object_Instance_Number(12);
|
||||
|
||||
setup();
|
||||
|
||||
uint32_t tickcount=xTaskGetTickCount();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS); // could be remove to speed the code
|
||||
|
||||
// do nothing if not connected to wifi
|
||||
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
{
|
||||
uint32_t newtick=xTaskGetTickCount();
|
||||
|
||||
// one second elapse at least (maybe much more if Wifi was deconnected for a long)
|
||||
if ((newtick<tickcount)||((newtick-tickcount)>=configTICK_RATE_HZ))
|
||||
{
|
||||
tickcount=newtick;
|
||||
dcc_timer_seconds(1);
|
||||
bvlc_maintenance_timer(1);
|
||||
handler_cov_timer_seconds(1);
|
||||
tsm_timer_milliseconds(1000);
|
||||
|
||||
// Read analog values from internal sensors
|
||||
Analog_Input_Present_Value_Set(0,temprature_sens_read());
|
||||
Analog_Input_Present_Value_Set(1,hall_sens_read());
|
||||
|
||||
}
|
||||
|
||||
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
|
||||
if (pdu_len)
|
||||
{
|
||||
npdu_handler(&src, &Rx_Buf[0], pdu_len);
|
||||
|
||||
if(Binary_Output_Present_Value(0)==BINARY_ACTIVE)
|
||||
gpio_set_level(BACNET_LED,1);
|
||||
else
|
||||
gpio_set_level(BACNET_LED,0);
|
||||
}
|
||||
|
||||
handler_cov_task();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Entry point */
|
||||
void app_main()
|
||||
{
|
||||
// Cannot run BACnet code here, the default stack size is to small : 4096 byte
|
||||
xTaskCreate(
|
||||
BACnetTask, /* Function to implement the task */
|
||||
"BACnetTask", /* Name of the task */
|
||||
10000, /* Stack size in words */
|
||||
NULL, /* Task input parameter */
|
||||
20, /* Priority of the task */
|
||||
NULL); /* Task handle. */
|
||||
//
|
||||
// Copyleft F.Chaxel 2017
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "client.h"
|
||||
|
||||
#include "handlers.h"
|
||||
#include "datalink.h"
|
||||
#include "dcc.h"
|
||||
#include "tsm.h"
|
||||
// conflict filename address.h with another file in default include paths
|
||||
#include "../lib/stack/address.h"
|
||||
#include "bip.h"
|
||||
|
||||
#include "device.h"
|
||||
#include "ai.h"
|
||||
#include "bo.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/netdb.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
// hidden function not in any .h files
|
||||
extern uint8_t temprature_sens_read();
|
||||
extern uint32_t hall_sens_read();
|
||||
|
||||
// Wifi params
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = "myWifi",
|
||||
.password = "myPass",
|
||||
},
|
||||
};
|
||||
|
||||
// GPIO 5 has a Led on Sparkfun ESP32 board
|
||||
#define BACNET_LED 5
|
||||
|
||||
uint8_t Handler_Transmit_Buffer[MAX_PDU] = { 0 };
|
||||
uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
EventGroupHandle_t wifi_event_group;
|
||||
const static int CONNECTED_BIT = BIT0;
|
||||
|
||||
/* BACnet handler, stack init, IAm */
|
||||
void StartBACnet()
|
||||
{
|
||||
/* we need to handle who-is to support dynamic device binding */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
/* set the handler for all the services we don't implement */
|
||||
/* It is required to send the proper reject message... */
|
||||
apdu_set_unrecognized_service_handler_handler
|
||||
(handler_unrecognized_service);
|
||||
/* Set the handlers for any confirmed services that we support. */
|
||||
/* We must implement read property - it's required! */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
handler_read_property);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
|
||||
handler_read_property_multiple);
|
||||
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
handler_write_property);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_SUBSCRIBE_COV,
|
||||
handler_cov_subscribe);
|
||||
|
||||
address_init();
|
||||
bip_init(NULL);
|
||||
Send_I_Am(&Handler_Transmit_Buffer[0]);
|
||||
}
|
||||
|
||||
/* wifi events handler : start & stop bacnet with an event */
|
||||
esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
switch(event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
break ;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
if (xEventGroupGetBits(wifi_event_group)!=CONNECTED_BIT)
|
||||
{
|
||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
||||
StartBACnet();
|
||||
}
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
/* This is a workaround as ESP32 WiFi libs don't currently
|
||||
auto-reassociate. */
|
||||
esp_wifi_connect();
|
||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||
bip_cleanup();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* tcpip & wifi station start */
|
||||
|
||||
void wifi_init_station(void)
|
||||
{
|
||||
tcpip_adapter_init();
|
||||
wifi_event_group = xEventGroupCreate();
|
||||
esp_event_loop_init(wifi_event_handler, NULL);
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
esp_wifi_init(&cfg);
|
||||
|
||||
esp_wifi_set_storage(WIFI_STORAGE_RAM);
|
||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
|
||||
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
|
||||
|
||||
esp_wifi_start() ;
|
||||
}
|
||||
|
||||
/* setup gpio & nv flash, call wifi init code */
|
||||
void setup()
|
||||
{
|
||||
gpio_pad_select_gpio(BACNET_LED);
|
||||
gpio_set_direction(BACNET_LED, GPIO_MODE_OUTPUT);
|
||||
|
||||
gpio_set_level(BACNET_LED,0);
|
||||
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES)
|
||||
{
|
||||
nvs_flash_erase();
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
wifi_init_station();
|
||||
}
|
||||
|
||||
/* Bacnet Task */
|
||||
void BACnetTask(void *pvParameters)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BACNET_ADDRESS src = {
|
||||
0
|
||||
};
|
||||
unsigned timeout = 1;
|
||||
|
||||
// Init Bacnet objets dictionnary
|
||||
Device_Init(NULL);
|
||||
Device_Set_Object_Instance_Number(12);
|
||||
|
||||
setup();
|
||||
|
||||
uint32_t tickcount=xTaskGetTickCount();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS); // could be remove to speed the code
|
||||
|
||||
// do nothing if not connected to wifi
|
||||
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
{
|
||||
uint32_t newtick=xTaskGetTickCount();
|
||||
|
||||
// one second elapse at least (maybe much more if Wifi was deconnected for a long)
|
||||
if ((newtick<tickcount)||((newtick-tickcount)>=configTICK_RATE_HZ))
|
||||
{
|
||||
tickcount=newtick;
|
||||
dcc_timer_seconds(1);
|
||||
bvlc_maintenance_timer(1);
|
||||
handler_cov_timer_seconds(1);
|
||||
tsm_timer_milliseconds(1000);
|
||||
|
||||
// Read analog values from internal sensors
|
||||
Analog_Input_Present_Value_Set(0,temprature_sens_read());
|
||||
Analog_Input_Present_Value_Set(1,hall_sens_read());
|
||||
|
||||
}
|
||||
|
||||
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
|
||||
if (pdu_len)
|
||||
{
|
||||
npdu_handler(&src, &Rx_Buf[0], pdu_len);
|
||||
|
||||
if(Binary_Output_Present_Value(0)==BINARY_ACTIVE)
|
||||
gpio_set_level(BACNET_LED,1);
|
||||
else
|
||||
gpio_set_level(BACNET_LED,0);
|
||||
}
|
||||
|
||||
handler_cov_task();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Entry point */
|
||||
void app_main()
|
||||
{
|
||||
// Cannot run BACnet code here, the default stack size is to small : 4096 byte
|
||||
xTaskCreate(
|
||||
BACnetTask, /* Function to implement the task */
|
||||
"BACnetTask", /* Name of the task */
|
||||
10000, /* Stack size in words */
|
||||
NULL, /* Task input parameter */
|
||||
20, /* Priority of the task */
|
||||
NULL); /* Task handle. */
|
||||
}
|
||||
+125
-125
@@ -1,125 +1,125 @@
|
||||
/*
|
||||
*
|
||||
* Automatically generated file; DO NOT EDIT.
|
||||
* Espressif IoT Development Framework Configuration
|
||||
*
|
||||
*/
|
||||
#define CONFIG_GATTC_ENABLE 1
|
||||
#define CONFIG_ESP32_PHY_MAX_TX_POWER 20
|
||||
#define CONFIG_PHY_ENABLED 1
|
||||
#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0
|
||||
#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16
|
||||
#define CONFIG_BLE_SMP_ENABLE 1
|
||||
#define CONFIG_IPC_TASK_STACK_SIZE 1024
|
||||
#define CONFIG_ESPTOOLPY_FLASHFREQ "40m"
|
||||
#define CONFIG_NEWLIB_STDOUT_ADDCR 1
|
||||
#define CONFIG_TASK_WDT_CHECK_IDLE_TASK 1
|
||||
#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB"
|
||||
#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1
|
||||
#define CONFIG_ETHERNET 1
|
||||
#define CONFIG_INT_WDT 1
|
||||
#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1
|
||||
#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO 1
|
||||
#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1
|
||||
#define CONFIG_AWS_IOT_MQTT_PORT 8883
|
||||
#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1
|
||||
#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10
|
||||
#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1
|
||||
#define CONFIG_BT_RESERVE_DRAM 0x10000
|
||||
#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1
|
||||
#define CONFIG_CONSOLE_UART_BAUDRATE 115200
|
||||
#define CONFIG_LWIP_MAX_SOCKETS 10
|
||||
#define CONFIG_EMAC_TASK_PRIORITY 20
|
||||
#define CONFIG_TIMER_TASK_STACK_DEPTH 2048
|
||||
#define CONFIG_FATFS_CODEPAGE 1
|
||||
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1
|
||||
#define CONFIG_ULP_COPROC_RESERVE_MEM 0
|
||||
#define CONFIG_ESPTOOLPY_BAUD 115200
|
||||
#define CONFIG_INT_WDT_CHECK_CPU1 1
|
||||
#define CONFIG_FLASHMODE_DIO 1
|
||||
#define CONFIG_ESPTOOLPY_AFTER_RESET 1
|
||||
#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-"
|
||||
#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1024
|
||||
#define CONFIG_ESP32_WIFI_AMPDU_ENABLED 1
|
||||
#define CONFIG_CONSOLE_UART_NUM 0
|
||||
#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1
|
||||
#define CONFIG_ESPTOOLPY_BAUD_115200B 1
|
||||
#define CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX 0
|
||||
#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1
|
||||
#define CONFIG_CONSOLE_UART_DEFAULT 1
|
||||
#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384
|
||||
#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4
|
||||
#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1
|
||||
#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1
|
||||
#define CONFIG_BTDM_CONTROLLER_RUN_CPU 0
|
||||
#define CONFIG_TCPIP_TASK_STACK_SIZE 2560
|
||||
#define CONFIG_TASK_WDT 1
|
||||
#define CONFIG_MAIN_TASK_STACK_SIZE 4096
|
||||
#define CONFIG_TASK_WDT_TIMEOUT_S 5
|
||||
#define CONFIG_INT_WDT_TIMEOUT_MS 300
|
||||
#define CONFIG_ESPTOOLPY_FLASHMODE "dio"
|
||||
#define CONFIG_BTC_TASK_STACK_SIZE 3072
|
||||
#define CONFIG_BLUEDROID_ENABLED 1
|
||||
#define CONFIG_ESPTOOLPY_BEFORE "default_reset"
|
||||
#define CONFIG_LOG_DEFAULT_LEVEL 3
|
||||
#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1
|
||||
#define CONFIG_TIMER_QUEUE_LENGTH 10
|
||||
#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32
|
||||
#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20
|
||||
#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024
|
||||
#define CONFIG_ESP32_WIFI_NVS_ENABLED 1
|
||||
#define CONFIG_AWS_IOT_SDK 1
|
||||
#define CONFIG_DMA_RX_BUF_NUM 10
|
||||
#define CONFIG_TCP_SYNMAXRTX 6
|
||||
#define CONFIG_PYTHON "python"
|
||||
#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1
|
||||
#define CONFIG_ESPTOOLPY_COMPRESSED 1
|
||||
#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv"
|
||||
#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1
|
||||
#define CONFIG_PARTITION_TABLE_SINGLE_APP 1
|
||||
#define CONFIG_WIFI_ENABLED 1
|
||||
#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1
|
||||
#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 4096
|
||||
#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000
|
||||
#define CONFIG_ESP32_APPTRACE_DEST_NONE 1
|
||||
#define CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET 0x10000
|
||||
#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32
|
||||
#define CONFIG_FATFS_CODEPAGE_ASCII 1
|
||||
#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 1
|
||||
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160
|
||||
#define CONFIG_FREERTOS_HZ 100
|
||||
#define CONFIG_LOG_COLORS 1
|
||||
#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1
|
||||
#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1
|
||||
#define CONFIG_ESP32_XTAL_FREQ 0
|
||||
#define CONFIG_MONITOR_BAUD_115200B 1
|
||||
#define CONFIG_LOG_BOOTLOADER_LEVEL 3
|
||||
#define CONFIG_SMP_ENABLE 1
|
||||
#define CONFIG_ESPTOOLPY_BEFORE_RESET 1
|
||||
#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200
|
||||
#define CONFIG_ESP32_XTAL_FREQ_AUTO 1
|
||||
#define CONFIG_TCP_MAXRTX 12
|
||||
#define CONFIG_ESPTOOLPY_AFTER "hard_reset"
|
||||
#define CONFIG_DMA_TX_BUF_NUM 10
|
||||
#define CONFIG_ESP32_DEBUG_OCDAWARE 1
|
||||
#define CONFIG_TIMER_TASK_PRIORITY 1
|
||||
#define CONFIG_BT_ENABLED 1
|
||||
#define CONFIG_MONITOR_BAUD 115200
|
||||
#define CONFIG_FREERTOS_CORETIMER_0 1
|
||||
#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv"
|
||||
#define CONFIG_MBEDTLS_HAVE_TIME 1
|
||||
#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1
|
||||
#define CONFIG_GATTS_ENABLE 1
|
||||
#define CONFIG_FREERTOS_ISR_STACKSIZE 1536
|
||||
#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1
|
||||
#define CONFIG_AWS_IOT_MQTT_HOST ""
|
||||
#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32
|
||||
#define CONFIG_BT_ACL_CONNECTIONS 4
|
||||
#define CONFIG_FATFS_MAX_LFN 255
|
||||
#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1
|
||||
#define CONFIG_APP_OFFSET 0x10000
|
||||
#define CONFIG_MEMMAP_SMP 1
|
||||
#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1
|
||||
#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200
|
||||
#define CONFIG_ESPTOOLPY_PORT "/dev/ttyUSB0"
|
||||
#define CONFIG_OPTIMIZATION_LEVEL_RELEASE 1
|
||||
/*
|
||||
*
|
||||
* Automatically generated file; DO NOT EDIT.
|
||||
* Espressif IoT Development Framework Configuration
|
||||
*
|
||||
*/
|
||||
#define CONFIG_GATTC_ENABLE 1
|
||||
#define CONFIG_ESP32_PHY_MAX_TX_POWER 20
|
||||
#define CONFIG_PHY_ENABLED 1
|
||||
#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0
|
||||
#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16
|
||||
#define CONFIG_BLE_SMP_ENABLE 1
|
||||
#define CONFIG_IPC_TASK_STACK_SIZE 1024
|
||||
#define CONFIG_ESPTOOLPY_FLASHFREQ "40m"
|
||||
#define CONFIG_NEWLIB_STDOUT_ADDCR 1
|
||||
#define CONFIG_TASK_WDT_CHECK_IDLE_TASK 1
|
||||
#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB"
|
||||
#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1
|
||||
#define CONFIG_ETHERNET 1
|
||||
#define CONFIG_INT_WDT 1
|
||||
#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1
|
||||
#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO 1
|
||||
#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1
|
||||
#define CONFIG_AWS_IOT_MQTT_PORT 8883
|
||||
#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1
|
||||
#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10
|
||||
#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1
|
||||
#define CONFIG_BT_RESERVE_DRAM 0x10000
|
||||
#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1
|
||||
#define CONFIG_CONSOLE_UART_BAUDRATE 115200
|
||||
#define CONFIG_LWIP_MAX_SOCKETS 10
|
||||
#define CONFIG_EMAC_TASK_PRIORITY 20
|
||||
#define CONFIG_TIMER_TASK_STACK_DEPTH 2048
|
||||
#define CONFIG_FATFS_CODEPAGE 1
|
||||
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1
|
||||
#define CONFIG_ULP_COPROC_RESERVE_MEM 0
|
||||
#define CONFIG_ESPTOOLPY_BAUD 115200
|
||||
#define CONFIG_INT_WDT_CHECK_CPU1 1
|
||||
#define CONFIG_FLASHMODE_DIO 1
|
||||
#define CONFIG_ESPTOOLPY_AFTER_RESET 1
|
||||
#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-"
|
||||
#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1024
|
||||
#define CONFIG_ESP32_WIFI_AMPDU_ENABLED 1
|
||||
#define CONFIG_CONSOLE_UART_NUM 0
|
||||
#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1
|
||||
#define CONFIG_ESPTOOLPY_BAUD_115200B 1
|
||||
#define CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX 0
|
||||
#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1
|
||||
#define CONFIG_CONSOLE_UART_DEFAULT 1
|
||||
#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384
|
||||
#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4
|
||||
#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1
|
||||
#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1
|
||||
#define CONFIG_BTDM_CONTROLLER_RUN_CPU 0
|
||||
#define CONFIG_TCPIP_TASK_STACK_SIZE 2560
|
||||
#define CONFIG_TASK_WDT 1
|
||||
#define CONFIG_MAIN_TASK_STACK_SIZE 4096
|
||||
#define CONFIG_TASK_WDT_TIMEOUT_S 5
|
||||
#define CONFIG_INT_WDT_TIMEOUT_MS 300
|
||||
#define CONFIG_ESPTOOLPY_FLASHMODE "dio"
|
||||
#define CONFIG_BTC_TASK_STACK_SIZE 3072
|
||||
#define CONFIG_BLUEDROID_ENABLED 1
|
||||
#define CONFIG_ESPTOOLPY_BEFORE "default_reset"
|
||||
#define CONFIG_LOG_DEFAULT_LEVEL 3
|
||||
#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1
|
||||
#define CONFIG_TIMER_QUEUE_LENGTH 10
|
||||
#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32
|
||||
#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20
|
||||
#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024
|
||||
#define CONFIG_ESP32_WIFI_NVS_ENABLED 1
|
||||
#define CONFIG_AWS_IOT_SDK 1
|
||||
#define CONFIG_DMA_RX_BUF_NUM 10
|
||||
#define CONFIG_TCP_SYNMAXRTX 6
|
||||
#define CONFIG_PYTHON "python"
|
||||
#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1
|
||||
#define CONFIG_ESPTOOLPY_COMPRESSED 1
|
||||
#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv"
|
||||
#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1
|
||||
#define CONFIG_PARTITION_TABLE_SINGLE_APP 1
|
||||
#define CONFIG_WIFI_ENABLED 1
|
||||
#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1
|
||||
#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 4096
|
||||
#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000
|
||||
#define CONFIG_ESP32_APPTRACE_DEST_NONE 1
|
||||
#define CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET 0x10000
|
||||
#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32
|
||||
#define CONFIG_FATFS_CODEPAGE_ASCII 1
|
||||
#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 1
|
||||
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160
|
||||
#define CONFIG_FREERTOS_HZ 100
|
||||
#define CONFIG_LOG_COLORS 1
|
||||
#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1
|
||||
#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1
|
||||
#define CONFIG_ESP32_XTAL_FREQ 0
|
||||
#define CONFIG_MONITOR_BAUD_115200B 1
|
||||
#define CONFIG_LOG_BOOTLOADER_LEVEL 3
|
||||
#define CONFIG_SMP_ENABLE 1
|
||||
#define CONFIG_ESPTOOLPY_BEFORE_RESET 1
|
||||
#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200
|
||||
#define CONFIG_ESP32_XTAL_FREQ_AUTO 1
|
||||
#define CONFIG_TCP_MAXRTX 12
|
||||
#define CONFIG_ESPTOOLPY_AFTER "hard_reset"
|
||||
#define CONFIG_DMA_TX_BUF_NUM 10
|
||||
#define CONFIG_ESP32_DEBUG_OCDAWARE 1
|
||||
#define CONFIG_TIMER_TASK_PRIORITY 1
|
||||
#define CONFIG_BT_ENABLED 1
|
||||
#define CONFIG_MONITOR_BAUD 115200
|
||||
#define CONFIG_FREERTOS_CORETIMER_0 1
|
||||
#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv"
|
||||
#define CONFIG_MBEDTLS_HAVE_TIME 1
|
||||
#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1
|
||||
#define CONFIG_GATTS_ENABLE 1
|
||||
#define CONFIG_FREERTOS_ISR_STACKSIZE 1536
|
||||
#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1
|
||||
#define CONFIG_AWS_IOT_MQTT_HOST ""
|
||||
#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32
|
||||
#define CONFIG_BT_ACL_CONNECTIONS 4
|
||||
#define CONFIG_FATFS_MAX_LFN 255
|
||||
#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1
|
||||
#define CONFIG_APP_OFFSET 0x10000
|
||||
#define CONFIG_MEMMAP_SMP 1
|
||||
#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1
|
||||
#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200
|
||||
#define CONFIG_ESPTOOLPY_PORT "/dev/ttyUSB0"
|
||||
#define CONFIG_OPTIMIZATION_LEVEL_RELEASE 1
|
||||
|
||||
+453
-453
@@ -1,453 +1,453 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2016 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include "bacdcode.h"
|
||||
#include "config.h"
|
||||
#include "bip6.h"
|
||||
#include "debug.h"
|
||||
#include "device.h"
|
||||
#include "net.h"
|
||||
#include <ifaddrs.h>
|
||||
|
||||
static void debug_print_ipv6(const char *str, const struct in6_addr * addr) {
|
||||
debug_printf( "BIP6: %s %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
|
||||
str,
|
||||
(int)addr->s6_addr[0], (int)addr->s6_addr[1],
|
||||
(int)addr->s6_addr[2], (int)addr->s6_addr[3],
|
||||
(int)addr->s6_addr[4], (int)addr->s6_addr[5],
|
||||
(int)addr->s6_addr[6], (int)addr->s6_addr[7],
|
||||
(int)addr->s6_addr[8], (int)addr->s6_addr[9],
|
||||
(int)addr->s6_addr[10], (int)addr->s6_addr[11],
|
||||
(int)addr->s6_addr[12], (int)addr->s6_addr[13],
|
||||
(int)addr->s6_addr[14], (int)addr->s6_addr[15]);
|
||||
}
|
||||
|
||||
/** @file linux/bip6.c Initializes BACnet/IPv6 interface (Linux). */
|
||||
|
||||
/* unix socket */
|
||||
static int BIP6_Socket = -1;
|
||||
/* local address - filled by init functions */
|
||||
static BACNET_IP6_ADDRESS BIP6_Addr;
|
||||
static BACNET_IP6_ADDRESS BIP6_Broadcast_Addr;
|
||||
|
||||
/**
|
||||
* Set the interface name. On Linux, ifname is the /dev/ name of the interface.
|
||||
*
|
||||
* @param ifname - C string for name or text address
|
||||
*/
|
||||
void bip6_set_interface(
|
||||
char *ifname)
|
||||
{
|
||||
struct ifaddrs *ifa, *ifa_tmp;
|
||||
struct sockaddr_in6 *sin;
|
||||
bool found = false;
|
||||
|
||||
if (getifaddrs(&ifa) == -1) {
|
||||
perror("BIP6: getifaddrs failed");
|
||||
exit(1);
|
||||
}
|
||||
ifa_tmp = ifa;
|
||||
debug_printf("BIP6: seeking interface: %s\n", ifname);
|
||||
while (ifa_tmp) {
|
||||
if ((ifa_tmp->ifa_addr) &&
|
||||
(ifa_tmp->ifa_addr->sa_family == AF_INET6)) {
|
||||
debug_printf("BIP6: found interface: %s\n", ifa_tmp->ifa_name);
|
||||
}
|
||||
if ((ifa_tmp->ifa_addr) &&
|
||||
(ifa_tmp->ifa_addr->sa_family == AF_INET6) &&
|
||||
(strcasecmp(ifa_tmp->ifa_name,ifname) == 0)) {
|
||||
sin = (struct sockaddr_in6*) ifa_tmp->ifa_addr;
|
||||
bvlc6_address_set(&BIP6_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]));
|
||||
debug_print_ipv6(ifname, (&sin->sin6_addr));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
ifa_tmp = ifa_tmp->ifa_next;
|
||||
}
|
||||
if (!found) {
|
||||
debug_printf("BIP6: unable to set interface: %s\n", ifname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(
|
||||
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(
|
||||
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(
|
||||
BACNET_IP6_ADDRESS *dest,
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
/* 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);
|
||||
debug_print_ipv6("Sending MPDU->", &bvlc_dest.sin6_addr);
|
||||
/* Send the packet */
|
||||
return sendto(BIP6_Socket, (char *) mtu, mtu_len, 0,
|
||||
(struct sockaddr *) &bvlc_dest, sizeof(bvlc_dest));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
fd_set read_fds;
|
||||
int max = 0;
|
||||
struct 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;
|
||||
}
|
||||
FD_ZERO(&read_fds);
|
||||
FD_SET(BIP6_Socket, &read_fds);
|
||||
max = BIP6_Socket;
|
||||
/* see if there is a packet for us */
|
||||
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
||||
received_bytes =
|
||||
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) {
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
/* pass the packet into the BBMD handler */
|
||||
debug_print_ipv6("Received MPDU->", &sin.sin6_addr);
|
||||
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 {
|
||||
npdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return npdu_len;
|
||||
}
|
||||
|
||||
/** Cleanup and close out the BACnet/IP services by closing the socket.
|
||||
* @ingroup DLBIP6
|
||||
*/
|
||||
void bip6_cleanup(
|
||||
void)
|
||||
{
|
||||
if (BIP6_Socket != -1) {
|
||||
close(BIP6_Socket);
|
||||
}
|
||||
BIP6_Socket = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** 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).
|
||||
*
|
||||
* @note For Linux, ifname is eth0, ath0, arc0, and others.
|
||||
*
|
||||
* @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 = 0; /* return from socket lib calls */
|
||||
struct sockaddr_in6 server = {0};
|
||||
struct in6_addr broadcast_address;
|
||||
struct ipv6_mreq join_request;
|
||||
int sockopt = 0;
|
||||
|
||||
if (ifname) {
|
||||
bip6_set_interface(ifname);
|
||||
} else {
|
||||
bip6_set_interface("eth0");
|
||||
}
|
||||
if (BIP6_Addr.port == 0) {
|
||||
bip6_set_port(0xBAC0);
|
||||
}
|
||||
debug_printf("BIP6: IPv6 UDP port: 0x%04X\n", htons(BIP6_Addr.port));
|
||||
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);
|
||||
}
|
||||
/* assumes that the driver has already been initialized */
|
||||
BIP6_Socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (BIP6_Socket < 0)
|
||||
return false;
|
||||
/* Allow us to use the same socket for sending and receiving */
|
||||
/* This makes sure that the src port is correct when sending */
|
||||
sockopt = 1;
|
||||
status =
|
||||
setsockopt(BIP6_Socket, SOL_SOCKET, SO_REUSEADDR, &sockopt,
|
||||
sizeof(sockopt));
|
||||
if (status < 0) {
|
||||
close(BIP6_Socket);
|
||||
BIP6_Socket = -1;
|
||||
return status;
|
||||
}
|
||||
/* allow us to send a broadcast */
|
||||
status =
|
||||
setsockopt(BIP6_Socket, SOL_SOCKET, SO_BROADCAST, &sockopt,
|
||||
sizeof(sockopt));
|
||||
if (status < 0) {
|
||||
close(BIP6_Socket);
|
||||
BIP6_Socket = -1;
|
||||
return false;
|
||||
}
|
||||
/* 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 choose the interface */
|
||||
join_request.ipv6mr_interface = 0;
|
||||
status = setsockopt(BIP6_Socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
&join_request, sizeof(join_request));
|
||||
if (status < 0) {
|
||||
perror("BIP: setsockopt(IPV6_JOIN_GROUP)");
|
||||
}
|
||||
|
||||
/* bind the socket to the local port number and IP address */
|
||||
server.sin6_family = AF_INET6;
|
||||
server.sin6_addr = in6addr_any;
|
||||
server.sin6_port = htons(BIP6_Addr.port);
|
||||
status = bind(BIP6_Socket, (const void*)&server, sizeof(server));
|
||||
if (status < 0) {
|
||||
perror("BIP: bind");
|
||||
close(BIP6_Socket);
|
||||
BIP6_Socket = -1;
|
||||
return false;
|
||||
}
|
||||
bvlc6_init();
|
||||
|
||||
return true;
|
||||
}
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2016 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include "bacdcode.h"
|
||||
#include "config.h"
|
||||
#include "bip6.h"
|
||||
#include "debug.h"
|
||||
#include "device.h"
|
||||
#include "net.h"
|
||||
#include <ifaddrs.h>
|
||||
|
||||
static void debug_print_ipv6(const char *str, const struct in6_addr * addr) {
|
||||
debug_printf( "BIP6: %s %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
|
||||
str,
|
||||
(int)addr->s6_addr[0], (int)addr->s6_addr[1],
|
||||
(int)addr->s6_addr[2], (int)addr->s6_addr[3],
|
||||
(int)addr->s6_addr[4], (int)addr->s6_addr[5],
|
||||
(int)addr->s6_addr[6], (int)addr->s6_addr[7],
|
||||
(int)addr->s6_addr[8], (int)addr->s6_addr[9],
|
||||
(int)addr->s6_addr[10], (int)addr->s6_addr[11],
|
||||
(int)addr->s6_addr[12], (int)addr->s6_addr[13],
|
||||
(int)addr->s6_addr[14], (int)addr->s6_addr[15]);
|
||||
}
|
||||
|
||||
/** @file linux/bip6.c Initializes BACnet/IPv6 interface (Linux). */
|
||||
|
||||
/* unix socket */
|
||||
static int BIP6_Socket = -1;
|
||||
/* local address - filled by init functions */
|
||||
static BACNET_IP6_ADDRESS BIP6_Addr;
|
||||
static BACNET_IP6_ADDRESS BIP6_Broadcast_Addr;
|
||||
|
||||
/**
|
||||
* Set the interface name. On Linux, ifname is the /dev/ name of the interface.
|
||||
*
|
||||
* @param ifname - C string for name or text address
|
||||
*/
|
||||
void bip6_set_interface(
|
||||
char *ifname)
|
||||
{
|
||||
struct ifaddrs *ifa, *ifa_tmp;
|
||||
struct sockaddr_in6 *sin;
|
||||
bool found = false;
|
||||
|
||||
if (getifaddrs(&ifa) == -1) {
|
||||
perror("BIP6: getifaddrs failed");
|
||||
exit(1);
|
||||
}
|
||||
ifa_tmp = ifa;
|
||||
debug_printf("BIP6: seeking interface: %s\n", ifname);
|
||||
while (ifa_tmp) {
|
||||
if ((ifa_tmp->ifa_addr) &&
|
||||
(ifa_tmp->ifa_addr->sa_family == AF_INET6)) {
|
||||
debug_printf("BIP6: found interface: %s\n", ifa_tmp->ifa_name);
|
||||
}
|
||||
if ((ifa_tmp->ifa_addr) &&
|
||||
(ifa_tmp->ifa_addr->sa_family == AF_INET6) &&
|
||||
(strcasecmp(ifa_tmp->ifa_name,ifname) == 0)) {
|
||||
sin = (struct sockaddr_in6*) ifa_tmp->ifa_addr;
|
||||
bvlc6_address_set(&BIP6_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]));
|
||||
debug_print_ipv6(ifname, (&sin->sin6_addr));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
ifa_tmp = ifa_tmp->ifa_next;
|
||||
}
|
||||
if (!found) {
|
||||
debug_printf("BIP6: unable to set interface: %s\n", ifname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(
|
||||
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(
|
||||
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(
|
||||
BACNET_IP6_ADDRESS *dest,
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
/* 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);
|
||||
debug_print_ipv6("Sending MPDU->", &bvlc_dest.sin6_addr);
|
||||
/* Send the packet */
|
||||
return sendto(BIP6_Socket, (char *) mtu, mtu_len, 0,
|
||||
(struct sockaddr *) &bvlc_dest, sizeof(bvlc_dest));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
fd_set read_fds;
|
||||
int max = 0;
|
||||
struct 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;
|
||||
}
|
||||
FD_ZERO(&read_fds);
|
||||
FD_SET(BIP6_Socket, &read_fds);
|
||||
max = BIP6_Socket;
|
||||
/* see if there is a packet for us */
|
||||
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
||||
received_bytes =
|
||||
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) {
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
/* pass the packet into the BBMD handler */
|
||||
debug_print_ipv6("Received MPDU->", &sin.sin6_addr);
|
||||
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 {
|
||||
npdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return npdu_len;
|
||||
}
|
||||
|
||||
/** Cleanup and close out the BACnet/IP services by closing the socket.
|
||||
* @ingroup DLBIP6
|
||||
*/
|
||||
void bip6_cleanup(
|
||||
void)
|
||||
{
|
||||
if (BIP6_Socket != -1) {
|
||||
close(BIP6_Socket);
|
||||
}
|
||||
BIP6_Socket = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** 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).
|
||||
*
|
||||
* @note For Linux, ifname is eth0, ath0, arc0, and others.
|
||||
*
|
||||
* @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 = 0; /* return from socket lib calls */
|
||||
struct sockaddr_in6 server = {0};
|
||||
struct in6_addr broadcast_address;
|
||||
struct ipv6_mreq join_request;
|
||||
int sockopt = 0;
|
||||
|
||||
if (ifname) {
|
||||
bip6_set_interface(ifname);
|
||||
} else {
|
||||
bip6_set_interface("eth0");
|
||||
}
|
||||
if (BIP6_Addr.port == 0) {
|
||||
bip6_set_port(0xBAC0);
|
||||
}
|
||||
debug_printf("BIP6: IPv6 UDP port: 0x%04X\n", htons(BIP6_Addr.port));
|
||||
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);
|
||||
}
|
||||
/* assumes that the driver has already been initialized */
|
||||
BIP6_Socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (BIP6_Socket < 0)
|
||||
return false;
|
||||
/* Allow us to use the same socket for sending and receiving */
|
||||
/* This makes sure that the src port is correct when sending */
|
||||
sockopt = 1;
|
||||
status =
|
||||
setsockopt(BIP6_Socket, SOL_SOCKET, SO_REUSEADDR, &sockopt,
|
||||
sizeof(sockopt));
|
||||
if (status < 0) {
|
||||
close(BIP6_Socket);
|
||||
BIP6_Socket = -1;
|
||||
return status;
|
||||
}
|
||||
/* allow us to send a broadcast */
|
||||
status =
|
||||
setsockopt(BIP6_Socket, SOL_SOCKET, SO_BROADCAST, &sockopt,
|
||||
sizeof(sockopt));
|
||||
if (status < 0) {
|
||||
close(BIP6_Socket);
|
||||
BIP6_Socket = -1;
|
||||
return false;
|
||||
}
|
||||
/* 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 choose the interface */
|
||||
join_request.ipv6mr_interface = 0;
|
||||
status = setsockopt(BIP6_Socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
&join_request, sizeof(join_request));
|
||||
if (status < 0) {
|
||||
perror("BIP: setsockopt(IPV6_JOIN_GROUP)");
|
||||
}
|
||||
|
||||
/* bind the socket to the local port number and IP address */
|
||||
server.sin6_family = AF_INET6;
|
||||
server.sin6_addr = in6addr_any;
|
||||
server.sin6_port = htons(BIP6_Addr.port);
|
||||
status = bind(BIP6_Socket, (const void*)&server, sizeof(server));
|
||||
if (status < 0) {
|
||||
perror("BIP: bind");
|
||||
close(BIP6_Socket);
|
||||
BIP6_Socket = -1;
|
||||
return false;
|
||||
}
|
||||
bvlc6_init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,98 +1,98 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual C++ Express 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet Stack Library", "BACnet Stack Library\BACnet Stack Library.vcxproj", "{E9A65567-B028-4278-881D-674604B2E126}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet Object Definitions", "BACnet Object Definitions\BACnet Object Definitions.vcxproj", "{6A8668E1-F08E-496B-B624-D6C05001806D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server\Server.vcxproj", "{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38} = {9D4C3515-CA91-4C54-93DC-9962A3139A38}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacwi", "Who-Is\Who-Is.vcxproj", "{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38} = {9D4C3515-CA91-4C54-93DC-9962A3139A38}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacdcc", "dcc\dcc.vcxproj", "{CC217FCF-AEF6-4859-8452-1E222C393383}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E9A65567-B028-4278-881D-674604B2E126} = {E9A65567-B028-4278-881D-674604B2E126}
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D} = {6A8668E1-F08E-496B-B624-D6C05001806D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet Handler Library", "BACnet Handler Library\BACnet Handler Library.vcxproj", "{9D4C3515-CA91-4C54-93DC-9962A3139A38}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E9A65567-B028-4278-881D-674604B2E126} = {E9A65567-B028-4278-881D-674604B2E126}
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D} = {6A8668E1-F08E-496B-B624-D6C05001806D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacwp", "writeprop\writeprop.vcxproj", "{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38} = {9D4C3515-CA91-4C54-93DC-9962A3139A38}
|
||||
{E9A65567-B028-4278-881D-674604B2E126} = {E9A65567-B028-4278-881D-674604B2E126}
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D} = {6A8668E1-F08E-496B-B624-D6C05001806D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacwir", "bacwir\bacwir.vcxproj", "{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacrp", "bacrp\bacrp.vcxproj", "{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38} = {9D4C3515-CA91-4C54-93DC-9962A3139A38}
|
||||
{E9A65567-B028-4278-881D-674604B2E126} = {E9A65567-B028-4278-881D-674604B2E126}
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D} = {6A8668E1-F08E-496B-B624-D6C05001806D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacepics", "bacepics\bacepics.vcxproj", "{17BEB9AD-5DA8-4B49-9369-B6715831C381}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E9A65567-B028-4278-881D-674604B2E126}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E9A65567-B028-4278-881D-674604B2E126}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E9A65567-B028-4278-881D-674604B2E126}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E9A65567-B028-4278-881D-674604B2E126}.Release|Win32.Build.0 = Release|Win32
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D}.Release|Win32.Build.0 = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|Win32.Build.0 = Release|Win32
|
||||
{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}.Release|Win32.Build.0 = Release|Win32
|
||||
{CC217FCF-AEF6-4859-8452-1E222C393383}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CC217FCF-AEF6-4859-8452-1E222C393383}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CC217FCF-AEF6-4859-8452-1E222C393383}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CC217FCF-AEF6-4859-8452-1E222C393383}.Release|Win32.Build.0 = Release|Win32
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38}.Release|Win32.Build.0 = Release|Win32
|
||||
{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}.Release|Win32.Build.0 = Release|Win32
|
||||
{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}.Release|Win32.Build.0 = Release|Win32
|
||||
{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}.Release|Win32.Build.0 = Release|Win32
|
||||
{17BEB9AD-5DA8-4B49-9369-B6715831C381}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{17BEB9AD-5DA8-4B49-9369-B6715831C381}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{17BEB9AD-5DA8-4B49-9369-B6715831C381}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{17BEB9AD-5DA8-4B49-9369-B6715831C381}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual C++ Express 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet Stack Library", "BACnet Stack Library\BACnet Stack Library.vcxproj", "{E9A65567-B028-4278-881D-674604B2E126}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet Object Definitions", "BACnet Object Definitions\BACnet Object Definitions.vcxproj", "{6A8668E1-F08E-496B-B624-D6C05001806D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server\Server.vcxproj", "{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38} = {9D4C3515-CA91-4C54-93DC-9962A3139A38}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacwi", "Who-Is\Who-Is.vcxproj", "{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38} = {9D4C3515-CA91-4C54-93DC-9962A3139A38}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacdcc", "dcc\dcc.vcxproj", "{CC217FCF-AEF6-4859-8452-1E222C393383}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E9A65567-B028-4278-881D-674604B2E126} = {E9A65567-B028-4278-881D-674604B2E126}
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D} = {6A8668E1-F08E-496B-B624-D6C05001806D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet Handler Library", "BACnet Handler Library\BACnet Handler Library.vcxproj", "{9D4C3515-CA91-4C54-93DC-9962A3139A38}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E9A65567-B028-4278-881D-674604B2E126} = {E9A65567-B028-4278-881D-674604B2E126}
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D} = {6A8668E1-F08E-496B-B624-D6C05001806D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacwp", "writeprop\writeprop.vcxproj", "{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38} = {9D4C3515-CA91-4C54-93DC-9962A3139A38}
|
||||
{E9A65567-B028-4278-881D-674604B2E126} = {E9A65567-B028-4278-881D-674604B2E126}
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D} = {6A8668E1-F08E-496B-B624-D6C05001806D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacwir", "bacwir\bacwir.vcxproj", "{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacrp", "bacrp\bacrp.vcxproj", "{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38} = {9D4C3515-CA91-4C54-93DC-9962A3139A38}
|
||||
{E9A65567-B028-4278-881D-674604B2E126} = {E9A65567-B028-4278-881D-674604B2E126}
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D} = {6A8668E1-F08E-496B-B624-D6C05001806D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bacepics", "bacepics\bacepics.vcxproj", "{17BEB9AD-5DA8-4B49-9369-B6715831C381}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E9A65567-B028-4278-881D-674604B2E126}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E9A65567-B028-4278-881D-674604B2E126}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E9A65567-B028-4278-881D-674604B2E126}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E9A65567-B028-4278-881D-674604B2E126}.Release|Win32.Build.0 = Release|Win32
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6A8668E1-F08E-496B-B624-D6C05001806D}.Release|Win32.Build.0 = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|Win32.Build.0 = Release|Win32
|
||||
{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A6287B6E-0BCE-43FA-ADFB-9263DB069BA4}.Release|Win32.Build.0 = Release|Win32
|
||||
{CC217FCF-AEF6-4859-8452-1E222C393383}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CC217FCF-AEF6-4859-8452-1E222C393383}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CC217FCF-AEF6-4859-8452-1E222C393383}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CC217FCF-AEF6-4859-8452-1E222C393383}.Release|Win32.Build.0 = Release|Win32
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9D4C3515-CA91-4C54-93DC-9962A3139A38}.Release|Win32.Build.0 = Release|Win32
|
||||
{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{826EF765-7828-44D3-B8AF-7AEDBAA8E0D2}.Release|Win32.Build.0 = Release|Win32
|
||||
{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7E30D4FE-B8A7-442D-B6FB-E8DC3129EFEB}.Release|Win32.Build.0 = Release|Win32
|
||||
{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{2DED9AEF-13AB-408B-B914-F7F30AE15EC0}.Release|Win32.Build.0 = Release|Win32
|
||||
{17BEB9AD-5DA8-4B49-9369-B6715831C381}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{17BEB9AD-5DA8-4B49-9369-B6715831C381}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{17BEB9AD-5DA8-4B49-9369-B6715831C381}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{17BEB9AD-5DA8-4B49-9369-B6715831C381}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet_Handler_Library", "BACnet_Handler_Library\BACnet_Handler_Library.vcxproj", "{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet_Object_Definitions", "BACnet_Object_Definitions\BACnet_Object_Definitions.vcxproj", "{6D42B11A-84DA-46DB-9D08-319329D51473}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet_Stack_Library", "BACnet_Stack_Library\BACnet_Stack_Library.vcxproj", "{D0875CC6-8B68-404C-ABD7-823FE0C084DD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "Server\Server.vcxproj", "{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Debug|x64.Build.0 = Debug|x64
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Release|x64.ActiveCfg = Release|x64
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Release|x64.Build.0 = Release|x64
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Release|x86.Build.0 = Release|Win32
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Debug|x64.Build.0 = Debug|x64
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Release|x64.ActiveCfg = Release|x64
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Release|x64.Build.0 = Release|x64
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Release|x86.Build.0 = Release|Win32
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Debug|x64.Build.0 = Debug|x64
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Release|x64.ActiveCfg = Release|x64
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Release|x64.Build.0 = Release|x64
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Release|x86.Build.0 = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|x64.Build.0 = Debug|x64
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|x86.Build.0 = Debug|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|x64.ActiveCfg = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|x86.ActiveCfg = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet_Handler_Library", "BACnet_Handler_Library\BACnet_Handler_Library.vcxproj", "{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet_Object_Definitions", "BACnet_Object_Definitions\BACnet_Object_Definitions.vcxproj", "{6D42B11A-84DA-46DB-9D08-319329D51473}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BACnet_Stack_Library", "BACnet_Stack_Library\BACnet_Stack_Library.vcxproj", "{D0875CC6-8B68-404C-ABD7-823FE0C084DD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "Server\Server.vcxproj", "{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Debug|x64.Build.0 = Debug|x64
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Release|x64.ActiveCfg = Release|x64
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Release|x64.Build.0 = Release|x64
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2001A15D-2D0E-4FFA-8B90-5E7938AE6ECF}.Release|x86.Build.0 = Release|Win32
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Debug|x64.Build.0 = Debug|x64
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Release|x64.ActiveCfg = Release|x64
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Release|x64.Build.0 = Release|x64
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6D42B11A-84DA-46DB-9D08-319329D51473}.Release|x86.Build.0 = Release|Win32
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Debug|x64.Build.0 = Debug|x64
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Release|x64.ActiveCfg = Release|x64
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Release|x64.Build.0 = Release|x64
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D0875CC6-8B68-404C-ABD7-823FE0C084DD}.Release|x86.Build.0 = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|x64.Build.0 = Debug|x64
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Debug|x86.Build.0 = Debug|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|x64.ActiveCfg = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|x86.ActiveCfg = Release|Win32
|
||||
{EF250061-B9E3-4EEF-8C87-4AB52AF30B3E}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
+528
-528
File diff suppressed because it is too large
Load Diff
@@ -1,459 +1,459 @@
|
||||
# List of available make goals:
|
||||
#
|
||||
# all Default target, builds the project
|
||||
# clean Clean up the project
|
||||
# rebuild Rebuild the project
|
||||
#
|
||||
# doc Build the documentation
|
||||
# cleandoc Clean up the documentation
|
||||
# rebuilddoc Rebuild the documentation
|
||||
#
|
||||
#
|
||||
# Copyright (c) 2009-2012 Atmel Corporation. All rights reserved.
|
||||
#
|
||||
# \asf_license_start
|
||||
#
|
||||
# \page License
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# 4. This software may only be redistributed and used in connection with an
|
||||
# Atmel microcontroller product.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
# EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# \asf_license_stop
|
||||
#
|
||||
|
||||
# Include the config.mk file from the current working path, e.g., where the
|
||||
# user called make.
|
||||
include config.mk
|
||||
|
||||
# Tool to use to generate documentation from the source code
|
||||
DOCGEN ?= doxygen
|
||||
|
||||
# Look for source files relative to the top-level source directory
|
||||
VPATH := $(PRJ_PATH)
|
||||
|
||||
# Output target file
|
||||
target := $(TARGET)
|
||||
|
||||
# Output project name (target name minus suffix)
|
||||
project := $(basename $(target))
|
||||
|
||||
# Output target file (typically ELF or static library)
|
||||
ifeq ($(suffix $(target)),.a)
|
||||
target_type := lib
|
||||
else
|
||||
ifeq ($(suffix $(target)),.elf)
|
||||
target_type := elf
|
||||
else
|
||||
$(error "Target type $(target_type) is not supported")
|
||||
endif
|
||||
endif
|
||||
|
||||
# Allow override of operating system detection. The user can add OS=Linux or
|
||||
# OS=Windows on the command line to explicit set the host OS.
|
||||
#
|
||||
# This allows to work around broken uname utility on certain systems.
|
||||
ifdef OS
|
||||
ifeq ($(strip $(OS)), Linux)
|
||||
os_type := Linux
|
||||
endif
|
||||
ifeq ($(strip $(OS)), Windows)
|
||||
os_type := windows32_64
|
||||
endif
|
||||
endif
|
||||
|
||||
os_type ?= $(strip $(shell uname))
|
||||
|
||||
ifeq ($(os_type),windows32)
|
||||
os := Windows
|
||||
else
|
||||
ifeq ($(os_type),windows64)
|
||||
os := Windows
|
||||
else
|
||||
ifeq ($(os_type),windows32_64)
|
||||
os ?= Windows
|
||||
else
|
||||
ifeq ($(os_type),)
|
||||
os := Windows
|
||||
else
|
||||
# Default to Linux style operating system. Both Cygwin and mingw are fully
|
||||
# compatible (for this Makefile) with Linux.
|
||||
os := Linux
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Output documentation directory and configuration file.
|
||||
docdir := ../doxygen/html
|
||||
doccfg := ../doxygen/doxyfile.doxygen
|
||||
|
||||
CROSS ?= avr-
|
||||
AR := $(CROSS)ar
|
||||
AS := $(CROSS)as
|
||||
CC := $(CROSS)gcc
|
||||
CPP := $(CROSS)gcc -E
|
||||
CXX := $(CROSS)g++
|
||||
LD := $(CROSS)g++
|
||||
NM := $(CROSS)nm
|
||||
OBJCOPY := $(CROSS)objcopy
|
||||
OBJDUMP := $(CROSS)objdump
|
||||
SIZE := $(CROSS)size
|
||||
|
||||
RM := rm
|
||||
ifeq ($(os),Windows)
|
||||
RMDIR := rmdir /S /Q
|
||||
else
|
||||
RMDIR := rmdir -p --ignore-fail-on-non-empty
|
||||
endif
|
||||
|
||||
# Strings for beautifying output
|
||||
MSG_CLEAN_FILES = "RM *.o *.d"
|
||||
MSG_CLEAN_DIRS = "RMDIR $(strip $(clean-dirs))"
|
||||
MSG_CLEAN_DOC = "RMDIR $(docdir)"
|
||||
MSG_MKDIR = "MKDIR $(dir $@)"
|
||||
|
||||
MSG_INFO = "INFO "
|
||||
|
||||
MSG_ARCHIVING = "AR $@"
|
||||
MSG_ASSEMBLING = "AS $@"
|
||||
MSG_BINARY_IMAGE = "OBJCOPY $@"
|
||||
MSG_COMPILING = "CC $@"
|
||||
MSG_COMPILING_CXX = "CXX $@"
|
||||
MSG_EEPROM_IMAGE = "OBJCOPY $@"
|
||||
MSG_EXTENDED_LISTING = "OBJDUMP $@"
|
||||
MSG_IHEX_IMAGE = "OBJCOPY $@"
|
||||
MSG_LINKING = "LN $@"
|
||||
MSG_PREPROCESSING = "CPP $@"
|
||||
MSG_SIZE = "SIZE $@"
|
||||
MSG_SYMBOL_TABLE = "NM $@"
|
||||
|
||||
MSG_GENERATING_DOC = "DOXYGEN $(docdir)"
|
||||
|
||||
# Don't use make's built-in rules and variables
|
||||
MAKEFLAGS += -rR
|
||||
|
||||
# Don't print 'Entering directory ...'
|
||||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
# Function for reversing the order of a list
|
||||
reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
|
||||
|
||||
# Hide command output by default, but allow the user to override this
|
||||
# by adding V=1 on the command line.
|
||||
#
|
||||
# This is inspired by the Kbuild system used by the Linux kernel.
|
||||
ifdef V
|
||||
ifeq ("$(origin V)", "command line")
|
||||
VERBOSE = $(V)
|
||||
endif
|
||||
endif
|
||||
ifndef VERBOSE
|
||||
VERBOSE = 0
|
||||
endif
|
||||
|
||||
ifeq ($(VERBOSE), 1)
|
||||
Q =
|
||||
else
|
||||
Q = @
|
||||
endif
|
||||
|
||||
arflags-gnu-y := $(ARFLAGS)
|
||||
asflags-gnu-y := $(ASFLAGS)
|
||||
cflags-gnu-y := $(CFLAGS)
|
||||
cxxflags-gnu-y := $(CXXFLAGS)
|
||||
cppflags-gnu-y := $(CPPFLAGS)
|
||||
cpuflags-gnu-y :=
|
||||
dbgflags-gnu-y := $(DBGFLAGS)
|
||||
libflags-gnu-y := $(foreach LIB,$(LIBS),-l$(LIB))
|
||||
ldflags-gnu-y := $(LDFLAGS)
|
||||
flashflags-gnu-y := $(FLASHFLAGS)
|
||||
eepromflags-gnu-y := $(EEPROMFLAGS)
|
||||
clean-files :=
|
||||
clean-dirs :=
|
||||
|
||||
clean-files += $(wildcard $(target) $(project).map)
|
||||
clean-files += $(wildcard $(project).hex $(project).eep)
|
||||
clean-files += $(wildcard $(project).lss $(project).sym)
|
||||
clean-files += $(wildcard $(build))
|
||||
|
||||
# Use pipes instead of temporary files for communication between processes
|
||||
cflags-gnu-y += -pipe
|
||||
asflags-gnu-y += -pipe
|
||||
ldflags-gnu-y += -pipe
|
||||
|
||||
# Archiver flags.
|
||||
arflags-gnu-y += rcs
|
||||
|
||||
# Always enable warnings. And be very careful about implicit
|
||||
# declarations.
|
||||
cflags-gnu-y += -Wall -Wstrict-prototypes -Wmissing-prototypes
|
||||
cflags-gnu-y += -Werror-implicit-function-declaration
|
||||
cxxflags-gnu-y += -Wall
|
||||
# IAR doesn't allow arithmetic on void pointers, so warn about that.
|
||||
cflags-gnu-y += -Wpointer-arith
|
||||
cxxflags-gnu-y += -Wpointer-arith
|
||||
|
||||
# Preprocessor flags.
|
||||
cppflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),-I$(INC))
|
||||
asflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),'-Wa,-I$(INC)')
|
||||
|
||||
# CPU specific flags.
|
||||
cpuflags-gnu-y += -mmcu=$(MCU)
|
||||
|
||||
# Dependency file flags.
|
||||
depflags = -MD -MP -MQ $@
|
||||
|
||||
# Debug specific flags.
|
||||
ifdef BUILD_DEBUG_LEVEL
|
||||
dbgflags-gnu-y += -g$(BUILD_DEBUG_LEVEL)
|
||||
else
|
||||
dbgflags-gnu-y += -gdwarf-2
|
||||
endif
|
||||
|
||||
# Optimization specific flags.
|
||||
ifdef BUILD_OPTIMIZATION
|
||||
optflags-gnu-y = -O$(BUILD_OPTIMIZATION)
|
||||
else
|
||||
optflags-gnu-y = $(OPTIMIZATION)
|
||||
endif
|
||||
|
||||
# Relax compilation and linking.
|
||||
cflags-gnu-y += -mrelax
|
||||
cxxflags-gnu-y += -mrelax
|
||||
asflags-gnu-y += -mrelax
|
||||
ldflags-gnu-y += -Wl,--relax
|
||||
|
||||
# Always preprocess assembler files.
|
||||
asflags-gnu-y += -x assembler-with-cpp
|
||||
# Compile C files using the GNU99 standard.
|
||||
cflags-gnu-y += -std=gnu99
|
||||
# Compile C++ files using the GNU++98 standard.
|
||||
cxxflags-gnu-y += -std=gnu++98
|
||||
|
||||
# Use unsigned character type when compiling.
|
||||
cflags-gnu-y += -funsigned-char
|
||||
cxxflags-gnu-y += -funsigned-char
|
||||
|
||||
# Don't use strict aliasing (very common in embedded applications).
|
||||
cflags-gnu-y += -fno-strict-aliasing
|
||||
cxxflags-gnu-y += -fno-strict-aliasing
|
||||
|
||||
# Separate each function and data into its own separate section to allow
|
||||
# garbage collection of unused sections.
|
||||
cflags-gnu-y += -ffunction-sections -fdata-sections
|
||||
cxxflags-gnu-y += -ffunction-sections -fdata-sections
|
||||
|
||||
# Garbage collect unreferred sections when linking.
|
||||
ldflags-gnu-y += -Wl,--gc-sections
|
||||
|
||||
# Output a link map file and a cross reference table
|
||||
ldflags-gnu-y += -Wl,-Map=$(project).map,--cref
|
||||
|
||||
# Add library search paths relative to the top level directory.
|
||||
ldflags-gnu-y += $(foreach _LIB_PATH,$(addprefix $(PRJ_PATH)/,$(LIB_PATH)),-L$(_LIB_PATH))
|
||||
|
||||
a_flags = $(cpuflags-gnu-y) $(depflags) $(cppflags-gnu-y) $(asflags-gnu-y) -D__ASSEMBLY__
|
||||
c_flags = $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cflags-gnu-y)
|
||||
cxx_flags= $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cxxflags-gnu-y)
|
||||
l_flags = $(cpuflags-gnu-y) $(optflags-gnu-y) $(ldflags-gnu-y)
|
||||
ar_flags = $(arflags-gnu-y)
|
||||
|
||||
# Intel Hex file production flags
|
||||
flashflags-gnu-y += -R .eeprom -R .usb_descriptor_table
|
||||
|
||||
# Eeprom file production flags
|
||||
eepromflags-gnu-y += -j .eeprom
|
||||
eepromflags-gnu-y += --set-section-flags=.eeprom="alloc,load"
|
||||
eepromflags-gnu-y += --change-section-lma .eeprom=0
|
||||
|
||||
# Source files list and part informations must already be included before
|
||||
# running this makefile
|
||||
|
||||
# If a custom build directory is specified, use it -- force trailing / in directory name.
|
||||
ifdef BUILD_DIR
|
||||
build-dir := $(dir $(BUILD_DIR))$(if $(notdir $(BUILD_DIR)),$(notdir $(BUILD_DIR))/)
|
||||
else
|
||||
build-dir =
|
||||
endif
|
||||
|
||||
# Create object files list from source files list.
|
||||
obj-y := $(addprefix $(build-dir), $(addsuffix .o,$(basename $(CSRCS) $(ASSRCS))))
|
||||
|
||||
# Create dependency files list from source files list.
|
||||
dep-files := $(wildcard $(foreach f,$(obj-y),$(basename $(f)).d))
|
||||
|
||||
clean-files += $(wildcard $(obj-y))
|
||||
clean-files += $(dep-files)
|
||||
|
||||
clean-dirs += $(call reverse,$(sort $(wildcard $(dir $(obj-y)))))
|
||||
|
||||
# Default target.
|
||||
.PHONY: all
|
||||
ifeq ($(target_type),lib)
|
||||
all: $(target) $(project).lss $(project).sym
|
||||
else
|
||||
ifeq ($(target_type),elf)
|
||||
all: $(target) $(project).hex $(project).lss $(project).sym
|
||||
endif
|
||||
endif
|
||||
|
||||
# Clean up the project.
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(if $(strip $(clean-files)),echo $(MSG_CLEAN_FILES))
|
||||
$(if $(strip $(clean-files)),$(Q)$(RM) $(clean-files),)
|
||||
@$(if $(strip $(clean-dirs)),echo $(MSG_CLEAN_DIRS))
|
||||
# Remove created directories, and make sure we only remove existing
|
||||
# directories, since recursive rmdir might help us a bit on the way.
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)$(if $(strip $(clean-dirs)), \
|
||||
$(RMDIR) $(strip $(subst /,\,$(clean-dirs))))
|
||||
else
|
||||
$(Q)$(if $(strip $(clean-dirs)), \
|
||||
for directory in $(strip $(clean-dirs)); do \
|
||||
if [ -d "$$directory" ]; then \
|
||||
$(RMDIR) $$directory; \
|
||||
fi \
|
||||
done \
|
||||
)
|
||||
endif
|
||||
|
||||
# Rebuild the project.
|
||||
.PHONY: rebuild
|
||||
rebuild: clean all
|
||||
|
||||
.PHONY: objfiles
|
||||
objfiles: $(obj-y)
|
||||
|
||||
# Create object files from C source files.
|
||||
$(build-dir)%.o: %.c $(MAKEFILE_PATH) config.mk
|
||||
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@))
|
||||
else
|
||||
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
|
||||
endif
|
||||
@echo $(MSG_COMPILING)
|
||||
$(Q)$(CC) $(c_flags) -c $< -o $@
|
||||
|
||||
# Create object files from C++ source files.
|
||||
$(build-dir)%.o: %.cpp $(MAKEFILE_PATH) config.mk
|
||||
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@))
|
||||
else
|
||||
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
|
||||
endif
|
||||
@echo $(MSG_COMPILING_CXX)
|
||||
$(Q)$(CXX) $(cxx_flags) -c $< -o $@
|
||||
|
||||
# Preprocess and assemble: create object files from assembler source files.
|
||||
$(build-dir)%.o: %.s $(MAKEFILE_PATH) config.mk
|
||||
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@))
|
||||
else
|
||||
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
|
||||
endif
|
||||
@echo $(MSG_ASSEMBLING)
|
||||
$(Q)$(CC) $(a_flags) -c $< -o $@
|
||||
|
||||
# Preprocess and assemble: create object files from assembler source files.
|
||||
$(build-dir)%.o: %.S $(MAKEFILE_PATH) config.mk
|
||||
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@))
|
||||
else
|
||||
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
|
||||
endif
|
||||
@echo $(MSG_ASSEMBLING)
|
||||
$(Q)$(CC) $(a_flags) -c $< -o $@
|
||||
|
||||
# Include all dependency files to add depedency to all header files in use.
|
||||
include $(dep-files)
|
||||
|
||||
ifeq ($(target_type),lib)
|
||||
# Archive object files into an archive
|
||||
$(target): $(MAKEFILE_PATH) config.mk $(obj-y)
|
||||
@echo $(MSG_ARCHIVING)
|
||||
$(Q)$(AR) $(ar_flags) $@ $(obj-y)
|
||||
@echo $(MSG_SIZE)
|
||||
$(Q)$(SIZE) -Bxt $@
|
||||
else
|
||||
ifeq ($(target_type),elf)
|
||||
# Link the object files into an ELF file. Also make sure the target is rebuilt
|
||||
# if the common Makefile.avr.in or project config.mk is changed.
|
||||
$(target): $(MAKEFILE_PATH) config.mk $(obj-y)
|
||||
@echo $(MSG_LINKING)
|
||||
$(Q)$(CC) $(l_flags) $(obj-y) $(libflags-gnu-y) -o $@
|
||||
@echo $(MSG_SIZE)
|
||||
$(Q)$(SIZE) -Ax $@
|
||||
$(Q)$(SIZE) -Bx $@
|
||||
endif
|
||||
endif
|
||||
|
||||
# Create extended function listing from target output file.
|
||||
%.lss: $(target)
|
||||
@echo $(MSG_EXTENDED_LISTING)
|
||||
$(Q)$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Create symbol table from target output file.
|
||||
%.sym: $(target)
|
||||
@echo $(MSG_SYMBOL_TABLE)
|
||||
$(Q)$(NM) -n $< > $@
|
||||
|
||||
# Create Intel HEX image from ELF output file.
|
||||
%.hex: $(target)
|
||||
@echo $(MSG_IHEX_IMAGE)
|
||||
$(Q)$(OBJCOPY) -O ihex $(flashflags-gnu-y) $< $@
|
||||
|
||||
# Create EEPROM Intel HEX image from ELF output file.
|
||||
%.eep: $(target)
|
||||
@echo $(MSG_EEPROM_IMAGE)
|
||||
$(Q)$(OBJCOPY) $(eepromflags-gnu-y) -O ihex $< $@ || exit 0
|
||||
|
||||
# Provide information about the detected host operating system.
|
||||
.SECONDARY: info-os
|
||||
info-os:
|
||||
@echo $(MSG_INFO)$(os) build host detected
|
||||
|
||||
# Build Doxygen generated documentation.
|
||||
.PHONY: doc
|
||||
doc:
|
||||
@echo $(MSG_GENERATING_DOC)
|
||||
$(Q)cd $(dir $(doccfg)) && $(DOCGEN) $(notdir $(doccfg))
|
||||
|
||||
# Clean Doxygen generated documentation.
|
||||
.PHONY: cleandoc
|
||||
cleandoc:
|
||||
@$(if $(wildcard $(docdir)),echo $(MSG_CLEAN_DOC))
|
||||
$(Q)$(if $(wildcard $(docdir)),$(RM) --recursive $(docdir))
|
||||
|
||||
# Rebuild the Doxygen generated documentation.
|
||||
.PHONY: rebuilddoc
|
||||
rebuilddoc: cleandoc doc
|
||||
# List of available make goals:
|
||||
#
|
||||
# all Default target, builds the project
|
||||
# clean Clean up the project
|
||||
# rebuild Rebuild the project
|
||||
#
|
||||
# doc Build the documentation
|
||||
# cleandoc Clean up the documentation
|
||||
# rebuilddoc Rebuild the documentation
|
||||
#
|
||||
#
|
||||
# Copyright (c) 2009-2012 Atmel Corporation. All rights reserved.
|
||||
#
|
||||
# \asf_license_start
|
||||
#
|
||||
# \page License
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# 4. This software may only be redistributed and used in connection with an
|
||||
# Atmel microcontroller product.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
# EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# \asf_license_stop
|
||||
#
|
||||
|
||||
# Include the config.mk file from the current working path, e.g., where the
|
||||
# user called make.
|
||||
include config.mk
|
||||
|
||||
# Tool to use to generate documentation from the source code
|
||||
DOCGEN ?= doxygen
|
||||
|
||||
# Look for source files relative to the top-level source directory
|
||||
VPATH := $(PRJ_PATH)
|
||||
|
||||
# Output target file
|
||||
target := $(TARGET)
|
||||
|
||||
# Output project name (target name minus suffix)
|
||||
project := $(basename $(target))
|
||||
|
||||
# Output target file (typically ELF or static library)
|
||||
ifeq ($(suffix $(target)),.a)
|
||||
target_type := lib
|
||||
else
|
||||
ifeq ($(suffix $(target)),.elf)
|
||||
target_type := elf
|
||||
else
|
||||
$(error "Target type $(target_type) is not supported")
|
||||
endif
|
||||
endif
|
||||
|
||||
# Allow override of operating system detection. The user can add OS=Linux or
|
||||
# OS=Windows on the command line to explicit set the host OS.
|
||||
#
|
||||
# This allows to work around broken uname utility on certain systems.
|
||||
ifdef OS
|
||||
ifeq ($(strip $(OS)), Linux)
|
||||
os_type := Linux
|
||||
endif
|
||||
ifeq ($(strip $(OS)), Windows)
|
||||
os_type := windows32_64
|
||||
endif
|
||||
endif
|
||||
|
||||
os_type ?= $(strip $(shell uname))
|
||||
|
||||
ifeq ($(os_type),windows32)
|
||||
os := Windows
|
||||
else
|
||||
ifeq ($(os_type),windows64)
|
||||
os := Windows
|
||||
else
|
||||
ifeq ($(os_type),windows32_64)
|
||||
os ?= Windows
|
||||
else
|
||||
ifeq ($(os_type),)
|
||||
os := Windows
|
||||
else
|
||||
# Default to Linux style operating system. Both Cygwin and mingw are fully
|
||||
# compatible (for this Makefile) with Linux.
|
||||
os := Linux
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Output documentation directory and configuration file.
|
||||
docdir := ../doxygen/html
|
||||
doccfg := ../doxygen/doxyfile.doxygen
|
||||
|
||||
CROSS ?= avr-
|
||||
AR := $(CROSS)ar
|
||||
AS := $(CROSS)as
|
||||
CC := $(CROSS)gcc
|
||||
CPP := $(CROSS)gcc -E
|
||||
CXX := $(CROSS)g++
|
||||
LD := $(CROSS)g++
|
||||
NM := $(CROSS)nm
|
||||
OBJCOPY := $(CROSS)objcopy
|
||||
OBJDUMP := $(CROSS)objdump
|
||||
SIZE := $(CROSS)size
|
||||
|
||||
RM := rm
|
||||
ifeq ($(os),Windows)
|
||||
RMDIR := rmdir /S /Q
|
||||
else
|
||||
RMDIR := rmdir -p --ignore-fail-on-non-empty
|
||||
endif
|
||||
|
||||
# Strings for beautifying output
|
||||
MSG_CLEAN_FILES = "RM *.o *.d"
|
||||
MSG_CLEAN_DIRS = "RMDIR $(strip $(clean-dirs))"
|
||||
MSG_CLEAN_DOC = "RMDIR $(docdir)"
|
||||
MSG_MKDIR = "MKDIR $(dir $@)"
|
||||
|
||||
MSG_INFO = "INFO "
|
||||
|
||||
MSG_ARCHIVING = "AR $@"
|
||||
MSG_ASSEMBLING = "AS $@"
|
||||
MSG_BINARY_IMAGE = "OBJCOPY $@"
|
||||
MSG_COMPILING = "CC $@"
|
||||
MSG_COMPILING_CXX = "CXX $@"
|
||||
MSG_EEPROM_IMAGE = "OBJCOPY $@"
|
||||
MSG_EXTENDED_LISTING = "OBJDUMP $@"
|
||||
MSG_IHEX_IMAGE = "OBJCOPY $@"
|
||||
MSG_LINKING = "LN $@"
|
||||
MSG_PREPROCESSING = "CPP $@"
|
||||
MSG_SIZE = "SIZE $@"
|
||||
MSG_SYMBOL_TABLE = "NM $@"
|
||||
|
||||
MSG_GENERATING_DOC = "DOXYGEN $(docdir)"
|
||||
|
||||
# Don't use make's built-in rules and variables
|
||||
MAKEFLAGS += -rR
|
||||
|
||||
# Don't print 'Entering directory ...'
|
||||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
# Function for reversing the order of a list
|
||||
reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
|
||||
|
||||
# Hide command output by default, but allow the user to override this
|
||||
# by adding V=1 on the command line.
|
||||
#
|
||||
# This is inspired by the Kbuild system used by the Linux kernel.
|
||||
ifdef V
|
||||
ifeq ("$(origin V)", "command line")
|
||||
VERBOSE = $(V)
|
||||
endif
|
||||
endif
|
||||
ifndef VERBOSE
|
||||
VERBOSE = 0
|
||||
endif
|
||||
|
||||
ifeq ($(VERBOSE), 1)
|
||||
Q =
|
||||
else
|
||||
Q = @
|
||||
endif
|
||||
|
||||
arflags-gnu-y := $(ARFLAGS)
|
||||
asflags-gnu-y := $(ASFLAGS)
|
||||
cflags-gnu-y := $(CFLAGS)
|
||||
cxxflags-gnu-y := $(CXXFLAGS)
|
||||
cppflags-gnu-y := $(CPPFLAGS)
|
||||
cpuflags-gnu-y :=
|
||||
dbgflags-gnu-y := $(DBGFLAGS)
|
||||
libflags-gnu-y := $(foreach LIB,$(LIBS),-l$(LIB))
|
||||
ldflags-gnu-y := $(LDFLAGS)
|
||||
flashflags-gnu-y := $(FLASHFLAGS)
|
||||
eepromflags-gnu-y := $(EEPROMFLAGS)
|
||||
clean-files :=
|
||||
clean-dirs :=
|
||||
|
||||
clean-files += $(wildcard $(target) $(project).map)
|
||||
clean-files += $(wildcard $(project).hex $(project).eep)
|
||||
clean-files += $(wildcard $(project).lss $(project).sym)
|
||||
clean-files += $(wildcard $(build))
|
||||
|
||||
# Use pipes instead of temporary files for communication between processes
|
||||
cflags-gnu-y += -pipe
|
||||
asflags-gnu-y += -pipe
|
||||
ldflags-gnu-y += -pipe
|
||||
|
||||
# Archiver flags.
|
||||
arflags-gnu-y += rcs
|
||||
|
||||
# Always enable warnings. And be very careful about implicit
|
||||
# declarations.
|
||||
cflags-gnu-y += -Wall -Wstrict-prototypes -Wmissing-prototypes
|
||||
cflags-gnu-y += -Werror-implicit-function-declaration
|
||||
cxxflags-gnu-y += -Wall
|
||||
# IAR doesn't allow arithmetic on void pointers, so warn about that.
|
||||
cflags-gnu-y += -Wpointer-arith
|
||||
cxxflags-gnu-y += -Wpointer-arith
|
||||
|
||||
# Preprocessor flags.
|
||||
cppflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),-I$(INC))
|
||||
asflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),'-Wa,-I$(INC)')
|
||||
|
||||
# CPU specific flags.
|
||||
cpuflags-gnu-y += -mmcu=$(MCU)
|
||||
|
||||
# Dependency file flags.
|
||||
depflags = -MD -MP -MQ $@
|
||||
|
||||
# Debug specific flags.
|
||||
ifdef BUILD_DEBUG_LEVEL
|
||||
dbgflags-gnu-y += -g$(BUILD_DEBUG_LEVEL)
|
||||
else
|
||||
dbgflags-gnu-y += -gdwarf-2
|
||||
endif
|
||||
|
||||
# Optimization specific flags.
|
||||
ifdef BUILD_OPTIMIZATION
|
||||
optflags-gnu-y = -O$(BUILD_OPTIMIZATION)
|
||||
else
|
||||
optflags-gnu-y = $(OPTIMIZATION)
|
||||
endif
|
||||
|
||||
# Relax compilation and linking.
|
||||
cflags-gnu-y += -mrelax
|
||||
cxxflags-gnu-y += -mrelax
|
||||
asflags-gnu-y += -mrelax
|
||||
ldflags-gnu-y += -Wl,--relax
|
||||
|
||||
# Always preprocess assembler files.
|
||||
asflags-gnu-y += -x assembler-with-cpp
|
||||
# Compile C files using the GNU99 standard.
|
||||
cflags-gnu-y += -std=gnu99
|
||||
# Compile C++ files using the GNU++98 standard.
|
||||
cxxflags-gnu-y += -std=gnu++98
|
||||
|
||||
# Use unsigned character type when compiling.
|
||||
cflags-gnu-y += -funsigned-char
|
||||
cxxflags-gnu-y += -funsigned-char
|
||||
|
||||
# Don't use strict aliasing (very common in embedded applications).
|
||||
cflags-gnu-y += -fno-strict-aliasing
|
||||
cxxflags-gnu-y += -fno-strict-aliasing
|
||||
|
||||
# Separate each function and data into its own separate section to allow
|
||||
# garbage collection of unused sections.
|
||||
cflags-gnu-y += -ffunction-sections -fdata-sections
|
||||
cxxflags-gnu-y += -ffunction-sections -fdata-sections
|
||||
|
||||
# Garbage collect unreferred sections when linking.
|
||||
ldflags-gnu-y += -Wl,--gc-sections
|
||||
|
||||
# Output a link map file and a cross reference table
|
||||
ldflags-gnu-y += -Wl,-Map=$(project).map,--cref
|
||||
|
||||
# Add library search paths relative to the top level directory.
|
||||
ldflags-gnu-y += $(foreach _LIB_PATH,$(addprefix $(PRJ_PATH)/,$(LIB_PATH)),-L$(_LIB_PATH))
|
||||
|
||||
a_flags = $(cpuflags-gnu-y) $(depflags) $(cppflags-gnu-y) $(asflags-gnu-y) -D__ASSEMBLY__
|
||||
c_flags = $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cflags-gnu-y)
|
||||
cxx_flags= $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cxxflags-gnu-y)
|
||||
l_flags = $(cpuflags-gnu-y) $(optflags-gnu-y) $(ldflags-gnu-y)
|
||||
ar_flags = $(arflags-gnu-y)
|
||||
|
||||
# Intel Hex file production flags
|
||||
flashflags-gnu-y += -R .eeprom -R .usb_descriptor_table
|
||||
|
||||
# Eeprom file production flags
|
||||
eepromflags-gnu-y += -j .eeprom
|
||||
eepromflags-gnu-y += --set-section-flags=.eeprom="alloc,load"
|
||||
eepromflags-gnu-y += --change-section-lma .eeprom=0
|
||||
|
||||
# Source files list and part informations must already be included before
|
||||
# running this makefile
|
||||
|
||||
# If a custom build directory is specified, use it -- force trailing / in directory name.
|
||||
ifdef BUILD_DIR
|
||||
build-dir := $(dir $(BUILD_DIR))$(if $(notdir $(BUILD_DIR)),$(notdir $(BUILD_DIR))/)
|
||||
else
|
||||
build-dir =
|
||||
endif
|
||||
|
||||
# Create object files list from source files list.
|
||||
obj-y := $(addprefix $(build-dir), $(addsuffix .o,$(basename $(CSRCS) $(ASSRCS))))
|
||||
|
||||
# Create dependency files list from source files list.
|
||||
dep-files := $(wildcard $(foreach f,$(obj-y),$(basename $(f)).d))
|
||||
|
||||
clean-files += $(wildcard $(obj-y))
|
||||
clean-files += $(dep-files)
|
||||
|
||||
clean-dirs += $(call reverse,$(sort $(wildcard $(dir $(obj-y)))))
|
||||
|
||||
# Default target.
|
||||
.PHONY: all
|
||||
ifeq ($(target_type),lib)
|
||||
all: $(target) $(project).lss $(project).sym
|
||||
else
|
||||
ifeq ($(target_type),elf)
|
||||
all: $(target) $(project).hex $(project).lss $(project).sym
|
||||
endif
|
||||
endif
|
||||
|
||||
# Clean up the project.
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(if $(strip $(clean-files)),echo $(MSG_CLEAN_FILES))
|
||||
$(if $(strip $(clean-files)),$(Q)$(RM) $(clean-files),)
|
||||
@$(if $(strip $(clean-dirs)),echo $(MSG_CLEAN_DIRS))
|
||||
# Remove created directories, and make sure we only remove existing
|
||||
# directories, since recursive rmdir might help us a bit on the way.
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)$(if $(strip $(clean-dirs)), \
|
||||
$(RMDIR) $(strip $(subst /,\,$(clean-dirs))))
|
||||
else
|
||||
$(Q)$(if $(strip $(clean-dirs)), \
|
||||
for directory in $(strip $(clean-dirs)); do \
|
||||
if [ -d "$$directory" ]; then \
|
||||
$(RMDIR) $$directory; \
|
||||
fi \
|
||||
done \
|
||||
)
|
||||
endif
|
||||
|
||||
# Rebuild the project.
|
||||
.PHONY: rebuild
|
||||
rebuild: clean all
|
||||
|
||||
.PHONY: objfiles
|
||||
objfiles: $(obj-y)
|
||||
|
||||
# Create object files from C source files.
|
||||
$(build-dir)%.o: %.c $(MAKEFILE_PATH) config.mk
|
||||
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@))
|
||||
else
|
||||
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
|
||||
endif
|
||||
@echo $(MSG_COMPILING)
|
||||
$(Q)$(CC) $(c_flags) -c $< -o $@
|
||||
|
||||
# Create object files from C++ source files.
|
||||
$(build-dir)%.o: %.cpp $(MAKEFILE_PATH) config.mk
|
||||
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@))
|
||||
else
|
||||
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
|
||||
endif
|
||||
@echo $(MSG_COMPILING_CXX)
|
||||
$(Q)$(CXX) $(cxx_flags) -c $< -o $@
|
||||
|
||||
# Preprocess and assemble: create object files from assembler source files.
|
||||
$(build-dir)%.o: %.s $(MAKEFILE_PATH) config.mk
|
||||
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@))
|
||||
else
|
||||
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
|
||||
endif
|
||||
@echo $(MSG_ASSEMBLING)
|
||||
$(Q)$(CC) $(a_flags) -c $< -o $@
|
||||
|
||||
# Preprocess and assemble: create object files from assembler source files.
|
||||
$(build-dir)%.o: %.S $(MAKEFILE_PATH) config.mk
|
||||
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
|
||||
ifeq ($(os),Windows)
|
||||
$(Q)test -d $(dir $@) || mkdir $(subst /,\,$(dir $@))
|
||||
else
|
||||
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
|
||||
endif
|
||||
@echo $(MSG_ASSEMBLING)
|
||||
$(Q)$(CC) $(a_flags) -c $< -o $@
|
||||
|
||||
# Include all dependency files to add depedency to all header files in use.
|
||||
include $(dep-files)
|
||||
|
||||
ifeq ($(target_type),lib)
|
||||
# Archive object files into an archive
|
||||
$(target): $(MAKEFILE_PATH) config.mk $(obj-y)
|
||||
@echo $(MSG_ARCHIVING)
|
||||
$(Q)$(AR) $(ar_flags) $@ $(obj-y)
|
||||
@echo $(MSG_SIZE)
|
||||
$(Q)$(SIZE) -Bxt $@
|
||||
else
|
||||
ifeq ($(target_type),elf)
|
||||
# Link the object files into an ELF file. Also make sure the target is rebuilt
|
||||
# if the common Makefile.avr.in or project config.mk is changed.
|
||||
$(target): $(MAKEFILE_PATH) config.mk $(obj-y)
|
||||
@echo $(MSG_LINKING)
|
||||
$(Q)$(CC) $(l_flags) $(obj-y) $(libflags-gnu-y) -o $@
|
||||
@echo $(MSG_SIZE)
|
||||
$(Q)$(SIZE) -Ax $@
|
||||
$(Q)$(SIZE) -Bx $@
|
||||
endif
|
||||
endif
|
||||
|
||||
# Create extended function listing from target output file.
|
||||
%.lss: $(target)
|
||||
@echo $(MSG_EXTENDED_LISTING)
|
||||
$(Q)$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Create symbol table from target output file.
|
||||
%.sym: $(target)
|
||||
@echo $(MSG_SYMBOL_TABLE)
|
||||
$(Q)$(NM) -n $< > $@
|
||||
|
||||
# Create Intel HEX image from ELF output file.
|
||||
%.hex: $(target)
|
||||
@echo $(MSG_IHEX_IMAGE)
|
||||
$(Q)$(OBJCOPY) -O ihex $(flashflags-gnu-y) $< $@
|
||||
|
||||
# Create EEPROM Intel HEX image from ELF output file.
|
||||
%.eep: $(target)
|
||||
@echo $(MSG_EEPROM_IMAGE)
|
||||
$(Q)$(OBJCOPY) $(eepromflags-gnu-y) -O ihex $< $@ || exit 0
|
||||
|
||||
# Provide information about the detected host operating system.
|
||||
.SECONDARY: info-os
|
||||
info-os:
|
||||
@echo $(MSG_INFO)$(os) build host detected
|
||||
|
||||
# Build Doxygen generated documentation.
|
||||
.PHONY: doc
|
||||
doc:
|
||||
@echo $(MSG_GENERATING_DOC)
|
||||
$(Q)cd $(dir $(doccfg)) && $(DOCGEN) $(notdir $(doccfg))
|
||||
|
||||
# Clean Doxygen generated documentation.
|
||||
.PHONY: cleandoc
|
||||
cleandoc:
|
||||
@$(if $(wildcard $(docdir)),echo $(MSG_CLEAN_DOC))
|
||||
$(Q)$(if $(wildcard $(docdir)),$(RM) --recursive $(docdir))
|
||||
|
||||
# Rebuild the Doxygen generated documentation.
|
||||
.PHONY: rebuilddoc
|
||||
rebuilddoc: cleandoc doc
|
||||
|
||||
+2337
-2337
File diff suppressed because it is too large
Load Diff
+326
-326
@@ -1,326 +1,326 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2015 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "bacdef.h"
|
||||
#include "keylist.h"
|
||||
/* me! */
|
||||
#include "vmac.h"
|
||||
|
||||
/** @file
|
||||
Handle VMAC address binding */
|
||||
|
||||
/* This module is used to handle the virtual MAC address binding that */
|
||||
/* occurs in BACnet for ZigBee or IPv6. */
|
||||
|
||||
/* Key List for storing the object data sorted by instance number */
|
||||
static OS_Keylist VMAC_List;
|
||||
|
||||
/**
|
||||
* Returns the number of VMAC in the list
|
||||
*/
|
||||
unsigned int VMAC_Count(void)
|
||||
{
|
||||
return (unsigned int)Keylist_Count(VMAC_List);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a VMAC to the list
|
||||
*
|
||||
* @param device_id - BACnet device object instance number
|
||||
* @param src - BACnet/IPv6 address
|
||||
*
|
||||
* @return true if the device ID and MAC are added
|
||||
*/
|
||||
bool VMAC_Add(uint32_t device_id, struct vmac_data *src)
|
||||
{
|
||||
bool status = false;
|
||||
struct vmac_data *pVMAC = NULL;
|
||||
int index = 0;
|
||||
size_t i = 0;
|
||||
|
||||
pVMAC = Keylist_Data(VMAC_List, device_id);
|
||||
if (!pVMAC) {
|
||||
pVMAC = calloc(1, sizeof(struct vmac_data));
|
||||
if (pVMAC) {
|
||||
/* copy the MAC into the data store */
|
||||
for (i = 0; i < sizeof(pVMAC->mac); i++) {
|
||||
if (i < src->mac_len) {
|
||||
pVMAC->mac[i] = src->mac[i];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pVMAC->mac_len = src->mac_len;
|
||||
index = Keylist_Data_Add(VMAC_List, device_id, pVMAC);
|
||||
if (index >= 0) {
|
||||
status = true;
|
||||
printf("VMAC %u added.\n", (unsigned int)device_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a VMAC in the list by seeking the Device ID, and deletes it.
|
||||
*
|
||||
* @param device_id - BACnet device object instance number
|
||||
*
|
||||
* @return pointer to the VMAC data from the list - be sure to free() it!
|
||||
*/
|
||||
bool VMAC_Delete(uint32_t device_id)
|
||||
{
|
||||
bool status = false;
|
||||
struct vmac_data *pVMAC;
|
||||
|
||||
pVMAC = Keylist_Data_Delete(VMAC_List, device_id);
|
||||
if (pVMAC) {
|
||||
free(pVMAC);
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a VMAC in the list by seeking the Device ID.
|
||||
*
|
||||
* @param device_id - BACnet device object instance number
|
||||
*
|
||||
* @return pointer to the VMAC data from the list
|
||||
*/
|
||||
struct vmac_data *VMAC_Find_By_Key(uint32_t device_id)
|
||||
{
|
||||
return Keylist_Data(VMAC_List, device_id);
|
||||
}
|
||||
|
||||
/** Compare the VMAC address
|
||||
*
|
||||
* @param vmac1 - VMAC address that will be compared to vmac2
|
||||
* @param vmac2 - VMAC address that will be compared to vmac1
|
||||
*
|
||||
* @return true if the addresses are different
|
||||
*/
|
||||
bool VMAC_Different(
|
||||
struct vmac_data *vmac1,
|
||||
struct vmac_data *vmac2)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned int i = 0;
|
||||
unsigned int mac_len = VMAC_MAC_MAX;
|
||||
|
||||
if (vmac1 && vmac2) {
|
||||
if (vmac1->mac_len != vmac2->mac_len) {
|
||||
status = true;
|
||||
} else {
|
||||
if (vmac1->mac_len < mac_len) {
|
||||
mac_len = (unsigned int)vmac1->mac_len;
|
||||
}
|
||||
for (i = 0; i < mac_len; i++) {
|
||||
if (vmac1->mac[i] != vmac2->mac[i]) {
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Compare the VMAC address
|
||||
*
|
||||
* @param vmac1 - VMAC address that will be compared to vmac2
|
||||
* @param vmac2 - VMAC address that will be compared to vmac1
|
||||
*
|
||||
* @return true if the addresses are the same
|
||||
*/
|
||||
bool VMAC_Match(
|
||||
struct vmac_data *vmac1,
|
||||
struct vmac_data *vmac2)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned int i = 0;
|
||||
unsigned int mac_len = VMAC_MAC_MAX;
|
||||
|
||||
if (vmac1 && vmac2 && vmac1->mac_len) {
|
||||
status = true;
|
||||
if (vmac1->mac_len != vmac2->mac_len) {
|
||||
status = false;
|
||||
} else {
|
||||
if (vmac1->mac_len < mac_len) {
|
||||
mac_len = (unsigned int)vmac1->mac_len;
|
||||
}
|
||||
for (i = 0; i < mac_len; i++) {
|
||||
if (vmac1->mac[i] != vmac2->mac[i]) {
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a VMAC in the list by seeking a matching VMAC address
|
||||
*
|
||||
* @param vmac - VMAC address that will be sought
|
||||
* @param device_id - BACnet device object instance number
|
||||
*
|
||||
* @return true if the VMAC address was found
|
||||
*/
|
||||
bool VMAC_Find_By_Data(struct vmac_data *vmac, uint32_t *device_id)
|
||||
{
|
||||
bool status = false;
|
||||
struct vmac_data *list_vmac;
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
|
||||
count = Keylist_Count(VMAC_List);
|
||||
while (count) {
|
||||
index = count - 1;
|
||||
list_vmac = Keylist_Data_Index(VMAC_List, index);
|
||||
if (list_vmac) {
|
||||
if (VMAC_Match(vmac, list_vmac)) {
|
||||
if (device_id) {
|
||||
*device_id = Keylist_Key(VMAC_List, index);
|
||||
}
|
||||
status = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
count--;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the memory used by the VMAC list data
|
||||
*/
|
||||
void VMAC_Cleanup(void)
|
||||
{
|
||||
struct vmac_data *pVMAC;
|
||||
|
||||
if (VMAC_List) {
|
||||
do {
|
||||
pVMAC = Keylist_Data_Pop(VMAC_List);
|
||||
if (pVMAC) {
|
||||
free(pVMAC);
|
||||
}
|
||||
} while (pVMAC);
|
||||
Keylist_Delete(VMAC_List);
|
||||
VMAC_List = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the VMAC list data
|
||||
*/
|
||||
void VMAC_Init(void)
|
||||
{
|
||||
VMAC_List = Keylist_Create();
|
||||
if (VMAC_List) {
|
||||
atexit(VMAC_Cleanup);
|
||||
printf("VMAC List initialized.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testVMAC(
|
||||
Test * pTest)
|
||||
{
|
||||
uint32_t device_id = 123;
|
||||
uint32_t test_device_id = 0;
|
||||
struct vmac_data test_vmac_data;
|
||||
struct vmac_data *pVMAC;
|
||||
unsigned int i = 0;
|
||||
bool status = false;
|
||||
|
||||
VMAC_Init();
|
||||
for (i = 0; i < VMAC_MAC_MAX; i++) {
|
||||
test_vmac_data.mac[i] = 1 + i;
|
||||
}
|
||||
test_vmac_data.mac_len = VMAC_MAC_MAX;
|
||||
status = VMAC_Add(device_id, &test_vmac_data);
|
||||
ct_test(pTest, status);
|
||||
pVMAC = VMAC_Find_By_Key(0);
|
||||
ct_test(pTest, pVMAC == NULL);
|
||||
pVMAC = VMAC_Find_By_Key(device_id);
|
||||
ct_test(pTest, pVMAC);
|
||||
status = VMAC_Different(pVMAC, &test_vmac_data);
|
||||
ct_test(pTest, !status);
|
||||
status = VMAC_Match(pVMAC, &test_vmac_data);
|
||||
ct_test(pTest, status);
|
||||
status = VMAC_Find_By_Data(&test_vmac_data, &test_device_id);
|
||||
ct_test(pTest, status);
|
||||
ct_test(pTest, test_device_id == device_id);
|
||||
status = VMAC_Delete(device_id);
|
||||
ct_test(pTest, status);
|
||||
pVMAC = VMAC_Find_By_Key(device_id);
|
||||
ct_test(pTest, pVMAC == NULL);
|
||||
VMAC_Cleanup();
|
||||
}
|
||||
|
||||
#ifdef TEST_VMAC
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet VMAC", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testVMAC);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2015 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "bacdef.h"
|
||||
#include "keylist.h"
|
||||
/* me! */
|
||||
#include "vmac.h"
|
||||
|
||||
/** @file
|
||||
Handle VMAC address binding */
|
||||
|
||||
/* This module is used to handle the virtual MAC address binding that */
|
||||
/* occurs in BACnet for ZigBee or IPv6. */
|
||||
|
||||
/* Key List for storing the object data sorted by instance number */
|
||||
static OS_Keylist VMAC_List;
|
||||
|
||||
/**
|
||||
* Returns the number of VMAC in the list
|
||||
*/
|
||||
unsigned int VMAC_Count(void)
|
||||
{
|
||||
return (unsigned int)Keylist_Count(VMAC_List);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a VMAC to the list
|
||||
*
|
||||
* @param device_id - BACnet device object instance number
|
||||
* @param src - BACnet/IPv6 address
|
||||
*
|
||||
* @return true if the device ID and MAC are added
|
||||
*/
|
||||
bool VMAC_Add(uint32_t device_id, struct vmac_data *src)
|
||||
{
|
||||
bool status = false;
|
||||
struct vmac_data *pVMAC = NULL;
|
||||
int index = 0;
|
||||
size_t i = 0;
|
||||
|
||||
pVMAC = Keylist_Data(VMAC_List, device_id);
|
||||
if (!pVMAC) {
|
||||
pVMAC = calloc(1, sizeof(struct vmac_data));
|
||||
if (pVMAC) {
|
||||
/* copy the MAC into the data store */
|
||||
for (i = 0; i < sizeof(pVMAC->mac); i++) {
|
||||
if (i < src->mac_len) {
|
||||
pVMAC->mac[i] = src->mac[i];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pVMAC->mac_len = src->mac_len;
|
||||
index = Keylist_Data_Add(VMAC_List, device_id, pVMAC);
|
||||
if (index >= 0) {
|
||||
status = true;
|
||||
printf("VMAC %u added.\n", (unsigned int)device_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a VMAC in the list by seeking the Device ID, and deletes it.
|
||||
*
|
||||
* @param device_id - BACnet device object instance number
|
||||
*
|
||||
* @return pointer to the VMAC data from the list - be sure to free() it!
|
||||
*/
|
||||
bool VMAC_Delete(uint32_t device_id)
|
||||
{
|
||||
bool status = false;
|
||||
struct vmac_data *pVMAC;
|
||||
|
||||
pVMAC = Keylist_Data_Delete(VMAC_List, device_id);
|
||||
if (pVMAC) {
|
||||
free(pVMAC);
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a VMAC in the list by seeking the Device ID.
|
||||
*
|
||||
* @param device_id - BACnet device object instance number
|
||||
*
|
||||
* @return pointer to the VMAC data from the list
|
||||
*/
|
||||
struct vmac_data *VMAC_Find_By_Key(uint32_t device_id)
|
||||
{
|
||||
return Keylist_Data(VMAC_List, device_id);
|
||||
}
|
||||
|
||||
/** Compare the VMAC address
|
||||
*
|
||||
* @param vmac1 - VMAC address that will be compared to vmac2
|
||||
* @param vmac2 - VMAC address that will be compared to vmac1
|
||||
*
|
||||
* @return true if the addresses are different
|
||||
*/
|
||||
bool VMAC_Different(
|
||||
struct vmac_data *vmac1,
|
||||
struct vmac_data *vmac2)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned int i = 0;
|
||||
unsigned int mac_len = VMAC_MAC_MAX;
|
||||
|
||||
if (vmac1 && vmac2) {
|
||||
if (vmac1->mac_len != vmac2->mac_len) {
|
||||
status = true;
|
||||
} else {
|
||||
if (vmac1->mac_len < mac_len) {
|
||||
mac_len = (unsigned int)vmac1->mac_len;
|
||||
}
|
||||
for (i = 0; i < mac_len; i++) {
|
||||
if (vmac1->mac[i] != vmac2->mac[i]) {
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Compare the VMAC address
|
||||
*
|
||||
* @param vmac1 - VMAC address that will be compared to vmac2
|
||||
* @param vmac2 - VMAC address that will be compared to vmac1
|
||||
*
|
||||
* @return true if the addresses are the same
|
||||
*/
|
||||
bool VMAC_Match(
|
||||
struct vmac_data *vmac1,
|
||||
struct vmac_data *vmac2)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned int i = 0;
|
||||
unsigned int mac_len = VMAC_MAC_MAX;
|
||||
|
||||
if (vmac1 && vmac2 && vmac1->mac_len) {
|
||||
status = true;
|
||||
if (vmac1->mac_len != vmac2->mac_len) {
|
||||
status = false;
|
||||
} else {
|
||||
if (vmac1->mac_len < mac_len) {
|
||||
mac_len = (unsigned int)vmac1->mac_len;
|
||||
}
|
||||
for (i = 0; i < mac_len; i++) {
|
||||
if (vmac1->mac[i] != vmac2->mac[i]) {
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a VMAC in the list by seeking a matching VMAC address
|
||||
*
|
||||
* @param vmac - VMAC address that will be sought
|
||||
* @param device_id - BACnet device object instance number
|
||||
*
|
||||
* @return true if the VMAC address was found
|
||||
*/
|
||||
bool VMAC_Find_By_Data(struct vmac_data *vmac, uint32_t *device_id)
|
||||
{
|
||||
bool status = false;
|
||||
struct vmac_data *list_vmac;
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
|
||||
count = Keylist_Count(VMAC_List);
|
||||
while (count) {
|
||||
index = count - 1;
|
||||
list_vmac = Keylist_Data_Index(VMAC_List, index);
|
||||
if (list_vmac) {
|
||||
if (VMAC_Match(vmac, list_vmac)) {
|
||||
if (device_id) {
|
||||
*device_id = Keylist_Key(VMAC_List, index);
|
||||
}
|
||||
status = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
count--;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the memory used by the VMAC list data
|
||||
*/
|
||||
void VMAC_Cleanup(void)
|
||||
{
|
||||
struct vmac_data *pVMAC;
|
||||
|
||||
if (VMAC_List) {
|
||||
do {
|
||||
pVMAC = Keylist_Data_Pop(VMAC_List);
|
||||
if (pVMAC) {
|
||||
free(pVMAC);
|
||||
}
|
||||
} while (pVMAC);
|
||||
Keylist_Delete(VMAC_List);
|
||||
VMAC_List = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the VMAC list data
|
||||
*/
|
||||
void VMAC_Init(void)
|
||||
{
|
||||
VMAC_List = Keylist_Create();
|
||||
if (VMAC_List) {
|
||||
atexit(VMAC_Cleanup);
|
||||
printf("VMAC List initialized.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testVMAC(
|
||||
Test * pTest)
|
||||
{
|
||||
uint32_t device_id = 123;
|
||||
uint32_t test_device_id = 0;
|
||||
struct vmac_data test_vmac_data;
|
||||
struct vmac_data *pVMAC;
|
||||
unsigned int i = 0;
|
||||
bool status = false;
|
||||
|
||||
VMAC_Init();
|
||||
for (i = 0; i < VMAC_MAC_MAX; i++) {
|
||||
test_vmac_data.mac[i] = 1 + i;
|
||||
}
|
||||
test_vmac_data.mac_len = VMAC_MAC_MAX;
|
||||
status = VMAC_Add(device_id, &test_vmac_data);
|
||||
ct_test(pTest, status);
|
||||
pVMAC = VMAC_Find_By_Key(0);
|
||||
ct_test(pTest, pVMAC == NULL);
|
||||
pVMAC = VMAC_Find_By_Key(device_id);
|
||||
ct_test(pTest, pVMAC);
|
||||
status = VMAC_Different(pVMAC, &test_vmac_data);
|
||||
ct_test(pTest, !status);
|
||||
status = VMAC_Match(pVMAC, &test_vmac_data);
|
||||
ct_test(pTest, status);
|
||||
status = VMAC_Find_By_Data(&test_vmac_data, &test_device_id);
|
||||
ct_test(pTest, status);
|
||||
ct_test(pTest, test_device_id == device_id);
|
||||
status = VMAC_Delete(device_id);
|
||||
ct_test(pTest, status);
|
||||
pVMAC = VMAC_Find_By_Key(device_id);
|
||||
ct_test(pTest, pVMAC == NULL);
|
||||
VMAC_Cleanup();
|
||||
}
|
||||
|
||||
#ifdef TEST_VMAC
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet VMAC", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testVMAC);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user