diff --git a/bacnet-stack/demo/handler/h_gas_a.c b/bacnet-stack/demo/handler/h_gas_a.c index e170bf00..a44f6634 100644 --- a/bacnet-stack/demo/handler/h_gas_a.c +++ b/bacnet-stack/demo/handler/h_gas_a.c @@ -1,82 +1,82 @@ -/** -* @file -* @author Daniel Blazevic -* @date 2013 -* @brief GetAlarmSummary ACK service handling -* -* @section LICENSE -* -* Copyright (C) 2013 Daniel Blazevic -* -* 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. -* -* @section DESCRIPTION -* -* The GetAlarmSummary ACK service handler is used by a client BACnet-user to -* obtain a summary of "active alarms." The term "active alarm" refers to -* BACnet standard objects that have an Event_State property whose value is -* not equal to NORMAL and a Notify_Type property whose value is ALARM. -*/ -#include -#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 "handlers.h" -#include "get_alarm_sum.h" - - -/** Example function to handle a GetAlarmSummary ACK. - * - * @param service_request [in] The contents of the service request. - * @param service_len [in] The length of the service_request. - * @param src [in] BACNET_ADDRESS of the source of the message - * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information - * decoded from the APDU header of this message. - */ -void get_alarm_summary_ack_handler( - uint8_t *service_request, - uint16_t service_len, - BACNET_ADDRESS *src, - BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data) -{ - uint16_t apdu_len = 0; - uint16_t len = 0; - BACNET_GET_ALARM_SUMMARY_DATA data; - - while(service_len - len){ - apdu_len = get_alarm_summary_ack_decode_apdu_data( - &service_request[len], - service_len - len, - &data); - - len += apdu_len; - - if(apdu_len > 0){ - /* FIXME: Add code to process data */ - } else { - break; - } - } -} +/** +* @file +* @author Daniel Blazevic +* @date 2013 +* @brief GetAlarmSummary ACK service handling +* +* @section LICENSE +* +* Copyright (C) 2013 Daniel Blazevic +* +* 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. +* +* @section DESCRIPTION +* +* The GetAlarmSummary ACK service handler is used by a client BACnet-user to +* obtain a summary of "active alarms." The term "active alarm" refers to +* BACnet standard objects that have an Event_State property whose value is +* not equal to NORMAL and a Notify_Type property whose value is ALARM. +*/ +#include +#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 "handlers.h" +#include "get_alarm_sum.h" + + +/** Example function to handle a GetAlarmSummary ACK. + * + * @param service_request [in] The contents of the service request. + * @param service_len [in] The length of the service_request. + * @param src [in] BACNET_ADDRESS of the source of the message + * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information + * decoded from the APDU header of this message. + */ +void get_alarm_summary_ack_handler( + uint8_t *service_request, + uint16_t service_len, + BACNET_ADDRESS *src, + BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data) +{ + uint16_t apdu_len = 0; + uint16_t len = 0; + BACNET_GET_ALARM_SUMMARY_DATA data; + + while(service_len - len){ + apdu_len = get_alarm_summary_ack_decode_apdu_data( + &service_request[len], + service_len - len, + &data); + + len += apdu_len; + + if(apdu_len > 0){ + /* FIXME: Add code to process data */ + } else { + break; + } + } +} diff --git a/bacnet-stack/demo/readbdt/Makefile b/bacnet-stack/demo/readbdt/Makefile index 40893a9b..bed0d5c8 100644 --- a/bacnet-stack/demo/readbdt/Makefile +++ b/bacnet-stack/demo/readbdt/Makefile @@ -1,38 +1,38 @@ -#Makefile to build BACnet Application for the GCC Port - -# tools - only if you need them. -# Most platforms have this already defined -# CC = gcc - -TARGET = bacrbdt - -TARGET_BIN = ${TARGET}$(TARGET_EXT) - -SRCS = main.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 GCC Port + +# tools - only if you need them. +# Most platforms have this already defined +# CC = gcc + +TARGET = bacrbdt + +TARGET_BIN = ${TARGET}$(TARGET_EXT) + +SRCS = main.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 diff --git a/bacnet-stack/demo/readbdt/main.c b/bacnet-stack/demo/readbdt/main.c index d9649ea5..aebc785c 100644 --- a/bacnet-stack/demo/readbdt/main.c +++ b/bacnet-stack/demo/readbdt/main.c @@ -1,201 +1,201 @@ -/************************************************************************** -* -* Copyright (C) 2012 Steve Karg -* -* 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. -* -*********************************************************************/ - -/* command line tool that sends a BACnet BVLC message, and displays the reply */ -#include -#include -#include -#include -#include /* for time */ -#include -#include "bactext.h" -#include "iam.h" -#include "address.h" -#include "config.h" -#include "bacdef.h" -#include "npdu.h" -#include "apdu.h" -#include "device.h" -#include "datalink.h" -#include "bvlc.h" -/* some demo stuff needed */ -#define DEBUG_ENABLED 0 -#include "debug.h" -#include "filename.h" -#include "handlers.h" -#include "client.h" -#include "txbuf.h" -#include "dlenv.h" - -/* buffer used for receive */ -static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; - -/* targets interpreted from the command line options */ -static uint32_t Target_BBMD_Address; -static uint16_t Target_BBMD_Port; - -static bool Error_Detected = false; - -static void MyAbortHandler( - BACNET_ADDRESS * src, - uint8_t invoke_id, - uint8_t abort_reason, - bool server) -{ - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - (void) server; - printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason)); - Error_Detected = true; -} - -static void MyRejectHandler( - BACNET_ADDRESS * src, - uint8_t invoke_id, - uint8_t reject_reason) -{ - /* FIXME: verify src and invoke id */ - (void) src; - (void) invoke_id; - printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason)); - Error_Detected = true; -} - -static void Init_Service_Handlers( - void) -{ - Device_Init(NULL); - /* we need to handle who-is - to support dynamic device binding to us */ - 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); - /* we must implement read property - it's required! */ - apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY, - handler_read_property); - /* handle the reply (request) coming back */ - apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_add); - /* handle any errors coming back */ - apdu_set_abort_handler(MyAbortHandler); - apdu_set_reject_handler(MyRejectHandler); -} - -int main( - int argc, - char *argv[]) -{ - BACNET_ADDRESS src = { - 0 - }; /* address where message came from */ - uint16_t pdu_len = 0; - unsigned timeout = 100; /* milliseconds */ - time_t total_seconds = 0; - time_t elapsed_seconds = 0; - time_t last_seconds = 0; - time_t current_seconds = 0; - time_t timeout_seconds = 0; - long port = 0; - - if (argc < 2) { - printf("Usage: %s IP [port]\r\n", filename_remove_path(argv[0])); - return 0; - } - if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) { - printf("Send a Read-Broadcast-Distribution-Table message to a BBMD.\r\n" - "\r\n" - "IP:\r\n" - "IP address of the BBMD in dotted decimal notation\r\n" - "[port]\r\n" - "optional BACnet/IP port number (default=47808=0xBAC0)\r\n" - "\r\n" - "To send a Read-Broadcast-Distribution-Table message to a BBMD\r\n" - "at 192.168.0.1 using port 47808:\r\n" - "%s 192.168.0.1 47808\r\n", - filename_remove_path(argv[0])); - return 0; - } - /* decode the command line parameters */ - if (argc > 1) { - Target_BBMD_Address = inet_addr(argv[1]); - if (Target_BBMD_Address == (-1)) { - fprintf(stderr, "IP=%s - failed to convert address.\r\n", - argv[1]); - return 1; - } - } - if (argc > 2) { - port = strtol(argv[2], NULL, 0); - if ((port > 0) && (port <= 65535)) { - Target_BBMD_Port = htons(port); - } else { - fprintf(stderr, "port=%ld - port must be between 0-65535.\r\n", - port); - return 1; - } - } else { - Target_BBMD_Port = htons(47808); - } - /* setup my info */ - Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); - Init_Service_Handlers(); - address_init(); - dlenv_init(); - atexit(datalink_cleanup); - /* configure the timeout values */ - last_seconds = time(NULL); - timeout_seconds = apdu_timeout() / 1000; - /* send the request */ - bvlc_bbmd_read_bdt(Target_BBMD_Address, Target_BBMD_Port); - /* loop forever */ - for (;;) { - /* increment timer - exit if timed out */ - current_seconds = time(NULL); - /* returns 0 bytes on timeout */ - pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); - /* process */ - if (pdu_len) { - npdu_handler(&src, &Rx_Buf[0], pdu_len); - } - if (Error_Detected) - break; - /* increment timer - exit if timed out */ - elapsed_seconds = current_seconds - last_seconds; - if (elapsed_seconds) { -#if defined(BACDL_BIP) && BBMD_ENABLED - bvlc_maintenance_timer(elapsed_seconds); -#endif - } - total_seconds += elapsed_seconds; - if (total_seconds > timeout_seconds) - break; - /* keep track of time for next check */ - last_seconds = current_seconds; - } - - return 0; -} +/************************************************************************** +* +* Copyright (C) 2012 Steve Karg +* +* 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. +* +*********************************************************************/ + +/* command line tool that sends a BACnet BVLC message, and displays the reply */ +#include +#include +#include +#include +#include /* for time */ +#include +#include "bactext.h" +#include "iam.h" +#include "address.h" +#include "config.h" +#include "bacdef.h" +#include "npdu.h" +#include "apdu.h" +#include "device.h" +#include "datalink.h" +#include "bvlc.h" +/* some demo stuff needed */ +#define DEBUG_ENABLED 0 +#include "debug.h" +#include "filename.h" +#include "handlers.h" +#include "client.h" +#include "txbuf.h" +#include "dlenv.h" + +/* buffer used for receive */ +static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; + +/* targets interpreted from the command line options */ +static uint32_t Target_BBMD_Address; +static uint16_t Target_BBMD_Port; + +static bool Error_Detected = false; + +static void MyAbortHandler( + BACNET_ADDRESS * src, + uint8_t invoke_id, + uint8_t abort_reason, + bool server) +{ + /* FIXME: verify src and invoke id */ + (void) src; + (void) invoke_id; + (void) server; + printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason)); + Error_Detected = true; +} + +static void MyRejectHandler( + BACNET_ADDRESS * src, + uint8_t invoke_id, + uint8_t reject_reason) +{ + /* FIXME: verify src and invoke id */ + (void) src; + (void) invoke_id; + printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason)); + Error_Detected = true; +} + +static void Init_Service_Handlers( + void) +{ + Device_Init(NULL); + /* we need to handle who-is + to support dynamic device binding to us */ + 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); + /* we must implement read property - it's required! */ + apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY, + handler_read_property); + /* handle the reply (request) coming back */ + apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_add); + /* handle any errors coming back */ + apdu_set_abort_handler(MyAbortHandler); + apdu_set_reject_handler(MyRejectHandler); +} + +int main( + int argc, + char *argv[]) +{ + BACNET_ADDRESS src = { + 0 + }; /* address where message came from */ + uint16_t pdu_len = 0; + unsigned timeout = 100; /* milliseconds */ + time_t total_seconds = 0; + time_t elapsed_seconds = 0; + time_t last_seconds = 0; + time_t current_seconds = 0; + time_t timeout_seconds = 0; + long port = 0; + + if (argc < 2) { + printf("Usage: %s IP [port]\r\n", filename_remove_path(argv[0])); + return 0; + } + if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) { + printf("Send a Read-Broadcast-Distribution-Table message to a BBMD.\r\n" + "\r\n" + "IP:\r\n" + "IP address of the BBMD in dotted decimal notation\r\n" + "[port]\r\n" + "optional BACnet/IP port number (default=47808=0xBAC0)\r\n" + "\r\n" + "To send a Read-Broadcast-Distribution-Table message to a BBMD\r\n" + "at 192.168.0.1 using port 47808:\r\n" + "%s 192.168.0.1 47808\r\n", + filename_remove_path(argv[0])); + return 0; + } + /* decode the command line parameters */ + if (argc > 1) { + Target_BBMD_Address = inet_addr(argv[1]); + if (Target_BBMD_Address == (-1)) { + fprintf(stderr, "IP=%s - failed to convert address.\r\n", + argv[1]); + return 1; + } + } + if (argc > 2) { + port = strtol(argv[2], NULL, 0); + if ((port > 0) && (port <= 65535)) { + Target_BBMD_Port = htons(port); + } else { + fprintf(stderr, "port=%ld - port must be between 0-65535.\r\n", + port); + return 1; + } + } else { + Target_BBMD_Port = htons(47808); + } + /* setup my info */ + Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); + Init_Service_Handlers(); + address_init(); + dlenv_init(); + atexit(datalink_cleanup); + /* configure the timeout values */ + last_seconds = time(NULL); + timeout_seconds = apdu_timeout() / 1000; + /* send the request */ + bvlc_bbmd_read_bdt(Target_BBMD_Address, Target_BBMD_Port); + /* loop forever */ + for (;;) { + /* increment timer - exit if timed out */ + current_seconds = time(NULL); + /* returns 0 bytes on timeout */ + pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout); + /* process */ + if (pdu_len) { + npdu_handler(&src, &Rx_Buf[0], pdu_len); + } + if (Error_Detected) + break; + /* increment timer - exit if timed out */ + elapsed_seconds = current_seconds - last_seconds; + if (elapsed_seconds) { +#if defined(BACDL_BIP) && BBMD_ENABLED + bvlc_maintenance_timer(elapsed_seconds); +#endif + } + total_seconds += elapsed_seconds; + if (total_seconds > timeout_seconds) + break; + /* keep track of time for next check */ + last_seconds = current_seconds; + } + + return 0; +} diff --git a/bacnet-stack/demo/readbdt/makefile.b32 b/bacnet-stack/demo/readbdt/makefile.b32 index 6840a4bc..28a307ed 100644 --- a/bacnet-stack/demo/readbdt/makefile.b32 +++ b/bacnet-stack/demo/readbdt/makefile.b32 @@ -1,140 +1,140 @@ -# -# Simple makefile to build an executable for Win32 -# -# This makefile assumes Borland bcc32 development environment -# on Windows NT/9x/2000/XP -# - -!ifndef BORLAND_DIR -BORLAND_DIR_Not_Defined: - @echo . - @echo You must define environment variable BORLAND_DIR to compile. -!endif - -# target -PRODUCT = bacrbdt -PRODUCT_EXE = $(PRODUCT).exe - -# tools -CC = $(BORLAND_DIR)\bin\bcc32 -MAKE=$(BORLAND_DIR)\bin\make.exe -#LINK = $(BORLAND_DIR)\bin\tlink32 -LINK = $(BORLAND_DIR)\bin\ilink32 - -BACNET_LIB_DIR = ..\..\lib -BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib - -# directories -BACNET_PORT = ..\..\ports\win32 -BACNET_INCLUDE = ..\..\include -BACNET_OBJECT = ..\object -BACNET_HANDLER = ..\handler -INCLUDES = \ - -I$(BACNET_INCLUDE) \ - -I$(BACNET_PORT) \ - -I$(BACNET_OBJECT) \ - -I$(BACNET_HANDLER) \ - -I$(BORLAND_DIR)\include - -# -BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL -#BACDL_DEFINE=-DBACDL_MSTP=1 -BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1 -DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) - -SRCS = main.c \ - $(BACNET_OBJECT)\device-client.c - -OBJS = $(SRCS:.c=.obj) - -# -# Compiler definitions -# -BCC_CFG = bcc32.cfg - -# -# Include directories -# -CFLAGS = $(INCLUDES) $(DEFINES) - -# -# Libraries -# -C_LIB_DIR = $(BORLAND_DIR)\lib - -LIBS = $(BACNET_LIB) \ - $(C_LIB_DIR)\IMPORT32.lib \ - $(C_LIB_DIR)\CW32MT.lib \ - -# -# Main target -# -# This should be the first one in the makefile - -all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE) - del $(BCC_CFG) - -install: $(PRODUCT_EXE) - copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE) - -# Linker specific: the link below is for BCC linker/compiler. If you link -# with a different linker - please change accordingly. -# - -# need a temp response file (@&&| ... |) because command line is too long -# $** lists each dependency -# $< target name -# $* target name without extension -$(PRODUCT_EXE) : $(OBJS) - @echo Running Linker for $(PRODUCT_EXE) - $(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&| - $(BORLAND_DIR)\lib\c0x32.obj $** - $< - $*.map - $(LIBS) -| - -# -# Utilities - -clean : - del $(OBJS) - del $(PRODUCT_EXE) - del $(PRODUCT).map - del $(PRODUCT).ilc - del $(PRODUCT).ild - del $(PRODUCT).ilf - del $(PRODUCT).ils - del $(PRODUCT).tds - del $(BCC_CFG) - -# -# Generic rules -# -.SUFFIXES: .cpp .c .sbr .obj - -# -# cc generic rule -# -.c.obj: - $(CC) +$(BCC_CFG) -o$@ $< - -# Compiler configuration file -$(BCC_CFG) : - Copy &&| - $(CFLAGS) - -c - -y #include line numbers in OBJ's - -v #include debug info - -w+ #turn on all warnings - -Od #disable all optimizations - #-a4 #32 bit data alignment - #-M # generate link map - #-ls # linker options - #-WM- #not multithread - -WM #multithread - -w-aus # ignore warning assigned a value that is never used - -w-sig # ignore warning conversion may lose sig digits -| $@ - -# EOF: makefile +# +# Simple makefile to build an executable for Win32 +# +# This makefile assumes Borland bcc32 development environment +# on Windows NT/9x/2000/XP +# + +!ifndef BORLAND_DIR +BORLAND_DIR_Not_Defined: + @echo . + @echo You must define environment variable BORLAND_DIR to compile. +!endif + +# target +PRODUCT = bacrbdt +PRODUCT_EXE = $(PRODUCT).exe + +# tools +CC = $(BORLAND_DIR)\bin\bcc32 +MAKE=$(BORLAND_DIR)\bin\make.exe +#LINK = $(BORLAND_DIR)\bin\tlink32 +LINK = $(BORLAND_DIR)\bin\ilink32 + +BACNET_LIB_DIR = ..\..\lib +BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib + +# directories +BACNET_PORT = ..\..\ports\win32 +BACNET_INCLUDE = ..\..\include +BACNET_OBJECT = ..\object +BACNET_HANDLER = ..\handler +INCLUDES = \ + -I$(BACNET_INCLUDE) \ + -I$(BACNET_PORT) \ + -I$(BACNET_OBJECT) \ + -I$(BACNET_HANDLER) \ + -I$(BORLAND_DIR)\include + +# +BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL +#BACDL_DEFINE=-DBACDL_MSTP=1 +BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1 +DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) + +SRCS = main.c \ + $(BACNET_OBJECT)\device-client.c + +OBJS = $(SRCS:.c=.obj) + +# +# Compiler definitions +# +BCC_CFG = bcc32.cfg + +# +# Include directories +# +CFLAGS = $(INCLUDES) $(DEFINES) + +# +# Libraries +# +C_LIB_DIR = $(BORLAND_DIR)\lib + +LIBS = $(BACNET_LIB) \ + $(C_LIB_DIR)\IMPORT32.lib \ + $(C_LIB_DIR)\CW32MT.lib \ + +# +# Main target +# +# This should be the first one in the makefile + +all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE) + del $(BCC_CFG) + +install: $(PRODUCT_EXE) + copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE) + +# Linker specific: the link below is for BCC linker/compiler. If you link +# with a different linker - please change accordingly. +# + +# need a temp response file (@&&| ... |) because command line is too long +# $** lists each dependency +# $< target name +# $* target name without extension +$(PRODUCT_EXE) : $(OBJS) + @echo Running Linker for $(PRODUCT_EXE) + $(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&| + $(BORLAND_DIR)\lib\c0x32.obj $** + $< + $*.map + $(LIBS) +| + +# +# Utilities + +clean : + del $(OBJS) + del $(PRODUCT_EXE) + del $(PRODUCT).map + del $(PRODUCT).ilc + del $(PRODUCT).ild + del $(PRODUCT).ilf + del $(PRODUCT).ils + del $(PRODUCT).tds + del $(BCC_CFG) + +# +# Generic rules +# +.SUFFIXES: .cpp .c .sbr .obj + +# +# cc generic rule +# +.c.obj: + $(CC) +$(BCC_CFG) -o$@ $< + +# Compiler configuration file +$(BCC_CFG) : + Copy &&| + $(CFLAGS) + -c + -y #include line numbers in OBJ's + -v #include debug info + -w+ #turn on all warnings + -Od #disable all optimizations + #-a4 #32 bit data alignment + #-M # generate link map + #-ls # linker options + #-WM- #not multithread + -WM #multithread + -w-aus # ignore warning assigned a value that is never used + -w-sig # ignore warning conversion may lose sig digits +| $@ + +# EOF: makefile diff --git a/bacnet-stack/indent.bat b/bacnet-stack/indent.bat index d4ceff45..a0f38fa6 100644 --- a/bacnet-stack/indent.bat +++ b/bacnet-stack/indent.bat @@ -1,23 +1,23 @@ -rem Indent the C and H files with specific coding standard -rem requires 'indent.exe' from MSYS (MinGW). -echo -kr -nut -nlp -ip4 -cli4 -bfda -nbc -nbbo -c0 -cd0 -cp0 -di0 -l79 -nhnl > ".indent.pro" - -call :treeProcess -goto :eof - -:treeProcess -rem perform the indent on all the files of this subdirectory: -for %%f in (*.c) do ( - indent.exe "%%f" -o "%%f" -) -for %%f in (*.h) do ( - indent.exe "%%f" -o "%%f" -) -rem loop over all directories and sub directories -for /D %%d in (*) do ( - cd %%d - call :treeProcess - cd .. -) -exit /b - +rem Indent the C and H files with specific coding standard +rem requires 'indent.exe' from MSYS (MinGW). +echo -kr -nut -nlp -ip4 -cli4 -bfda -nbc -nbbo -c0 -cd0 -cp0 -di0 -l79 -nhnl > ".indent.pro" + +call :treeProcess +goto :eof + +:treeProcess +rem perform the indent on all the files of this subdirectory: +for %%f in (*.c) do ( + indent.exe "%%f" -o "%%f" +) +for %%f in (*.h) do ( + indent.exe "%%f" -o "%%f" +) +rem loop over all directories and sub directories +for /D %%d in (*) do ( + cd %%d + call :treeProcess + cd .. +) +exit /b + diff --git a/bacnet-stack/ports/lwip/bip.c b/bacnet-stack/ports/lwip/bip.c index 14df1f55..0b406b92 100644 --- a/bacnet-stack/ports/lwip/bip.c +++ b/bacnet-stack/ports/lwip/bip.c @@ -1,343 +1,343 @@ -/*####COPYRIGHTBEGIN#### - ------------------------------------------- - Copyright (C) 2012 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 /* for standard integer types uint8_t etc. */ -#include /* for the standard bool type. */ -#include "bacdef.h" -#include "bacdcode.h" -#include "bacint.h" -#include "bip.h" -#include "bvlc.h" -#include "handlers.h" -#include "net.h" /* custom per port */ - -/** @file bip.c Configuration and Operations for BACnet/IP */ - -/* port to use - stored in network byte order */ -static uint16_t BIP_Port = 0xBAC0; -/* IP Address - stored in network byte order */ -static struct in_addr BIP_Address; -/* Broadcast Address - stored in network byte order */ -static struct in_addr BIP_Broadcast_Address; -/* lwIP socket, of sorts */ -static struct udp_pcb *Server_upcb; - -void bip_set_addr( - uint32_t net_address) -{ /* in network byte order */ - BIP_Address.s_addr = net_address; -} - -/* returns network byte order */ -uint32_t bip_get_addr( - void) -{ - return BIP_Address.s_addr; -} - -void bip_set_broadcast_addr( - uint32_t net_address) -{ /* in network byte order */ - BIP_Broadcast_Address.s_addr = net_address; -} - -/* returns network byte order */ -uint32_t bip_get_broadcast_addr( - void) -{ - return BIP_Broadcast_Address.s_addr; -} - - -void bip_set_port( - uint16_t port) -{ /* in network byte order */ - BIP_Port = port; -} - -/* returns network byte order */ -uint16_t bip_get_port( - void) -{ - return BIP_Port; -} - -static void bip_mac_to_addr( - struct ip_addr *address, - uint8_t *mac) -{ - if (mac && address) { - address->addr = ((u32_t) ((((uint32_t) mac[0]) << 24) & 0xff000000)); - address->addr |= ((u32_t) ((((uint32_t) mac[1]) << 16) & 0x00ff0000)); - address->addr |= ((u32_t) ((((uint32_t) mac[2]) << 8) & 0x0000ff00)); - address->addr |= ((u32_t) (((uint32_t) mac[3]) & 0x000000ff)); - } -} - -static void bip_addr_to_mac( - uint8_t *mac, - struct ip_addr *address) -{ - if (mac && address) { - mac[0] = (uint8_t)(address->addr >> 24); - mac[1] = (uint8_t)(address->addr >> 16); - mac[2] = (uint8_t)(address->addr >> 8); - mac[3] = (uint8_t)(address->addr); - } -} - -static int bip_decode_bip_address( - BACNET_ADDRESS * bac_addr, - struct ip_addr *address, /* in network format */ - uint16_t * port) -{ /* in network format */ - int len = 0; - - if (bac_addr) { - bip_mac_to_addr(address, &bac_addr->mac[0]); - memcpy(port, &bac_addr->mac[4], 2); - len = 6; - } - - return len; -} - -/** Function to send a packet out the BACnet/IP socket (Annex J). - * @ingroup DLBIP - * - * @param dest [in] Destination address (may encode an IP address and port #). - * @param npdu_data [in] The NPDU header (Network) information (not used). - * @param pdu [in] Buffer of data to be sent - may be null (why?). - * @param pdu_len [in] Number of bytes in the pdu buffer. - * @return Number of bytes sent on success, negative number 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) -{ - struct pbuf *pkt = NULL; - uint8_t *mtu = NULL; - int mtu_len = 0; - /* addr and port in host format */ - struct ip_addr dst_ip; - uint16_t port = 0; - uint16_t length = pdu_len + 4; - err_t status = ERR_OK; - - (void) npdu_data; - pkt = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL); - if (pkt == NULL) { - return 0; - } - mtu = (uint8_t *)pkt->payload; - mtu[0] = BVLL_TYPE_BACNET_IP; - if (dest->net == BACNET_BROADCAST_NETWORK) { - /* broadcast */ - dst_ip.addr = BIP_Broadcast_Address.s_addr; - port = BIP_Port; - mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; - } else if (dest->mac_len == 6) { - /* unicast */ - bip_decode_bip_address(dest, &dst_ip, &port); - mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU; - } else { - /* invalid address */ - return -1; - } - mtu_len = 2; - mtu_len += - encode_unsigned16(&mtu[mtu_len], - (uint16_t) (pdu_len + 4 /*inclusive */ )); - memcpy(&mtu[mtu_len], pdu, pdu_len); - mtu_len += pdu_len; - pkt->len = mtu_len; - /* Send the packet */ - status = udp_sendto(Server_upcb, pkt, &dst_ip, port); - /* free the buffer pbuf */ - pbuf_free(pkt); - if (status != ERR_OK) { - return 0; - } - - return mtu_len; -} - -void bip_server_callback( - void *arg, - struct udp_pcb *upcb, - struct pbuf *pkt, - struct ip_addr *addr, - u16_t port) -{ - uint8_t function = 0; - uint16_t pdu_len = 0; - uint16_t pdu_offset = 0; - BACNET_ADDRESS src = { - 0 - }; /* address where message came from */ - struct ip_addr sin_addr; - uint16_t sin_port = 0; - uint8_t *pdu = (uint8_t *)pkt->payload; - - /* the signature of a BACnet/IP packet */ - if (pdu[0] != BVLL_TYPE_BACNET_IP) { - return; - } - function = pdu[1]; - if ((function == BVLC_ORIGINAL_UNICAST_NPDU) || - (function == BVLC_ORIGINAL_BROADCAST_NPDU)) { - /* ignore messages from me */ - if ((addr->addr == BIP_Address.s_addr) && - (port == BIP_Port)) { - pdu_len = 0; - } else { - /* data in src->mac[] is in network format */ - src.mac_len = 6; - bip_addr_to_mac(&src.mac[0], addr); - memcpy(&src.mac[4], &port, 2); - /* decode the length of the PDU - length is inclusive of BVLC */ - (void) decode_unsigned16(&pdu[2], &pdu_len); - /* subtract off the BVLC header */ - pdu_len -= 4; - pdu_offset = 4; - } - } else if (function == BVLC_FORWARDED_NPDU) { - bip_mac_to_addr(&sin_addr, &pdu[4]); - memcpy(&sin_port, &pdu[8], 2); - if ((sin_addr.addr == BIP_Address.s_addr) && - (sin_port == BIP_Port)) { - /* ignore forwarded messages from me */ - pdu_len = 0; - } else { - /* data in src->mac[] is in network format */ - src.mac_len = 6; - bip_addr_to_mac(&src.mac[0], &sin_addr); - memcpy(&src.mac[4], &sin_port, 2); - /* decode the length of the PDU - length is inclusive of BVLC */ - (void) decode_unsigned16(&pdu[2], &pdu_len); - /* subtract off the BVLC header */ - pdu_len -= 10; - pdu_offset = 10; - } - } - if (pdu_len) { - npdu_handler(&src, &pdu[pdu_offset], pdu_len); - } -#if 0 - /* prepare for next packet */ - udp_disconnect(upcb); - udp_bind(upcb, IP_ADDR_ANY, BIP_Port); - /* Set a receive callback for the upcb */ - udp_recv(upcb, bip_server_callback, NULL); -#endif - /* free our packet */ - pbuf_free(pkt); -} - -void bip_get_my_address( - BACNET_ADDRESS * my_address) -{ - int i = 0; - - if (my_address) { - my_address->mac_len = 6; - memcpy(&my_address->mac[0], &BIP_Address.s_addr, 4); - memcpy(&my_address->mac[4], &BIP_Port, 2); - my_address->net = 0; /* local only, no routing */ - my_address->len = 0; /* no SLEN */ - for (i = 0; i < MAX_MAC_LEN; i++) { - /* no SADR */ - my_address->adr[i] = 0; - } - } - - return; -} - -void bip_get_broadcast_address( - BACNET_ADDRESS * dest) -{ /* destination address */ - int i = 0; /* counter */ - - if (dest) { - dest->mac_len = 6; - memcpy(&dest->mac[0], &BIP_Broadcast_Address.s_addr, 4); - memcpy(&dest->mac[4], &BIP_Port, 2); - dest->net = BACNET_BROADCAST_NETWORK; - dest->len = 0; /* no SLEN */ - for (i = 0; i < MAX_MAC_LEN; i++) { - /* no SADR */ - dest->adr[i] = 0; - } - } - - return; -} - -/** Initialize the BACnet/IP services at the given interface. - * @ingroup DLBIP - * -# Gets the local IP address and local broadcast address from the system, - * and saves it into the BACnet/IP data structures. - * -# Opens a UDP socket - * -# Configures the socket for sending and receiving - * -# Configures the socket so it can send broadcasts - * -# Binds the socket to the local IP address at the specified port for - * BACnet/IP (by default, 0xBAC0 = 47808). - * - * @note For Windows, ifname is the dotted ip address of the interface. - * - * @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 bip_init( - char *ifname) -{ - (void)ifname; - /* Create a new UDP control block */ - Server_upcb = udp_new(); - if (Server_upcb == NULL) { - /* increase MEMP_NUM_UDP_PCB in lwipopts.h */ - while(1) {}; - } - /* Bind the upcb to the UDP_PORT port */ - /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */ - udp_bind(Server_upcb, IP_ADDR_ANY, BIP_Port); - /* Set a receive callback for the upcb */ - udp_recv(Server_upcb, bip_server_callback, NULL); - - return true; -} +/*####COPYRIGHTBEGIN#### + ------------------------------------------- + Copyright (C) 2012 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 /* for standard integer types uint8_t etc. */ +#include /* for the standard bool type. */ +#include "bacdef.h" +#include "bacdcode.h" +#include "bacint.h" +#include "bip.h" +#include "bvlc.h" +#include "handlers.h" +#include "net.h" /* custom per port */ + +/** @file bip.c Configuration and Operations for BACnet/IP */ + +/* port to use - stored in network byte order */ +static uint16_t BIP_Port = 0xBAC0; +/* IP Address - stored in network byte order */ +static struct in_addr BIP_Address; +/* Broadcast Address - stored in network byte order */ +static struct in_addr BIP_Broadcast_Address; +/* lwIP socket, of sorts */ +static struct udp_pcb *Server_upcb; + +void bip_set_addr( + uint32_t net_address) +{ /* in network byte order */ + BIP_Address.s_addr = net_address; +} + +/* returns network byte order */ +uint32_t bip_get_addr( + void) +{ + return BIP_Address.s_addr; +} + +void bip_set_broadcast_addr( + uint32_t net_address) +{ /* in network byte order */ + BIP_Broadcast_Address.s_addr = net_address; +} + +/* returns network byte order */ +uint32_t bip_get_broadcast_addr( + void) +{ + return BIP_Broadcast_Address.s_addr; +} + + +void bip_set_port( + uint16_t port) +{ /* in network byte order */ + BIP_Port = port; +} + +/* returns network byte order */ +uint16_t bip_get_port( + void) +{ + return BIP_Port; +} + +static void bip_mac_to_addr( + struct ip_addr *address, + uint8_t *mac) +{ + if (mac && address) { + address->addr = ((u32_t) ((((uint32_t) mac[0]) << 24) & 0xff000000)); + address->addr |= ((u32_t) ((((uint32_t) mac[1]) << 16) & 0x00ff0000)); + address->addr |= ((u32_t) ((((uint32_t) mac[2]) << 8) & 0x0000ff00)); + address->addr |= ((u32_t) (((uint32_t) mac[3]) & 0x000000ff)); + } +} + +static void bip_addr_to_mac( + uint8_t *mac, + struct ip_addr *address) +{ + if (mac && address) { + mac[0] = (uint8_t)(address->addr >> 24); + mac[1] = (uint8_t)(address->addr >> 16); + mac[2] = (uint8_t)(address->addr >> 8); + mac[3] = (uint8_t)(address->addr); + } +} + +static int bip_decode_bip_address( + BACNET_ADDRESS * bac_addr, + struct ip_addr *address, /* in network format */ + uint16_t * port) +{ /* in network format */ + int len = 0; + + if (bac_addr) { + bip_mac_to_addr(address, &bac_addr->mac[0]); + memcpy(port, &bac_addr->mac[4], 2); + len = 6; + } + + return len; +} + +/** Function to send a packet out the BACnet/IP socket (Annex J). + * @ingroup DLBIP + * + * @param dest [in] Destination address (may encode an IP address and port #). + * @param npdu_data [in] The NPDU header (Network) information (not used). + * @param pdu [in] Buffer of data to be sent - may be null (why?). + * @param pdu_len [in] Number of bytes in the pdu buffer. + * @return Number of bytes sent on success, negative number 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) +{ + struct pbuf *pkt = NULL; + uint8_t *mtu = NULL; + int mtu_len = 0; + /* addr and port in host format */ + struct ip_addr dst_ip; + uint16_t port = 0; + uint16_t length = pdu_len + 4; + err_t status = ERR_OK; + + (void) npdu_data; + pkt = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL); + if (pkt == NULL) { + return 0; + } + mtu = (uint8_t *)pkt->payload; + mtu[0] = BVLL_TYPE_BACNET_IP; + if (dest->net == BACNET_BROADCAST_NETWORK) { + /* broadcast */ + dst_ip.addr = BIP_Broadcast_Address.s_addr; + port = BIP_Port; + mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; + } else if (dest->mac_len == 6) { + /* unicast */ + bip_decode_bip_address(dest, &dst_ip, &port); + mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU; + } else { + /* invalid address */ + return -1; + } + mtu_len = 2; + mtu_len += + encode_unsigned16(&mtu[mtu_len], + (uint16_t) (pdu_len + 4 /*inclusive */ )); + memcpy(&mtu[mtu_len], pdu, pdu_len); + mtu_len += pdu_len; + pkt->len = mtu_len; + /* Send the packet */ + status = udp_sendto(Server_upcb, pkt, &dst_ip, port); + /* free the buffer pbuf */ + pbuf_free(pkt); + if (status != ERR_OK) { + return 0; + } + + return mtu_len; +} + +void bip_server_callback( + void *arg, + struct udp_pcb *upcb, + struct pbuf *pkt, + struct ip_addr *addr, + u16_t port) +{ + uint8_t function = 0; + uint16_t pdu_len = 0; + uint16_t pdu_offset = 0; + BACNET_ADDRESS src = { + 0 + }; /* address where message came from */ + struct ip_addr sin_addr; + uint16_t sin_port = 0; + uint8_t *pdu = (uint8_t *)pkt->payload; + + /* the signature of a BACnet/IP packet */ + if (pdu[0] != BVLL_TYPE_BACNET_IP) { + return; + } + function = pdu[1]; + if ((function == BVLC_ORIGINAL_UNICAST_NPDU) || + (function == BVLC_ORIGINAL_BROADCAST_NPDU)) { + /* ignore messages from me */ + if ((addr->addr == BIP_Address.s_addr) && + (port == BIP_Port)) { + pdu_len = 0; + } else { + /* data in src->mac[] is in network format */ + src.mac_len = 6; + bip_addr_to_mac(&src.mac[0], addr); + memcpy(&src.mac[4], &port, 2); + /* decode the length of the PDU - length is inclusive of BVLC */ + (void) decode_unsigned16(&pdu[2], &pdu_len); + /* subtract off the BVLC header */ + pdu_len -= 4; + pdu_offset = 4; + } + } else if (function == BVLC_FORWARDED_NPDU) { + bip_mac_to_addr(&sin_addr, &pdu[4]); + memcpy(&sin_port, &pdu[8], 2); + if ((sin_addr.addr == BIP_Address.s_addr) && + (sin_port == BIP_Port)) { + /* ignore forwarded messages from me */ + pdu_len = 0; + } else { + /* data in src->mac[] is in network format */ + src.mac_len = 6; + bip_addr_to_mac(&src.mac[0], &sin_addr); + memcpy(&src.mac[4], &sin_port, 2); + /* decode the length of the PDU - length is inclusive of BVLC */ + (void) decode_unsigned16(&pdu[2], &pdu_len); + /* subtract off the BVLC header */ + pdu_len -= 10; + pdu_offset = 10; + } + } + if (pdu_len) { + npdu_handler(&src, &pdu[pdu_offset], pdu_len); + } +#if 0 + /* prepare for next packet */ + udp_disconnect(upcb); + udp_bind(upcb, IP_ADDR_ANY, BIP_Port); + /* Set a receive callback for the upcb */ + udp_recv(upcb, bip_server_callback, NULL); +#endif + /* free our packet */ + pbuf_free(pkt); +} + +void bip_get_my_address( + BACNET_ADDRESS * my_address) +{ + int i = 0; + + if (my_address) { + my_address->mac_len = 6; + memcpy(&my_address->mac[0], &BIP_Address.s_addr, 4); + memcpy(&my_address->mac[4], &BIP_Port, 2); + my_address->net = 0; /* local only, no routing */ + my_address->len = 0; /* no SLEN */ + for (i = 0; i < MAX_MAC_LEN; i++) { + /* no SADR */ + my_address->adr[i] = 0; + } + } + + return; +} + +void bip_get_broadcast_address( + BACNET_ADDRESS * dest) +{ /* destination address */ + int i = 0; /* counter */ + + if (dest) { + dest->mac_len = 6; + memcpy(&dest->mac[0], &BIP_Broadcast_Address.s_addr, 4); + memcpy(&dest->mac[4], &BIP_Port, 2); + dest->net = BACNET_BROADCAST_NETWORK; + dest->len = 0; /* no SLEN */ + for (i = 0; i < MAX_MAC_LEN; i++) { + /* no SADR */ + dest->adr[i] = 0; + } + } + + return; +} + +/** Initialize the BACnet/IP services at the given interface. + * @ingroup DLBIP + * -# Gets the local IP address and local broadcast address from the system, + * and saves it into the BACnet/IP data structures. + * -# Opens a UDP socket + * -# Configures the socket for sending and receiving + * -# Configures the socket so it can send broadcasts + * -# Binds the socket to the local IP address at the specified port for + * BACnet/IP (by default, 0xBAC0 = 47808). + * + * @note For Windows, ifname is the dotted ip address of the interface. + * + * @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 bip_init( + char *ifname) +{ + (void)ifname; + /* Create a new UDP control block */ + Server_upcb = udp_new(); + if (Server_upcb == NULL) { + /* increase MEMP_NUM_UDP_PCB in lwipopts.h */ + while(1) {}; + } + /* Bind the upcb to the UDP_PORT port */ + /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */ + udp_bind(Server_upcb, IP_ADDR_ANY, BIP_Port); + /* Set a receive callback for the upcb */ + udp_recv(Server_upcb, bip_server_callback, NULL); + + return true; +} diff --git a/bacnet-stack/ports/lwip/net.h b/bacnet-stack/ports/lwip/net.h index 7edb4f0e..338023c6 100644 --- a/bacnet-stack/ports/lwip/net.h +++ b/bacnet-stack/ports/lwip/net.h @@ -1,55 +1,55 @@ -/************************************************************************** -* -* Copyright (C) 2012 Steve Karg -* -* 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 NET_H -#define NET_H - -#include -#include -#include -#include "lwip/def.h" -#include "lwip/udp.h" -#include "lwip/memp.h" -#include "netif/etharp.h" -#include "lwip/dhcp.h" -#include "ethernetif.h" -#include "lwip/inet.h" - -/* members are in network byte order */ -struct sockaddr_in { - u8_t sin_len; - u8_t sin_family; - u16_t sin_port; - struct in_addr sin_addr; - char sin_zero[8]; -}; - -struct sockaddr { - u8_t sa_len; - u8_t sa_family; - char sa_data[14]; -}; - -#endif +/************************************************************************** +* +* Copyright (C) 2012 Steve Karg +* +* 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 NET_H +#define NET_H + +#include +#include +#include +#include "lwip/def.h" +#include "lwip/udp.h" +#include "lwip/memp.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "ethernetif.h" +#include "lwip/inet.h" + +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + u8_t sin_family; + u16_t sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +struct sockaddr { + u8_t sa_len; + u8_t sa_family; + char sa_data[14]; +}; + +#endif diff --git a/bacnet-stack/unittest.bat b/bacnet-stack/unittest.bat index 38e37052..3dcb5eca 100644 --- a/bacnet-stack/unittest.bat +++ b/bacnet-stack/unittest.bat @@ -1,10 +1,10 @@ -@echo off -echo Build with MinGW and MSYS: mingw.sourceforge.net -rem set PATH=C:\MinGW\msys\1.0\bin;C:\MinGW\bin -rem assumes rm, cp, size are already in path -set CC=gcc -set AR=ar -set MAKE=make -rem make BACNET_PORT=win32 BUILD=release -f test.mak clean all -make -s -f test.mak clean all - +@echo off +echo Build with MinGW and MSYS: mingw.sourceforge.net +rem set PATH=C:\MinGW\msys\1.0\bin;C:\MinGW\bin +rem assumes rm, cp, size are already in path +set CC=gcc +set AR=ar +set MAKE=make +rem make BACNET_PORT=win32 BUILD=release -f test.mak clean all +make -s -f test.mak clean all +