re-save line endings to LF for git

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