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