Replace blurbs that match the name (case insensitive) with NULL.
[metze/wireshark/wip.git] / epan / dissectors / packet-bacapp.c
index 0ae3eb2a4bb7a5bd4f67c8c4b782e4a906b8e24f..debdeca4a7d528508153dbe84e6cc5cfe4ab132c 100644 (file)
@@ -1,13 +1,13 @@
 /* packet-bacapp.c
  * Routines for BACnet (APDU) dissection
- * Copyright 2001, Hartmut Mueller <hartmut@abmlinux.org>, FH Dortmund
- * Enhanced by Steve Karg, 2005, <skarg@users.sourceforge.net>, Atlanta
- * Enhanced by Herbert Lischka, 2005, <lischka@kieback-peter.de>, Berlin
+ * Copyright 2001, Hartmut Mueller <hartmut[AT]abmlinux.org>, FH Dortmund
+ * Enhanced by Steve Karg, 2005, <skarg[AT]users.sourceforge.net>, Atlanta
+ * Enhanced by Herbert Lischka, 2005, <lischka[AT]kieback-peter.de>, Berlin
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald[AT]wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * Copied from README.developer,v 1.23
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include "packet-bacapp.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/reassemble.h>
+#include <epan/expert.h>
+
+/* formerly bacapp.h  contains definitions and forward declarations */
+
+#ifndef FAULT
+#define FAULT                  proto_tree_add_text(subtree, tvb, offset, tvb_length(tvb) - offset, "something is going wrong here !!"); \
+       offset = tvb_length(tvb);
+#endif
+
+/* BACnet PDU Types */
+#define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST 0
+#define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST 1
+#define BACAPP_TYPE_SIMPLE_ACK 2
+#define BACAPP_TYPE_COMPLEX_ACK 3
+#define BACAPP_TYPE_SEGMENT_ACK 4
+#define BACAPP_TYPE_ERROR 5
+#define BACAPP_TYPE_REJECT 6
+#define BACAPP_TYPE_ABORT 7
+#define MAX_BACAPP_TYPE 8
+
+#define BACAPP_SEGMENTED_REQUEST 0x08
+#define BACAPP_MORE_SEGMENTS 0x04
+#define BACAPP_SEGMENTED_RESPONSE 0x02
+#define BACAPP_SEGMENT_NAK 0x02
+#define BACAPP_SENT_BY 0x01
+
+
+/**
+ * dissect_bacapp ::= CHOICE {
+ *  confirmed-request-PDU       [0] BACnet-Confirmed-Request-PDU,
+ *  unconfirmed-request-PDU     [1] BACnet-Unconfirmed-Request-PDU,
+ *  simpleACK-PDU               [2] BACnet-SimpleACK-PDU,
+ *  complexACK-PDU              [3] BACnet-ComplexACK-PDU,
+ *  segmentACK-PDU              [4] BACnet-SegmentACK-PDU,
+ *  error-PDU                   [5] BACnet-Error-PDU,
+ *  reject-PDU                  [6] BACnet-Reject-PDU,
+ *  abort-PDU                   [7] BACnet-Abort-PDU
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ **/
+static void
+dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/**
+ * ConfirmedRequest-PDU ::= SEQUENCE {
+ *     pdu-type                                        [0] Unsigned (0..15), -- 0 for this PDU Type
+ *  segmentedMessage                   [1] BOOLEAN,
+ *  moreFollows                                        [2] BOOLEAN,
+ *  segmented-response-accepted        [3] BOOLEAN,
+ *  reserved                                   [4] Unsigned (0..3), -- must be set zero
+ *  max-segments-accepted              [5] Unsigned (0..7), -- as per 20.1.2.4
+ *  max-APDU-length-accepted   [5] Unsigned (0..15), -- as per 20.1.2.5
+ *  invokeID                                   [6] Unsigned (0..255),
+ *  sequence-number                            [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
+ *  proposed-window-size               [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
+ *  service-choice                             [9] BACnetConfirmedServiceChoice,
+ *  service-request                            [10] BACnet-Confirmed-Service-Request OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param ack - indocates whether working on request or ack
+ * @param svc - output variable to return service choice
+ * @param tt  - output varable to return service choice item
+ * @return modified offset
+ */
+static guint
+fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 ack,
+                               gint *svc, proto_item **tt);
+
+/**
+ * Unconfirmed-Request-PDU ::= SEQUENCE {
+ *     pdu-type                [0] Unsigned (0..15), -- 1 for this PDU type
+ *  reserved           [1] Unsigned (0..15), -- must be set zero
+ *  service-choice     [2] BACnetUnconfirmedServiceChoice,
+ *  service-request    [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * SimpleACK-PDU ::= SEQUENCE {
+ *     pdu-type                [0] Unsigned (0..15), -- 2 for this PDU type
+ *  reserved           [1] Unsigned (0..15), -- must be set zero
+ *  invokeID           [2] Unsigned (0..255),
+ *  service-ACK-choice [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ComplexACK-PDU ::= SEQUENCE {
+ *     pdu-type                                [0] Unsigned (0..15), -- 3 for this PDU Type
+ *  segmentedMessage           [1] BOOLEAN,
+ *  moreFollows                                [2] BOOLEAN,
+ *  reserved                           [3] Unsigned (0..3), -- must be set zero
+ *  invokeID                           [4] Unsigned (0..255),
+ *  sequence-number                    [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
+ *  proposed-window-size       [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
+ *  service-ACK-choice                 [7] BACnetConfirmedServiceChoice,
+ *  service-ACK                                [8] BACnet-Confirmed-Service-Request  -- Context-specific tags 0..8 are NOT used in header encoding
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * SegmentACK-PDU ::= SEQUENCE {
+ *     pdu-type                                [0] Unsigned (0..15), -- 4 for this PDU Type
+ *  reserved                           [1] Unsigned (0..3), -- must be set zero
+ *  negative-ACK                       [2] BOOLEAN,
+ *  server                                     [3] BOOLEAN,
+ *  original-invokeID          [4] Unsigned (0..255),
+ *  sequence-number                    [5] Unsigned (0..255),
+ *  actual-window-size         [6] Unsigned (0..127)
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Error-PDU ::= SEQUENCE {
+ *     pdu-type                                [0] Unsigned (0..15), -- 5 for this PDU Type
+ *  reserved                           [1] Unsigned (0..3), -- must be set zero
+ *  original-invokeID          [2] Unsigned (0..255),
+ *  error-choice                       [3] BACnetConfirmedServiceChoice,
+ *  error                                      [4] BACnet-Error
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Reject-PDU ::= SEQUENCE {
+ *     pdu-type                                [0] Unsigned (0..15), -- 6 for this PDU Type
+ *  reserved                           [1] Unsigned (0..3), -- must be set zero
+ *  original-invokeID          [2] Unsigned (0..255),
+ *  reject-reason                      [3] BACnetRejectReason
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Abort-PDU ::= SEQUENCE {
+ *     pdu-type                                [0] Unsigned (0..15), -- 7 for this PDU Type
+ *  reserved                           [1] Unsigned (0..3), -- must be set zero
+ *  server                                     [2] BOOLEAN,
+ *  original-invokeID          [3] Unsigned (0..255),
+ *  abort-reason                       [4] BACnetAbortReason
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fUnsignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fSignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @param lvt length of String
+ * @return modified offset
+ */
+static guint
+fOctetString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt);
+
+/**
+ * 20.2.12, adds the label with Date Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fDate    (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * 20.2.13, adds the label with Time Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * 20.2.14, adds Object Identifier to tree
+ * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fObjectIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnet-Confirmed-Service-Request ::= CHOICE {
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param service_choice
+ * @return offset
+ */
+static guint
+fConfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
+
+/**
+ * BACnet-Confirmed-Service-ACK ::= CHOICE {
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param service_choice
+ * @return offset
+ */
+static guint
+fConfirmedServiceAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
+
+/**
+ * AcknowledgeAlarm-Request ::= SEQUENCE {
+ *     acknowledgingProcessIdentifier  [0]     Unsigned32,
+ *     eventObjectIdentifier   [1] BACnetObjectIdentifer,
+ *     eventStateAcknowledge   [2] BACnetEventState,
+ *     timeStamp       [3] BACnetTimeStamp,
+ *     acknowledgementSource   [4] Character String,
+ *  timeOfAcknowledgement      [5] BACnetTimeStamp
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAcknowledgeAlarmRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedCOVNotification-Request ::= SEQUENCE {
+ *     subscriberProcessIdentifier     [0]     Unsigned32,
+ *     initiatingDeviceIdentifier      [1] BACnetObjectIdentifer,
+ *     monitoredObjectIdentifier       [2] BACnetObjectIdentifer,
+ *     timeRemaining   [3] unsigned,
+ *     listOfValues    [4] SEQUENCE OF BACnetPropertyValues
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedEventNotification-Request ::= SEQUENCE {
+ *     ProcessIdentifier       [0]     Unsigned32,
+ *     initiatingDeviceIdentifier      [1] BACnetObjectIdentifer,
+ *     eventObjectIdentifier   [2] BACnetObjectIdentifer,
+ *     timeStamp       [3] BACnetTimeStamp,
+ *     notificationClass       [4] unsigned,
+ *     priority        [5] unsigned8,
+ *     eventType       [6] BACnetEventType,
+ *     messageText     [7] CharacterString OPTIONAL,
+ *     notifyType      [8] BACnetNotifyType,
+ *     ackRequired     [9] BOOLEAN OPTIONAL,
+ *     fromState       [10] BACnetEventState OPTIONAL,
+ *     toState [11] BACnetEventState,
+ *     eventValues     [12] BACnetNotificationParameters OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo,  proto_tree *tree, guint offset);
+
+/**
+ * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
+ *     objectIdentifier        BACnetObjectIdentifer,
+ *     alarmState      BACnetEventState,
+ *     acknowledgedTransitions  BACnetEventTransitionBits
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetAlarmSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetEnrollmentSummary-Request ::= SEQUENCE {
+ *     acknowledgmentFilter    [0]     ENUMERATED {
+ *      all (0),
+ *      acked   (1),
+ *      not-acked   (2)
+ *      },
+ *     enrollmentFilter        [1] BACnetRecipientProcess OPTIONAL,
+ *     eventStateFilter        [2] ENUMERATED {
+ *      offnormal   (0),
+ *      fault   (1),
+ *      normal  (2),
+ *      all (3),
+ *      active  (4)
+ *      },
+ *     eventTypeFilter [3] BACnetEventType OPTIONAL,
+ *     priorityFilter  [4] SEQUENCE {
+ *      minPriority [0] Unsigned8,
+ *      maxPriority [1] Unsigned8
+ *      } OPTIONAL,
+ *  notificationClassFilter    [5] Unsigned OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetEnrollmentSummaryRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
+ *     objectIdentifier        BACnetObjectIdentifer,
+ *     eventType       BACnetEventType,
+ *     eventState      BACnetEventState,
+ *     priority    Unsigned8,
+ *  notificationClass   Unsigned OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetEnrollmentSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetEventInformation-Request ::= SEQUENCE {
+ *     lastReceivedObjectIdentifier    [0] BACnetObjectIdentifer
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetEventInformationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetEventInformation-ACK ::= SEQUENCE {
+ *     listOfEventSummaries    [0] listOfEventSummaries,
+ *  moreEvents  [1] BOOLEAN
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetEventInformationACK (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * LifeSafetyOperation-Request ::= SEQUENCE {
+ *     requestingProcessIdentifier     [0]     Unsigned32
+ *     requestingSource        [1] CharacterString
+ *     request [2] BACnetLifeSafetyOperation
+ *     objectIdentifier        [3] BACnetObjectIdentifier OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * SubscribeCOV-Request ::= SEQUENCE {
+ *     subscriberProcessIdentifier     [0]     Unsigned32
+ *     monitoredObjectIdentifier       [1] BACnetObjectIdentifier
+ *     issueConfirmedNotifications     [2] BOOLEAN OPTIONAL
+ *     lifetime        [3] Unsigned OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param label
+ * @param src
+ * @return modified offset
+ */
+static guint
+fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * SubscribeCOVProperty-Request ::= SEQUENCE {
+ *     subscriberProcessIdentifier     [0]     Unsigned32
+ *     monitoredObjectIdentifier       [1] BACnetObjectIdentifier
+ *     issueConfirmedNotifications     [2] BOOLEAN OPTIONAL
+ *     lifetime        [3] Unsigned OPTIONAL
+ *     monitoredPropertyIdentifier     [4] BACnetPropertyReference OPTIONAL
+ *     covIncrement    [5] Unsigned OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * AtomicReadFile-Request ::= SEQUENCE {
+ *     fileIdentifier  BACnetObjectIdentifier,
+ *  accessMethod       CHOICE {
+ *     streamAccess    [0] SEQUENCE {
+ *             fileStartPosition       INTEGER,
+ *                     requestedOctetCount     Unsigned
+ *                     },
+ *             recordAccess    [1] SEQUENCE {
+ *                     fileStartRecord INTEGER,
+ *                     requestedRecordCount    Unsigned
+ *                     }
+ *             }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * AtomicWriteFile-ACK ::= SEQUENCE {
+ *     endOfFile       BOOLEAN,
+ *  accessMethod       CHOICE {
+ *     streamAccess    [0] SEQUENCE {
+ *             fileStartPosition       INTEGER,
+ *                     fileData        OCTET STRING
+ *                     },
+ *             recordAccess    [1] SEQUENCE {
+ *                     fileStartRecord INTEGER,
+ *                     returnedRecordCount     Unsigned,
+ *                     fileRecordData  SEQUENCE OF OCTET STRING
+ *                     }
+ *             }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAtomicReadFileAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * AtomicWriteFile-Request ::= SEQUENCE {
+ *     fileIdentifier  BACnetObjectIdentifier,
+ *  accessMethod       CHOICE {
+ *     streamAccess    [0] SEQUENCE {
+ *             fileStartPosition       INTEGER,
+ *                     fileData        OCTET STRING
+ *                     },
+ *             recordAccess    [1] SEQUENCE {
+ *                     fileStartRecord INTEGER,
+ *                     recordCount     Unsigned,
+ *                     fileRecordData  SEQUENCE OF OCTET STRING
+ *                     }
+ *             }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * AtomicWriteFile-ACK ::= SEQUENCE {
+ *             fileStartPosition       [0] INTEGER,
+ *             fileStartRecord [1] INTEGER,
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAtomicWriteFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * AddListElement-Request ::= SEQUENCE {
+ *     objectIdentifier        [0] BACnetObjectIdentifier,
+ *  propertyIdentifier  [1] BACnetPropertyIdentifier,
+ *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
+ *  listOfElements  [3] ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * CreateObject-Request ::= SEQUENCE {
+ *     objectSpecifier [0] ObjectSpecifier,
+ *  listOfInitialValues        [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * CreateObject-Request ::= BACnetObjectIdentifier
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fCreateObjectAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * DeleteObject-Request ::= SEQUENCE {
+ *     ObjectIdentifier        BACnetObjectIdentifer
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadProperty-Request ::= SEQUENCE {
+ *     objectIdentifier        [0]     BACnetObjectIdentifier,
+ *     propertyIdentifier      [1] BACnetPropertyIdentifier,
+ *     propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadProperty-ACK ::= SEQUENCE {
+ *     objectIdentifier        [0]     BACnetObjectIdentifier,
+ *     propertyIdentifier      [1] BACnetPropertyIdentifier,
+ *     propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
+ *     propertyValue   [3] ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadPropertyAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadPropertyConditional-Request ::= SEQUENCE {
+ *     objectSelectionCriteria [0] objectSelectionCriteria,
+ *     listOfPropertyReferences        [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * ReadPropertyConditional-ACK ::= SEQUENCE {
+ *     listOfPReadAccessResults        SEQUENCE OF ReadAccessResult OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadPropertyConditionalAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadPropertyMultiple-Request ::= SEQUENCE {
+ *  listOfReadAccessSpecs      SEQUENCE OF ReadAccessSpecification
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return offset modified
+ */
+static guint
+fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * ReadPropertyMultiple-Ack ::= SEQUENCE {
+ *  listOfReadAccessResults    SEQUENCE OF ReadAccessResult
+ * }
+ * @param tvb
+ * @parma pinfo
+ * @param tree
+ * @param offset
+ * @return offset modified
+ */
+static guint
+fReadPropertyMultipleAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadRange-Request ::= SEQUENCE {
+ *     objectIdentifier        [0] BACnetObjectIdentifier,
+ *  propertyIdentifier [1] BACnetPropertyIdentifier,
+ *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ *     range   CHOICE {
+ *             byPosition      [3] SEQUENCE {
+ *                     referencedIndex Unsigned,
+ *                     count INTEGER
+ *                     },
+ *             byTime  [4] SEQUENCE {
+ *                     referenceTime BACnetDateTime,
+ *                     count INTEGER
+ *                     },
+ *             timeRange       [5] SEQUENCE {
+ *                     beginningTime BACnetDateTime,
+ *                     endingTime BACnetDateTime
+ *                     },
+ *             } OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadRangeRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadRange-ACK ::= SEQUENCE {
+ *     objectIdentifier        [0] BACnetObjectIdentifier,
+ *  propertyIdentifier [1] BACnetPropertyIdentifier,
+ *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ *  resultFlags        [3] BACnetResultFlags,
+ *  itemCount  [4] Unsigned,
+ *  itemData   [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadRangeAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * RemoveListElement-Request ::= SEQUENCE {
+ *     objectIdentifier        [0]     BACnetObjectIdentifier,
+ *     propertyIdentifier      [1] BACnetPropertyIdentifier,
+ *     propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
+ *     listOfElements  [3] ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * WriteProperty-Request ::= SEQUENCE {
+ *     objectIdentifier        [0]     BACnetObjectIdentifier,
+ *     propertyIdentifier      [1] BACnetPropertyIdentifier,
+ *     propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
+ *     propertyValue   [3] ABSTRACT-SYNTAX.&Type
+ *  priority   [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * WritePropertyMultiple-Request ::= SEQUENCE {
+ *     listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * DeviceCommunicationControl-Request ::= SEQUENCE {
+ *     timeDuration    [0] Unsigned16 OPTIONAL,
+ *  enable-disable     [1] ENUMERATED {
+ *             enable (0),
+ *             disable (1)
+ *             },
+ *  password   [2] CharacterString (SIZE(1..20)) OPTIONAL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDeviceCommunicationControlRequest(tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
+ *     vendorID        [0]     Unsigned,
+ *     serviceNumber   [1] Unsigned,
+ *     serviceParameters       [2] ABSTRACT-SYNTAX.&Type OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
+ *     vendorID        [0]     Unsigned,
+ *     serviceNumber   [1] Unsigned,
+ *     resultBlock     [2] ABSTRACT-SYNTAX.&Type OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedTextMessage-Request ::=  SEQUENCE {
+ *  textMessageSourceDevice [0] BACnetObjectIdentifier,
+ *  messageClass [1] CHOICE {
+ *      numeric [0] Unsigned,
+ *      character [1] CharacterString
+ *      } OPTIONAL,
+ *  messagePriority [2] ENUMERATED {
+ *      normal (0),
+ *      urgent (1)
+ *      },
+ *  message [3] CharacterString
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReinitializeDevice-Request ::= SEQUENCE {
+ *  reinitializedStateOfDevice [0] ENUMERATED {
+ *             coldstart (0),
+ *             warmstart (1),
+ *             startbackup (2),
+ *             endbackup (3),
+ *             startrestore (4),
+ *             endrestore (5),
+ *             abortrestor (6)
+ *             },
+ *  password   [1] CharacterString (SIZE(1..20)) OPTIONAL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReinitializeDeviceRequest(tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * VTOpen-Request ::= SEQUENCE {
+ *  vtClass    BACnetVTClass,
+ *  localVTSessionIdentifier   Unsigned8
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTOpen-ACK ::= SEQUENCE {
+ *  remoteVTSessionIdentifier  Unsigned8
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtOpenAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTClose-Request ::= SEQUENCE {
+ *  listOfRemoteVTSessionIdentifiers   SEQUENCE OF Unsigned8
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtCloseRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTData-Request ::= SEQUENCE {
+ *  vtSessionIdentifier        Unsigned8,
+ *  vtNewData  OCTET STRING,
+ *  vtDataFlag Unsigned (0..1)
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtDataRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTData-ACK ::= SEQUENCE {
+ *  allNewDataAccepted [0] BOOLEAN,
+ *  acceptedOctetCount [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = FALSE
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtDataAck (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * Authenticate-Request ::= SEQUENCE {
+ *  pseudoRandomNumber [0] Unsigned32,
+ *  excpectedInvokeID  [1] Unsigned8 OPTIONAL,
+ *  operatorName       [2] CharacterString OPTIONAL,
+ *  operatorPassword   [3] CharacterString (SIZE(1..20)) OPTIONAL,
+ *  startEncypheredSession     [4] BOOLEAN OPTIONAL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAuthenticateRequest (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * Authenticate-ACK ::= SEQUENCE {
+ *  modifiedRandomNumber       Unsigned32,
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAuthenticateAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * RequestKey-Request ::= SEQUENCE {
+ *  requestingDeviceIdentifier BACnetObjectIdentifier,
+ *  requestingDeviceAddress    BACnetAddress,
+ *  remoteDeviceIdentifier     BACnetObjectIdentifier,
+ *  remoteDeviceAddress        BACnetAddress
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRequestKeyRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Unconfirmed-Service-Request ::= CHOICE {
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param service_choice
+ * @return modified offset
+ */
+static guint
+fUnconfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
+
+/**
+ * UnconfirmedCOVNotification-Request ::= SEQUENCE {
+ *     subscriberProcessIdentifier     [0]     Unsigned32,
+ *     initiatingDeviceIdentifier      [1] BACnetObjectIdentifer,
+ *     monitoredObjectIdentifier       [2] BACnetObjectIdentifer,
+ *     timeRemaining   [3] unsigned,
+ *     listOfValues    [4] SEQUENCE OF BACnetPropertyValues
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * UnconfirmedEventNotification-Request ::= SEQUENCE {
+ *     ProcessIdentifier       [0]     Unsigned32,
+ *     initiatingDeviceIdentifier      [1] BACnetObjectIdentifer,
+ *     eventObjectIdentifier   [2] BACnetObjectIdentifer,
+ *     timeStamp       [3] BACnetTimeStamp,
+ *     notificationClass       [4] unsigned,
+ *     priority        [5] unsigned8,
+ *     eventType       [6] BACnetEventType,
+ *     messageText     [7] CharacterString OPTIONAL,
+ *     notifyType      [8] BACnetNotifyType,
+ *     ackRequired     [9] BOOLEAN OPTIONAL,
+ *     fromState       [10] BACnetEventState OPTIONAL,
+ *     toState [11] BACnetEventState,
+ *     eventValues     [12] BACnetNotificationParameters OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * I-Am-Request ::= SEQUENCE {
+ *     aAmDeviceIdentifier     BACnetObjectIdentifier,
+ *  maxAPDULengthAccepted      Unsigned,
+ *     segmentationSupported   BACnetSegmentation,
+ *     vendorID        Unsigned
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fIAmRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+
+/**
+ * I-Have-Request ::= SEQUENCE {
+ *     deviceIdentifier        BACnetObjectIdentifier,
+ *  objectIdentifier   BACnetObjectIdentifier,
+ *     objectName      CharacterString
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fIHaveRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
+ *     vendorID        [0]     Unsigned,
+ *     serviceNumber   [1] Unsigned,
+ *     serviceParameters       [2] ABSTRACT-SYNTAX.&Type OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * UnconfirmedTextMessage-Request ::=  SEQUENCE {
+ *  textMessageSourceDevice [0] BACnetObjectIdentifier,
+ *  messageClass [1] CHOICE {
+ *      numeric [0] Unsigned,
+ *      character [1] CharacterString
+ *      } OPTIONAL,
+ *  messagePriority [2] ENUMERATED {
+ *      normal (0),
+ *      urgent (1)
+ *      },
+ *  message [3] CharacterString
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * TimeSynchronization-Request ::=  SEQUENCE {
+ *  BACnetDateTime
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * UTCTimeSynchronization-Request ::=  SEQUENCE {
+ *  BACnetDateTime
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUTCTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * Who-Has-Request ::=  SEQUENCE {
+ *  limits SEQUENCE {
+ *      deviceInstanceRangeLowLimit [0] Unsigned (0..4194303),
+ *      deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
+ *      } OPTIONAL,
+ *  object CHOICE {
+ *      objectIdentifier [2] BACnetObjectIdentifier,
+ *      objectName [3] CharacterString
+ *      }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWhoHas (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Who-Is-Request ::= SEQUENCE {
+ *     deviceInstanceRangeLowLimit     [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
+ *     deviceInstanceRangeHighLimit    [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWhoIsRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * BACnet-Error ::= CHOICE {
+ *  addListElement          [8] ChangeList-Error,
+ *  removeListElement       [9] ChangeList-Error,
+ *  writePropertyMultiple   [16] WritePropertyMultiple-Error,
+ *  confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
+ *  vtClose                 [22] VTClose-Error,
+ *  readRange               [26] ObjectAccessService-Error
+ *                      [default] Error
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param service
+ * @return modified offset
+ */
+static guint
+fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service);
+
+/**
+ * Dissect a BACnetError in a context tag
+ *
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ChangeList-Error ::= SEQUENCE {
+ *    errorType     [0] Error,
+ *    firstFailedElementNumber  [1] Unsigned
+ *    }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * CreateObject-Error ::= SEQUENCE {
+ *    errorType     [0] Error,
+ *    firstFailedElementNumber  [1] Unsigned
+ *    }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
+ *    errorType     [0] Error,
+ *    vendorID      [1] Unsigned,
+ *    serviceNumber [2] Unsigned,
+ *    errorParameters   [3] ABSTRACT-SYNTAX.&Type OPTIONAL
+ *    }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * WritePropertyMultiple-Error ::= SEQUENCE {
+ *    errorType     [0] Error,
+ *    firstFailedWriteAttempt  [1] Unsigned
+ *    }
+ * }
+ * @param tvb
+ * @pram pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTClose-Error ::= SEQUENCE {
+ *    errorType     [0] Error,
+ *    listOfVTSessionIdentifiers  [1] SEQUENCE OF Unsigned8 OPTIONAL
+ *    }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnet Application Types chapter 20.2.1
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fApplicationTypes   (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * BACnetActionCommand ::= SEQUENCE {
+ *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
+ *  objectIdentifier    [1] BACnetObjectIdentifier,
+ *  propertyIdentifier  [2] BACnetPropertyIdentifier,
+ *  propertyArrayIndex  [3] Unsigned OPTIONAL, -- used only with array datatype
+ *  propertyValue       [4] ABSTRACT-SYNTAX.&Type,
+ *  priority            [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
+ *  postDelay           [6] Unsigned OPTIONAL,
+ *  quitOnFailure       [7] BOOLEAN,
+ *  writeSuccessful     [8] BOOLEAN
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param matching tag number
+ * @return modified offset
+ */
+static guint
+fActionCommand (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match);
+
+/**
+ * BACnetActionList ::= SEQUENCE {
+ *  action  [0] SEQUENCE of BACnetActionCommand
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fActionList (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/** BACnetAddress ::= SEQUENCE {
+ *  network-number  Unsigned16, -- A value 0 indicates the local network
+ *  mac-address     OCTET STRING -- A string of length 0 indicates a broadcast
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAddress (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * BACnetAddressBinding ::= SEQUENCE {
+ *     deviceObjectID  BACnetObjectIdentifier
+ *     deviceAddress   BacnetAddress
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAddressBinding (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetCalendaryEntry ::= CHOICE {
+ *     date        [0] Date,
+ *     dateRange   [1] BACnetDateRange,
+ *  weekNDay    [2] BacnetWeekNday
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fCalendaryEntry (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * BACnetClientCOV ::= CHOICE {
+ *     real-increment  REAL,
+ *     default-increment   NULL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fClientCOV (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+
+/**
+ * BACnetDailySchedule ::= SEQUENCE {
+ *  day-schedule    [0] SENQUENCE OF BACnetTimeValue
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDailySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetWeeklySchedule ::= SEQUENCE {
+ *  week-schedule    SENQUENCE SIZE (7) OF BACnetDailySchedule
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWeeklySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetDateRange ::= SEQUENCE {
+ *  StartDate   Date,
+ *  EndDate     Date
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDateRange (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * BACnetDateTime ::= SEQUENCE {
+ *  date   Date,
+ *  time   Time
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fDateTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * BACnetDestination ::= SEQUENCE {
+ *  validDays   BACnetDaysOfWeek,
+ *  fromTime    Time,
+ *  toTime      Time,
+ *  recipient   BACnetRecipient,
+ *  processIdentifier   Unsigned32,
+ *  issueConfirmedNotifications BOOLEAN,
+ *  transitions BACnetEventTransitionBits
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDestination (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
+ *  objectIdentifier    [0] BACnetObjectIdentifier,
+ *  propertyIdentifier  [1] BACnetPropertyIdentifier,
+ *  propertyArrayIndex  [2] Unsigend OPTIONAL,
+ *  deviceIdentifier    [3] BACnetObjectIdentifier OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDeviceObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetDeviceObjectReference ::= SEQUENCE {
+ *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
+ *  objectIdentifier    [1] BACnetObjectIdentifier
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDeviceObjectReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+#if 0
+/**
+ * BACnetEventParameter ::= CHOICE {
+ *     change-of-bitstring [0] SEQUENCE {
+ *     time-delay [0] Unsigned,
+ *     bitmask [1] BIT STRING,
+ *     list-of-bitstring-values [2] SEQUENCE OF BIT STRING
+ *     },
+ *  change-of-state [1] SEQUENCE {
+ *     time-delay [0] Unsigned,
+ *     list-of-values [1] SEQUENCE OF BACnetPropertyStates
+ *     },
+ *   change-of-value [2] SEQUENCE {
+ *     time-delay [0] Unsigned,
+ *     cov-criteria [1] CHOICE {
+ *             bitmask [0] BIT STRING,
+ *             referenced-property-increment [1] REAL
+ *                     }
+ *             },
+ *     command-failure [3] SEQUENCE {
+ *             time-delay [0] Unsigned,
+ *             feedback-property-reference [1] BACnetDeviceObjectPropertyReference
+ *             },
+ *     floating-limit [4] SEQUENCE {
+ *             time-delay [0] Unsigned,
+ *             setpoint-reference [1] BACnetDeviceObjectPropertyReference,
+ *             low-diff-limit [2] REAL,
+ *             high-diff-limit [3] REAL,
+ *             deadband [4] REAL
+ *             },
+ *     out-of-range [5] SEQUENCE {
+ *             time-delay [0] Unsigned,
+ *             low-limit [1] REAL,
+ *             high-limit [2] REAL,
+ *             deadband [3] REAL
+ *             },
+ *     buffer-ready [7] SEQUENCE {
+ *             notification-threshold [0] Unsigned,
+ *             previous-notification-count [1] Unsigned32
+ *             }
+ *     change-of-life-safety [8] SEQUENCE {
+ *             time-delay [0] Unsigned,
+ *             list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
+ *             list-of-alarm-values [2] SEQUENCE OF BACnetLifeSafetyState,
+ *             mode-property-reference [3] BACnetDeviceObjectPropertyReference
+ *             }
+ *     }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset);
+#endif
+
+
+
+/**
+ * BACnetLogRecord ::= SEQUENCE {
+ *     timestamp [0] BACnetDateTime,
+ *     logDatum [1] CHOICE {
+ *             log-status [0] BACnetLogStatus,
+ *             boolean-value [1] BOOLEAN,
+ *             real-value [2] REAL,
+ *             enum-value [3] ENUMERATED, -- Optionally limited to 32 bits
+ *             unsigned-value [4] Unsigned, -- Optionally limited to 32 bits
+ *             signed-value [5] INTEGER, -- Optionally limited to 32 bits
+ *             bitstring-value [6] BIT STRING,-- Optionally limited to 32 bits
+ *             null-value [7] NULL,
+ *             failure [8] Error,
+ *             time-change [9] REAL,
+ *             any-value [10] ABSTRACT-SYNTAX.&Type -- Optional
+ *             }
+ *     statusFlags [2] BACnetStatusFlags OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fLogRecord (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+
+/**
+ * BACnetNotificationParameters ::= CHOICE {
+ *     change-of-bitstring     [0]     SEQUENCE {
+ *      referenced-bitstring    [0] BIT STRING,
+ *      status-flags    [1] BACnetStatusFlags
+ *      },
+ *  change-of-state [1]        SEQUENCE {
+ *      new-state   [0] BACnetPropertyStatus,
+ *      status-flags    [1] BACnetStatusFlags
+ *      },
+ *  change-of-value [2]        SEQUENCE {
+ *      new-value   [0] CHOICE {
+ *          changed-bits   [0] BIT STRING,
+ *          changed-value    [1] REAL
+ *          },
+ *      status-flags    [1] BACnetStatusFlags
+ *      },
+ *  command-failure [3]        SEQUENCE {
+ *      command-value   [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
+ *      status-flags    [1] BACnetStatusFlags
+ *      feedback-value    [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
+ *      },
+ *  floating-limit [4] SEQUENCE {
+ *      reference-value   [0] REAL,
+ *      status-flags    [1] BACnetStatusFlags
+ *      setpoint-value   [2] REAL,
+ *      error-limit   [3] REAL
+ *      },
+ *  out-of-range [5]   SEQUENCE {
+ *      exceeding-value   [0] REAL,
+ *      status-flags    [1] BACnetStatusFlags
+ *      deadband   [2] REAL,
+ *      exceeded-limit   [0] REAL
+ *      },
+ *  complex-event-type  [6] SEQUENCE OF BACnetPropertyValue,
+ *  buffer-ready [7]   SEQUENCE {
+ *      buffer-device   [0] BACnetObjectIdentifier,
+ *      buffer-object    [1] BACnetObjectIdentifier
+ *      previous-notification   [2] BACnetDateTime,
+ *      current-notification   [3] BACnetDateTime
+ *      },
+ *  change-of-life-safety [8]  SEQUENCE {
+ *      new-state   [0] BACnetLifeSafetyState,
+ *      new-mode    [1] BACnetLifeSafetyState
+ *      status-flags   [2] BACnetStatusFlags,
+ *      operation-expected   [3] BACnetLifeSafetyOperation
+ *      }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fNotificationParameters (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetObjectPropertyReference ::= SEQUENCE {
+ *     objectIdentifier        [0] BACnetObjectIdentifier,
+ *     propertyIdentifier      [1] BACnetPropertyIdentifier,
+ *     propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+#if 0
+/**
+ * BACnetObjectPropertyValue ::= SEQUENCE {
+ *             objectIdentifier [0] BACnetObjectIdentifier,
+ *             propertyIdentifier [1] BACnetPropertyIdentifier,
+ *             propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ *                             -- if omitted with an array the entire array is referenced
+ *             value [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
+ *             priority [4] Unsigned (1..16) OPTIONAL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset);
+#endif
+
+/**
+ * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fPriorityArray (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+static guint
+fPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list);
+
+/**
+ * BACnetPropertyReference ::= SEQUENCE {
+ *     propertyIdentifier      [0] BACnetPropertyIdentifier,
+ *     propertyArrayIndex      [1] Unsigned OPTIONAL, -- used only with array datatype
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fBACnetPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list);
+
+/* static guint
+fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset); */
+
+static guint
+fLOPR (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+static guint
+fRestartReason (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetPropertyValue ::= SEQUENCE {
+ *             PropertyIdentifier [0] BACnetPropertyIdentifier,
+ *             propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
+ *                             -- if omitted with an array the entire array is referenced
+ *             value [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
+ *             priority [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fBACnetPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+static guint
+fPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset);
+
+/**
+ * BACnet Application PDUs chapter 21
+ * BACnetRecipient::= CHOICE {
+ *     device  [0] BACnetObjectIdentifier
+ *     address [1] BACnetAddress
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRecipient (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnet Application PDUs chapter 21
+ * BACnetRecipientProcess::= SEQUENCE {
+ *     recipient       [0] BACnetRecipient
+ *     processID       [1] Unsigned32
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRecipientProcess (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+#if 0
+/**
+ * BACnetSessionKey ::= SEQUENCE {
+ *     sessionKey      OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
+ *     peerAddress     BACnetAddress
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ * @todo check if checksum is displayed correctly
+ */
+static guint
+fSessionKey (tvbuff_t *tvb, proto_tree *tree, guint offset);
+#endif
+
+/**
+ * BACnetSpecialEvent ::= SEQUENCE {
+ *     period          CHOICE {
+ *             calendarEntry           [0] BACnetCalendarEntry,
+ *             calendarRefernce        [1] BACnetObjectIdentifier
+ *             },
+ *             listOfTimeValues        [2] SEQUENCE OF BACnetTimeValue,
+ *             eventPriority           [3] Unsigned (1..16)
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSpecialEvent (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetTimeStamp ::= CHOICE {
+ *     time                    [0] Time,
+ *     sequenceNumber  [1] Unsigned (0..65535),
+ *     dateTime                [2] BACnetDateTime
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fTimeStamp (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * BACnetTimeValue ::= SEQUENCE {
+ *     time    Time,
+ *     value   ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fTimeValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+#if 0
+/**
+ * BACnetVTSession ::= SEQUENCE {
+ *     local-vtSessionID       Unsigned8,
+ *     remote-vtSessionID      Unsigned8,
+ *     remote-vtAddress        BACnetAddress
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVTSession (tvbuff_t *tvb, proto_tree *tree, guint offset);
+#endif
+
+/**
+ * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
+ * -- first octet month (1..12) January = 1, X'FF' = any month
+ * -- second octet weekOfMonth where: 1 = days numbered 1-7
+ * -- 2 = days numbered 8-14
+ * -- 3 = days numbered 15-21
+ * -- 4 = days numbered 22-28
+ * -- 5 = days numbered 29-31
+ * -- 6 = last 7 days of this month
+ * -- X'FF' = any week of this month
+ * -- third octet dayOfWeek (1..7) where 1 = Monday
+ * -- 7 = Sunday
+ * -- X'FF' = any day of week
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWeekNDay (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * ReadAccessResult ::= SEQUENCE {
+ *     objectIdentifier        [0] BACnetObjectIdentifier,
+ *     listOfResults   [1] SEQUENCE OF SEQUENCE {
+ *             propertyIdentifier      [2] BACnetPropertyIdentifier,
+ *             propertyArrayIndex      [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
+ *             readResult      CHOICE {
+ *                     propertyValue   [4] ABSTRACT-SYNTAX.&Type,
+ *                     propertyAccessError     [5] Error
+ *             }
+ *  } OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadAccessResult (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadAccessSpecification ::= SEQUENCE {
+ *     objectIdentifier        [0] BACnetObjectIdentifier,
+ *     listOfPropertyReferences        [1] SEQUENCE OF BACnetPropertyReference
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * WriteAccessSpecification ::= SEQUENCE {
+ *     objectIdentifier        [0] BACnetObjectIdentifier,
+ *     listOfProperty  [1] SEQUENCE OF BACnetPropertyValue
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWriteAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+
+/********************************************************* Helper functions *******************************************/
+
+/**
+ * extracts the tag number from the tag header.
+ * @param tvb "TestyVirtualBuffer"
+ * @param offset in actual tvb
+ * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
+ */
+static guint
+fTagNo (tvbuff_t *tvb, guint offset);
+
+/**
+ * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
+ * @param tvb = "TestyVirtualBuffer"
+ * @param offset = offset in actual tvb
+ * @return tag_no BACnet 20.2.1.2 Tag Number
+ * @return class_tag BACnet 20.2.1.1 Class
+ * @return lvt BACnet 20.2.1.3 Length/Value/Type
+ * @return offs = length of this header
+ */
+
+static guint
+fTagHeader (tvbuff_t *tvb, guint offset, guint8 *tag_no, guint8* class_tag, guint32 *lvt);
+
+
+/**
+ * adds processID with max 32Bit unsigned Integer Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fProcessId (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * adds timeSpan with max 32Bit unsigned Integer Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fTimeSpan (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * BACnet Application PDUs chapter 21
+ * BACnetPropertyIdentifier::= ENUMERATED {
+ *      @see bacapp_property_identifier
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param tt returnvalue of this item
+ * @return modified offset
+ */
+static guint
+fPropertyIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnet Application PDUs chapter 21
+ * BACnetPropertyArrayIndex::= ENUMERATED {
+ *      @see bacapp_property_array_index
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param tt returnvalue of this item
+ * @return modified offset
+ */
+static guint
+fPropertyArrayIndex (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
+ *     objectIdentifier        [0] BACnetObjectIdentifier,
+ *  eventState  [1] BACnetEventState,
+ *  acknowledgedTransitions [2] BACnetEventTransitionBits,
+ *  eventTimeStamps [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
+ *  notifyType  [4] BACnetNotifyType,
+ *  eventEnable [5] BACnetEventTransitionBits,
+ *  eventPriorities [6] SEQUENCE SIZE (3) OF Unsigned
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+flistOfEventSummaries (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * SelectionCriteria ::= SEQUENCE {
+ *     propertyIdentifier      [0] BACnetPropertyIdentifier,
+ *     propertyArrayIndex      [1] Unsigned OPTIONAL, -- used only with array datatype
+ *  relationSpecifier  [2] ENUMERATED { bacapp_relationSpecifier },
+ *  comparisonValue    [3] ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * objectSelectionCriteria ::= SEQUENCE {
+ *     selectionLogic  [0] ENUMERATED { bacapp_selectionLogic },
+ *     listOfSelectionCriteria [1] SelectionCriteria
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fObjectSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * BACnet-Error ::= SEQUENCE {
+ *    error-class ENUMERATED {},
+ *    error-code  ENUMERATED {}
+ *    }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Generic handler for context tagged values.  Mostly for handling
+ * vendor-defined properties and services.
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ * @todo beautify this ugly construct
+ */
+static guint
+fContextTaggedValue(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * realizes some ABSTRACT-SYNTAX.&Type
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ * @todo beautify this ugly construct
+ */
+static guint
+fAbstractSyntaxNType (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+
+static guint
+fBitStringTagVS (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
+       const value_string *src);
+
+/**
+ * register_bacapp
+ */
+void
+proto_register_bacapp(void);
+
+/**
+ * proto_reg_handoff_bacapp
+ */
+void
+proto_reg_handoff_bacapp(void);
+
+/**
+ * converts XXX coded strings to UTF-8
+ * else 'in' is copied to 'out'
+ * @param in  -- pointer to string
+ * @param inbytesleft
+ * @param out -- pointer to string
+ * @param outbytesleft
+ * @param fromcoding
+ * @return count of modified characters of returned string, -1 for errors
+ */
+static guint32
+fConvertXXXtoUTF8(gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding);
+
+static void
+uni_to_string(char * data, gsize str_length, char *dest_buf);
+
+/* <<<< formerly bacapp.h */
+
+/* some hashes for segmented messages */
+static GHashTable *msg_fragment_table = NULL;
+static GHashTable *msg_reassembled_table = NULL;
 
 /* some necessary forward function prototypes */
 static guint
-fApplicationTypesEnumerated (tvbuff_t *tvb, proto_tree *tree, guint offset, 
+fApplicationTypesEnumerated (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
        const gchar *label, const value_string *vs);
 
 static const char *bacapp_unknown_service_str = "unknown service";
@@ -40,14 +2175,14 @@ static const char *Vendor_Proprietary_Fmt = "(%d) Vendor Proprietary Value";
 
 static const value_string
 BACnetTypeName[] = {
-       {0, "Confirmed-Request "},
-       {1, "Unconfirmed-Request "},
-       {2, "SimpleACK "},
-       {3, "ComplexACK "},
-       {4, "SegmentACK "},
-       {5, "Error "},
-       {6, "Reject "},
-       {7, "Abort "},
+       {0, "Confirmed-REQ"},
+       {1, "Unconfirmed-REQ"},
+       {2, "Simple-ACK"},
+       {3, "Complex-ACK"},
+       {4, "Segment-ACK"},
+       {5, "Error"},
+       {6, "Reject"},
+       {7, "Abort"},
        {0, NULL }
 };
 
@@ -121,6 +2256,19 @@ BACnetRejectReason [] = {
        {0,NULL}
 };
 
+static const value_string
+BACnetRestartReason [] = {
+       {0,"unknown"},
+       {1,"coldstart"},
+       {2,"warmstart"},
+       {3,"detected-power-lost"},
+       {4,"detected-powered-off"},
+       {5,"hardware-watchdog"},
+       {6,"software-watchdog"},
+       {7,"suspended"},
+       {0,NULL}
+};
+
 static const value_string
 BACnetApplicationTagNumber [] = {
        {0,"Null"},
@@ -156,6 +2304,38 @@ BACnetFileAccessMethod [] = {
        {0,NULL}
 };
 
+/* For some reason, BACnet defines the choice parameter
+   in the file read and write services backwards from the
+   BACnetFileAccessMethod enumeration.
+*/
+static const value_string
+BACnetFileAccessOption [] = {
+       {0,"stream access"},
+       {1,"record access"},
+       {0,NULL}
+};
+
+static const value_string
+BACnetFileStartOption [] = {
+       {0, "File Start Position: "},
+       {1, "File Start Record: "},
+       {0, NULL}
+};
+
+static const value_string
+BACnetFileRequestCount [] = {
+       {0, "Requested Octet Count: "},
+       {1, "Requested Record Count: "},
+       {0, NULL}
+};
+
+static const value_string
+BACnetFileWriteInfo [] = {
+       {0, "File Data: "},
+       {1, "Record Count: "},
+       {0, NULL}
+};
+
 static const value_string
 BACnetAbortReason [] = {
        {0,"other"},
@@ -202,8 +2382,8 @@ BACnetLifeSafetyOperation [] = {
        {8,"unsilence-audible"},
        {9,"unsilence-visual"},
        {0,NULL}
-/* Enumerated values 0-63 are reserved for definition by ASHRAE. 
-   Enumerated values 64-65535 may be used by others subject to 
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+   Enumerated values 64-65535 may be used by others subject to
    procedures and constraints described in Clause 23. */
 };
 
@@ -241,8 +2421,8 @@ BACnetLifeSafetyState [] = {
        {22,"supervisory"},
        {23,"test-supervisory"},
        {0,NULL}
-/* Enumerated values 0-255 are reserved for definition by ASHRAE. 
-   Enumerated values 256-65535 may be used by others subject to 
+/* Enumerated values 0-255 are reserved for definition by ASHRAE.
+   Enumerated values 256-65535 may be used by others subject to
    procedures and constraints described in Clause 23. */
 };
 
@@ -329,31 +2509,55 @@ BACnetUnconfirmedServiceRequest [] = {
 
 static const value_string
 BACnetObjectType [] = {
-       {0,"analog-input object"},
-       {1,"analog-output object"},
-       {2,"analog-value object"},
-       {3,"binary-input object"},
-       {4,"binary-output object"},
-       {5,"binary-value object"},
-       {6,"calendar object"},
-       {7,"command object"},
-       {8,"device object"},
-       {9,"event-enrollment object"},
-       {10,"file object"},
-       {11,"group object"},
-       {12,"loop object"},
-       {13,"multi-state-input object"},
-       {14,"multi-state-output object"},
-       {15,"notification-class object"},
-       {16,"program object"},
-       {17,"schedule object"},
-       {18,"averaging object"},
-       {19,"multi-state-value object"},
-       {20,"trend-log object"},
-       {21,"life-safety-point object"},
-       {22,"life-safety-zone object"},
-       {23,"accumulator object"},
-       {24,"pulse-converter object"},
+       {0,"analog-input"},
+       {1,"analog-output"},
+       {2,"analog-value"},
+       {3,"binary-input"},
+       {4,"binary-output"},
+       {5,"binary-value"},
+       {6,"calendar"},
+       {7,"command"},
+       {8,"device"},
+       {9,"event-enrollment"},
+       {10,"file"},
+       {11,"group"},
+       {12,"loop"},
+       {13,"multi-state-input"},
+       {14,"multi-state-output"},
+       {15,"notification-class"},
+       {16,"program"},
+       {17,"schedule"},
+       {18,"averaging"},
+       {19,"multi-state-value"},
+       {20,"trend-log"},
+       {21,"life-safety-point"},
+       {22,"life-safety-zone"},
+       {23,"accumulator"},
+       {24,"pulse-converter"},
+       {25,"event-log"},
+       {26,"global-group"},
+       {27,"trend-log-multiple"},
+       {28,"load-control"},
+       {29,"structured-view"},
+       {30,"access-door"},             /* 30-37 added with addanda 135-2008j */
+       {32,"access-credential"},
+       {33,"access-point"},
+       {34,"access-rights"},
+       {35,"access-user"},
+       {36,"access-zone"},
+       {37,"credential-data-input"},
+       {39,"bitstring-value"},         /* 39-50 added with addenda 135-2008w */
+       {40,"characterstring-value"},
+       {41,"date-pattern-value"},
+       {42,"date-value"},
+       {43,"datetime-pattern-value"},
+       {44,"datetime-value"},
+       {45,"integer-value"},
+       {46,"large-analog-value"},
+       {47,"octetstring-value"},
+       {48,"positive-Integer-value"},
+       {49,"time-pattern-value"},
+       {50,"time-value"},
        {0, NULL}
 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
    Enumerated values 128-1023 may be used by others subject to
@@ -375,7 +2579,7 @@ BACnetEngineeringUnits [] = {
        {10,"Megavolt Amperes"},
        {11,"Volt Amperes Reactive"},
        {12,"Kilovolt Amperes Reactive"},
-       {13,"Megavolt Amperes Ractive"},
+       {13,"Megavolt Amperes Reactive"},
        {14,"Degrees Phase"},
        {15,"Power Factor"},
        {16,"Joules"},
@@ -390,7 +2594,7 @@ BACnetEngineeringUnits [] = {
        {25,"Cycles Per Hour"},
        {26,"Cycles Per Minute"},
        {27,"Hertz"},
-       {28,"Gramms Of Water Per Kilogram Dry Air"},
+       {28,"Grams Of Water Per Kilogram Dry Air"},
        {29,"Relative Humidity"},
        {30,"Millimeters"},
        {31,"Meters"},
@@ -400,7 +2604,7 @@ BACnetEngineeringUnits [] = {
        {35,"Watts Per Sq meter"},
        {36,"Lumens"},
        {37,"Lux"},
-       {38,"Foot Candels"},
+       {38,"Foot Candles"},
        {39,"Kilograms"},
        {40,"Pounds Mass"},
        {41,"Tons"},
@@ -425,7 +2629,7 @@ BACnetEngineeringUnits [] = {
        {60,"Centimeters Of Mercury"},
        {61,"Inches Of Mercury"},
        {62,"Degrees Celsius"},
-       {63,"Degress Kelvin"},
+       {63,"Degrees Kelvin"},
        {64,"Degrees Fahrenheit"},
        {65,"Degree Days Celsius"},
        {66,"Degree Days Fahrenheit"},
@@ -553,8 +2757,8 @@ BACnetEngineeringUnits [] = {
        {188,"newtons-per-meter"},
        {189,"watts-per-meter-per-degree-Kelvin"},
        {0,NULL}
-/* Enumerated values 0-255 are reserved for definition by ASHRAE. 
-   Enumerated values 256-65535 may be used by others subject to 
+/* Enumerated values 0-255 are reserved for definition by ASHRAE.
+   Enumerated values 256-65535 may be used by others subject to
    the procedures and constraints described in Clause 23. */
 };
 
@@ -562,9 +2766,9 @@ static const value_string
 BACnetErrorCode [] = {
        {0,"other"},
        {1,"authentication-failed"},
-       {2,"character-set-not-supported"},
-       {3,"configuration-in-progress"},
-       {4,"device-busy"},
+       {2,"configuration-in-progress"},
+       {3,"device-busy"},
+       {4,"dynamic-creation-not-supported"},
        {5,"file-access-denied"},
        {6,"incompatible-security-levels"},
        {7,"inconsistent-parameters"},
@@ -605,15 +2809,17 @@ BACnetErrorCode [] = {
        {42,"invalid-array-index"},
        {43,"cov-subscription-failed"},
        {44,"not-cov-property"},
-       {45,"optional-functionaltity-not-supported"},
+       {45,"optional-functionality-not-supported"},
        {46,"invalid-configuration-data"},
        {47,"datatype-not-supported"},
        {48,"duplicate-name"},
        {49,"duplicate-object-id"},
        {50,"property-is-not-an-array"},
+       {73,"invalid-event-state"},
+       {74,"no-alarm-configured"},
        {0, NULL}
-/* Enumerated values 0-255 are reserved for definition by ASHRAE. 
-   Enumerated values 256-65535 may be used by others subject to the 
+/* Enumerated values 0-255 are reserved for definition by ASHRAE.
+   Enumerated values 256-65535 may be used by others subject to the
    procedures and constraints described in Clause 23. */
 };
 
@@ -752,7 +2958,7 @@ BACnetPropertyIdentifier [] = {
        {130,"event-time-stamp"},
        {131,"log-buffer"},
        {132,"log-device-object-property"},
-       {133,"log-enable"},
+       {133,"enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
        {134,"log-interval"},
        {135,"maximum-value"},
        {136,"minimum-value"},
@@ -792,7 +2998,7 @@ BACnetPropertyIdentifier [] = {
        {170,"manual-slave-address-binding"},
        {171,"slave-address-binding"},
        {172,"slave-proxy-enable"},
-       {173,"last-notify-time"},
+       {173,"last-notify-record"},             /* bug 4117 */
        {174,"schedule-default"},
        {175,"accepted-modes"},
        {176,"adjust-value"},
@@ -812,9 +3018,130 @@ BACnetPropertyIdentifier [] = {
        {190,"value-before-change"},
        {191,"value-set"},
        {192,"value-change-time"},
+       {193,"align-intervals"},
+       {194,"group-member-names"},
+       {195,"interval-offset"},
+       {196,"last-restart-reason"},
+       {197,"logging-type"},
+       {198,"member-status-flags"},
+       {199,"notification-period"},
+       {200,"previous-notify-record"},
+       {201,"requested-update-interval"},
+       {202,"restart-notification-recipients"},
+       {203,"time-of-device-restart"},
+       {204,"time-synchronization-recipients"},
+       {205,"trigger"},
+       {206,"UTC-time-synchronization-recipients"},
+       {207,"node-subtype"},
+       {208,"node-type"},
+       {209,"structured-object-list"},
+       {210,"subordinate-annotations"},
+       {211,"subordinate-list"},
+       {212,"actual-shed-level"},
+       {213,"duty-window"},
+       {214,"expected-shed-level"},
+       {215,"full-duty-baseline"},
+       {216,"node-subtype"},
+       {217,"node-type"},
+       {218,"requested-shed-level"},
+       {219,"shed-duration"},
+       {220,"shed-level-descriptions"},
+       {221,"shed-levels"},
+       {222,"state-description"},
+       {226,"door-alarm-state"},
+       {227,"door-extended-pulse-time"},
+       {228,"door-members"},
+       {229,"door-open-too-long-time"},
+       {230,"door-pulse-time"},
+       {231,"door-status"},
+       {232,"door-unlock-delay-time"},
+       {233,"lock-status"},
+       {234,"masked-alarm-values"},
+       {235,"secured-status"},
+       {244,"absentee-limit"},         /* added with addenda 135-2008j */
+       {245,"access-alarm-events"},
+       {246,"access-doors"},
+       {247,"access-event"},
+       {248,"access-event-authentication-factor"},
+       {249,"access-event-credential"},
+       {250,"access-event-time"},
+       {251,"access-transaction-events"},
+       {252,"accompaniment"},
+       {253,"accompaniment-time"},
+       {254,"activation-time"},
+       {255,"active-authentication-policy"},
+       {256,"assigned-access-rights"},
+       {257,"authentication-factors"},
+       {258,"authentication-policy-list"},
+       {259,"authentication-policy-names"},
+       {260,"authentication-status"},
+       {261,"authorization-mode"},
+       {262,"belongs-to"},
+       {263,"credential-disable"},
+       {264,"credential-status"},
+       {265,"credentials"},
+       {266,"credentials-in-zone"},
+       {267,"days-remaining"},
+       {268,"entry-points"},
+       {269,"exit-points"},
+       {270,"expiry-time"},
+       {271,"extended-time-enable"},
+       {272,"failed-attempt-events"},
+       {273,"failed-attempts"},
+       {274,"failed-attempts-time"},
+       {275,"last-access-event"},
+       {276,"last-access-point"},
+       {277,"last-credential-added"},
+       {278,"last-credential-added-time"},
+       {279,"last-credential-removed"},
+       {280,"last-credential-removed-time"},
+       {281,"last-use-time"},
+       {282,"lockout"},
+       {283,"lockout-relinquish-time"},
+       {284,"master-exemption"},
+       {285,"max-failed-attempts"},
+       {286,"members"},
+       {287,"muster-point"},
+       {288,"negative-access-rules"},
+       {289,"number-of-authentication-policies"},
+       {290,"occupancy-count"},
+       {291,"occupancy-count-adjust"},
+       {292,"occupancy-count-enable"},
+       {293,"occupancy-exemption"},
+       {294,"occupancy-lower-limit"},
+       {295,"occupancy-lower-limit-enforced"},
+       {296,"occupancy-state"},
+       {297,"occupancy-upper-limit"},
+       {298,"occupancy-upper-limit-enforced"},
+       {299,"passback-exemption"},
+       {300,"passback-mode"},
+       {301,"passback-timeout"},
+       {302,"positive-access-rules"},
+       {303,"reason-for-disable"},
+       {304,"supported-formats"},
+       {305,"supported-format-classes"},
+       {306,"threat-authority"},
+       {307,"threat-level"},
+       {308,"trace-flag"},
+       {309,"transaction-notification-class"},
+       {310,"user-external-identifier"},
+       {311,"user-information-reference"},
+       /* enumeration values 312-316 reserved for future addenda */
+       {317,"user-name"},
+       {318,"user-type"},
+       {319,"uses-remaining"},
+       {320,"zone-from"},
+       {321,"zone-to"},
+       {322,"access-event-tag"},
+       {323,"global-identifier"},
+       /* enumeration values 324-325 reserved for future addenda */
+       {326,"verification-time"},
+       {342,"bit-mask"},               /* addenda 135-2008w */
+       {343,"bit-text"},
+       {344,"is-utc"},
        {0, NULL}
-/* Enumerated values 0-511 are reserved for definition by ASHRAE. 
-   Enumerated values 512-4194303 may be used by others subject to 
+/* Enumerated values 0-511 are reserved for definition by ASHRAE.
+   Enumerated values 512-4194303 may be used by others subject to
    the procedures and constraints described in Clause 23. */
 };
 
@@ -826,15 +3153,21 @@ BACnetBinaryPV [] = {
 };
 
 
+#define ANSI_X34 0
+#define IBM_MS_DBCS 1
+#define JIS_C_6226 2
+#define ISO_10646_UCS4 3
+#define ISO_10646_UCS2 4
+#define ISO_18859_1 5
 static const value_string
 BACnetCharacterSet [] = {
-       {0,"ANSI X3.4"},
-       {1,"IBM/Microsoft DBCS"},
-       {2,"JIS C 6226"},
-       {3,"ISO 10646(UCS-4)"},
-       {4,"ISO 10646(UCS-2)"},
-       {5,"ISO 18859-1"},
-       {0,NULL}
+       {ANSI_X34,      "ANSI X3.4 / UTF-8 (since 2010)"},
+       {IBM_MS_DBCS,   "IBM/Microsoft DBCS"},
+       {JIS_C_6226,    "JIS C 6226"},
+       {ISO_10646_UCS4, "ISO 10646(UCS-4)"},
+       {ISO_10646_UCS2, "ISO 10646(UCS-2)"},
+       {ISO_18859_1,   "ISO 18859-1"},
+       {0,             NULL}
 };
 
 static const value_string
@@ -973,8 +3306,10 @@ weekofmonth [] = {
        {0,NULL }
 };
 
+/* note: notification class object recipient-list uses
+   different day-of-week enum */
 static const value_string
-days [] = {
+day_of_week [] = {
        {1,"Monday" },
        {2,"Tuesday" },
        {3,"Wednesday" },
@@ -983,7 +3318,7 @@ days [] = {
        {6,"Saturday" },
        {7,"Sunday" },
        {255,"any day of week" },
-       {0,NULL },
+       {0,NULL }
 };
 
 static const value_string
@@ -995,9 +3330,9 @@ BACnetErrorClass [] = {
        {4,"security" },
        {5,"services" },
        {6,"vt" },
-       {0,NULL },
-/* Enumerated values 0-63 are reserved for definition by ASHRAE. 
-   Enumerated values64-65535 may be used by others subject to 
+       {0,NULL }
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+   Enumerated values64-65535 may be used by others subject to
    the procedures and constraints described in Clause 23. */
 };
 
@@ -1010,7 +3345,7 @@ BACnetVTClass [] = {
        {4,"dec-vt200" },
        {5,"hp-700-94" },
        {6,"ibm-3130" },
-       {0,NULL },
+       {0,NULL }
 };
 
 static const value_string
@@ -1027,12 +3362,16 @@ BACnetEventType [] = {
        {9,"extended" },
        {10,"buffer-ready" },
        {11,"unsigned-range" },
-       {0,NULL },
-/* Enumerated values 0-63 are reserved for definition by ASHRAE. 
-   Enumerated values 64-65535 may be used by others subject to 
-   the procedures and constraints described in Clause 23. 
-   It is expected that these enumerated values will correspond 
-   to the use of the complex-event-type CHOICE [6] of the 
+       {14,"double-out-of-range"},             /* added with addenda 135-2008w */
+       {15,"signed-out-of-range"},
+       {16,"unsigned-out-of-range"},
+       {17,"change-of-characterstring"},
+       {0,NULL }
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+   Enumerated values 64-65535 may be used by others subject to
+   the procedures and constraints described in Clause 23.
+   It is expected that these enumerated values will correspond
+   to the use of the complex-event-type CHOICE [6] of the
    BACnetNotificationParameters production. */
 };
 
@@ -1044,9 +3383,9 @@ BACnetEventState [] = {
        {3,"high-limit" },
        {4,"low-limit" },
        {5,"life-safety-alarm" },
-       {0,NULL },
-/* Enumerated values 0-63 are reserved for definition by ASHRAE. 
-   Enumerated values 64-65535 may be used by others subject to 
+       {0,NULL }
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+   Enumerated values 64-65535 may be used by others subject to
    the procedures and constraints described in Clause 23.  */
 };
 
@@ -1054,7 +3393,7 @@ static const value_string
 BACnetLogStatus [] = {
        {0,"log-disabled" },
        {1,"buffer-purged" },
-       {0,NULL },
+       {0,NULL }
 };
 
 static const value_string
@@ -1063,7 +3402,7 @@ BACnetMaintenance [] = {
        {1,"periodic-test" },
        {2,"need-service-operational" },
        {3,"need-service-inoperative" },
-       {0,NULL },
+       {0,NULL }
 };
 
 static const value_string
@@ -1071,7 +3410,7 @@ BACnetNotifyType [] = {
        {0,"alarm" },
        {1,"event" },
        {2,"ack-notification" },
-       {0,NULL },
+       {0,NULL }
 };
 
 static const value_string
@@ -1135,10 +3474,11 @@ BACnetPropertyStates [] = {
        {11,"unsigned-value"},
        {12,"life-safety-mode"},
        {13,"life-safety-state"},
+       {14,"door-alarm-state"},
        {0,NULL}
-/* Tag values 0-63 are reserved for definition by ASHRAE. 
-   Tag values of 64-254 may be used by others to accommodate 
-   vendor specific properties that have discrete or enumerated values, 
+/* Tag values 0-63 are reserved for definition by ASHRAE.
+   Tag values of 64-254 may be used by others to accommodate
+   vendor specific properties that have discrete or enumerated values,
    subject to the constraints described in Clause 23. */
 };
 
@@ -1150,8 +3490,8 @@ BACnetProgramError [] = {
        {3,"program"},
        {4,"other"},
        {0,NULL}
-/* Enumerated values 0-63 are reserved for definition by ASHRAE. 
-   Enumerated values 64-65535 may be used by others subject to 
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+   Enumerated values 64-65535 may be used by others subject to
    the procedures and constraints described in Clause 23. */
 };
 
@@ -1204,6 +3544,375 @@ BACnetTagNames[] = {
        { 0, NULL }
 };
 
+static const value_string
+BACnetReadRangeOptions[] = {
+       { 3, "range byPosition" },
+       { 4, "range byTime" },
+       { 5, "range timeRange" },
+       { 6, "range bySequenceNumber" },
+       { 7, "range byTime" },
+       { 0, NULL }
+};
+
+/* Present_Value for Load Control Object */
+static const value_string
+BACnetShedState[] = {
+       { 0, "shed-inactive" },
+       { 1, "shed-request-pending" },
+       { 2, "shed-compliant" },
+       { 3, "shed-non-compliant" },
+       { 0, NULL }
+};
+
+static const value_string
+BACnetVendorIdentifiers [] = {
+       { 0, "ASHRAE" },
+       { 1, "NIST" },
+       { 2, "The Trane Company" },
+       { 3, "McQuay International" },
+       { 4, "PolarSoft" },
+       { 5, "Johnson Controls, Inc." },
+       { 6, "American Auto-Matrix" },
+       { 7, "Siemens Building Technologies, Ltd., Landis & Staefa Division Europe" },
+       { 8, "Delta Controls" },
+       { 9, "Siemens Building Technologies, Inc." },
+       { 10, "Tour Andover Controls Corporation" },
+       { 11, "TAC" },
+       { 12, "Orion Analysis Corporation" },
+       { 13, "Teletrol Systems Inc." },
+       { 14, "Cimetrics Technology" },
+       { 15, "Cornell University" },
+       { 16, "United Technologies Carrier" },
+       { 17, "Honeywell Inc." },
+       { 18, "Alerton / Honeywell" },
+       { 19, "TAC AB" },
+       { 20, "Hewlett-Packard Company" },
+       { 21, "Dorsette's Inc." },
+       { 22, "Cerberus AG" },
+       { 23, "York Controls Group" },
+       { 24, "Automated Logic Corporation" },
+       { 25, "CSI Control Systems International" },
+       { 26, "Phoenix Controls Corporation" },
+       { 27, "Innovex Technologies, Inc." },
+       { 28, "KMC Controls, Inc." },
+       { 29, "Xn Technologies, Inc." },
+       { 30, "Hyundai Information Technology Co., Ltd." },
+       { 31, "Tokimec Inc." },
+       { 32, "Simplex" },
+       { 33, "North Communications Limited" },
+       { 34, "Notifier" },
+       { 35, "Reliable Controls Corporation" },
+       { 36, "Tridium Inc." },
+       { 37, "Sierra Monitor Corp." },
+       { 38, "Silicon Energy" },
+       { 39, "Kieback & Peter GmbH & Co KG" },
+       { 40, "Anacon Systems, Inc." },
+       { 41, "Systems Controls & Instruments, LLC" },
+       { 42, "Lithonia Lighting" },
+       { 43, "Micropower Manufacturing" },
+       { 44, "Matrix Controls" },
+       { 45, "METALAIRE" },
+       { 46, "ESS Engineering" },
+       { 47, "Sphere Systems Pty Ltd." },
+       { 48, "Walker Technologies Corporation" },
+       { 49, "H I Solutions, Inc." },
+       { 50, "MBS GmbH" },
+       { 51, "SAMSON AG" },
+       { 52, "Badger Meter Inc." },
+       { 53, "DAIKIN Industries Ltd." },
+       { 54, "NARA Controls Inc." },
+       { 55, "Mammoth Inc." },
+       { 56, "Liebert Corporation" },
+       { 57, "SEMCO Incorporated" },
+       { 58, "Air Monitor Corporation" },
+       { 59, "TRIATEK, Inc." },
+       { 60, "NexLight" },
+       { 61, "Multistack" },
+       { 62, "TSI Incorporated" },
+       { 63, "Weather-Rite, Inc." },
+       { 64, "Dunham-Bush" },
+       { 65, "Reliance Electric" },
+       { 66, "LCS Inc." },
+       { 67, "Regulator Australia PTY Ltd." },
+       { 68, "Touch-Plate Lighting Controls" },
+       { 69, "Amann GmbH" },
+       { 70, "RLE Technologies" },
+       { 71, "Cardkey Systems" },
+       { 72, "SECOM Co., Ltd." },
+       { 73, "ABB Gebaudetechnik AG Bereich NetServ" },
+       { 74, "KNX Association cvba" },
+       { 75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
+       { 76, "Nohmi Bosai, Ltd." },
+       { 77, "Carel S.p.A." },
+       { 78, "AirSense Technology, Inc." },
+       { 79, "Hochiki Corporation" },
+       { 80, "Fr. Sauter AG" },
+       { 81, "Matsushita Electric Works, Ltd." },
+       { 82, "Mitsubishi Electric Corporation, Inazawa Works" },
+       { 83, "Mitsubishi Heavy Industries, Ltd." },
+       { 84, "ITT Bell & Gossett" },
+       { 85, "Yamatake Building Systems Co., Ltd." },
+       { 86, "The Watt Stopper, Inc." },
+       { 87, "Aichi Tokei Denki Co., Ltd." },
+       { 88, "Activation Technologies, LLC" },
+       { 89, "Saia-Burgess Controls, Ltd." },
+       { 90, "Hitachi, Ltd." },
+       { 91, "Novar Corp./Trend Control Systems Ltd." },
+       { 92, "Mitsubishi Electric Lighting Corporation" },
+       { 93, "Argus Control Systems, Ltd." },
+       { 94, "Kyuki Corporation" },
+       { 95, "Richards-Zeta Building Intelligence, Inc." },
+       { 96, "Scientech R&D, Inc." },
+       { 97, "VCI Controls, Inc." },
+       { 98, "Toshiba Corporation" },
+       { 99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
+       { 100, "Custom Mechanical Equipment, LLC" },
+       { 101, "ClimateMaster" },
+       { 102, "ICP Panel-Tec, Inc." },
+       { 103, "D-Tek Controls" },
+       { 104, "NEC Engineering, Ltd." },
+       { 105, "PRIVA BV" },
+       { 106, "Meidensha Corporation" },
+       { 107, "JCI Systems Integration Services" },
+       { 108, "Freedom Corporation" },
+       { 109, "Neuberger Gebaudeautomation GmbH" },
+       { 110, "Sitronix" },
+       { 111, "Leviton Manufacturing" },
+       { 112, "Fujitsu Limited" },
+       { 113, "Emerson Network Power" },
+       { 114, "S. A. Armstrong, Ltd." },
+       { 115, "Visonet AG" },
+       { 116, "M&M Systems, Inc." },
+       { 117, "Custom Software Engineering" },
+       { 118, "Nittan Company, Limited" },
+       { 119, "Elutions Inc. (Wizcon Systems SAS)" },
+       { 120, "Pacom Systems Pty., Ltd." },
+       { 121, "Unico, Inc." },
+       { 122, "Ebtron, Inc." },
+       { 123, "Scada Engine" },
+       { 124, "AC Technology Corporation" },
+       { 125, "Eagle Technology" },
+       { 126, "Data Aire, Inc." },
+       { 127, "ABB, Inc." },
+       { 128, "Transbit Sp. z o. o." },
+       { 129, "Toshiba Carrier Corporation" },
+       { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
+       { 131, "Tokai Soft" },
+       { 132, "Lumisys" },
+       { 133, "Veris Industries" },
+       { 134, "Centaurus Prime" },
+       { 135, "Sand Network Systems" },
+       { 136, "Regulvar, Inc." },
+       { 137, "Fastek International, Ltd." },
+       { 138, "PowerCold Comfort Air Solutions, Inc." },
+       { 139, "I Controls" },
+       { 140, "Viconics Electronics, Inc." },
+       { 141, "Yaskawa Electric America, Inc." },
+       { 142, "Plueth Regelsysteme" },
+       { 143, "Digitale Mess- und Steuersysteme AG" },
+       { 144, "Fujitsu General Limited" },
+       { 145, "Project Engineering S.r.l." },
+       { 146, "Sanyo Electric Co., Ltd." },
+       { 147, "Integrated Information Systems, Inc." },
+       { 148, "Temco Controls, Ltd." },
+       { 149, "Airtek Technologies, Inc." },
+       { 150, "Advantech Corporation" },
+       { 151, "Titan Products, Ltd." },
+       { 152, "Regel Partners" },
+       { 153, "National Environmental Product" },
+       { 154, "Unitec Corporation" },
+       { 155, "Kanden Engineering Company" },
+       { 156, "Messner Gebaudetechnik GmbH" },
+       { 157, "Integrated.CH" },
+       { 158, "EH Price Limited" },
+       { 159, "SE-Elektronic GmbH" },
+       { 160, "Rockwell Automation" },
+       { 161, "Enflex Corp." },
+       { 162, "ASI Controls" },
+       { 163, "SysMik GmbH Dresden" },
+       { 164, "HSC Regelungstechnik GmbH" },
+       { 165, "Smart Temp Australia Pty. Ltd." },
+       { 166, "PCI Lighting Control Systems" },
+       { 167, "Duksan Mecasys Co., Ltd." },
+       { 168, "Fuji IT Co., Ltd." },
+       { 169, "Vacon Plc" },
+       { 170, "Leader Controls" },
+       { 171, "Cylon Controls, Ltd." },
+       { 172, "Compas" },
+       { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
+       { 174, "Building Control Integrators" },
+       { 175, "ITG Worldwide (M) Sdn Bhd" },
+       { 176, "Lutron Electronics Co., Inc." },
+       { 177, "Cooper-Atkins Corporation" },
+       { 178, "LOYTEC Electronics GmbH" },
+       { 179, "ProLon" },
+       { 180, "Mega Controls Limited" },
+       { 181, "Micro Control Systems, Inc." },
+       { 182, "Kiyon, Inc." },
+       { 183, "Dust Networks" },
+       { 184, "Advanced Building Automation Systems" },
+       { 185, "Hermos AG" },
+       { 186, "CEZIM" },
+       { 187, "Softing" },
+       { 188, "Lynxspring" },
+       { 189, "Schneider Toshiba Inverter Europe" },
+       { 190, "Danfoss Drives A/S" },
+       { 191, "Eaton Corporation" },
+       { 192, "Matyca S.A." },
+       { 193, "Botech AB" },
+       { 194, "Noveo, Inc." },
+       { 195, "AMEV" },
+       { 196, "Yokogawa Electric Corporation" },
+       { 197, "GFR Gesellschaft fur Regelungstechnik" },
+       { 198, "Exact Logic" },
+       { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
+       { 200, "Kandenko Co., Ltd." },
+       { 201, "DTF, Daten-Technik Fries" },
+       { 202, "Klimasoft, Ltd." },
+       { 203, "Toshiba Schneider Inverter Corporation" },
+       { 204, "Control Applications, Ltd." },
+       { 205, "KDT Systems Co., Ltd." },
+       { 206, "Onicon Incorporated" },
+       { 207, "Automation Displays, Inc." },
+       { 208, "Control Solutions, Inc." },
+       { 209, "Remsdaq Limited" },
+       { 210, "NTT Facilities, Inc." },
+       { 211, "VIPA GmbH" },
+       { 212, "TSC21 Association of Japan" },
+       { 213, "BBP Energie Ltee" },
+       { 214, "HRW Limited" },
+       { 215, "Lighting Control & Design, Inc." },
+       { 216, "Mercy Electronic and Electrical Industries" },
+       { 217, "Samsung SDS Co., Ltd" },
+       { 218, "Impact Facility Solutions, Inc." },
+       { 219, "Aircuity" },
+       { 220, "Control Techniques, Ltd." },
+       { 221, "Evolve Control Systems, LLC" },
+       { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
+       { 223, "Cerus Industrial" },
+       { 224, "Chloride Power Protection Company" },
+       { 225, "Computrols, Inc." },
+       { 226, "Phoenix Contact GmbH & Co. KG" },
+       { 227, "Grundfos Management A/S" },
+       { 228, "Ridder Drive Systems" },
+       { 229, "Soft Device SDN BHD" },
+       { 230, "Integrated Control Technology Limited" },
+       { 231, "AIRxpert Systems, Inc." },
+       { 232, "Microtrol Limited" },
+       { 233, "Red Lion Controls" },
+       { 234, "Digital Electronics Corporation" },
+       { 235, "Ennovatis GmbH" },
+       { 236, "Serotonin Software Technologies, Inc." },
+       { 237, "LS Industrial Systems Co., Ltd." },
+       { 238, "Square D Company" },
+       { 239, "S Squared Innovations, Inc." },
+       { 240, "Aricent Ltd." },
+       { 241, "EtherMetrics, LLC" },
+       { 242, "Industrial Control Communications, Inc." },
+       { 243, "Paragon Controls, Inc." },
+       { 244, "A. O. Smith Corporation" },
+       { 245, "Contemporary Control Systems, Inc." },
+       { 246, "Intesis Software SL" },
+       { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
+       { 248, "Heat-Timer Corporation" },
+       { 249, "Ingrasys Technology, Inc." },
+       { 250, "Costerm Building Automation" },
+       { 251, "Wilo AG" },
+       { 252, "Embedia Technologies Corp." },
+       { 253, "Technilog" },
+       { 254, "HR Controls Ltd. & Co. KG" },
+       { 255, "Lennox International, Inc." },
+       { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
+       { 257, "Thermomax, Ltd." },
+       { 258, "ELCON Electronic Control, Ltd." },
+       { 259, "Larmia Control AB" },
+       { 260, "BACnet Stack at SourceForge" },
+       { 261, "G4S Security Services A/S" },
+       { 262, "Sitek S.p.A." },
+       { 263, "Cristal Controles" },
+       { 264, "Regin AB" },
+       { 265, "Dimension Software, Inc. " },
+       { 266, "SynapSense Corporation" },
+       { 267, "Beijing Nantree Electronic Co., Ltd." },
+       { 268, "Camus Hydronics Ltd." },
+       { 269, "Kawasaki Heavy Industries, Ltd. " },
+       { 270, "Critical Environment Technologies" },
+       { 271, "ILSHIN IBS Co., Ltd." },
+       { 272, "ELESTA Energy Control AG" },
+       { 273, "KROPMAN Installatietechniek" },
+       { 274, "Baldor Electric Company" },
+       { 275, "INGA mbH" },
+       { 276, "GE Consumer & Industrial" },
+       { 277, "Functional Devices, Inc." },
+       { 278, "ESAC" },
+       { 279, "M-System Co., Ltd." },
+       { 280, "Yokota Co., Ltd." },
+       { 281, "Hitranse Technology Co., LTD" },
+       { 282, "Federspiel Controls" },
+       { 283, "Kele, Inc." },
+       { 284, "Opera Electronics, Inc." },
+       { 285, "Gentec" },
+       { 286, "Embedded Science Labs, LLC" },
+       { 287, "Parker Hannifin Corporation" },
+       { 288, "MaCaPS International Limited" },
+       { 289, "Link4 Corporation" },
+       { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
+       { 291, "Pribusin, Inc." },
+       { 292, "Advantage Controls" },
+       { 293, "Critical Room Control" },
+       { 294, "LEGRAND" },
+       { 295, "Tongdy Control Technology Co., Ltd." },
+       { 296, "ISSARO Integrierte Systemtechnik" },
+       { 297, "Pro-Dev Industries" },
+       { 298, "DRI-STEEM" },
+       { 299, "Creative Electronic GmbH" },
+       { 300, "Swegon AB" },
+       { 301, "Jan Brachacek" },
+       { 302, "Hitachi Appliances, Inc." },
+       { 303, "Real Time Automation, Inc." },
+       { 304, "ITEC Hankyu-Hanshin Co." },
+       { 305, "Cyrus E&M Engineering Co., Ltd." },
+       { 306, "Racine Federated, Inc." },
+       { 307, "Verari Systems, Inc." },
+       { 308, "Elesta GmbH Building Automation" },
+       { 309, "Securiton" },
+       { 310, "OSlsoft, Inc." },
+       { 311, "Hanazeder Electronic GmbH" },
+       { 312, "Honeywell Security Deutschland, Novar GmbH" },
+       { 313, "Siemens Energy & Automation, Inc." },
+       { 314, "ETM Professional Control GmbH" },
+       { 315, "Meitav-tec, Ltd." },
+       { 316, "Janitza Electronics GmbH" },
+       { 317, "MKS Nordhausen" },
+       { 318, "De Gier Drive Systems B.V." },
+       { 319, "Cypress Envirosystems" },
+       { 320, "SMARTron s.r.o." },
+       { 321, "Verari Systems, Inc." },
+       { 322, "K-W Electronic Service, Inc." },
+       { 323, "ALFA-SMART Energy Management" },
+       { 324, "Telkonet, Inc." },
+       { 325, "Securiton GmbH" },
+       { 326, "Cemtrex, Inc." },
+       { 327, "Performance Technologies, Inc." },
+       { 328, "Xtralis (Aust) Pty Ltd" },
+       { 329, "TROX GmbH" },
+       { 330, "Beijing Hysine Technology Co., Ltd" },
+       { 331, "RCK Controls, Inc." },
+       { 332, "ACELIA" },
+       { 333, "Novar/Honeywell" },
+       { 334, "The S4 Group, Inc." },
+       { 335, "Schneider Electric" },
+       { 336, "LHA Systems" },
+       { 337, "GHM engineering Group, Inc." },
+       { 338, "Cllimalux S.A." },
+       { 339, "VAISALA Oyj" },
+       { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
+       { 342, "POWERPEG NSI Limited" },
+       { 343, "BACnet Interoperability Testing Services, Inc." },
+       { 344, "Teco a.s." },
+       { 0, NULL }
+};
+
 static int proto_bacapp = -1;
 static int hf_bacapp_type = -1;
 static int hf_bacapp_pduflags = -1;
@@ -1236,9 +3945,26 @@ static int hf_bacapp_tag_value32 = -1;
 static int hf_bacapp_tag_ProcessId = -1;
 static int hf_bacapp_tag_initiatingObjectType = -1;
 static int hf_bacapp_vpart = -1;
-
 static int hf_bacapp_uservice = -1;
-
+static int hf_BACnetPropertyIdentifier = -1;
+static int hf_BACnetVendorIdentifier = -1;
+static int hf_BACnetRestartReason = -1;
+static int hf_bacapp_tag_IPV4 = -1;
+static int hf_bacapp_tag_IPV6 = -1;
+static int hf_bacapp_tag_PORT = -1;
+/* some more variables for segmented messages */
+static int hf_msg_fragments = -1;
+static int hf_msg_fragment = -1;
+static int hf_msg_fragment_overlap = -1;
+static int hf_msg_fragment_overlap_conflicts = -1;
+static int hf_msg_fragment_multiple_tails = -1;
+static int hf_msg_fragment_too_long_fragment = -1;
+static int hf_msg_fragment_error = -1;
+static int hf_msg_reassembled_in = -1;
+static int hf_msg_reassembled_length = -1;
+
+static gint ett_msg_fragment = -1;
+static gint ett_msg_fragments = -1;
 
 static gint ett_bacapp = -1;
 static gint ett_bacapp_control = -1;
@@ -1248,11 +3974,47 @@ static gint ett_bacapp_value = -1;
 
 static dissector_handle_t data_handle;
 static gint32 propertyIdentifier = -1;
+static gint32 propertyArrayIndex = -1;
 static guint32 object_type = 4096;
 
 static guint8 bacapp_flags = 0;
 static guint8 bacapp_seq = 0;
 
+static const fragment_items msg_frag_items = {
+       /* Fragment subtrees */
+       &ett_msg_fragment,
+       &ett_msg_fragments,
+       /* Fragment fields */
+       &hf_msg_fragments,
+       &hf_msg_fragment,
+       &hf_msg_fragment_overlap,
+       &hf_msg_fragment_overlap_conflicts,
+       &hf_msg_fragment_multiple_tails,
+       &hf_msg_fragment_too_long_fragment,
+       &hf_msg_fragment_error,
+       /* Reassembled in field */
+       &hf_msg_reassembled_in,
+       /* Reassembled length field */
+       &hf_msg_reassembled_length,
+       /* Tag */
+       "Message fragments"
+};
+
+/* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
+static const guint MaxAPDUSize [] = { 50,128,206,480,1024,1476 };
+
+static guint
+fGetMaxAPDUSize(guint8 idx)
+{
+       /* only 16 values are defined, so use & 0x0f */
+       /* check the size of the Array, deliver either the entry
+          or the first entry if idx is outside of the array (bug 3736 comment#7) */
+       if ((idx & 0x0f) >= (gint)(sizeof(MaxAPDUSize)/sizeof(guint)))
+               return MaxAPDUSize[0];
+       else
+               return MaxAPDUSize[idx & 0x0f];
+}
+
 /* Used when there are ranges of reserved and proprietary enumerations */
 static const char*
 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
@@ -1266,17 +4028,20 @@ val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
 
 /* from clause 20.2.1.3.2 Constructed Data */
 /* returns true if the extended value is used */
-static gboolean tag_is_extended_value(guint8 tag)
+static gboolean
+tag_is_extended_value(guint8 tag)
 {
        return (tag & 0x07) == 5;
 }
 
-static gboolean tag_is_opening(guint8 tag)
+static gboolean
+tag_is_opening(guint8 tag)
 {
        return (tag & 0x07) == 6;
 }
 
-static gboolean tag_is_closing(guint8 tag)
+static gboolean
+tag_is_closing(guint8 tag)
 {
        return (tag & 0x07) == 7;
 }
@@ -1284,22 +4049,26 @@ static gboolean tag_is_closing(guint8 tag)
 /* from clause 20.2.1.1 Class
    class bit shall be one for context specific tags */
 /* returns true if the tag is context specific */
-static gboolean tag_is_context_specific(guint8 tag)
+static gboolean
+tag_is_context_specific(guint8 tag)
 {
        return (tag & 0x08) != 0;
 }
 
-static gboolean tag_is_extended_tag_number(guint8 tag)
+static gboolean
+tag_is_extended_tag_number(guint8 tag)
 {
        return ((tag & 0xF0) == 0xF0);
 }
 
-static guint32 object_id_type(guint32 object_identifier)
+static guint32
+object_id_type(guint32 object_identifier)
 {
        return ((object_identifier >> 22) & 0x3FF);
 }
 
-static guint32 object_id_instance(guint32 object_identifier)
+static guint32
+object_id_instance(guint32 object_identifier)
 {
        return (object_identifier & 0x3FFFFF);
 }
@@ -1314,7 +4083,7 @@ static gboolean
 fUnsigned32 (tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
 {
        gboolean valid = TRUE;
-       
+
        switch (lvt) {
                case 1:
                        *val = tvb_get_guint8(tvb, offset);
@@ -1332,7 +4101,7 @@ fUnsigned32 (tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
                        valid = FALSE;
                        break;
        }
-       
+
        return valid;
 }
 
@@ -1342,7 +4111,7 @@ fUnsigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
        gboolean valid = FALSE;
        gint64 value = 0;
        guint8 data, i;
-       
+
        if (lvt && (lvt <= 8)) {
                valid = TRUE;
                data = tvb_get_guint8(tvb, offset);
@@ -1352,7 +4121,7 @@ fUnsigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
                }
                *val = value;
        }
-       
+
        return valid;
 }
 
@@ -1367,7 +4136,8 @@ fSigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
 {
        gboolean valid = FALSE;
        gint64 value = 0;
-       guint8 data, i;
+       guint8 data;
+        guint32 i;
 
        /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
        if (lvt && (lvt <= 7)) {
@@ -1375,6 +4145,8 @@ fSigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
                data = tvb_get_guint8(tvb, offset);
                if ((data & 0x80) != 0)
                        value = (-1 << 8) | data;
+               else
+                       value = data;
                for (i = 1; i < lvt; i++) {
                        data = tvb_get_guint8(tvb, offset+i);
                        value = (value << 8) + data;
@@ -1401,12 +4173,12 @@ fTagHeaderTree (tvbuff_t *tvb, proto_tree *tree, guint offset,
        tag = tvb_get_guint8(tvb, offset);
        *tag_info = 0;
        *lvt = tag & 0x07;
-    /* To solve the problem of lvt values of 6/7 being indeterminate - it */
-    /* can mean open/close tag or length of 6/7 after the length is */
-    /* computed below - store whole tag info, not just context bit. */
+       /* To solve the problem of lvt values of 6/7 being indeterminate - it */
+       /* can mean open/close tag or length of 6/7 after the length is */
+       /* computed below - store whole tag info, not just context bit. */
        if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
        *tag_no = tag >> 4;
-       if (tag_is_extended_tag_number(tag)) { 
+       if (tag_is_extended_tag_number(tag)) {
                *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
        }
        if (tag_is_extended_value(tag)) {       /* length is more than 4 Bytes */
@@ -1426,11 +4198,10 @@ fTagHeaderTree (tvbuff_t *tvb, proto_tree *tree, guint offset,
        }
        if (tree)
        {
-               if (tag_is_closing(tag) || tag_is_opening(tag))
-                       ti = proto_tree_add_text(tree, tvb, offset, tag_len,
-                               "%s: %u", match_strval(
-                                       tag & 0x07, BACnetTagNames),
-                               *tag_no);
+               if (tag_is_opening(tag))
+                       ti = proto_tree_add_text(tree, tvb, offset, tag_len, "{[%u]", *tag_no );
+               else if (tag_is_closing(tag))
+                       ti = proto_tree_add_text(tree, tvb, offset, tag_len, "}[%u]", *tag_no );
                else if (tag_is_context_specific(tag)) {
                        ti = proto_tree_add_text(tree, tvb, offset, tag_len,
                                "Context Tag: %u, Length/Value/Type: %u",
@@ -1442,6 +4213,7 @@ fTagHeaderTree (tvbuff_t *tvb, proto_tree *tree, guint offset,
                                        BACnetApplicationTagNumber,
                                        ASHRAE_Reserved_Fmt),
                                        *lvt);
+
                subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
                /* details if needed */
                proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, FALSE);
@@ -1477,7 +4249,7 @@ fTagHeaderTree (tvbuff_t *tvb, proto_tree *tree, guint offset,
                        proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
                                tvb, lvt_offset, lvt_len, *lvt);
        }
-  
+
        return tag_len;
 }
 
@@ -1534,7 +4306,7 @@ fUnsignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
        guint64 val = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
-    guint tag_len;
+       guint tag_len;
        proto_item *ti;
        proto_tree *subtree;
 
@@ -1542,13 +4314,13 @@ fUnsignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
        /* only support up to an 8 byte (64-bit) integer */
        if (fUnsigned64 (tvb, offset + tag_len, lvt, &val))
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-                       "%s(Unsigned) %" PRIu64, label, val);
+                       "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
        else
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
                        "%s - %u octets (Unsigned)", label, lvt);
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-       
+
        return offset+tag_len+lvt;
 }
 
@@ -1569,7 +4341,7 @@ fEnumeratedTagSplit (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar
        if (fUnsigned32 (tvb, offset+tag_len, lvt, &val)) {
                if (vs)
                        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-                               "%s %s", label, val_to_split_str(val, split_val, vs,    
+                               "%s %s", label, val_to_split_str(val, split_val, vs,
                                ASHRAE_Reserved_Fmt,Vendor_Proprietary_Fmt));
                else
                        ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
@@ -1586,7 +4358,7 @@ fEnumeratedTagSplit (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar
 
 static guint
 fEnumeratedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
-       const value_string *vs)
+               const value_string *vs)
 {
        return fEnumeratedTagSplit (tvb, tree, offset, label, vs, 0);
 }
@@ -1604,13 +4376,13 @@ fSignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
        tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
        if (fSigned64 (tvb, offset + tag_len, lvt, &val))
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-                       "%s(Signed) %" PRId64, label, val);
+                       "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
        else
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
                        "%s - %u octets (Signed)", label, lvt);
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-       
+
        return offset+tag_len+lvt;
 }
 
@@ -1620,17 +4392,17 @@ fRealTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
        guint8 tag_no, tag_info;
        guint32 lvt;
        guint tag_len;
-       gfloat f_val = 0.0;
+       gfloat f_val;
        proto_item *ti;
        proto_tree *subtree;
-       
+
        tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
        f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
        ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
                "%s%f (Real)", label, f_val);
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-       
+
        return offset+tag_len+4;
 }
 
@@ -1640,17 +4412,17 @@ fDoubleTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
        guint8 tag_no, tag_info;
        guint32 lvt;
        guint tag_len;
-       gdouble d_val = 0.0;
+       gdouble d_val;
        proto_item *ti;
        proto_tree *subtree;
-       
+
        tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
        d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
        ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
-               "%s%lf (Double)", label, d_val);
+               "%s%f (Double)", label, d_val);
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-       
+
        return offset+tag_len+8;
 }
 
@@ -1665,15 +4437,15 @@ fProcessId (tvbuff_t *tvb, proto_tree *tree, guint offset)
 
        tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
        if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
-               ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId, 
+               ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
                        tvb, offset, lvt+tag_len, val);
        else
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
                        "Process Identifier - %u octets (Signed)", lvt);
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
-       fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-       
-       return offset+tag_len+lvt;
+       offset += tag_len + lvt;
+
+       return offset;
 }
 
 static guint
@@ -1687,10 +4459,10 @@ fTimeSpan (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
 
        tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
        if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
-               ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, 
-               "%s (hh.mm.ss): %d.%02d.%02d%s", 
-               label, 
-               (val / 3600), ((val % 3600) / 60), (val % 60), 
+               ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+               "%s (hh.mm.ss): %d.%02d.%02d%s",
+               label,
+               (val / 3600), ((val % 3600) / 60), (val % 60),
                val == 0 ? " (indefinite)" : "");
        else
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
@@ -1715,10 +4487,10 @@ fWeekNDay (tvbuff_t *tvb, proto_tree *tree, guint offset)
        month = tvb_get_guint8(tvb, offset+tag_len);
        weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
        dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
-       ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s", 
-                        val_to_str(month, months, "month (%d) not found"), 
-                        val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"), 
-                        val_to_str(dayOfWeek, days, "day of week (%d) not found"));
+       ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
+                                val_to_str(month, months, "month (%d) not found"),
+                                val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
+                                val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
 
@@ -1754,7 +4526,7 @@ fDate (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
                                months,
                                "month (%d) not found"),
                        day, year, val_to_str(weekday,
-                               days,
+                               day_of_week,
                                "(%d) not found"));
        }
        else
@@ -1762,7 +4534,7 @@ fDate (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
                        "%s%s %d, any year, (Day of Week = %s)",
                        label, val_to_str(month, months, "month (%d) not found"),
-                       day, val_to_str(weekday, days, "(%d) not found"));
+                       day, val_to_str(weekday, day_of_week, "(%d) not found"));
        }
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
@@ -1793,11 +4565,11 @@ fTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
                        label,
                        hour > 12 ? hour - 12 : hour,
                        minute, second, msec,
-                       hour > 12 ? "P.M." : "A.M.",
+                       hour >= 12 ? "P.M." : "A.M.",
                        hour, minute, second, msec);
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-       
+
        return offset+tag_len+lvt;
 }
 
@@ -1816,20 +4588,22 @@ fDateTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
 }
 
 static guint
-fTimeValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fTimeValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
-       guint32 lvt;                               
+       guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_is_closing(tag_info)) {   /* closing Tag, but not for me */
                        return offset;
                }
                offset = fTime    (tvb,tree,offset,"Time: ");
-               offset = fApplicationTypes(tvb, tree, offset, "Value: ");
+               offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
+
+               if (offset==lastoffset) break;    /* exit loop if nothing happens inside */
        }
        return offset;
 }
@@ -1837,130 +4611,167 @@ fTimeValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
 static guint
 fCalendaryEntry (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
-    guint8 tag_no, tag_info;
-    guint32 lvt;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
 
        switch (fTagNo(tvb, offset)) {
        case 0: /* Date */
                offset = fDate    (tvb, tree, offset, "Date: ");
                break;
        case 1: /* dateRange */
-        offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+               offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
                offset = fDateRange (tvb, tree, offset);
-        offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+               offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
                break;
        case 2: /* BACnetWeekNDay */
                offset = fWeekNDay (tvb, tree, offset);
                break;
        default:
                return offset;
-               break;
        }
 
        return offset;
 }
 
-static guint
-fTimeStamp (tvbuff_t *tvb, proto_tree *tree, guint offset)
+static guint fTimeStamp (tvbuff_t *tvb, proto_tree *tree,
+       guint offset, const gchar *label)
 {
        guint8 tag_no = 0, tag_info = 0;
        guint32 lvt = 0;
 
-       if (tvb_length_remaining(tvb, offset) > 0) {    /* don't loop, it's a CHOICE */
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {   /* don't loop, it's a CHOICE */
                switch (fTagNo(tvb, offset)) {
                case 0: /* time */
-                       offset = fTime (tvb, tree, offset, "timestamp: ");
+                       offset = fTime (tvb, tree, offset, label?label:"timestamp: ");
                        break;
                case 1: /* sequenceNumber */
-                       offset = fUnsignedTag (tvb, tree, offset, "sequence Number: ");
+                       offset = fUnsignedTag (tvb, tree, offset,
+                               label?label:"sequence Number: ");
                        break;
                case 2: /* dateTime */
                        offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fDateTime (tvb, tree, offset, "timestamp: ");
+                       offset = fDateTime (tvb, tree, offset, label?label:"timestamp: ");
                        offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                default:
                        return offset;
-                       break;
                }
        }
+
        return offset;
 }
 
-#if 0
+
 static guint
-fSetpointReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fClientCOV (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
-
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-       
-               switch (fTagNo(tvb, offset)) {
-               case 0: /* setpointReference */
-                       offset = fBACnetObjectPropertyReference (tvb,tree,offset);
-                       break;
-               default:
-                       return offset;
-                       break;
-               }
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
+               offset = fApplicationTypes(tvb,pinfo,tree,offset, "increment: ");
        }
        return offset;
 }
-#endif
 
-#if 0
-static guint
-fClientCOV (tvbuff_t *tvb, proto_tree *tree, guint offset)
-{
-       if (tvb_length_remaining(tvb, offset) > 0) {
-        offset = fApplicationTypes(tvb,tree,offset, "increment: ");
-    }
-    return offset;
-}
+static const value_string
+BACnetDaysOfWeek [] = {
+       {0,"Monday" },
+       {1,"Tuesday" },
+       {2,"Wednesday" },
+       {3,"Thursday" },
+       {4,"Friday" },
+       {5,"Saturday" },
+       {6,"Sunday" },
+       {0,NULL }
+};
 
 static guint
-fDestination (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fDestination (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       if (tvb_length_remaining(tvb, offset) > 0) {
-               offset = fApplicationTypesEnumerated(tvb,tree,offset, 
-                       "valid Days: ", days);
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
+               offset = fApplicationTypesEnumerated(tvb,pinfo,tree,offset,
+                       "valid Days: ", BACnetDaysOfWeek);
                offset = fTime (tvb,tree,offset,"from time: ");
                offset = fTime (tvb,tree,offset,"to time: ");
-               offset = fRecipient (tvb,tree,offset);
+               offset = fRecipient (tvb,pinfo,tree,offset);
                offset = fProcessId (tvb,tree,offset);
-               offset = fApplicationTypes (tvb,tree,offset,
+               offset = fApplicationTypes (tvb,pinfo,tree,offset,
                        "issue confirmed notifications: ");
-               offset = fApplicationTypesEnumerated (tvb,tree,offset,
+               offset = fBitStringTagVS (tvb,tree,offset,
                        "transitions: ", BACnetEventTransitionBits);
        }
        return offset;
 }
 
-#endif
 
 static guint
 fOctetString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
 {
        gchar *tmp;
-    guint start = offset;
+       guint start = offset;
+       guint8 tag_no, tag_info;
+       proto_tree* subtree = tree;
+       proto_item* ti = 0;
+
+       offset += fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+
+       if (lvt > 0)
+       {
+               tmp = tvb_bytes_to_str(tvb, offset, lvt);
+               ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
+               offset += lvt;
+       }
+
+       if (ti)
+               subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+
+       fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
+
+       return offset;
+}
+
+static guint
+fMacAddress (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
+{
+       gchar *tmp;
+       guint start = offset;
        guint8 tag_no, tag_info;
-    proto_tree* subtree = tree;
-    proto_item* ti = 0;
+       proto_tree* subtree = tree;
+       proto_item* ti = 0;
 
        offset += fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
 
+       ti = proto_tree_add_text(tree, tvb, offset, 6, "%s", label); /* just add the label, with the tagHeader information in its subtree */
+
        if (lvt > 0)
-    {
-           tmp = tvb_bytes_to_str(tvb, offset, lvt);
-           ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
+       {
+               if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
+
+                       guint32 ip = tvb_get_ipv4(tvb, offset);
+                       guint16 port =  tvb_get_ntohs(tvb, offset+4);
+
+                       proto_tree_add_ipv4(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ip);
+                       proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, port);
+
+               } else {
+                       if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
+                       struct e_in6_addr addr;
+                       guint16 port =  tvb_get_ntohs(tvb, offset+16);
+                       tvb_get_ipv6(tvb, offset, &addr);
+
+                       proto_tree_add_ipv6(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, (const guint8 *) &addr);
+                       proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, port);
+
+                       } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
+                               tmp = tvb_bytes_to_str(tvb, offset, lvt);
+                               ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s", tmp);
+                       }
+               }
                offset += lvt;
-    }
+       }
 
        if (ti)
-        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+               subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
 
-    fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
+       fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
 
        return offset;
 }
@@ -1970,29 +4781,28 @@ fAddress (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
        guint8 tag_no, tag_info;
        guint32 lvt;
-    guint offs;
+       guint offs;
 
        offset = fUnsignedTag (tvb, tree, offset, "network-number");
        offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
        if (lvt == 0) {
-               proto_tree_add_text(tree, tvb, offset, offs, "mac-address: broadcast");
+               proto_tree_add_text(tree, tvb, offset, offs, "MAC-address: broadcast");
                offset += offs;
        } else
-               offset = fOctetString (tvb, tree, offset, "mac-address: ", lvt);
+               offset = fMacAddress (tvb, tree, offset, "MAC-address: ", lvt);
+
        return offset;
 }
 
-#if 0
 static guint
 fSessionKey (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
        offset = fOctetString (tvb,tree,offset,"session key: ", 8);
        return fAddress (tvb,tree,offset);
 }
-#endif
 
 static guint
-fObjectIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fObjectIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint8  tag_no, tag_info;
        guint32 lvt;
@@ -2012,6 +4822,15 @@ fObjectIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
                        ASHRAE_Reserved_Fmt,
                        Vendor_Proprietary_Fmt),
                object_id_instance(object_id));
+       if (col_get_writable(pinfo->cinfo))
+               col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
+                       val_to_split_str(object_type,
+                               128,
+                               BACnetObjectType,
+                               ASHRAE_Reserved_Fmt,
+                               Vendor_Proprietary_Fmt),
+                               object_id_instance(object_id));
+
        /* here are the details of how we arrived at the above text */
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
@@ -2024,99 +4843,97 @@ fObjectIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
 }
 
 static guint
-fRecipient (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fRecipient (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint8  tag_no, tag_info;
+       guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-       
-               switch (fTagNo(tvb, offset)) {
-               case 0: /* device */
-                       offset = fObjectIdentifier (tvb, tree, offset);
-                       break;
-               case 1: /* address */
+       fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
+       if (tag_no < 2) {
+               if (tag_no == 0) { /* device */
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+               }
+               else {  /* address */
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        offset = fAddress (tvb, tree, offset);
-                       break;
-               default:
-                       return offset;
-                       break;
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                }
        }
        return offset;
 }
 
 static guint
-fRecipientProcess (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fRecipientProcess (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
+       guint8  tag_no, tag_info;
+       guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-       
+
                switch (fTagNo(tvb, offset)) {
                case 0: /* recipient */
-                       offset = fRecipient (tvb, tree, offset);
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fRecipient (tvb, pinfo, tree, offset);
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                case 1: /* processId */
                        offset = fProcessId (tvb, tree, offset);
+                       lastoffset = offset;
                        break;
                default:
-                       return offset;
                        break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fAddressBinding (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAddressBinding (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       offset = fObjectIdentifier (tvb, tree, offset);
+       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
        return fAddress (tvb, tree, offset);
 }
 
 static guint
-fActionCommand (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fActionCommand (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
-       proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       /* set the optional global properties to indicate not-used */
+       propertyArrayIndex = -1;
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {  
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               if (tag_is_closing(tag_info) ) {
+                       if (tag_no == tag_match) {
+                               return offset;
+                       }
+                       offset += len;
                        subtree = tree;
                        continue;
                }
                switch (tag_no) {
-       
+
                case 0: /* deviceIdentifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 1: /* objectIdentifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 2: /* propertyIdentifier */
-                       offset = fPropertyIdentifier (tvb, subtree, offset);
+                       offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 3: /* propertyArrayIndex */
-                       offset = fUnsignedTag (tvb,subtree,offset,"Property Array Index: ");
+                       offset = fPropertyArrayIndex (tvb, subtree, offset);
                        break;
                case 4: /* propertyValue */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType (tvb, subtree, offset);
-                               break;
-                       }
-                       FAULT;
+                       offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
                        break;
                case 5: /* priority */
                        offset = fUnsignedTag (tvb,subtree,offset,"Priority: ");
@@ -2135,37 +4952,104 @@ fActionCommand (tvbuff_t *tvb, proto_tree *tree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
+/* BACnetActionList ::= SEQUENCE{
+      action [0] SEQUENCE OF BACnetActionCommand
+      }
+*/
 static guint
-fActionList (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fActionList (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fActionCommand (tvb,tree,offset);
+       guint lastoffset = 0, len;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+       proto_tree *subtree = tree;
+       proto_item *ti;
+
+       while (tvb_reported_length_remaining(tvb, offset)) {
+               lastoffset = offset;
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               if (tag_is_closing(tag_info)) {
+                       offset += len;
+                       subtree = tree;
+                       continue;
+               }
+               if (tag_is_opening(tag_info)) {
+                       ti = proto_tree_add_text(tree, tvb, offset, 1, "Action List");
+                       subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+                       offset += fTagHeaderTree (tvb, subtree, offset,
+                               &tag_no, &tag_info, &lvt);
+               }
+               switch (tag_no) {
+                       case 0: /* BACnetActionCommand */
+                               offset = fActionCommand (tvb, pinfo, subtree, offset, tag_no);
+                               break;
+                       default:
+                               break;
+               }
+               if (offset == lastoffset) break;    /* nothing happened, exit loop */
+       }
+       return offset;
 }
 
 static guint
-fPropertyIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fPropertyIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint8 tag_no, tag_info;
        guint32 lvt;
        guint tag_len;
        proto_item *ti;
        proto_tree *subtree;
+       const gchar *label = "Property Identifier";
 
        propertyIdentifier = 0; /* global Variable */
        tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-       if (fUnsigned32 (tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier))
+       /* can we decode this value? */
+       if (fUnsigned32 (tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-                       "property Identifier: %s",
+                       "%s: %s (%u)", label,
                        val_to_split_str(propertyIdentifier, 512,
                                BACnetPropertyIdentifier,
                                ASHRAE_Reserved_Fmt,
-                               Vendor_Proprietary_Fmt));
+                               Vendor_Proprietary_Fmt), propertyIdentifier);
+               if (col_get_writable(pinfo->cinfo))
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+                               val_to_split_str(propertyIdentifier, 512,
+                                       BACnetPropertyIdentifier,
+                                       ASHRAE_Reserved_Fmt,
+                                       Vendor_Proprietary_Fmt));
+       } else {
+               /* property identifiers cannot be larger than 22-bits */
+               return offset;
+       }
+       subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+       fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+       proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
+               offset+tag_len, lvt, FALSE);
+
+       return offset+tag_len+lvt;
+}
+
+static guint
+fPropertyArrayIndex (tvbuff_t *tvb, proto_tree *tree, guint offset)
+{
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+       guint tag_len;
+       proto_item *ti;
+       proto_tree *subtree;
+
+       tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+       if (fUnsigned32 (tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
+               ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+                       "property Array Index (Unsigned) %u", propertyArrayIndex);
        else
                ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-               "Property Identifier - %u octets", lvt);
+                       "property Array Index - %u octets (Unsigned)", lvt);
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
 
@@ -2177,29 +5061,30 @@ fCharacterString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *la
 {
        guint8 tag_no, tag_info, character_set;
        guint32 lvt, l;
-       size_t inbytesleft, outbytesleft = 512;
+       gsize inbytesleft, outbytesleft = 512;
        guint offs, extra = 1;
        guint8 *str_val;
+       const char *coding;
        guint8 bf_arr[512], *out = &bf_arr[0];
        proto_item *ti;
        proto_tree *subtree;
-    guint start = offset;
+       guint start = offset;
 
-       if (tvb_length_remaining(tvb, offset) > 0) {
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
 
                offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-       
+
                character_set = tvb_get_guint8(tvb, offset+offs);
-        /* Account for code page if DBCS */
-        if (character_set == 1)
-        {
-            extra = 3;
-        }
-        offset += (offs+extra);
-        lvt -= (extra);
+               /* Account for code page if DBCS */
+               if (character_set == 1)
+               {
+                   extra = 3;
+               }
+               offset += (offs+extra);
+               lvt -= (extra);
 
                do {
-                       l = inbytesleft = min(lvt, 255);
+                       inbytesleft = l = MIN(lvt, 255);
                        /*
                         * XXX - are we guaranteed that these encoding
                         * names correspond, on *all* platforms with
@@ -2219,41 +5104,49 @@ fCharacterString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *la
                        str_val = tvb_get_ephemeral_string(tvb, offset, l);
                        /** this decoding may be not correct for multi-byte characters, Lka */
                        switch (character_set) {
-                       case 0x00:      /* ANSI_X3.4 */
+                       case ANSI_X34:
                                fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ANSI_X3.4");
+                               coding = "ANSI X3.4";
                                break;
-                       case 1: /* IBM/MICROSOFT DBCS */
+                       case IBM_MS_DBCS:
                                out = str_val;
+                               coding = "IBM MS DBCS";
                                break;
-                       case 2: /* JIS C 6226 */
+                       case JIS_C_6226:
                                out = str_val;
+                               coding = "JIS C 6226";
                                break;
-                       case 3: /* UCS-4 */
+                       case ISO_10646_UCS4:
                                fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-4BE");
+                               coding = "ISO 10646 UCS-4";
                                break;
-                       case 4: /* UCS-2 */
+                       case ISO_10646_UCS2:
                                fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-2BE");
+                               coding = "ISO 10646 UCS-2";
                                break;
-                       case 5: /* ISO8859-1 */
+                       case ISO_18859_1:
                                fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ISO8859-1");
+                               coding = "ISO 8859-1";
                                break;
                        default:
                                out = str_val;
+                               coding = "unknown";
                                break;
                        }
-                       ti = proto_tree_add_text(tree, tvb, offset, l, "%s'%s'", label, out);
+                       ti = proto_tree_add_text(tree, tvb, offset, l, "%s%s'%s'", label, coding, out);
                        lvt-=l;
                        offset+=l;
                } while (lvt > 0);
 
                subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
 
-        fTagHeaderTree (tvb, subtree, start, &tag_no, &tag_info, &lvt);
+               fTagHeaderTree (tvb, subtree, start, &tag_no, &tag_info, &lvt);
                proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, FALSE);
-        if (character_set == 1)
-        {
-            proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
-        }
+
+               if (character_set == 1)
+               {
+                   proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
+               }
        }
        return offset;
 }
@@ -2264,14 +5157,27 @@ fBitStringTagVS (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *lab
 {
        guint8 tag_no, tag_info, tmp;
        gint j, unused, skip;
+       guint start = offset;
        guint offs;
        guint32 lvt, i, numberOfBytes;
        guint8 bf_arr[256];
-       
+       proto_tree* subtree = tree;
+       proto_item* ti = 0;
+
        offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
        numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
        offset+=offs;
        unused = tvb_get_guint8(tvb, offset); /* get the unused Bits */
+       ti = proto_tree_add_text(tree, tvb, start, offs+lvt,
+                               "%s(Bit String)",
+                               label);
+       if (ti) {
+               subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+       }
+       fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
+       proto_tree_add_text(subtree, tvb, offset, 1,
+                               "Unused bits: %u",
+                               unused);
        skip = 0;
        for (i = 0; i < numberOfBytes; i++) {
                tmp = tvb_get_guint8(tvb, (offset)+i+1);
@@ -2279,36 +5185,33 @@ fBitStringTagVS (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *lab
                for (j = 0; j < 8-skip; j++) {
                        if (src != NULL) {
                                if (tmp & (1 << (7 - j)))
-                                       proto_tree_add_text(tree, tvb,
+                                       proto_tree_add_text(subtree, tvb,
                                                offset+i+1, 1,
-                                               "%s%s = TRUE",
-                                               label,
+                                               "%s = TRUE",
                                                val_to_str((guint) (i*8 +j),
                                                        src,
                                                        ASHRAE_Reserved_Fmt));
                                else
-                                       proto_tree_add_text(tree, tvb,
+                                       proto_tree_add_text(subtree, tvb,
                                                offset+i+1, 1,
-                                               "%s%s = FALSE",
-                                               label,
+                                               "%s = FALSE",
                                                val_to_str((guint) (i*8 +j),
                                                        src,
                                                        ASHRAE_Reserved_Fmt));
-
                        } else {
-                               bf_arr[min(255,(i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
+                               bf_arr[MIN(255,(i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
                        }
                }
        }
 
        if (src == NULL)
        {
-               bf_arr[min(255,numberOfBytes*8-unused)] = 0;
-               proto_tree_add_text(tree, tvb, offset, lvt, "%sB'%s'", label, bf_arr);
+               bf_arr[MIN(255,numberOfBytes*8-unused)] = 0;
+               proto_tree_add_text(subtree, tvb, offset, lvt, "B'%s'", bf_arr);
        }
 
        offset+=lvt;
-       
+
        return offset;
 }
 
@@ -2319,84 +5222,113 @@ fBitStringTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label
 }
 
 /* handles generic application types, as well as enumerated and enumerations
-   with reserved and proprietarty ranges (split) */  
+   with reserved and proprietarty ranges (split) */
 static guint
-fApplicationTypesEnumeratedSplit (tvbuff_t *tvb, proto_tree *tree, guint offset, 
+fApplicationTypesEnumeratedSplit (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
        const gchar *label, const value_string *src, guint32 split_val)
 {
        guint8 tag_no, tag_info;
        guint32 lvt;
        guint tag_len;
 
-       if (tvb_length_remaining(tvb, offset) > 0) {
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
 
                tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-       
-               switch (tag_no) {
-                       case 0: /** NULL 20.2.2 */
-                               offset = fNullTag(tvb, tree, offset, label);
-                               break;
-                       case 1: /** BOOLEAN 20.2.3 */
-                               offset = fBooleanTag(tvb, tree, offset, label);
-                               break;
-                       case 2: /** Unsigned Integer 20.2.4 */
-                               offset = fUnsignedTag(tvb, tree, offset, label);
-                               break;
-                       case 3: /** Signed Integer 20.2.5 */
-                               offset = fSignedTag(tvb, tree, offset, label);
-                               break;
-                       case 4: /** Real 20.2.6 */
-                               offset = fRealTag(tvb, tree, offset, label);
-                               break;
-                       case 5: /** Double 20.2.7 */
-                               offset = fDoubleTag(tvb, tree, offset, label);
-                               break;
-                       case 6: /** Octet String 20.2.8 */
-                               offset = fOctetString (tvb, tree, offset, label, lvt);
-                               break;
-                       case 7: /** Character String 20.2.9 */
-                               offset = fCharacterString (tvb,tree,offset,label);
-                               break;
-                       case 8: /** Bit String 20.2.10 */
-                               offset = fBitStringTagVS (tvb, tree, offset, label, src);
-                               break;
-                       case 9: /** Enumerated 20.2.11 */
-                               offset = fEnumeratedTagSplit (tvb, tree, offset, label, src, split_val);
-                               break;
-                       case 10: /** Date 20.2.12 */
-                               offset = fDate (tvb, tree, offset, label);
-                               break;
-                       case 11: /** Time 20.2.13 */
-                               offset = fTime (tvb, tree, offset, label);
-                               break;
-                       case 12: /** BACnetObjectIdentifier 20.2.14 */
-                               offset = fObjectIdentifier (tvb, tree, offset);
-                               break;
-                       case 13: /* reserved for ASHRAE */
-                       case 14:
-                       case 15:
-                               proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
-                               offset+=lvt+tag_len;
-                               break;
-                       default:
-                               break;
+               if (!tag_is_context_specific(tag_info))
+               {
+                       switch (tag_no) {
+                               case 0: /** NULL 20.2.2 */
+                                       offset = fNullTag(tvb, tree, offset, label);
+                                       break;
+                               case 1: /** BOOLEAN 20.2.3 */
+                                       offset = fBooleanTag(tvb, tree, offset, label);
+                                       break;
+                               case 2: /** Unsigned Integer 20.2.4 */
+                                       offset = fUnsignedTag(tvb, tree, offset, label);
+                                       break;
+                               case 3: /** Signed Integer 20.2.5 */
+                                       offset = fSignedTag(tvb, tree, offset, label);
+                                       break;
+                               case 4: /** Real 20.2.6 */
+                                       offset = fRealTag(tvb, tree, offset, label);
+                                       break;
+                               case 5: /** Double 20.2.7 */
+                                       offset = fDoubleTag(tvb, tree, offset, label);
+                                       break;
+                               case 6: /** Octet String 20.2.8 */
+                                       offset = fOctetString (tvb, tree, offset, label, lvt);
+                                       break;
+                               case 7: /** Character String 20.2.9 */
+                                       offset = fCharacterString (tvb,tree,offset,label);
+                                       break;
+                               case 8: /** Bit String 20.2.10 */
+                                       offset = fBitStringTagVS (tvb, tree, offset, label, src);
+                                       break;
+                               case 9: /** Enumerated 20.2.11 */
+                                       offset = fEnumeratedTagSplit (tvb, tree, offset, label, src, split_val);
+                                       break;
+                               case 10: /** Date 20.2.12 */
+                                       offset = fDate (tvb, tree, offset, label);
+                                       break;
+                               case 11: /** Time 20.2.13 */
+                                       offset = fTime (tvb, tree, offset, label);
+                                       break;
+                               case 12: /** BACnetObjectIdentifier 20.2.14 */
+                                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+                                       break;
+                               case 13: /* reserved for ASHRAE */
+                               case 14:
+                               case 15:
+                                       proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
+                                       offset+=lvt+tag_len;
+                                       break;
+                               default:
+                                       break;
+                       }
+
                }
        }
        return offset;
 }
 
 static guint
-fApplicationTypesEnumerated (tvbuff_t *tvb, proto_tree *tree, guint offset, 
+fShedLevel (tvbuff_t *tvb, proto_tree *tree, guint offset)
+{
+       guint lastoffset = 0;
+
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+               lastoffset = offset;
+
+               switch (fTagNo(tvb,offset)) {
+               case 0: /* percent */
+                       offset = fUnsignedTag (tvb, tree, offset, "shed percent: ");
+                       break;
+               case 1: /* level */
+                       offset = fUnsignedTag (tvb, tree, offset, "shed level: ");
+                       break;
+               case 2: /* amount */
+                       offset = fRealTag(tvb, tree, offset, "shed amount: ");
+                       break;
+               default:
+                       return offset;
+               }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
+       }
+       return offset;
+}
+
+static guint
+fApplicationTypesEnumerated (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
        const gchar *label, const value_string *vs)
 {
-  return fApplicationTypesEnumeratedSplit(tvb, tree, offset, label, vs, 0);
+  return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
 }
 
 static guint
-fApplicationTypes (tvbuff_t *tvb, proto_tree *tree, guint offset, 
+fApplicationTypes (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
        const gchar *label)
 {
-  return fApplicationTypesEnumeratedSplit(tvb, tree, offset, label, NULL, 0);
+  return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
 }
 
 static guint
@@ -2412,7 +5344,7 @@ fContextTaggedValue(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *
        (void)label;
        tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
        /* cap the the suggested length in case of bad data */
-       tvb_len = tvb_length_remaining(tvb, offset+tag_len);
+       tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
        if ((tvb_len >= 0) && ((guint32)tvb_len < lvt))
        {
                lvt = tvb_len;
@@ -2422,18 +5354,18 @@ fContextTaggedValue(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *
 
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
        fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-       
+
        return offset + tag_len + lvt;
 }
 
 static guint
-fAbstractSyntaxNType (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAbstractSyntaxNType (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint8 tag_no, tag_info;
        guint32 lvt;
        guint lastoffset = 0, depth = 0;
        char ar[256];
-       
+
        if (propertyIdentifier >= 0)
        {
                g_snprintf (ar, sizeof(ar), "%s: ",
@@ -2446,7 +5378,7 @@ fAbstractSyntaxNType (tvbuff_t *tvb, proto_tree *tree, guint offset)
        {
                g_snprintf (ar, sizeof(ar), "Abstract Type: ");
        }
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
@@ -2455,52 +5387,112 @@ fAbstractSyntaxNType (tvbuff_t *tvb, proto_tree *tree, guint offset)
 
                /* Application Tags */
                switch (propertyIdentifier) {
-               case 2: /* BACnetActionList */
-                       offset = fActionList (tvb,tree,offset);
+               case 2: /* action */
+                       /* loop object is application tagged,
+                               command object is context tagged */
+                       if (tag_is_context_specific(tag_info)) {
+                               /* BACnetActionList */
+                               offset = fActionList (tvb, pinfo, tree,offset);
+                       } else {
+                               /* BACnetAction */
+                               offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
+                                       BACnetAction);
+                       }
                        break;
                case 30: /* BACnetAddressBinding */
-                       offset = fAddressBinding (tvb,tree,offset);
+                       offset = fAddressBinding (tvb,pinfo,tree,offset);
+                       break;
+               case 54: /* list of object property reference */
+                       offset = fLOPR (tvb, pinfo, tree,offset);
+                       break;
+               case 55: /* list-of-session-keys */
+                       fSessionKey (tvb, tree, offset);
                        break;
                case 79: /* object-type */
                case 96: /* protocol-object-types-supported */
-                       offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, ar, 
+                       offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset, ar,
                                BACnetObjectType, 128);
                        break;
                case 97: /* Protocol-Services-Supported */
-                       offset = fApplicationTypesEnumerated (tvb, tree, offset, ar, 
+                       offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
                                BACnetServicesSupported);
                        break;
+               case 102: /* recipient-list */
+                       offset = fDestination (tvb, pinfo, tree, offset);
+                       break;
                case 107: /* segmentation-supported */
-                       offset = fApplicationTypesEnumerated (tvb, tree, offset, ar, 
+                       offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
                                BACnetSegmentation);
                        break;
                case 111: /* Status-Flags */
-                       offset = fApplicationTypesEnumerated (tvb, tree, offset, ar, 
+                       offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
                                BACnetStatusFlags);
                        break;
                case 112: /* System-Status */
-                       offset = fApplicationTypesEnumerated (tvb, tree, offset, ar, 
+                       offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
                                BACnetDeviceStatus);
                        break;
                case 117: /* units */
-                       offset = fApplicationTypesEnumerated (tvb, tree, offset, ar, 
+                       offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
                                BACnetEngineeringUnits);
                        break;
-               case 87:        /* priority-array */
-                       offset = fPriorityArray (tvb, tree, offset);
+               case 87:        /* priority-array -- accessed as a BACnetARRAY */
+                       if (propertyArrayIndex == 0) {
+                               /* BACnetARRAY index 0 refers to the length
+                               of the array, not the elements of the array */
+                               offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
+                       } else {
+                               offset = fPriorityArray (tvb, pinfo, tree, offset);
+                       }
                        break;
                case 38:        /* exception-schedule */
                        if (object_type < 128)
                        {
-                               offset = fSpecialEvent (tvb,tree,offset);
-                               break;
+                               if (propertyArrayIndex == 0) {
+                                       /* BACnetARRAY index 0 refers to the length
+                                       of the array, not the elements of the array */
+                                       offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
+                               } else {
+                                       offset = fSpecialEvent (tvb,pinfo,tree,offset);
+                               }
                        }
-               case 123:       /* weekly-schedule */
+                       break;
+               case 19:  /* controlled-variable-reference */
+               case 60:  /* manipulated-variable-reference */
+               case 109: /* Setpoint-Reference */
+               case 132: /* log-device-object-property */
+                       offset = fDeviceObjectPropertyReference (tvb, pinfo, tree, offset);
+                       break;
+               case 123:       /* weekly-schedule -- accessed as a BACnetARRAY */
                        if (object_type < 128)
                        {
-                               offset = fWeeklySchedule (tvb,tree,offset);
-                               break;
+                               if (propertyArrayIndex == 0) {
+                                       /* BACnetARRAY index 0 refers to the length
+                                       of the array, not the elements of the array */
+                                       offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
+                               } else {
+                                       offset = fWeeklySchedule (tvb, pinfo, tree, offset);
+                               }
                        }
+                       break;
+               case 127:       /* client COV increment */
+                       offset = fClientCOV (tvb, pinfo, tree, offset);
+                       break;
+               case 131:  /* log-buffer */
+                       offset = fLogRecord (tvb, pinfo, tree, offset);
+                       break;
+               case 159: /* member-of */
+               case 165: /* zone-members */
+                       offset = fDeviceObjectReference (tvb, pinfo, tree, offset);
+                       break;
+               case 196: /* last-restart-reason */
+                       offset = fRestartReason (tvb, pinfo, tree, offset);
+                       break;
+               case 212: /* actual-shed-level */
+               case 214: /* expected-shed-level */
+               case 218: /* requested-shed-level */
+                       offset = fShedLevel (tvb, tree, offset);
+                       break;
                default:
                        if (tag_info)
                        {
@@ -2521,51 +5513,68 @@ fAbstractSyntaxNType (tvbuff_t *tvb, proto_tree *tree, guint offset)
                        }
                        else
                        {
-                               offset = fApplicationTypes (tvb, tree, offset, ar);
+                               offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
                        }
                        break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 
 }
 
 static guint
-fPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 tagoffset)
+fPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_info)
+{
+       guint8 tag_no;
+       guint32 lvt;
+
+       if (tag_is_opening(tag_info)) {
+               offset += fTagHeaderTree(tvb, tree, offset,
+                       &tag_no, &tag_info, &lvt);
+               offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
+               if (tvb_length_remaining(tvb, offset) > 0) {
+                       offset += fTagHeaderTree(tvb, tree, offset,
+                               &tag_no, &tag_info, &lvt);
+               }
+       } else {
+               proto_tree_add_text(tree, tvb, offset, tvb_length(tvb) - offset,
+                       "expected Opening Tag!"); \
+               offset = tvb_length(tvb);
+       }
+
+       return offset;
+}
+
+
+static guint
+fPropertyIdentifierValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset)
 {
        guint lastoffset = offset;
-       proto_item *tt;
-       proto_tree *subtree;
        guint8 tag_no, tag_info;
        guint32 lvt;
-       
-       offset = fPropertyReference(tvb, tree, offset, tagoffset, 0);
+
+       offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
        if (offset > lastoffset)
        {
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_no == tagoffset+2) {  /* Value - might not be present in ReadAccessResult */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(tree, tvb, offset, 1, "propertyValue");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType (tvb, subtree, offset);
-                               offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                       }
+                       offset = fPropertyValue (tvb, pinfo, tree, offset, tag_info);
                }
        }
        return offset;
 }
 
 static guint
-fBACnetPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fBACnetPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               offset = fPropertyValue(tvb, tree, offset, 0);
+               offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
                if (offset > lastoffset)
                {
                        /* detect optional priority
@@ -2574,24 +5583,35 @@ fBACnetPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
                        if (tag_is_context_specific(tag_info) && (tag_no == 3))
                                offset = fUnsignedTag (tvb,tree,offset,"Priority: ");
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fSubscribeCOVPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+       proto_tree *subtree = tree;
+       proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-       
-               switch (fTagNo(tvb,offset)) {
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               if (tag_is_closing(tag_info)) {
+                       offset += len;
+                       subtree = tree;
+                       continue;
+               }
+
+               switch (tag_no) {
                case 0: /* ProcessId */
                        offset = fUnsignedTag (tvb, tree, offset, "subscriber Process Id: ");
                        break;
                case 1: /* monitored ObjectId */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 2: /* issueConfirmedNotifications */
                        offset = fBooleanTag (tvb, tree, offset, "issue Confirmed Notifications: ");
@@ -2600,33 +5620,42 @@ fSubscribeCOVPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
                        offset = fTimeSpan (tvb,tree,offset,"life time");
                        break;
                case 4: /* monitoredPropertyIdentifier */
-                       offset = fBACnetPropertyReference (tvb, tree, offset, 0);
+                       if (tag_is_opening(tag_info)) {
+                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "monitoredPropertyIdentifier");
+                               if (tt) {
+                                       subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                               }
+                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                               offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
+                               break;
+                       }
+                       FAULT;
                        break;
                case 5: /* covIncrement */
                        offset = fRealTag (tvb, tree, offset, "COV Increment: ");
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fSubscribeCOVRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fSubscribeCOVPropertyRequest(tvb, tree, offset);
+       return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
 }
 
 static guint
-fWhoHas (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWhoHas (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-       
+
                switch (fTagNo(tvb, offset)) {
                case 0: /* deviceInstanceLowLimit */
                        offset = fUnsignedTag (tvb, tree, offset, "device Instance Low Limit: ");
@@ -2635,31 +5664,32 @@ fWhoHas (tvbuff_t *tvb, proto_tree *tree, guint offset)
                        offset = fUnsignedTag (tvb, tree, offset, "device Instance High Limit: ");
                        break;
                case 2: /* BACnetObjectId */
-                       offset = fObjectIdentifier (tvb, tree, offset);
-               break;
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+                       break;
                case 3: /* messageText */
                        offset = fCharacterString (tvb,tree,offset, "Object Name: ");
                        break;
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 
 static guint
-fDailySchedule (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fDailySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
-       
+
        fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
        if (tag_is_opening(tag_info) && tag_no == 0)
        {
                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+               while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
                        lastoffset = offset;
                        fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                        if (tag_is_closing(tag_info)) {
@@ -2667,8 +5697,9 @@ fDailySchedule (tvbuff_t *tvb, proto_tree *subtree, guint offset)
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                return offset;
                        }
-                       
-                       offset = fTimeValue (tvb, subtree, offset);
+
+                       offset = fTimeValue (tvb, pinfo, subtree, offset);
+                       if (offset == lastoffset) break;    /* nothing happened, exit loop */
                }
        }
        else if (tag_no == 0 && lvt == 0)
@@ -2680,24 +5711,35 @@ fDailySchedule (tvbuff_t *tvb, proto_tree *subtree, guint offset)
 }
 
 static guint
-fWeeklySchedule (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWeeklySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
-       guint i=1;
+       guint i = 1; /* day of week array index */
        proto_tree *subtree = tree;
        proto_item *tt;
-       
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+
+       if (propertyArrayIndex > 0) {
+               /* BACnetARRAY index 0 refers to the length
+               of the array, not the elements of the array.
+               BACnetARRAY index -1 is our internal flag that
+               the optional index was not used.
+               BACnetARRAY refers to this as all elements of the array.
+               If the optional index is specified for a BACnetARRAY,
+               then that specific array element is referenced. */
+               i = propertyArrayIndex;
+       }
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_is_closing(tag_info)) {
                        return offset; /* outer encoding will print out closing tag */
                }
-               tt = proto_tree_add_text(tree, tvb, offset, 0, val_to_str(i++, days, "day of week (%d) not found"));
+               tt = proto_tree_add_text(tree, tvb, offset, 0, "%s", val_to_str(i++, day_of_week, "day of week (%d) not found"));
                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-               offset = fDailySchedule (tvb,subtree,offset);
+               offset = fDailySchedule (tvb, pinfo, subtree, offset);
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
@@ -2706,16 +5748,16 @@ fWeeklySchedule (tvbuff_t *tvb, proto_tree *tree, guint offset)
 static guint
 fUTCTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
-       if (tvb_length_remaining(tvb, offset) <= 0)
+       if (tvb_reported_length_remaining(tvb, offset) <= 0)
                return offset;
-       
+
        return fDateTime (tvb, tree, offset, "UTC-Time: ");
 }
 
 static guint
 fTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
-       if (tvb_length_remaining(tvb, offset) <= 0)
+       if (tvb_reported_length_remaining(tvb, offset) <= 0)
                return offset;
 
        return fDateTime (tvb, tree, offset, NULL);
@@ -2724,23 +5766,95 @@ fTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
 static guint
 fDateRange  (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
-       if (tvb_length_remaining(tvb, offset) <= 0)
+       if (tvb_reported_length_remaining(tvb, offset) <= 0)
                return offset;
-    offset = fDate (tvb,tree,offset,"Start Date: ");
+       offset = fDate (tvb,tree,offset,"Start Date: ");
        return fDate (tvb, tree, offset, "End Date: ");
 }
 
 static guint
-fConfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVendorIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+       guint32 val = 0;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+       guint tag_len;
+       proto_item *ti;
+       proto_tree *subtree;
+       const gchar *label = "Vendor ID";
+
+       tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+       if (fUnsigned32 (tvb, offset + tag_len, lvt, &val))
+               ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+                       "%s: %s (%u)", label,
+                       val_to_str(val,BACnetVendorIdentifiers,"Unknown Vendor"), val);
+       else
+               ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+                       "%s - %u octets (Unsigned)", label, lvt);
+       subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+       fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+
+       if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1  and <= 2 are supported */
+               proto_item *expert_item;
+               expert_item = proto_tree_add_text(tree, tvb, 0, lvt, "Wrong length indicated. Expected 1 or 2, got %u", lvt);
+               expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1 or 2, got %u", lvt);
+               PROTO_ITEM_SET_GENERATED(expert_item);
+               return offset+tag_len+lvt;
+       }
+
+       proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
+               offset+tag_len, lvt, FALSE);
+
+       return offset+tag_len+lvt;
+}
+
+static guint
+fRestartReason (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+       guint32 val = 0;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+       guint tag_len;
+       proto_item *ti;
+       proto_tree *subtree;
+       const gchar *label = "Restart Reason";
+
+       tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+       if (fUnsigned32 (tvb, offset + tag_len, lvt, &val))
+               ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+                       "%s: %s (%u)", label,
+                       val_to_str(val,BACnetRestartReason,"Unknown reason"), val);
+       else
+               ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+                       "%s - %u octets (Unsigned)", label, lvt);
+       subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+       fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+
+       if (lvt != 1) {
+               proto_item *expert_item;
+               expert_item = proto_tree_add_text(tree, tvb, 0, lvt, "Wrong length indicated. Expected 1, got %u", lvt);
+               expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", lvt);
+               PROTO_ITEM_SET_GENERATED(expert_item);
+               return offset+tag_len+lvt;
+       }
+
+       proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
+               offset+tag_len, lvt, FALSE);
+
+       return offset+tag_len+lvt;
+}
+
+static guint
+fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
 
                case 0: /* textMessageSourceDevice */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 1: /* messageClass */
                        switch (fTagNo(tvb, offset)) {
@@ -2761,36 +5875,35 @@ fConfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
                        break;
                default:
                        return offset;
-                       break;  
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fUnconfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fConfirmedTextMessageRequest(tvb, tree, offset);
+       return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
 }
 
 static guint
-fConfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
        proto_item *tt;
 
-       /* exit loop if nothing happens inside */ 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  
+       /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {
                lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_is_closing(tag_info)) {
                        if (tag_no == 2) /* Make sure it's the expected tag */
                        {
-                               offset += fTagHeaderTree (tvb, subtree, offset,
-                                       &tag_no, &tag_info, &lvt);
+                               offset += len;
                                subtree = tree;
                                continue;
                        }
@@ -2802,7 +5915,7 @@ fConfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
                switch (tag_no) {
 
                case 0: /* vendorID */
-                       offset = fUnsignedTag (tvb, subtree, offset, "vendor ID: ");
+                       offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 1: /* serviceNumber */
                        offset = fUnsignedTag (tvb, subtree, offset, "service Number: ");
@@ -2812,7 +5925,7 @@ fConfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
                                tt = proto_tree_add_text(subtree, tvb, offset, 1, "service Parameters");
                                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
                                propertyIdentifier = -1;
-                               offset = fAbstractSyntaxNType (tvb, subtree, offset);
+                               offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
                                break;
                        }
                        FAULT;
@@ -2820,24 +5933,25 @@ fConfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fConfirmedPrivateTransferRequest(tvb, tree, offset);
+       return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
 }
 
 static guint
-fConfirmedPrivateTransferAck(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fConfirmedPrivateTransferRequest(tvb, tree, offset);
+       return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
 }
 
 static guint
-fLifeSafetyOperationRequest(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
+fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
@@ -2850,10 +5964,10 @@ fLifeSafetyOperationRequest(tvbuff_t *tvb, proto_tree *tree, guint offset, const
                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
        }
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-       
+
                switch (tag_no) {
                case 0: /* subscriberProcessId */
                        offset = fUnsignedTag (tvb, subtree, offset, "requesting Process Id: ");
@@ -2862,21 +5976,22 @@ fLifeSafetyOperationRequest(tvbuff_t *tvb, proto_tree *tree, guint offset, const
                        offset = fCharacterString (tvb, tree, offset, "requesting Source: ");
                        break;
                case 2: /* request */
-                       offset = fEnumeratedTagSplit (tvb, tree, offset, 
+                       offset = fEnumeratedTagSplit (tvb, tree, offset,
                                "request: ", BACnetLifeSafetyOperation, 64);
                        break;
                case 3: /* objectId */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
-static guint fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset)
+static guint
+fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
        switch (fTagNo(tvb, offset))
        {
@@ -2884,54 +5999,54 @@ static guint fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset
                offset = fBooleanTag (tvb, tree, offset, "boolean-value: ");
                break;
        case 1:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "binary-value: ", BACnetBinaryPV, 2);
                break;
        case 2:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "event-type: ", BACnetEventType, 12);
                break;
        case 3:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "polarity: ", BACnetPolarity, 2);
                break;
        case 4:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "program-change: ", BACnetProgramRequest, 5);
                break;
        case 5:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "program-state: ", BACnetProgramState, 5);
                break;
        case 6:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "reason-for-halt: ", BACnetProgramError, 5);
                break;
        case 7:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "reliability: ", BACnetReliability, 10);
                break;
        case 8:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "state: ", BACnetEventState, 64);
                break;
        case 9:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "system-status: ", BACnetDeviceStatus, 64);
                break;
        case 10:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "units: ", BACnetEngineeringUnits, 2);
                break;
        case 11:
                offset = fUnsignedTag(tvb, tree, offset, "unsigned-value: ");
                break;
        case 12:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "life-safety-mode: ", BACnetLifeSafetyMode, 64);
                break;
        case 13:
-               offset = fEnumeratedTagSplit (tvb, tree, offset, 
+               offset = fEnumeratedTagSplit (tvb, tree, offset,
                        "life-safety-state: ", BACnetLifeSafetyState, 64);
                break;
        default:
@@ -2940,8 +6055,106 @@ static guint fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset
        return offset;
 }
 
+
+/*
+BACnetDeviceObjectPropertyValue ::= SEQUENCE {
+      deviceIdentifier       [0]      BACnetObjectIdentifier,
+      objectIdentifier       [1]      BACnetObjectIdentifier,
+      propertyIdentifier     [2]      BACnetPropertyIdentifier,
+      arrayIndex             [3]      Unsigned OPTIONAL,
+      value                  [4]      ABSTRACT-SYNTAX.&Type
+      }
+*/
+static guint
+fDeviceObjectPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+       guint lastoffset = 0;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+
+       while (tvb_reported_length_remaining(tvb, offset)) {
+               lastoffset = offset;
+               /* check the tag.  A closing tag means we are done */
+               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               if (tag_is_closing(tag_info)) {
+                       return offset;
+               }
+               switch (tag_no) {
+               case 0: /* deviceIdentifier */
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+                       break;
+               case 1: /* objectIdentifier */
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+                       break;
+               case 2: /* propertyIdentifier */
+                       offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
+                       break;
+               case 3: /* arrayIndex - OPTIONAL */
+                       offset = fUnsignedTag (tvb, tree, offset,
+                               "arrayIndex: ");
+                       break;
+               case 4: /* value */
+                       offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
+                       offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       break;
+               default:
+                       return offset;
+               }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
+       }
+       return offset;
+}
+
+
+/*
+BACnetDeviceObjectPropertyReference ::= SEQUENCE {
+      objectIdentifier       [0]      BACnetObjectIdentifier,
+      propertyIdentifier     [1]      BACnetPropertyIdentifier,
+      propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
+                                                                -- if omitted with an array then
+                                                                -- the entire array is referenced
+      deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
+      }
+*/
+static guint
+fDeviceObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+       guint lastoffset = 0;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+
+       while (tvb_reported_length_remaining(tvb, offset)) {
+               lastoffset = offset;
+               /* check the tag.  A closing tag means we are done */
+               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               if (tag_is_closing(tag_info)) {
+                       return offset;
+               }
+               switch (tag_no) {
+               case 0: /* objectIdentifier */
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+                       break;
+               case 1: /* propertyIdentifier */
+                       offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
+                       break;
+               case 2: /* arrayIndex - OPTIONAL */
+                       offset = fUnsignedTag (tvb, tree, offset,
+                               "arrayIndex: ");
+                       break;
+               case 3: /* deviceIdentifier - OPTIONAL */
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+                       break;
+               default:
+                       return offset;
+               }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
+       }
+       return offset;
+}
+
 static guint
-fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fNotificationParameters (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = offset;
        guint8 tag_no, tag_info;
@@ -2949,61 +6162,66 @@ fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
        proto_tree *subtree = tree;
        proto_item *tt;
 
-       tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters");
+       fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+       tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters (%d) %s",
+               tag_no, val_to_str(tag_no, BACnetEventType, "invalid type"));
        subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-       /* Opeing tag for parameter choice */
+       /* Opening tag for parameter choice */
        offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
 
        switch (tag_no) {
        case 0: /* change-of-bitstring */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
                        switch (fTagNo(tvb, offset)) {
                        case 0:
-                               offset = fBitStringTag (tvb, subtree, offset, 
+                               offset = fBitStringTag (tvb, subtree, offset,
                                        "referenced-bitstring: ");
                                break;
                        case 1:
-                               offset = fEnumeratedTag (tvb, subtree, offset, 
+                               offset = fBitStringTagVS (tvb, subtree, offset,
                                        "status-flags: ", BACnetStatusFlags);
+                       lastoffset = offset;
                                break;
                        default:
-                               return offset;
                                break;
                        }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
                break;
        case 1: /* change-of-state */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
                        switch (fTagNo(tvb, offset)) {
                        case 0:
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                offset = fBACnetPropertyStates(tvb, subtree, offset);
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                               break;
                        case 1:
-                               offset = fEnumeratedTag (tvb, subtree, offset, 
+                               offset = fBitStringTagVS (tvb, subtree, offset,
                                        "status-flags: ", BACnetStatusFlags);
                        lastoffset = offset;
                                break;
                        default:
                                break;
                        }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
                break;
-    case 2: /* change-of-value */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+       case 2: /* change-of-value */
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
                        switch (fTagNo(tvb, offset)) {
                        case 0:
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                switch (fTagNo(tvb, offset)) {
                                case 0:
-                                       offset = fBitStringTag (tvb, subtree, offset, 
+                                       offset = fBitStringTag (tvb, subtree, offset,
                                                "changed-bits: ");
                                        break;
                                case 1:
-                                       offset = fRealTag (tvb, subtree, offset, 
+                                       offset = fRealTag (tvb, subtree, offset,
                                                "changed-value: ");
                                        break;
                                default:
@@ -3012,44 +6230,54 @@ fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                break;
                        case 1:
-                               offset = fEnumeratedTag (tvb, subtree, offset, 
+                               offset = fBitStringTagVS (tvb, subtree, offset,
                                        "status-flags: ", BACnetStatusFlags);
+                       lastoffset = offset;
                                break;
                        default:
                                break;
                        }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
                break;
-    case 3: /* command-failure */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+       case 3: /* command-failure */
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
                        switch (fTagNo(tvb, offset)) {
                        case 0: /* "command-value: " */
+                               /* from BACnet Table 13-3,
+                                       Standard Object Property Values Returned in Notifications */
+                               propertyIdentifier = 85; /* PRESENT_VALUE */
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType (tvb, subtree, offset);
+                               offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                break;
                        case 1:
-                               offset = fEnumeratedTag (tvb, subtree, offset, 
+                               offset = fBitStringTagVS (tvb, subtree, offset,
                                        "status-flags: ", BACnetStatusFlags);
+                               break;
                        case 2: /* "feedback-value: " */
+                               propertyIdentifier = 40; /* FEEDBACK_VALUE */
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType (tvb, subtree, offset);
+                               offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       lastoffset = offset;
+                               break;
                        default:
                                break;
                        }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
                break;
-    case 4: /* floating-limit */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+       case 4: /* floating-limit */
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
                        switch (fTagNo(tvb, offset)) {
                        case 0:
                                offset = fRealTag (tvb, subtree, offset, "reference-value: ");
                                break;
                        case 1:
-                               offset = fEnumeratedTag (tvb, subtree, offset, 
+                               offset = fBitStringTagVS (tvb, subtree, offset,
                                        "status-flags: ", BACnetStatusFlags);
                                break;
                        case 2:
@@ -3057,20 +6285,23 @@ fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                break;
                        case 3:
                                offset = fRealTag (tvb, subtree, offset, "error-limit: ");
+                       lastoffset = offset;
+                               break;
                        default:
                                break;
                        }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
                break;
-    case 5: /* out-of-range */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+       case 5: /* out-of-range */
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
                        switch (fTagNo(tvb, offset)) {
                        case 0:
                                offset = fRealTag (tvb, subtree, offset, "exceeding-value: ");
                                break;
                        case 1:
-                               offset = fEnumeratedTag (tvb, subtree, offset, 
+                               offset = fBitStringTagVS (tvb, subtree, offset,
                                        "status-flags: ", BACnetStatusFlags);
                                break;
                        case 2:
@@ -3078,26 +6309,30 @@ fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                break;
                        case 3:
                                offset = fRealTag (tvb, subtree, offset, "exceeded-limit: ");
+                       lastoffset = offset;
+                               break;
                        default:
                                break;
                        }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
            break;
        case 6:
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-                       offset =fBACnetPropertyValue (tvb,subtree,offset);
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
+                       offset =fBACnetPropertyValue (tvb,pinfo,subtree,offset);
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
                break;
        case 7: /* buffer-ready */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
                        switch (fTagNo(tvb, offset)) {
                        case 0:
-                               offset = fObjectIdentifier (tvb, subtree, offset); /* buffer-device */
+                               offset = fObjectIdentifier (tvb, pinfo, subtree, offset); /* buffer-device */
                                break;
                        case 1:
-                               offset = fObjectIdentifier (tvb, subtree, offset); /* buffer-object */
+                               offset = fObjectIdentifier (tvb, pinfo, subtree, offset); /* buffer-object */
                                break;
                        case 2:
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
@@ -3108,38 +6343,116 @@ fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                offset = fDateTime (tvb, subtree, offset, "current-notification: ");
                                offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       lastoffset = offset;
+                               break;
                        default:
                                break;
                        }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
                break;
-    case 8: /* change-of-life-safety */
-               while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+       case 8: /* change-of-life-safety */
+               while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+                       lastoffset = offset;
                        switch (fTagNo(tvb, offset)) {
                        case 0:
-                               offset = fEnumeratedTagSplit (tvb, subtree, offset, 
+                               offset = fEnumeratedTagSplit (tvb, subtree, offset,
                                        "new-state: ", BACnetLifeSafetyState, 256);
                                break;
                        case 1:
-                               offset = fEnumeratedTagSplit (tvb, subtree, offset, 
-                                       "new-mode: ", BACnetLifeSafetyState, 256);
+                               offset = fEnumeratedTagSplit (tvb, subtree, offset,
+                                       "new-mode: ", BACnetLifeSafetyMode, 256);
                                break;
                        case 2:
-                               offset = fEnumeratedTag (tvb, subtree, offset, 
+                               offset = fBitStringTagVS (tvb, subtree, offset,
                                        "status-flags: ", BACnetStatusFlags);
+                               break;
                        case 3:
-                               offset = fEnumeratedTagSplit (tvb, subtree, offset, 
+                               offset = fEnumeratedTagSplit (tvb, subtree, offset,
                                        "operation-expected: ", BACnetLifeSafetyOperation, 64);
+                       lastoffset = offset;
+                               break;
                        default:
-                               return offset;
                                break;
                        }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
                }
-           break;
+               break;
+       case 9: /* extended */
+               while (tvb_reported_length_remaining(tvb, offset)) {
+                       lastoffset = offset;
+                       switch (fTagNo(tvb, offset)) {
+                       case 0:
+                               offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
+                               break;
+                       case 1:
+                               offset = fUnsignedTag (tvb, subtree, offset,
+                                       "extended-event-type: ");
+                               break;
+                       case 2: /* parameters */
+                               offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                               offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
+                               offset = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
+                               offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       lastoffset = offset;
+                               break;
+                       default:
+                               break;
+                       }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
+               }
+               break;
+       case 10: /* buffer ready */
+               while (tvb_reported_length_remaining(tvb, offset)) {
+                       lastoffset = offset;
+                       switch (fTagNo(tvb, offset)) {
+                       case 0: /* buffer-property */
+                               offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                               offset = fDeviceObjectPropertyReference (tvb, pinfo, subtree, offset);
+                               offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                               break;
+                       case 1:
+                               offset = fUnsignedTag (tvb, subtree, offset,
+                                       "previous-notification: ");
+                               break;
+                       case 2:
+                               offset = fUnsignedTag (tvb, subtree, offset,
+                                       "current-notification: ");
+                       lastoffset = offset;
+                               break;
+                       default:
+                               break;
+                       }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
+               }
+               break;
+       case 11: /* unsigned range */
+               while (tvb_reported_length_remaining(tvb, offset)) {
+                       lastoffset = offset;
+                       switch (fTagNo(tvb, offset)) {
+                       case 0:
+                               offset = fUnsignedTag (tvb, subtree, offset,
+                                       "exceeding-value: ");
+                               break;
+                       case 1:
+                               offset = fBitStringTagVS (tvb, subtree, offset,
+                                       "status-flags: ", BACnetStatusFlags);
+                               break;
+                       case 2:
+                               offset = fUnsignedTag (tvb, subtree, offset,
+                                       "exceeded-limit: ");
+                       lastoffset = offset;
+                               break;
+                       default:
+                               break;
+                       }
+                       if (offset == lastoffset) break;     /* nothing happened, exit loop */
+               }
+               break;
        default:
                break;
        }
+
        /* Closing tag for parameter choice */
        offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
 
@@ -3152,11 +6465,11 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
                case 0: /* change-of-bitstring */
-                       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
                                lastoffset = offset;
                                switch (fTagNo(tvb, offset)) {
                                case 0:
@@ -3173,16 +6486,16 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                        return offset;
                                }
                        }
-        break;
+                       break;
                case 1: /* change-of-state */
-                       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-                       lastoffset = offset;
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+                               lastoffset = offset;
                                switch (fTagNo(tvb, offset)) {
                                case 0:
                                        offset = fTimeSpan (tvb, tree, offset, "Time Delay");
                                        break;
                                case 1: /* SEQUENCE OF BACnetPropertyStates */
-                                       offset = fEnumeratedTagSplit (tvb, tree, offset, 
+                                       offset = fEnumeratedTagSplit (tvb, tree, offset,
                                                "value: ", BACnetPropertyStates, 64);
                                        break;
                                default:
@@ -3190,9 +6503,9 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                }
                        }
                        break;
-        case 2: /* change-of-value */
-                       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-                       lastoffset = offset;
+               case 2: /* change-of-value */
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+                               lastoffset = offset;
                                switch (fTagNo(tvb, offset)) {
                                case 0:
                                        offset = fTimeSpan   (tvb, tree, offset, "Time Delay");
@@ -3203,7 +6516,7 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                                offset = fBitStringTag (tvb, tree, offset, "bitmask: ");
                                                break;
                                        case 1:
-                                               offset = fRealTag (tvb, tree, offset, 
+                                               offset = fRealTag (tvb, tree, offset,
                                                        "referenced Property Increment: ");
                                                break;
                                        default:
@@ -3213,30 +6526,30 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                        return offset;
                                }
                        }
-               break;
-        case 3: /* command-failure */
-                       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-                       lastoffset = offset;
+                       break;
+               case 3: /* command-failure */
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+                               lastoffset = offset;
                                switch (fTagNo(tvb, offset)) {
                                case 0:
                                        offset = fTimeSpan   (tvb, tree, offset, "Time Delay");
                                        break;
                                case 1:
-                                       offset = fDeviceObjectPropertyReference (tvb,tree,offset);
+                                       offset = fDeviceObjectPropertyReference (tvb,pinfo,tree,offset);
                                default:
                                        return offset;
                                }
                        }
-        break;
-        case 4: /* floating-limit */
-                       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-                       lastoffset = offset;
+                       break;
+               case 4: /* floating-limit */
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+                               lastoffset = offset;
                                switch (fTagNo(tvb, offset)) {
                                case 0:
                                        offset = fTimeSpan   (tvb, tree, offset, "Time Delay");
                                        break;
                                case 1:
-                                       offset = fDeviceObjectPropertyReference (tvb,tree,offset);
+                                       offset = fDeviceObjectPropertyReference (tvb,pinfo,tree,offset);
                                        break;
                                case 2:
                                        offset = fRealTag (tvb, tree, offset, "low diff limit: ");
@@ -3253,7 +6566,7 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
                        }
                        break;
                case 5: /* out-of-range */
-                       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
                                lastoffset = offset;
                                switch (fTagNo(tvb, offset)) {
                                case 0:
@@ -3272,12 +6585,12 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                        return offset;
                                }
                        }
-        break;
+                       break;
                case 6:
-                       offset = fBACnetPropertyValue (tvb,tree,offset);
+                       offset = fBACnetPropertyValue (tvb,pinfo,tree,offset);
                        break;
                case 7: /* buffer-ready */
-                       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
                                lastoffset = offset;
                                switch (fTagNo(tvb, offset)) {
                                case 0:
@@ -3291,24 +6604,24 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                        return offset;
                                }
                        }
-        break;
+                       break;
                case 8: /* change-of-life-safety */
-                       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
                                lastoffset = offset;
                                switch (fTagNo(tvb, offset)) {
                                case 0:
                                        offset = fTimeSpan (tvb, tree, offset, "Time Delay");
                                        break;
                                case 1:
-                                       offset = fEnumeratedTagSplit (tvb, tree, offset, 
+                                       offset = fEnumeratedTagSplit (tvb, tree, offset,
                                                "life safety alarm value: ", BACnetLifeSafetyState, 256);
                                        break;
                                case 2:
-                                       offset = fEnumeratedTagSplit (tvb, tree, offset, 
+                                       offset = fEnumeratedTagSplit (tvb, tree, offset,
                                                "alarm value: ", BACnetLifeSafetyState, 256);
                                        break;
                                case 3:
-                                       offset = fDeviceObjectPropertyReference (tvb, tree, offset);
+                                       offset = fDeviceObjectPropertyReference (tvb, pinfo, tree, offset);
                                        break;
                                default:
                                        return offset;
@@ -3321,22 +6634,29 @@ fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
        }
        return offset;
 }
+#endif
 
 static guint
-fLogRecord (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fLogRecord (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
                case 0: /* timestamp */
-                       offset = fDateTime (tvb,tree,offset,NULL);
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fDate (tvb,tree,offset,"Date: ");
+                       offset = fTime (tvb,tree,offset,"Time: ");
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                case 1: /* logDatum: don't loop, it's a CHOICE */
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        switch (fTagNo(tvb, offset)) {
                        case 0: /* logStatus */
-                               offset = fEnumeratedTag (tvb, tree, offset, 
+                               offset = fEnumeratedTag (tvb, tree, offset,
                                        "log status: ", BACnetLogStatus);
                                break;
                        case 1:
@@ -3361,53 +6681,57 @@ fLogRecord (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                offset = fNullTag(tvb, tree, offset, "null value: ");
                                break;
                        case 8:
-                               offset = fError (tvb,tree,offset);
+                               offset = fError (tvb, pinfo, tree, offset);
                                break;
                        case 9:
                                offset = fRealTag (tvb, tree, offset, "time change: ");
                                break;
                        case 10:        /* any Value */
-                               offset = fAbstractSyntaxNType (tvb, tree, offset);
+                               offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                               offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
+                               offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                                break;
                        default:
                                return offset;
                        }
-        break;
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       break;
                case 2:
-                       offset = fEnumeratedTag (tvb, tree, offset, 
-                               "status Flags: ", BACnetStatusFlags);
+                       offset = fEnumeratedTag (tvb, tree, offset,
+                               "Status Flags: ", BACnetStatusFlags);
                        break;
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
-#endif
+
 
 static guint
-fConfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-       
+
                switch (fTagNo(tvb,offset)) {
                case 0: /* ProcessId */
                        offset = fProcessId (tvb,tree,offset);
                        break;
                case 1: /* initiating ObjectId */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 2: /* event ObjectId */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 3: /* time stamp */
                        offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fTimeStamp (tvb, tree, offset);
+                       offset = fTimeStamp (tvb, tree, offset, NULL);
                        offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                case 4: /* notificationClass */
@@ -3417,7 +6741,7 @@ fConfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offse
                        offset = fUnsignedTag (tvb, tree, offset, "Priority: ");
                        break;
                case 6: /* EventType */
-                       offset = fEnumeratedTagSplit (tvb, tree, offset, 
+                       offset = fEnumeratedTagSplit (tvb, tree, offset,
                                "Event Type: ", BACnetEventType, 64);
                        break;
                case 7: /* messageText */
@@ -3431,59 +6755,59 @@ fConfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offse
                        offset = fBooleanTag (tvb, tree, offset, "ack Required: ");
                        break;
                case 10: /* fromState */
-                       offset = fEnumeratedTagSplit (tvb, tree, offset, 
+                       offset = fEnumeratedTagSplit (tvb, tree, offset,
                                "from State: ", BACnetEventState, 64);
                        break;
                case 11: /* toState */
-                       offset = fEnumeratedTagSplit (tvb, tree, offset, 
+                       offset = fEnumeratedTagSplit (tvb, tree, offset,
                                "to State: ", BACnetEventState, 64);
                        break;
                case 12: /* NotificationParameters */
                        offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fNotificationParameters (tvb, tree, offset);
+                       offset = fNotificationParameters (tvb, pinfo, tree, offset);
                        offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                default:
                        break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fConfirmedEventNotificationRequest (tvb, tree, offset);
+       return fConfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
 }
 
 static guint
-fConfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
        proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {   
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               if (tag_is_closing(tag_info)) {
+                       offset += len;
                        subtree = tree;
                        continue;
                }
-       
+
                switch (tag_no) {
                case 0: /* ProcessId */
                        offset = fProcessId (tvb,tree,offset);
                        break;
-               case 1: /* initiating ObjectId */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+               case 1: /* initiating DeviceId */
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 2: /* monitored ObjectId */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 3: /* time remaining */
                        offset = fTimeSpan (tvb, tree, offset, "Time remaining");
@@ -3493,48 +6817,48 @@ fConfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
                                tt = proto_tree_add_text(subtree, tvb, offset, 1, "list of Values");
                                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fBACnetPropertyValue (tvb, subtree, offset);
+                               offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
                                break;
                        }
                        FAULT;
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fConfirmedCOVNotificationRequest (tvb, tree, offset);
+       return fConfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
 }
 
 static guint
-fAcknowledgeAlarmRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAcknowledgeAlarmRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no = 0, tag_info = 0;
        guint32 lvt = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
                case 0: /* acknowledgingProcessId */
                        offset = fUnsignedTag (tvb, tree, offset, "acknowledging Process Id: ");
                        break;
                case 1: /* eventObjectId */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 2: /* eventStateAcknowledged */
-                       offset = fEnumeratedTagSplit (tvb, tree, offset, 
+                       offset = fEnumeratedTagSplit (tvb, tree, offset,
                                "event State Acknowledged: ", BACnetEventState, 64);
                        break;
                case 3: /* timeStamp */
                        offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fTimeStamp(tvb, tree, offset);
+                       offset = fTimeStamp(tvb, tree, offset, NULL);
                        offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                case 4: /* acknowledgementSource */
@@ -3542,227 +6866,268 @@ fAcknowledgeAlarmRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
                        break;
                case 5: /* timeOfAcknowledgement */
                        offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fTimeStamp(tvb, tree, offset);
+                       offset = fTimeStamp(tvb, tree, offset, "acknowledgement timestamp: ");
                        offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fGetAlarmSummaryAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetAlarmSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
-               offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, 
+               offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
+               offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
                        "alarm State: ", BACnetEventState, 64);
-               offset = fApplicationTypesEnumerated (tvb, tree, offset, 
+               offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
                        "acknowledged Transitions: ", BACnetEventTransitionBits);
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return  offset;
 }
 
 static guint
-fGetEnrollmentSummaryRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetEnrollmentSummaryRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
                case 0: /* acknowledgmentFilter */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
+                       offset = fEnumeratedTag (tvb, tree, offset,
                                "acknowledgment Filter: ", BACnetAcknowledgementFilter);
                        break;
-               case 1: /* eventObjectId */
+               case 1: /* eventObjectId - OPTIONAL */
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fRecipientProcess (tvb, pinfo, tree, offset);
                        offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fRecipientProcess (tvb, tree, offset);
                        break;
                case 2: /* eventStateFilter */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
+                       offset = fEnumeratedTag (tvb, tree, offset,
                                "event State Filter: ", BACnetEventStateFilter);
                        break;
-               case 3: /* eventTypeFilter */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
+               case 3: /* eventTypeFilter - OPTIONAL */
+                       offset = fEnumeratedTag (tvb, tree, offset,
                                "event Type Filter: ", BACnetEventType);
                        break;
                case 4: /* priorityFilter */
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        offset = fUnsignedTag (tvb, tree, offset, "min Priority: ");
                        offset = fUnsignedTag (tvb, tree, offset, "max Priority: ");
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
-               case 5: /* notificationClassFilter */
+               case 5: /* notificationClassFilter - OPTIONAL */
                        offset = fUnsignedTag (tvb, tree, offset, "notification Class Filter: ");
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fGetEnrollmentSummaryAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetEnrollmentSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
-               offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, 
+               offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
+               offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
                        "event Type: ", BACnetEventType, 64);
-               offset = fApplicationTypesEnumerated (tvb, tree, offset, 
-                       "event State: ", BACnetEventStateFilter);
-               offset = fApplicationTypes (tvb, tree, offset, "Priority: ");
-               offset = fApplicationTypes (tvb, tree, offset, "Notification Class: ");
+               offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
+                       "event State: ", BACnetEventState);
+               offset = fApplicationTypes (tvb, pinfo, tree, offset, "Priority: ");
+               offset = fApplicationTypes (tvb, pinfo, tree, offset, "Notification Class: ");
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
 
        return  offset;
 }
 
 static guint
-fGetEventInformationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetEventInformationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
-
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-               switch (fTagNo(tvb, offset)) {
-               case 0: /* lastReceivedObjectId */
-                       offset = fObjectIdentifier (tvb, tree, offset);
-                       break;
-               default:
-                       return offset;
-                       break;
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
+               if (fTagNo(tvb, offset) == 0) {
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                }
        }
        return offset;
 }
 
 static guint
-flistOfEventSummaries (tvbuff_t *tvb, proto_tree *tree, guint offset)
+flistOfEventSummaries (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+       proto_tree* subtree = tree;
+       proto_item* ti = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               switch (fTagNo(tvb, offset)) {
+               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               /* we are finished here if we spot a closing tag */
+               if (tag_is_closing(tag_info)) {
+                       break;
+               }
+               switch (tag_no) {
                case 0: /* ObjectId */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 1: /* eventState */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
-                               "event State: ", BACnetEventStateFilter);
+                       offset = fEnumeratedTag (tvb, tree, offset,
+                               "event State: ", BACnetEventState);
                        break;
                case 2: /* acknowledgedTransitions */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
+                       offset = fBitStringTagVS (tvb, tree, offset,
                                "acknowledged Transitions: ", BACnetEventTransitionBits);
                        break;
                case 3: /* eventTimeStamps */
-                       offset = fTime (tvb, tree, offset, "time Stamp: ");
-                       offset = fTime (tvb, tree, offset, "time Stamp: ");
-                       offset = fTime (tvb, tree, offset, "time Stamp: ");
+                       ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
+                       if (ti) {
+                               subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+                       }
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fTimeStamp (tvb, subtree, offset,"TO-OFFNORMAL timestamp: ");
+                       offset = fTimeStamp (tvb, subtree, offset,"TO-FAULT timestamp: ");
+                       offset = fTimeStamp (tvb, subtree, offset,"TO-NORMAL timestamp: ");
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                        break;
                case 4: /* notifyType */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
+                       offset = fEnumeratedTag (tvb, tree, offset,
                                "Notify Type: ", BACnetNotifyType);
                        break;
                case 5: /* eventEnable */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
+                       offset = fBitStringTagVS (tvb, tree, offset,
                                "event Enable: ", BACnetEventTransitionBits);
                        break;
                case 6: /* eventPriorities */
-                       offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
-                       offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
-                       offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
+                       ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventPriorities");
+                       if (ti) {
+                               subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+                       }
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fUnsignedTag (tvb, subtree, offset, "TO-OFFNORMAL Priority: ");
+                       offset = fUnsignedTag (tvb, subtree, offset, "TO-FAULT Priority: ");
+                       offset = fUnsignedTag (tvb, subtree, offset, "TO-NORMAL Priority: ");
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                        break;
                default:
                        return offset;
+               }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
+       }
+       return offset;
+}
+
+static guint
+fLOPR (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+       guint lastoffset = 0;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
+
+       col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
+               lastoffset = offset;
+               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               /* we are finished here if we spot a closing tag */
+               if (tag_is_closing(tag_info)) {
                        break;
                }
+               offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fGetEventInformationACK (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetEventInformationACK (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
                case 0: /* listOfEventSummaries */
                        offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
-                       offset = flistOfEventSummaries (tvb, tree, offset);
+                       offset = flistOfEventSummaries (tvb, pinfo, tree, offset);
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                case 1: /* moreEvents */
                        offset = fBooleanTag (tvb, tree, offset, "more Events: ");
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fAddListElementRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
        proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_is_closing(tag_info)) {
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
+                       offset += len;
                        subtree = tree;
                        continue;
                }
-       
+
                switch (tag_no) {
                case 0: /* ObjectId */
-                       offset = fBACnetObjectPropertyReference (tvb, subtree, offset);
+                       offset = fBACnetObjectPropertyReference (tvb, pinfo, subtree, offset);
                        break;
                case 3: /* listOfElements */
                        if (tag_is_opening(tag_info)) {
                                tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfElements");
                                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType (tvb, subtree, offset);
+                               offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
                                break;
                        }
                        FAULT;
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fDeleteObjectRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fObjectIdentifier (tvb, tree, offset);
+       return fObjectIdentifier (tvb, pinfo, tree, offset);
 }
 
 static guint
@@ -3770,9 +7135,9 @@ fDeviceCommunicationControlRequest(tvbuff_t *tvb, proto_tree *tree, guint offset
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-       
+
                switch (fTagNo(tvb, offset)) {
                case 0: /* timeDuration */
                        offset = fUnsignedTag (tvb,tree,offset,"time Duration: ");
@@ -3781,13 +7146,13 @@ fDeviceCommunicationControlRequest(tvbuff_t *tvb, proto_tree *tree, guint offset
                        offset = fEnumeratedTag (tvb, tree, offset, "enable-disable: ",
                                BACnetEnableDisable);
                        break;
-               case 2: /* password */
+               case 2: /* password - OPTIONAL */
                        offset = fCharacterString (tvb, tree, offset, "Password: ");
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
@@ -3797,58 +7162,59 @@ fReinitializeDeviceRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-       
+
                switch (fTagNo(tvb, offset)) {
                case 0: /* reinitializedStateOfDevice */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
-                               "reinitialized State Of Device: ", 
+                       offset = fEnumeratedTag (tvb, tree, offset,
+                               "reinitialized State Of Device: ",
                                BACnetReinitializedStateOfDevice);
                        break;
-               case 1: /* password */
+               case 1: /* password - OPTIONAL */
                        offset = fCharacterString (tvb, tree, offset, "Password: ");
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fVtOpenRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       offset = fApplicationTypesEnumerated (tvb, tree, offset, 
+       offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
                "vtClass: ", BACnetVTClass);
-       return fApplicationTypes (tvb,tree,offset,"local VT Session ID: ");
+       return fApplicationTypes (tvb, pinfo, tree,offset,"local VT Session ID: ");
 }
 
 static guint
-fVtOpenAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVtOpenAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fApplicationTypes (tvb,tree,offset,"remote VT Session ID: ");
+       return fApplicationTypes (tvb, pinfo, tree,offset,"remote VT Session ID: ");
 }
 
 static guint
-fVtCloseRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVtCloseRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               offset= fApplicationTypes (tvb,tree,offset,"remote VT Session ID: ");
+               offset= fApplicationTypes (tvb, pinfo, tree,offset,"remote VT Session ID: ");
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fVtDataRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVtDataRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       offset= fApplicationTypes (tvb,tree,offset,"VT Session ID: ");
-       offset = fApplicationTypes (tvb, tree, offset, "VT New Data: ");
-       return fApplicationTypes (tvb,tree,offset,"VT Data Flag: ");;
+       offset= fApplicationTypes (tvb, pinfo, tree,offset,"VT Session ID: ");
+       offset = fApplicationTypes (tvb, pinfo, tree, offset, "VT New Data: ");
+       return fApplicationTypes (tvb, pinfo, tree,offset,"VT Data Flag: ");;
 }
 
 static guint
@@ -3856,9 +7222,9 @@ fVtDataAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-       
+
                switch (fTagNo(tvb,offset)) {
                case 0: /* BOOLEAN */
                        offset = fBooleanTag (tvb, tree, offset, "all New Data Accepted: ");
@@ -3869,6 +7235,7 @@ fVtDataAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
@@ -3878,9 +7245,9 @@ fAuthenticateRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-       
+
                switch (fTagNo(tvb,offset)) {
                case 0: /* Unsigned32 */
                        offset = fUnsignedTag (tvb, tree, offset, "pseudo Random Number: ");
@@ -3900,156 +7267,145 @@ fAuthenticateRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fAuthenticateAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAuthenticateAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fApplicationTypes (tvb, tree, offset, "modified Random Number: ");
+       return fApplicationTypes (tvb, pinfo, tree, offset, "modified Random Number: ");
 }
 
 static guint
-fRequestKeyRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fRequestKeyRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       offset = fObjectIdentifier (tvb, tree, offset); /* Requesting Device Identifier */
+       offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* Requesting Device Identifier */
        offset = fAddress (tvb, tree, offset);
-       offset = fObjectIdentifier (tvb, tree, offset); /* Remote Device Identifier */
+       offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* Remote Device Identifier */
        return fAddress (tvb, tree, offset);
 }
 
 static guint
-fRemoveListElementRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        /* Same as AddListElement request after service choice */
-       return fAddListElementRequest(tvb, tree, offset);
+       return fAddListElementRequest(tvb, pinfo, tree, offset);
 }
 
 static guint
-fReadPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fBACnetObjectPropertyReference(tvb, tree, offset);
+       return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
 }
 
 static guint
-fReadPropertyAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadPropertyAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
-    proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       /* set the optional global properties to indicate not-used */
+       propertyArrayIndex = -1;
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_is_closing(tag_info)) {
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
+                       offset += len;
                        subtree = tree;
                        continue;
                }
                switch (tag_no) {
                case 0: /* objectIdentifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 1: /* propertyIdentifier */
-                       offset = fPropertyIdentifier (tvb, subtree, offset);
+                       offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 2: /* propertyArrayIndex */
-                       offset = fSignedTag (tvb, subtree, offset, "property Array Index: ");
+                       offset = fPropertyArrayIndex (tvb, subtree, offset);
                        break;
                case 3: /* propertyValue */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType (tvb, subtree, offset);
-                               break;
-                       }
-                       FAULT;
+                       offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
                        break;
                default:
                        break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fWritePropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
-    proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       /* set the optional global properties to indicate not-used */
+       propertyArrayIndex = -1;
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               /* quit loop if we spot a closing tag */
                if (tag_is_closing(tag_info)) {
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
                        subtree = tree;
-                       continue;
+                       break;
                }
-       
+
                switch (tag_no) {
                case 0: /* objectIdentifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 1: /* propertyIdentifier */
-                       offset = fPropertyIdentifier (tvb, subtree, offset);
+                       offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 2: /* propertyArrayIndex */
-                       offset = fSignedTag (tvb, subtree, offset, "property Array Index: ");
+                       offset = fPropertyArrayIndex (tvb, subtree, offset);
                        break;
                case 3: /* propertyValue */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType (tvb, subtree, offset);
-                               break;
-                       }
-                       FAULT;
+                       offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
                        break;
                case 4: /* Priority (only used for write) */
-                       offset = fSignedTag (tvb, subtree, offset, "Priority: ");
+                       offset = fUnsignedTag (tvb, subtree, offset, "Priority: ");
                        break;
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fWriteAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fWriteAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {   
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
+               if (tag_is_closing(tag_info)) {
+                       offset += len;
                        continue;
                }
-       
+
                switch (tag_no) {
                case 0: /* objectIdentifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 1: /* listOfPropertyValues */
                        if (tag_is_opening(tag_info)) {
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fBACnetPropertyValue (tvb, subtree, offset);
+                               offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
                                break;
                        }
                        FAULT;
@@ -4057,71 +7413,81 @@ fWriteAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fWritePropertyMultipleRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        if (offset >= tvb_reported_length(tvb))
                return offset;
 
-       return fWriteAccessSpecification (tvb, tree, offset);
+       col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+       return fWriteAccessSpecification (tvb, pinfo, tree, offset);
 }
 
 static guint
-fPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
+fPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       /* set the optional global properties to indicate not-used */
+       propertyArrayIndex = -1;
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
                        return offset;
+               } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
+                       return offset;
                }
                switch (tag_no-tagoffset) {
                case 0: /* PropertyIdentifier */
-                       offset = fPropertyIdentifier (tvb, tree, offset);
+                       offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 1: /* propertyArrayIndex */
-                       offset = fUnsignedTag (tvb, tree, offset, "property Array Index: ");
+                       offset = fPropertyArrayIndex (tvb, tree, offset);
                        if (list != 0) break; /* Continue decoding if this may be a list */
                default:
                        lastoffset = offset; /* Set loop end condition */
                        break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fBACnetPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 list)
+fBACnetPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list)
 {
-       return fPropertyReference(tvb, tree, offset, 0, list);
+       col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+       return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
 }
 
 static guint
-fBACnetObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               
+
                switch (fTagNo(tvb,offset)) {
                case 0: /* ObjectIdentifier */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 1: /* PropertyIdentifier and propertyArrayIndex */
-                       offset = fPropertyReference (tvb, tree, offset, 1, 0);
+                       offset = fPropertyReference (tvb, pinfo, tree, offset, 1, 0);
+                       col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
                default:
                        lastoffset = offset; /* Set loop end condition */
                        break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
@@ -4136,7 +7502,7 @@ fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
        proto_tree* subtree = tree;
        proto_item* tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
                if (tag_is_closing(tag_info)) {
@@ -4146,26 +7512,19 @@ fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
                }
                switch (tag_no) {
                case 0: /* ObjectIdentifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 1: /* PropertyIdentifier */
-                       offset = fPropertyIdentifier (tvb, subtree, offset);
+                       offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 2: /* propertyArrayIndex */
                        offset = fUnsignedTag (tvb, subtree, offset, "property Array Index: ");
                        break;
                case 3:  /* Value */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType   (tvb, subtree, offset);
-                               break;
-                       }
-                       FAULT;
+                       offset = fPropertyValue (tvb, subtree, offset, tag_info);
                        break;
                case 4:  /* Priority */
-                       offset = fSignedTag (tvb, subtree, offset, "Priority: ");
+                       offset = fUnsignedTag (tvb, subtree, offset, "Priority: ");
                        break;
                default:
                        break;
@@ -4175,105 +7534,98 @@ fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
 }
 #endif
 
-#if 0
 static guint
-fDeviceObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fPriorityArray (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
+       char i = 1, ar[256];
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-               
-               switch (fTagNo(tvb,offset)) {
-               case 0: /* ObjectIdentifier */
-                       offset = fBACnetObjectPropertyReference (tvb, tree, offset);
-                       break;
-               case 3: /* deviceIdentifier */
-                       offset = fObjectIdentifier (tvb, tree, offset);
-                       break;
-               default:
-                       return offset;
-               }
-       }
-       return offset;
-}
-#endif
-
-static guint
-fPriorityArray (tvbuff_t *tvb, proto_tree *tree, guint offset)
-{
-       char i, ar[256];
-
-       if (offset >= tvb_reported_length(tvb))
-               return offset;
-       
-       for (i = 1; i <= 16; i++) {
+       if (propertyArrayIndex > 0) {
+               /* BACnetARRAY index 0 refers to the length
+               of the array, not the elements of the array.
+               BACnetARRAY index -1 is our internal flag that
+               the optional index was not used.
+               BACnetARRAY refers to this as all elements of the array.
+               If the optional index is specified for a BACnetARRAY,
+               then that specific array element is referenced. */
+               i = propertyArrayIndex;
+       }
+       while (tvb_reported_length_remaining(tvb, offset)) {
+               /* exit loop if nothing happens inside */
+               lastoffset = offset;
                g_snprintf (ar, sizeof(ar), "%s[%d]: ",
                        val_to_split_str(87 , 512,
                                BACnetPropertyIdentifier,
                                ASHRAE_Reserved_Fmt,
                                Vendor_Proprietary_Fmt),
-                       i);
-               /* DMR Replace with fAbstractNSyntax */
-               offset = fApplicationTypes(tvb, tree, offset, ar);
+                       i++);
+               /* DMR Should be fAbstractNSyntax, but that's where we came from! */
+               offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
+               /* there are only 16 priority array elements */
+               if (i > 16) {
+                       break;
+               }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
+
        return offset;
 }
 
-#if 0
 static guint
-fDeviceObjectReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fDeviceObjectReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               
+
                switch (fTagNo(tvb,offset)) {
-               case 0: /* deviceIdentifier */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+               case 0: /* deviceIdentifier - OPTIONAL */
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 1: /* ObjectIdentifier */
-                       offset = fObjectIdentifier (tvb, tree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
-#endif
 
 static guint
-fSpecialEvent (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fSpecialEvent (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
 {
        guint8 tag_no, tag_info;
        guint32 lvt;
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {   
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               /* maybe a SEQUENCE of SpecialEvents if we spot a closing tag */
+               if (tag_is_closing(tag_info)) {
+                       offset += len;
                        continue;
                }
-        
+
                switch (tag_no) {
                case 0: /* calendaryEntry */
-            if (tag_is_opening(tag_info))
-            {
+                       if (tag_is_opening(tag_info))
+                       {
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fCalendaryEntry (tvb, subtree, offset);
+                               offset = fCalendaryEntry (tvb, subtree, offset);
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-            }
+                       }
                        break;
                case 1: /* calendarReference */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 2: /* list of BACnetTimeValue */
                        if (tag_is_opening(tag_info)) {
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fTimeValue (tvb, subtree, offset);
+                               offset = fTimeValue (tvb, pinfo, subtree, offset);
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                break;
                        }
@@ -4285,64 +7637,76 @@ fSpecialEvent (tvbuff_t *tvb, proto_tree *subtree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fSelectionCriteria (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
+       guint8 tag_no, tag_info;
+       guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               /* maybe a listOfSelectionCriteria if we spot a closing tag */
+               if (tag_is_closing(tag_info)) {
+                       offset += len;
+                       continue;
+               }
+
                switch (fTagNo(tvb,offset)) {
                case 0: /* propertyIdentifier */
-                       offset = fPropertyIdentifier (tvb, tree, offset);
+                       offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 1: /* propertyArrayIndex */
-                       offset = fUnsignedTag (tvb, tree, offset, "property Array Index: ");
+                       offset = fPropertyArrayIndex (tvb, tree, offset);
                        break;
                case 2: /* relationSpecifier */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
+                       offset = fEnumeratedTag (tvb, tree, offset,
                                "relation Specifier: ", BACnetRelationSpecifier);
                        break;
                case 3: /* comparisonValue */
-                       offset = fAbstractSyntaxNType   (tvb, tree, offset);
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
+                       offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fObjectSelectionCriteria (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fObjectSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {  
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
-                       continue;
+               /* quit loop if we spot a closing tag */
+               if (tag_is_closing(tag_info)) {
+                       break;
                }
-       
+
                switch (tag_no) {
                case 0: /* selectionLogic */
-                       offset = fEnumeratedTag (tvb, subtree, offset, 
+                       offset = fEnumeratedTag (tvb, subtree, offset,
                                "selection Logic: ", BACnetSelectionLogic);
                        break;
                case 1: /* listOfSelectionCriteria */
                        if (tag_is_opening(tag_info)) {
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fSelectionCriteria (tvb, subtree, offset);
+                               offset = fSelectionCriteria (tvb, pinfo, subtree, offset);
+                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                break;
                        }
                        FAULT;
@@ -4350,107 +7714,108 @@ fObjectSelectionCriteria (tvbuff_t *tvb, proto_tree *subtree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 
 static guint
-fReadPropertyConditionalRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {   
+
+               if (tag_is_opening(tag_info) && tag_no < 2) {
                        offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                       continue;
-               }
-       
-               switch (tag_no) {
-               case 0: /* objectSelectionCriteria */
-                       offset = fObjectSelectionCriteria (tvb, subtree, offset);
-                       break;
-               case 1: /* listOfPropertyReferences */
-                       if (tag_is_opening(tag_info)) {
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fBACnetPropertyReference (tvb, subtree, offset, 1);
+                       switch (tag_no) {
+                       case 0: /* objectSelectionCriteria */
+                               offset = fObjectSelectionCriteria (tvb, pinfo, subtree, offset);
                                break;
+                       case 1: /* listOfPropertyReferences */
+                               offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
+                               break;
+                       default:
+                               return offset;
                        }
-                       FAULT;
-                       break;
-               default:
-                       return offset;
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fReadAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fReadAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
+       proto_item *tt;
+       proto_tree *subtree = tree;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {   
-                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no,
-                               &tag_info, &lvt);
-                       continue;
-               }
-       
                switch (tag_no) {
                case 0: /* objectIdentifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 1: /* listOfPropertyReferences */
                        if (tag_is_opening(tag_info)) {
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fBACnetPropertyReference (tvb, subtree, offset, 1);
-                               break;
+                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfPropertyReferences");
+                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                               offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                               offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
+                       } else if (tag_is_closing(tag_info)) {
+                               offset += fTagHeaderTree (tvb, subtree, offset,
+                                       &tag_no, &tag_info, &lvt);
+                               subtree = tree;
+                       } else {
+                               /* error condition: let caller handle */
+                               return offset;
                        }
-                       FAULT;
                        break;
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fReadAccessResult (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadAccessResult (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint lastoffset = 0, len;
        guint8 tag_no;
        guint8 tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
        proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {   
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
-                       if (tag_no == 4 || tag_no == 5) subtree = tree; /* Value and error have extra subtree */
+               len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               /* maybe a listOfReadAccessResults if we spot a closing tag here */
+               if (tag_is_closing(tag_info)) {
+                       offset += len;
+                       if ((tag_no == 4 || tag_no == 5) && (subtree != tree)) subtree = subtree->parent; /* Value and error have extra subtree */
                        continue;
                }
-       
+
                switch (tag_no) {
                case 0: /* objectSpecifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
+                       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
                        break;
                case 1: /* list of Results */
                        if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfResults");
+                               tt = proto_tree_add_text(tree, tvb, offset, 1, "listOfResults");
                                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                break;
@@ -4458,15 +7823,15 @@ fReadAccessResult (tvbuff_t *tvb, proto_tree *tree, guint offset)
                        FAULT;
                        break;
                case 2: /* propertyIdentifier */
-                       offset = fPropertyValue(tvb, subtree, offset, 2);
+                       offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
                        break;
                case 5: /* propertyAccessError */
                        if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyAccessError");
+                               tt = proto_tree_add_text(tree, tvb, offset, 1, "propertyAccessError");
                                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
                                offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                                /* Error Code follows */
-                               offset = fError(tvb, subtree, offset);
+                               offset = fError(tvb, pinfo, subtree, offset);
                                break;
                        }
                        FAULT;
@@ -4474,219 +7839,152 @@ fReadAccessResult (tvbuff_t *tvb, proto_tree *tree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 
 static guint
-fReadPropertyConditionalAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadPropertyConditionalAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        /* listOfReadAccessResults */
-       return fReadAccessResult (tvb, tree, offset);
+       return fReadAccessResult (tvb, pinfo, tree, offset);
 }
 
 
 static guint
-fObjectSpecifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
-{
-       guint lastoffset = 0;
-
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-               switch (fTagNo(tvb, offset)) {
-               case 0: /* objectType */
-                       proto_tree_add_item(tree, hf_bacapp_tag_initiatingObjectType, tvb, offset++, 1, TRUE);
-                       break;
-               case 1: /* objectIdentifier */
-                       offset = fObjectIdentifier (tvb, tree, offset);
-                       break;
-               default:
-                       return offset;
-               }
-       }
-       return offset;
-}
-
-static guint
-fCreateObjectRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
 {
        guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0) && (offset > lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {   
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
-                       continue;
-               }
-       
-               switch (tag_no) {
-               case 0: /* objectSpecifier */
-                       offset = fObjectSpecifier (tvb, subtree, offset);
-                       break;
-               case 1: /* propertyValue */
-                       if (tag_is_opening(tag_info)) {
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fBACnetPropertyValue (tvb, subtree, offset);
+
+               if (tag_no < 2)
+               {
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       switch (tag_no) {
+                       case 0: /* objectSpecifier */
+                               switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
+                               case 0: /* objectType */
+                                       offset = fEnumeratedTagSplit (tvb, subtree, offset, "Object Type: ", BACnetObjectType, 128);
+                                       break;
+                               case 1: /* objectIdentifier */
+                                       offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
+                                       break;
+                               default:
+                                       break;
+                               }
+                               break;
+                       case 1: /* propertyValue */
+                               if (tag_is_opening(tag_info)) {
+                                       offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
+                                       break;
+                               }
+                               FAULT;
+                               break;
+                       default:
                                break;
                        }
-                       FAULT;
-                       break;
-               default:
-                       return offset;
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                }
+               if (offset == lastoffset) break;    /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fCreateObjectAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fCreateObjectAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fObjectIdentifier (tvb, tree, offset);
+       return fObjectIdentifier (tvb, pinfo, tree, offset);
 }
 
 static guint
-fReadRangeRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadRangeRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
        proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
+       offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
+
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
+               /* optional range choice */
                fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {  
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
-                       subtree = tree;
-                       continue;
-               }
-       
-               switch (tag_no) {
-               case 0: /* objectSpecifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
-                       break;
-               case 1: /* propertyIdentifier */
-                       offset = fPropertyIdentifier (tvb, subtree, offset);
-                       break;
-               case 2: /* propertyArrayIndex Optional */
-                       offset = fUnsignedTag (tvb, subtree, offset, "Property Array Index: ");
-                       break;
-               case 3: /* range byPosition */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "range byPosition");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fApplicationTypes (tvb, subtree, offset, "reference Index: ");
-                               offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
+               if (tag_is_opening(tag_info)) {
+                       tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetReadRangeOptions, "unknown range option"));
+                       subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       switch (tag_no) {
+                       case 3: /* range byPosition */
+                       case 6: /* range bySequenceNumber, 2004 spec */
+                               offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Index: ");
+                               offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Count: ");
                                break;
-                       }
-                       FAULT;
-                       break;
-               case 4: /* range byTime */
-        case 7: /* 2004 spec */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "range byTime");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       case 4: /* range byTime - deprecated in 2004 */
+                       case 7: /* 2004 spec */
                                offset = fDateTime(tvb, subtree, offset, "reference Date/Time: ");
-                               offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
+                               offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Count: ");
                                break;
-                       }
-                       FAULT;
-                       break;
-               case 5: /* range timeRange */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "range timeRange");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fApplicationTypes (tvb, subtree, offset, "beginning Time: ");
-                               offset = fApplicationTypes (tvb, subtree, offset, "ending Time: ");
+                       case 5: /* range timeRange - deprecated in 2004 */
+                               offset = fDateTime(tvb, subtree, offset, "beginning Time: ");
+                               offset = fDateTime(tvb, subtree, offset, "ending Time: ");
                                break;
-                       }
-                       FAULT;
-                       break;
-        case 6: /* range bySequenceNumber, 2004 spec */
-            if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "range bySequenceNumber");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fApplicationTypes (tvb, subtree, offset, "referenceIndex: ");
-                               offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
+                       default:
                                break;
-            }
-                       FAULT;
-                       break;
-               default:
-                       return offset;
+                       }
+                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
                }
        }
        return offset;
 }
 
 static guint
-fReadRangeAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadRangeAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
        proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {
-                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                       subtree = tree;
-                       continue;
-               }
-       
-               switch (tag_no) {
-               case 0: /* objectSpecifier */
-                       offset = fObjectIdentifier (tvb, subtree, offset);
-                       break;
-               case 1: /* propertyIdentifier */
-                       offset = fPropertyIdentifier (tvb, subtree, offset);
-                       break;
-               case 2: /* propertyArrayIndex Optional */
-                       offset = fUnsignedTag (tvb, subtree, offset, "Property Array Index: ");
-                       break;
-               case 3: /* resultFlags */
-                       offset = fEnumeratedTag (tvb, tree, offset, 
-                               "result Flags: ", BACnetResultFlags);
-                       break;
-               case 4: /* itemCount */
-                       offset = fUnsignedTag (tvb, subtree, offset, "item Count: ");
-                       break;
-               case 5: /* itemData */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fAbstractSyntaxNType   (tvb, subtree, offset);
-                               break;
-                       }
-                       FAULT;
-                       break;
-               case 6: /* firstSequenceNumber */
-                       offset = fUnsignedTag (tvb, subtree, offset, "first Sequence Number: ");
-                       break;
-               default:
-                       return offset;
-               }
+       /* set the optional global properties to indicate not-used */
+       propertyArrayIndex = -1;
+       /* objectIdentifier, propertyIdentifier, and
+          OPTIONAL propertyArrayIndex */
+       offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
+       /* resultFlags => BACnetResultFlags ::= BIT STRING */
+       offset = fBitStringTagVS (tvb, tree, offset,
+               "resultFlags: ",
+               BACnetResultFlags);
+       /* itemCount */
+       offset = fUnsignedTag (tvb, subtree, offset, "item Count: ");
+       /* itemData */
+       fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+       if (tag_is_opening(tag_info)) {
+               col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+               tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
+               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+               offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
+               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
        }
+       /* firstSequenceNumber - OPTIONAL */
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
+               offset = fUnsignedTag (tvb, subtree, offset, "first Sequence Number: ");
+       }
+
        return offset;
 }
 
-static guint fAccessMethod(tvbuff_t *tvb, proto_tree *tree, guint offset)
+static guint
+fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
+       guint lastoffset = 0;
        guint32 lvt;
        guint8 tag_no, tag_info;
        proto_item* tt;
@@ -4694,104 +7992,65 @@ static guint fAccessMethod(tvbuff_t *tvb, proto_tree *tree, guint offset)
 
        fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
 
-       switch (tag_no) {
-       case 0: /* streamAccess */
-               if (tag_is_opening(tag_info)) {  
-                       tt = proto_tree_add_text(tree, tvb, offset, 1, "stream Access");
-                       subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fApplicationTypes (tvb, subtree, offset, "File Start Position: ");
-                       offset = fApplicationTypes (tvb, subtree, offset, "file Data: ");
-               }
-               if (bacapp_flags & 0x04) { /* More Flag is set */
-                       break;
-               }
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {
-                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-               }
-               break;
-       case 1: /* recordAccess */
-               if (tag_is_opening(tag_info)) {
-                       tt = proto_tree_add_text(tree, tvb, offset, 1, "record Access");
-                       subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                       offset = fApplicationTypes (tvb, subtree, offset, "File Start Record: ");
-                       offset = fApplicationTypes (tvb, subtree, offset, "Record Count: ");
-                       offset = fApplicationTypes (tvb, subtree, offset, "Data: ");
-               }
-               if (bacapp_flags & 0x04) { /* More Flag is set */
-                       break;
+       if (tag_is_opening(tag_info))
+       {
+               tt = proto_tree_add_text(tree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetFileAccessOption, "invalid access method"));
+               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+               offset = fApplicationTypes (tvb, pinfo, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "invalid option"));
+               offset = fApplicationTypes (tvb, pinfo, subtree, offset, val_to_str(tag_no, BACnetFileWriteInfo, "unknown option"));
+
+               if (tag_no == 1)
+               {
+                       while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset))
+                       {  /* exit loop if nothing happens inside */
+                               lastoffset = offset;
+                               offset = fApplicationTypes (tvb, pinfo, subtree, offset, "Record Data: ");
+                       }
                }
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) {
-                       offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+
+               if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0)
+               {
+                       /* More Flag is not set, so we can look for closing tag in this segment */
+                       fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+                       if (tag_is_closing(tag_info)) {
+                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                       }
                }
-               break;
-       default:
-               break;
        }
-       
        return offset;
 }
 
 static guint
-fAtomicReadFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
        guint8 tag_no, tag_info;
        guint32 lvt;
        proto_tree *subtree = tree;
-       proto_item *tt;
-
-       offset = fObjectIdentifier (tvb, tree, offset);
-
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-               if (tag_is_closing(tag_info)) { 
-                       offset += fTagHeaderTree (tvb, subtree, offset,
-                               &tag_no, &tag_info, &lvt);
-                       subtree = tree;
-                       continue;
-               }
-
-               switch (tag_no) {
-               case 0: /* streamAccess */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "stream Access");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fSignedTag (tvb, subtree, offset, "File Start Position: ");
-                               offset = fUnsignedTag (tvb, subtree, offset, "requested Octet Count: ");
-                               break;
-                       }
-                       FAULT;
-                       break;
-               case 1: /* recordAccess */
-                       if (tag_is_opening(tag_info)) {
-                               tt = proto_tree_add_text(subtree, tvb, offset, 1, "record Access");
-                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-                               offset = fSignedTag (tvb, subtree, offset, "File Start Record: ");
-                               offset = fUnsignedTag (tvb, subtree, offset, "requested Record Count: ");
-                               break;
-                       }
-                       FAULT;
-                       break;
-               default:
-                       return offset;
-               }
+       proto_item *tt;
+
+       offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+
+       fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+
+       if (tag_is_opening(tag_info))
+       {
+               tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetFileAccessOption, "unknown access method"));
+               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+               offset = fSignedTag (tvb, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "unknown option"));
+               offset = fUnsignedTag (tvb, subtree, offset, val_to_str(tag_no, BACnetFileRequestCount, "unknown option"));
+               offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
        }
        return offset;
 }
 
 static guint
-fAtomicWriteFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
 
-       offset = fObjectIdentifier (tvb, tree, offset); /* file Identifier */
-    offset = fAccessMethod(tvb, tree, offset);
+       offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* file Identifier */
+       offset = fAccessMethod(tvb, pinfo, tree, offset);
 
        return offset;
 }
@@ -4799,196 +8058,183 @@ fAtomicWriteFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
 static guint
 fAtomicWriteFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
-       switch (fTagNo(tvb, offset)) {
-       case 0: /* streamAccess */
-               offset = fSignedTag (tvb, tree, offset, "File Start Position: ");
-               break;
-       case 1: /* recordAccess */
-               offset = fSignedTag (tvb, tree, offset, "File Start Record: ");
-               break;
-       default:
-               return offset;
-       }
-       return offset;
+       guint tag_no = fTagNo(tvb, offset);
+       return fSignedTag (tvb, tree, offset, val_to_str(tag_no, BACnetFileStartOption, "unknown option"));
 }
 
 static guint
-fAtomicReadFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAtomicReadFileAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint8 tag_no, tag_info;
-       guint32 lvt;
-       proto_tree *subtree = tree;
-
-       fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-       offset = fApplicationTypes (tvb, subtree, offset, "End Of File: ");
-    offset = fAccessMethod(tvb, tree, offset);
+       offset = fApplicationTypes (tvb, pinfo, tree, offset, "End Of File: ");
+       offset = fAccessMethod(tvb,pinfo, tree, offset);
 
-    return offset;
+       return offset;
 }
 
 static guint
-fReadPropertyMultipleRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
 {
-       return fReadAccessSpecification (tvb,subtree,offset);
+       col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+       return fReadAccessSpecification (tvb,pinfo,subtree,offset);
 }
 
 static guint
-fReadPropertyMultipleAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadPropertyMultipleAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       return fReadAccessResult (tvb,tree,offset);
+       col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+       return fReadAccessResult (tvb,pinfo,tree,offset);
 }
 
 static guint
-fConfirmedServiceRequest (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
+fConfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
 {
-       if (tvb_length_remaining(tvb,offset) <= 0)
+       if (tvb_reported_length_remaining(tvb,offset) <= 0)
                return offset;
 
        switch (service_choice) {
        case 0: /* acknowledgeAlarm */
-               offset = fAcknowledgeAlarmRequest (tvb, tree, offset);
+               offset = fAcknowledgeAlarmRequest (tvb, pinfo, tree, offset);
                break;
        case 1: /* confirmedCOVNotification */
-               offset = fConfirmedCOVNotificationRequest (tvb, tree, offset);
+               offset = fConfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
                break;
        case 2: /* confirmedEventNotification */
-               offset = fConfirmedEventNotificationRequest (tvb, tree, offset);
+               offset = fConfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
                break;
        case 3: /* confirmedGetAlarmSummary conveys no parameters */
                break;
        case 4: /* getEnrollmentSummaryRequest */
-               offset = fGetEnrollmentSummaryRequest (tvb, tree, offset);
+               offset = fGetEnrollmentSummaryRequest (tvb, pinfo, tree, offset);
                break;
        case 5: /* subscribeCOVRequest */
-               offset = fSubscribeCOVRequest(tvb, tree, offset);
+               offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
                break;
        case 6: /* atomicReadFile-Request */
-               offset = fAtomicReadFileRequest(tvb, tree, offset);
+               offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
                break;
        case 7: /* atomicWriteFile-Request */
-               offset = fAtomicWriteFileRequest(tvb, tree, offset);
+               offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
                break;
        case 8: /* AddListElement-Request */
-               offset = fAddListElementRequest(tvb, tree, offset);
+               offset = fAddListElementRequest(tvb, pinfo, tree, offset);
                break;
        case 9: /* removeListElement-Request */
-               offset = fRemoveListElementRequest(tvb, tree, offset);
+               offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
                break;
        case 10: /* createObjectRequest */
-               offset = fCreateObjectRequest(tvb, tree, offset);
+               offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
                break;
        case 11: /* deleteObject */
-               offset = fDeleteObjectRequest(tvb, tree, offset);
+               offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
                break;
        case 12:
-               offset = fReadPropertyRequest(tvb, tree, offset);
+               offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
                break;
        case 13:
-               offset = fReadPropertyConditionalRequest(tvb, tree, offset);
+               offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
                break;
        case 14:
-               offset = fReadPropertyMultipleRequest(tvb, tree, offset);
+               offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
                break;
        case 15:
-               offset = fWritePropertyRequest(tvb, tree, offset);
+               offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
                break;
        case 16:
-               offset = fWritePropertyMultipleRequest(tvb, tree, offset);
+               offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
                break;
        case 17:
                offset = fDeviceCommunicationControlRequest(tvb, tree, offset);
                break;
        case 18:
-               offset = fConfirmedPrivateTransferRequest(tvb, tree, offset);
+               offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
                break;
        case 19:
-               offset = fConfirmedTextMessageRequest(tvb, tree, offset);
+               offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
                break;
        case 20:
                offset = fReinitializeDeviceRequest(tvb, tree, offset);
                break;
        case 21:
-               offset = fVtOpenRequest(tvb, tree, offset);
+               offset = fVtOpenRequest(tvb, pinfo, tree, offset);
                break;
        case 22:
-               offset = fVtCloseRequest (tvb, tree, offset);
+               offset = fVtCloseRequest (tvb, pinfo, tree, offset);
                break;
        case 23:
-               offset = fVtDataRequest (tvb, tree, offset);
+               offset = fVtDataRequest (tvb, pinfo, tree, offset);
                break;
        case 24:
                offset = fAuthenticateRequest (tvb, tree, offset);
                break;
        case 25:
-               offset = fRequestKeyRequest (tvb, tree, offset);
+               offset = fRequestKeyRequest (tvb, pinfo, tree, offset);
                break;
        case 26:
-               offset = fReadRangeRequest (tvb, tree, offset);
+               offset = fReadRangeRequest (tvb, pinfo, tree, offset);
                break;
        case 27:
-               offset = fLifeSafetyOperationRequest(tvb, tree, offset, NULL);
+               offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
                break;
        case 28:
-               offset = fSubscribeCOVPropertyRequest(tvb, tree, offset);
+               offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
                break;
        case 29:
-               offset = fGetEventInformationRequest (tvb, tree, offset);
+               offset = fGetEventInformationRequest (tvb, pinfo, tree, offset);
                break;
        default:
                return offset;
-               break;
        }
        return offset;
 }
 
 static guint
-fConfirmedServiceAck (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
+fConfirmedServiceAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
 {
-       if (tvb_length_remaining(tvb,offset) <= 0)
+       if (tvb_reported_length_remaining(tvb,offset) <= 0)
                return offset;
 
        switch (service_choice) {
        case 3: /* confirmedEventNotificationAck */
-               offset = fGetAlarmSummaryAck (tvb, tree, offset);
+               offset = fGetAlarmSummaryAck (tvb, pinfo, tree, offset);
                break;
        case 4: /* getEnrollmentSummaryAck */
-               offset = fGetEnrollmentSummaryAck (tvb, tree, offset);
+               offset = fGetEnrollmentSummaryAck (tvb, pinfo, tree, offset);
                break;
        case 6: /* atomicReadFile */
-               offset = fAtomicReadFileAck (tvb, tree, offset);
+               offset = fAtomicReadFileAck (tvb, pinfo, tree, offset);
                break;
        case 7: /* atomicReadFileAck */
                offset = fAtomicWriteFileAck (tvb, tree, offset);
                break;
        case 10: /* createObject */
-               offset = fCreateObjectAck (tvb, tree, offset);
+               offset = fCreateObjectAck (tvb, pinfo, tree, offset);
                break;
        case 12:
-               offset = fReadPropertyAck (tvb, tree, offset);
+               offset = fReadPropertyAck (tvb, pinfo, tree, offset);
                break;
        case 13:
-               offset = fReadPropertyConditionalAck (tvb, tree, offset);
+               offset = fReadPropertyConditionalAck (tvb, pinfo, tree, offset);
                break;
        case 14:
-               offset = fReadPropertyMultipleAck (tvb, tree, offset);
+               offset = fReadPropertyMultipleAck (tvb, pinfo, tree, offset);
                break;
        case 18:
-               offset = fConfirmedPrivateTransferAck(tvb, tree, offset);
+               offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
                break;
        case 21:
-               offset = fVtOpenAck (tvb, tree, offset);
+               offset = fVtOpenAck (tvb, pinfo, tree, offset);
                break;
        case 23:
                offset = fVtDataAck (tvb, tree, offset);
                break;
        case 24:
-               offset = fAuthenticateAck (tvb, tree, offset);
+               offset = fAuthenticateAck (tvb, pinfo, tree, offset);
                break;
        case 26:
-               offset = fReadRangeAck (tvb, tree, offset);
+               offset = fReadRangeAck (tvb, pinfo, tree, offset);
                break;
        case 29:
-               offset = fGetEventInformationACK (tvb, tree, offset);
+               offset = fGetEventInformationACK (tvb, pinfo, tree, offset);
                break;
        default:
                return offset;
@@ -4997,33 +8243,33 @@ fConfirmedServiceAck (tvbuff_t *tvb, proto_tree *tree, guint offset, gint servic
 }
 
 static guint
-fIAmRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fIAmRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        /* BACnetObjectIdentifier */
-       offset = fApplicationTypes (tvb, tree, offset, "BACnet Object Identifier: ");
+       offset = fApplicationTypes (tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
 
        /* MaxAPDULengthAccepted */
-       offset = fApplicationTypes (tvb, tree, offset, "Maximum ADPU Length Accepted: ");
+       offset = fApplicationTypes (tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
 
        /* segmentationSupported */
-       offset = fApplicationTypesEnumerated (tvb, tree, offset, 
+       offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
                "Segmentation Supported: ", BACnetSegmentation);
 
        /* vendor ID */
-       return fUnsignedTag (tvb, tree, offset, "Vendor ID: ");
+       return fVendorIdentifier (tvb, pinfo, tree, offset);
 }
 
 static guint
-fIHaveRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fIHaveRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        /* BACnetDeviceIdentifier */
-       offset = fApplicationTypes (tvb, tree, offset, "Device Identifier: ");
+       offset = fApplicationTypes (tvb, pinfo, tree, offset, "Device Identifier: ");
 
        /* BACnetObjectIdentifier */
-       offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
+       offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
 
        /* ObjectName */
-       return fApplicationTypes (tvb, tree, offset, "Object Name: ");
+       return fApplicationTypes (tvb, pinfo, tree, offset, "Object Name: ");
 
 }
 
@@ -5032,7 +8278,7 @@ fWhoIsRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
                case 0: /* DeviceInstanceRangeLowLimit Optional */
@@ -5043,42 +8289,42 @@ fWhoIsRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
                        break;
                default:
                        return offset;
-                       break;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fUnconfirmedServiceRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
+fUnconfirmedServiceRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
 {
-       if (tvb_length_remaining(tvb,offset) <= 0)
+       if (tvb_reported_length_remaining(tvb,offset) <= 0)
                return offset;
-       
+
        switch (service_choice) {
        case 0: /* I-Am-Request */
-               offset = fIAmRequest  (tvb, tree, offset);
+               offset = fIAmRequest  (tvb, pinfo, tree, offset);
                break;
        case 1: /* i-Have Request */
-               offset = fIHaveRequest  (tvb, tree, offset);
+               offset = fIHaveRequest  (tvb, pinfo, tree, offset);
        break;
        case 2: /* unconfirmedCOVNotification */
-               offset = fUnconfirmedCOVNotificationRequest (tvb, tree, offset);
+               offset = fUnconfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
                break;
        case 3: /* unconfirmedEventNotification */
-               offset = fUnconfirmedEventNotificationRequest (tvb, tree, offset);
+               offset = fUnconfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
                break;
        case 4: /* unconfirmedPrivateTransfer */
-               offset = fUnconfirmedPrivateTransferRequest(tvb, tree, offset);
+               offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
                break;
        case 5: /* unconfirmedTextMessage */
-               offset = fUnconfirmedTextMessageRequest(tvb, tree, offset);
+               offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
                break;
        case 6: /* timeSynchronization */
                offset = fTimeSynchronizationRequest  (tvb, tree, offset);
                break;
        case 7: /* who-Has */
-               offset = fWhoHas (tvb, tree, offset);
+               offset = fWhoHas (tvb, pinfo, tree, offset);
                break;
        case 8: /* who-Is */
                offset = fWhoIsRequest  (tvb, tree, offset);
@@ -5093,7 +8339,7 @@ fUnconfirmedServiceRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset, gint
 }
 
 static guint
-fStartConfirmed(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset, guint8 ack,
+fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset, guint8 ack,
                                gint *svc, proto_item **tt)
 {
        proto_item *tc;
@@ -5113,12 +8359,12 @@ fStartConfirmed(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset, guint8 ack
        if (bacapp_flags & 0x08)
                *svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
 
-    proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
        tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, TRUE);
        bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
 
-    proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, TRUE);
-    proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, TRUE);
+       proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, TRUE);
+       proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, TRUE);
        if (ack == 0) /* The following are for ConfirmedRequest, not Complex ack */
        {
            proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, TRUE);
@@ -5127,58 +8373,57 @@ fStartConfirmed(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset, guint8 ack
                proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
                                                        offset, 1, TRUE);
        }
-    offset++;
-    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
-    if (bacapp_flags & 0x08) {
-        bacapp_seq = tvb_get_guint8(tvb, offset);
-        proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
-            offset++, 1, TRUE);
-        proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
-            offset++, 1, TRUE);
-    }
-    *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
-        offset++, 1, TRUE);
+       offset++;
+       proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
+       if (bacapp_flags & 0x08) {
+               bacapp_seq = tvb_get_guint8(tvb, offset);
+               proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
+                   offset++, 1, TRUE);
+               proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
+                   offset++, 1, TRUE);
+       }
+       *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
+                                 offset++, 1, TRUE);
        return offset;
 }
 
 static guint
-fConfirmedRequestPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
+{      /* BACnet-Confirmed-Request */
+       /* ASHRAE 135-2001 20.1.2 */
+
+       return fConfirmedServiceRequest (tvb, pinfo, bacapp_tree, offset, svc);
+}
+
+static guint
+fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
 {      /* BACnet-Confirmed-Request */
        /* ASHRAE 135-2001 20.1.2 */
        gint svc;
        proto_item *tt = 0;
 
-       offset = fStartConfirmed(tvb, bacapp_tree, offset, 0, &svc, &tt);
-       if (bacapp_seq > 0) /* Can't handle continuation segments, so just treat as data */
-       {
-               proto_tree_add_text(bacapp_tree, tvb, offset, 0, "(continuation)");
-               return offset;
-       }
-       else
-       {
-               /* Service Request follows... Variable Encoding 20.2ff */
-               return fConfirmedServiceRequest (tvb, bacapp_tree, offset, svc);
-       }
+       offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
+       return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
 }
 
 static guint
-fUnconfirmedRequestPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
 {      /* BACnet-Unconfirmed-Request-PDU */
        /* ASHRAE 135-2001 20.1.3 */
 
        gint tmp;
 
-    proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
 
-    tmp = tvb_get_guint8(tvb, offset);
-    proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
-            offset++, 1, TRUE);
-    /* Service Request follows... Variable Encoding 20.2ff */
-    return fUnconfirmedServiceRequest  (tvb, bacapp_tree, offset, tmp);
+       tmp = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
+           offset++, 1, TRUE);
+       /* Service Request follows... Variable Encoding 20.2ff */
+       return fUnconfirmedServiceRequest  (tvb, pinfo, bacapp_tree, offset, tmp);
 }
 
 static guint
-fSimpleAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
 {      /* BACnet-Simple-Ack-PDU */
        /* ASHRAE 135-2001 20.1.4 */
 
@@ -5186,125 +8431,125 @@ fSimpleAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
 
        tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
 
-    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
-        offset++, 1, TRUE);
-    proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
-        offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+                           offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
+                           offset++, 1, TRUE);
+
        return offset;
 }
 
 static guint
-fComplexAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
+{      /* BACnet-Complex-Ack-PDU */
+       /* ASHRAE 135-2001 20.1.5 */
+
+       /* Service ACK follows... */
+       return fConfirmedServiceAck (tvb, pinfo, bacapp_tree, offset, svc);
+}
+
+static guint
+fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
 {      /* BACnet-Complex-Ack-PDU */
        /* ASHRAE 135-2001 20.1.5 */
        gint svc;
        proto_item *tt = 0;
 
-       offset = fStartConfirmed(tvb, bacapp_tree, offset, 1, &svc, &tt);
-
-       if (bacapp_seq > 0) /* Can't handle continuation segments, so just treat as data */
-       {
-               proto_tree_add_text(bacapp_tree, tvb, offset, 0, "(continuation)");
-               return offset;
-       }
-       else
-       {
-           /* Service ACK follows... */
-               return fConfirmedServiceAck (tvb, bacapp_tree, offset, svc);
-       }
+       offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
+       return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
 }
 
-
 static guint
-fSegmentAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
 {      /* BACnet-SegmentAck-PDU */
        /* ASHRAE 135-2001 20.1.6 */
 
        proto_item *tc;
        proto_tree *bacapp_tree_control;
 
-    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
-    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
-
-    proto_tree_add_item(bacapp_tree, hf_bacapp_NAK, tvb, offset, 1, TRUE);
-    proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
-    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
-        offset++, 1, TRUE);
-    proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
-            offset++, 1, TRUE);
-    proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
-            offset++, 1, TRUE);
+       tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
+       bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
+
+       proto_tree_add_item(bacapp_tree, hf_bacapp_NAK, tvb, offset, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+                           offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
+                           offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
+                           offset++, 1, TRUE);
        return offset;
 }
 
-static guint fContextTaggedError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+static guint
+fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-    guint8 tag_info = 0;
-    guint8 parsed_tag = 0;
-    guint32 lvt = 0;
-    offset += fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
-    offset = fError(tvb, tree, offset);
-    return offset + fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
+       guint8 tag_info = 0;
+       guint8 parsed_tag = 0;
+       guint32 lvt = 0;
+       offset += fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
+       offset = fError(tvb, pinfo, tree, offset);
+       return offset + fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
 }
 
 static guint
-fConfirmedPrivateTransferError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
+       guint8 tag_no = 0, tag_info = 0;
+       guint32 lvt = 0;
+       proto_tree *subtree = tree;
+       proto_item *tt;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {
+               /* exit loop if nothing happens inside */
                lastoffset = offset;
-               switch (fTagNo(tvb, offset)) {
+               fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+               switch (tag_no) {
                case 0: /* errorType */
-                       offset = fContextTaggedError(tvb,tree,offset);
+                       offset = fContextTaggedError(tvb, pinfo, subtree, offset);
                        break;
                case 1: /* vendorID */
-                       offset = fUnsignedTag (tvb,tree,offset,"vendor ID: ");
+                       offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
                        break;
                case 2: /* serviceNumber */
-                       offset = fUnsignedTag (tvb,tree,offset,"service Number: ");
-                       break;
-        case 3: /* errorParameters */
-            offset = fAbstractSyntaxNType   (tvb, tree, offset);
-            break;
-               default:
-                       return offset;
-               }
-       }
-       return offset;
-}
-
-static guint
-fCreateObjectError(tvbuff_t *tvb, proto_tree *tree, guint offset)
-{
-       guint lastoffset = 0;
-
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-               switch (fTagNo(tvb, offset)) {
-               case 0: /* errorType */
-                       offset = fContextTaggedError(tvb,tree,offset);
+                       offset = fUnsignedTag (tvb, subtree, offset, "service Number: ");
                        break;
-               case 1: /* firstFailedElementNumber */
-                       offset = fUnsignedTag (tvb,tree,offset,"first failed element number: ");
+               case 3: /* errorParameters */
+                       if (tag_is_opening(tag_info)) {
+                               tt = proto_tree_add_text(subtree, tvb, offset, 1,
+                                       "error Parameters");
+                               subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                               propertyIdentifier = -1;
+                               offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+                               offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
+                       } else if (tag_is_closing(tag_info)) {
+                               offset += fTagHeaderTree (tvb, subtree, offset,
+                                       &tag_no, &tag_info, &lvt);
+                               subtree = tree;
+                       } else {
+                               /* error condition: let caller handle */
+                               return offset;
+                       }
                        break;
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fChangeListError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
                case 0: /* errorType */
-                       offset = fContextTaggedError(tvb,tree,offset);
+                       offset = fContextTaggedError(tvb, pinfo, tree, offset);
                        break;
                case 1: /* firstFailedElementNumber */
                        offset = fUnsignedTag (tvb,tree,offset,"first failed element number: ");
@@ -5312,312 +8557,466 @@ fChangeListError(tvbuff_t *tvb, proto_tree *tree, guint offset)
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
-#if 0
 static guint
-fVTSession(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       if (tvb_length_remaining(tvb, offset) > 0) {    /* don't loop */
-               offset = fUnsignedTag (tvb,tree,offset, "local-VTSessionID: ");
-               offset = fUnsignedTag (tvb,tree,offset, "remote-VTSessionID: ");
-               offset = fAddress (tvb,tree,offset);
-       }
-       return offset;
+       /* Identical to CreateObjectError */
+       return fCreateObjectError(tvb, pinfo, tree, offset);
 }
-#endif
 
 static guint
-fVTCloseError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-       guint lastoffset = 0;
+       guint8 tag_no = 0, tag_info = 0;
+       guint32 lvt = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
-               lastoffset = offset;
-               switch (fTagNo(tvb, offset)) {
-               case 0: /* errorType */
-                       offset = fContextTaggedError(tvb,tree,offset);
-                       break;
-               case 1: /* listOfVTSessionIdentifiers */
-                       offset = fUnsignedTag (tvb,tree,offset,"VT SessionID: ");
-                       break;
-               default:
-                       return offset;
+       if (fTagNo(tvb, offset) == 0)
+       {
+               /* errorType */
+               offset = fContextTaggedError(tvb, pinfo, tree,offset);
+               if (fTagNo(tvb, offset) == 1)
+               {
+                       /* listOfVTSessionIdentifiers [OPTIONAL] */
+                       offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fVtCloseRequest (tvb, pinfo, tree, offset);
+                       offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
                }
        }
+       /* should report bad packet if initial tag wasn't 0 */
        return offset;
 }
 
 static guint
-fWritePropertyMultipleError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
        guint lastoffset = 0;
+       guint8 tag_no = 0, tag_info = 0;
+       guint32 lvt = 0;
 
-       while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
+       col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+       while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
                lastoffset = offset;
                switch (fTagNo(tvb, offset)) {
                case 0: /* errorType */
-                       offset = fContextTaggedError(tvb,tree,offset);
+                       offset = fContextTaggedError(tvb, pinfo, tree, offset);
                        break;
                case 1: /* firstFailedWriteAttempt */
-                       offset = fUnsignedTag (tvb,tree,offset,"first failed write attempt: ");
+                       offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+                       offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
+                       offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
                        break;
                default:
                        return offset;
                }
+               if (offset == lastoffset) break;     /* nothing happened, exit loop */
        }
        return offset;
 }
 
 static guint
-fError (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fError (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 {
-    offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, 
-        "error Class: ", BACnetErrorClass, 64);
-    return fApplicationTypesEnumeratedSplit (tvb, tree, offset, 
-        "error Code: ", BACnetErrorCode, 256);
+       offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
+                                                  "error Class: ", BACnetErrorClass, 64);
+       return fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
+                                                "error Code: ", BACnetErrorCode, 256);
 }
 
 static guint
-fBACnetError (tvbuff_t *tvb, proto_tree *tree, guint offset, guint service)
+fBACnetError (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service)
 {
-    switch (service) {
-    case 8:  /* no break here !!!! */
-    case 9:
-        offset = fChangeListError (tvb, tree, offset);
-        break;
-    case 10:
-        offset = fCreateObjectError (tvb,tree,offset);
-        break;
-    case 16:
-        offset = fWritePropertyMultipleError (tvb,tree,offset);
-        break;
-    case 18:
-        offset = fConfirmedPrivateTransferError (tvb,tree,offset);
-    case 22:
-        offset = fVTCloseError (tvb,tree,offset);
-    default:
-        return fError (tvb, tree, offset);
-        break;
-    }
-    return offset;
+       switch (service) {
+       case 8:  /* no break here !!!! */
+       case 9:
+               offset = fChangeListError (tvb, pinfo, tree, offset);
+               break;
+       case 10:
+               offset = fCreateObjectError (tvb, pinfo, tree, offset);
+               break;
+       case 16:
+               offset = fWritePropertyMultipleError (tvb, pinfo, tree, offset);
+               break;
+       case 18:
+               offset = fConfirmedPrivateTransferError (tvb,pinfo,tree,offset);
+               break;
+       case 22:
+               offset = fVTCloseError (tvb, pinfo, tree, offset);
+               break;
+       default:
+               return fError (tvb, pinfo, tree, offset);
+       }
+       return offset;
 }
 
 static guint
-fErrorPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
 {      /* BACnet-Error-PDU */
        /* ASHRAE 135-2001 20.1.7 */
 
        proto_item *tc, *tt;
        proto_tree *bacapp_tree_control;
-    guint8 tmp;
+       guint8 tmp;
 
-    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
-    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
+       tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
+       bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
 
-    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
-        offset++, 1, TRUE);
-    tmp = tvb_get_guint8(tvb, offset);
-    tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
-        offset++, 1, TRUE);
-    /* Error Handling follows... */
-    return fBACnetError (tvb, bacapp_tree, offset, tmp);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+                           offset++, 1, TRUE);
+       tmp = tvb_get_guint8(tvb, offset);
+       tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
+                                offset++, 1, TRUE);
+       /* Error Handling follows... */
+       return fBACnetError (tvb, pinfo, bacapp_tree, offset, tmp);
 }
 
 static guint
-fRejectPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
 {      /* BACnet-Reject-PDU */
        /* ASHRAE 135-2001 20.1.8 */
 
        proto_item *tc;
        proto_tree *bacapp_tree_control;
 
-    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
-    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
+       tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
+                                bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
 
-    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
-        offset++, 1, TRUE);
-    proto_tree_add_item(bacapp_tree, hf_BACnetRejectReason, tvb,
-        offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+                           offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_BACnetRejectReason, tvb,
+                           offset++, 1, TRUE);
        return offset;
 }
 
 static guint
-fAbortPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
 {      /* BACnet-Abort-PDU */
        /* ASHRAE 135-2001 20.1.9 */
 
        proto_item *tc;
        proto_tree *bacapp_tree_control;
 
-    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
-    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
+       tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
+       bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
 
-    proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
-    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
-        offset++, 1, TRUE);
-    proto_tree_add_item(bacapp_tree, hf_BACnetAbortReason, tvb,
-        offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+                           offset++, 1, TRUE);
+       proto_tree_add_item(bacapp_tree, hf_BACnetAbortReason, tvb,
+                           offset++, 1, TRUE);
        return offset;
 }
 
-void
+static guint
+do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       guint8 flag, bacapp_type;
+       guint offset = 0;
+
+       flag = (gint) tvb_get_guint8(tvb, 0);
+       bacapp_type = (flag >> 4) & 0x0f;
+
+       if (tvb == NULL || tree == NULL) {
+               return 0;
+       }
+
+       /* ASHRAE 135-2001 20.1.1 */
+       switch (bacapp_type) {
+       case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:     /* BACnet-Confirmed-Service-Request */
+               offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
+               break;
+       case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:   /* BACnet-Unconfirmed-Request-PDU */
+               offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
+               break;
+       case BACAPP_TYPE_SIMPLE_ACK:    /* BACnet-Simple-Ack-PDU */
+               offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
+               break;
+       case BACAPP_TYPE_COMPLEX_ACK:   /* BACnet-Complex-Ack-PDU */
+               offset = fComplexAckPDU(tvb, pinfo, tree, offset);
+               break;
+       case BACAPP_TYPE_SEGMENT_ACK:   /* BACnet-SegmentAck-PDU */
+               offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
+               break;
+       case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
+               offset = fErrorPDU(tvb, pinfo, tree, offset);
+               break;
+       case BACAPP_TYPE_REJECT:        /* BACnet-Reject-PDU */
+               offset = fRejectPDU(tvb, pinfo, tree, offset);
+               break;
+       case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
+               offset = fAbortPDU(tvb, pinfo, tree, offset);
+               break;
+       }
+       return offset;
+}
+
+static void
 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       gint8 tmp, bacapp_type;
-       tvbuff_t *next_tvb;
+       guint8 flag, bacapp_type;
+       guint save_fragmented = FALSE, data_offset = 0, bacapp_apdu_size = fGetMaxAPDUSize(0), fragment = FALSE;
+       tvbuff_t* new_tvb = NULL;
        guint offset = 0;
-       guint8 bacapp_service, bacapp_reason;
-       guint8 bacapp_invoke_id;
+       guint8 bacapp_seqno = 0;
+       guint8 bacapp_service, bacapp_reason, bacapp_prop_win_size;
+       guint8 bacapp_invoke_id = 0;
        proto_item *ti;
-       proto_tree *bacapp_tree;
-
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
-       if (check_col(pinfo->cinfo, COL_INFO))
-               col_add_str(pinfo->cinfo, COL_INFO, "BACnet APDU ");
-       
-       tmp = (gint) tvb_get_guint8(tvb, 0);
-       bacapp_type = (tmp >> 4) & 0x0f;
+       proto_tree *bacapp_tree = NULL;
+
+       gint svc;
+       proto_item *tt = 0;
+       gint8 ack = 0;
+
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
+       col_clear (pinfo->cinfo, COL_INFO);
+
+       flag = tvb_get_guint8(tvb, 0);
+       bacapp_type = (flag >> 4) & 0x0f;
 
        /* show some descriptive text in the INFO column */
-       if (check_col(pinfo->cinfo, COL_INFO))
+       col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
+               val_to_str(bacapp_type, BACnetTypeName, "# unknown APDU #"));
+
+       switch (bacapp_type)
        {
-               col_clear(pinfo->cinfo, COL_INFO);
-               col_add_str(pinfo->cinfo, COL_INFO,
-                       val_to_str(bacapp_type, BACnetTypeName, "#### unknown APDU ##### "));
-               switch (bacapp_type)
-               {
-                       case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
-                               /* segmented messages have 2 additional bytes */
-                               if (tmp & BACAPP_SEGMENTED_REQUEST)
-                               {
-                                       bacapp_invoke_id = tvb_get_guint8(tvb, offset + 4);
-                                       bacapp_service = tvb_get_guint8(tvb, offset + 5);
-                               }
-                               else
-                               {
-                                       bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
-                                       bacapp_service = tvb_get_guint8(tvb, offset + 3);
-                               }
-                               col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
-                                       bacapp_invoke_id,
-                                       val_to_str(bacapp_service, 
-                                               BACnetConfirmedServiceChoice,
-                                               bacapp_unknown_service_str));
-                               break;
-                       case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
-                               bacapp_service = tvb_get_guint8(tvb, offset + 1);
-                               col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
-                                       val_to_str(bacapp_service, 
-                                               BACnetUnconfirmedServiceChoice,
-                                               bacapp_unknown_service_str));
-                               break;
-                       case BACAPP_TYPE_SIMPLE_ACK:
+               case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
+                       /* segmented messages have 2 additional bytes */
+                       if (flag & BACAPP_SEGMENTED_REQUEST)
+                       {
+                               fragment = TRUE;
+                               ack = 0;
+                               bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_guint8(tvb, offset + 1)); /* has 16 values, reserved are 50 Bytes */
+                               bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
+                               bacapp_seqno = tvb_get_guint8(tvb, offset + 3);
+                               bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 4);
+                               bacapp_service = tvb_get_guint8(tvb, offset + 5);
+                               data_offset = 6;
+
+                       }
+                       else
+                       {
+                               bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
+                               bacapp_service = tvb_get_guint8(tvb, offset + 3);
+                       }
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
+                               val_to_str(bacapp_service,
+                                       BACnetConfirmedServiceChoice,
+                                       bacapp_unknown_service_str),bacapp_invoke_id);
+                       break;
+               case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
+                       bacapp_service = tvb_get_guint8(tvb, offset + 1);
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+                               val_to_str(bacapp_service,
+                                       BACnetUnconfirmedServiceChoice,
+                                       bacapp_unknown_service_str));
+                       break;
+               case BACAPP_TYPE_SIMPLE_ACK:
+                       bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
+                       bacapp_service = tvb_get_guint8(tvb, offset + 2);
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+                               val_to_str(bacapp_service,
+                                       BACnetConfirmedServiceChoice,
+                                       bacapp_unknown_service_str), bacapp_invoke_id);
+                       break;
+               case BACAPP_TYPE_COMPLEX_ACK:
+                       /* segmented messages have 2 additional bytes */
+                       if (flag & BACAPP_SEGMENTED_REQUEST)
+                       {
+                               fragment = TRUE;
+                               ack = 1;
+                               bacapp_apdu_size = fGetMaxAPDUSize(0); /* has minimum of 50 Bytes */
                                bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
-                               bacapp_service = tvb_get_guint8(tvb, offset + 2);
-                               col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
-                                       bacapp_invoke_id,
-                                       val_to_str(bacapp_service, 
-                                               BACnetConfirmedServiceChoice,
-                                               bacapp_unknown_service_str));
-                               break;
-                       case BACAPP_TYPE_COMPLEX_ACK:
-                               /* segmented messages have 2 additional bytes */
-                               if (tmp & BACAPP_SEGMENTED_REQUEST)
-                               {
-                                       bacapp_invoke_id = tvb_get_guint8(tvb, offset + 3);
-                                       bacapp_service = tvb_get_guint8(tvb, offset + 4);
-                               }
-                               else
-                               {
-                                       bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
-                                       bacapp_service = tvb_get_guint8(tvb, offset + 2);
-                               }
-                               col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
-                                       bacapp_invoke_id,
-                                       val_to_str(bacapp_service, 
-                                               BACnetConfirmedServiceChoice,
-                                               bacapp_unknown_service_str));
-                               break;
-                       case BACAPP_TYPE_SEGMENT_ACK:
-                               /* nothing more to add */
-                               break;
-                       case BACAPP_TYPE_ERROR:
+                               bacapp_seqno = tvb_get_guint8(tvb, offset + 2);
+                               bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 3);
+                               bacapp_service = tvb_get_guint8(tvb, offset + 4);
+                               data_offset = 5;
+                       }
+                       else
+                       {
                                bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
                                bacapp_service = tvb_get_guint8(tvb, offset + 2);
-                               col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
-                                       bacapp_invoke_id,
-                                       val_to_str(bacapp_service, 
-                                               BACnetConfirmedServiceChoice,
-                                               bacapp_unknown_service_str));
-                               break;
-                       case BACAPP_TYPE_REJECT:
-                               bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
-                               bacapp_reason = tvb_get_guint8(tvb, offset + 2);
-                               col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s", 
-                                       bacapp_invoke_id,
-                                       val_to_split_str(bacapp_reason,
-                                               64,
-                                               BACnetRejectReason,
-                                               ASHRAE_Reserved_Fmt,
-                                               Vendor_Proprietary_Fmt));
+                       }
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+                               val_to_str(bacapp_service,
+                                       BACnetConfirmedServiceChoice,
+                                       bacapp_unknown_service_str), bacapp_invoke_id);
+                       break;
+               case BACAPP_TYPE_SEGMENT_ACK:
+                       /* nothing more to add */
+                       break;
+               case BACAPP_TYPE_ERROR:
+                       bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
+                       bacapp_service = tvb_get_guint8(tvb, offset + 2);
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+                               val_to_str(bacapp_service,
+                                       BACnetConfirmedServiceChoice,
+                                       bacapp_unknown_service_str), bacapp_invoke_id);
+                       break;
+               case BACAPP_TYPE_REJECT:
+                       bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
+                       bacapp_reason = tvb_get_guint8(tvb, offset + 2);
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+                               val_to_split_str(bacapp_reason,
+                                       64,
+                                       BACnetRejectReason,
+                                       ASHRAE_Reserved_Fmt,
+                                       Vendor_Proprietary_Fmt), bacapp_invoke_id);
+                       break;
+               case BACAPP_TYPE_ABORT:
+                       bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
+                       bacapp_reason = tvb_get_guint8(tvb, offset + 2);
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+                               val_to_split_str(bacapp_reason,
+                                       64,
+                                       BACnetAbortReason,
+                                       ASHRAE_Reserved_Fmt,
+                                       Vendor_Proprietary_Fmt), bacapp_invoke_id);
+                       break;
+               /* UNKNOWN */
+               default:
+                       /* nothing more to add */
+                       break;
+       }
+
+       save_fragmented = pinfo->fragmented;
+
+       if (tree) {
+
+               ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE);
+               bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
+
+               if (!fragment)
+                       offset = do_the_dissection(tvb,pinfo,bacapp_tree);
+               else
+                       fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
+                       /* not resetting the offset so the remaining can be done */
+       }
+
+       if (fragment) { /* fragmented */
+               fragment_data *frag_msg = NULL;
+
+               new_tvb = NULL;
+               pinfo->fragmented = TRUE;
+
+               frag_msg = fragment_add_seq_check(tvb, data_offset, pinfo,
+                       bacapp_invoke_id, /* ID for fragments belonging together */
+                       msg_fragment_table, /* list of message fragments */
+                       msg_reassembled_table, /* list of reassembled messages */
+                       bacapp_seqno, /* fragment sequence number */
+                       tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
+                       flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
+               new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
+                               "Reassembled BACapp", frag_msg, &msg_frag_items,
+                               NULL, tree);
+
+               if (new_tvb) { /* Reassembled */
+                       col_append_str(pinfo->cinfo, COL_INFO,
+                               " (Message Reassembled)");
+               } else { /* Not last packet of reassembled Short Message */
+                       col_append_fstr(pinfo->cinfo, COL_INFO,
+                       " (Message fragment %u)", bacapp_seqno);
+               }
+               if (new_tvb) { /* take it all */
+                       switch (bacapp_type)
+                       {
+                               case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
+                                       fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
                                break;
-                       case BACAPP_TYPE_ABORT:
-                               bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
-                               bacapp_reason = tvb_get_guint8(tvb, offset + 2);
-                               col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
-                                       bacapp_invoke_id,
-                                       val_to_split_str(bacapp_reason,
-                                               64,
-                                               BACnetAbortReason,
-                                               ASHRAE_Reserved_Fmt,
-                                               Vendor_Proprietary_Fmt));
+                               case BACAPP_TYPE_COMPLEX_ACK:
+                                       fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
                                break;
-                       /* UNKNOWN */
-                       default:
-                               /* nothing more to add */
+                               default:
+                                       /* do nothing */
                                break;
+                       }
+                       /* } */
                }
        }
-   
-    if (tree) {
-               ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE);
-               bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
 
-               /* ASHRAE 135-2001 20.1.1 */
-       switch (bacapp_type) {
-       case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:     /* BACnet-Confirmed-Service-Request */
-               offset = fConfirmedRequestPDU(tvb, bacapp_tree, offset);
-               break;
-       case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:   /* BACnet-Unconfirmed-Request-PDU */
-               offset = fUnconfirmedRequestPDU(tvb, bacapp_tree, offset);
-               break;
-       case BACAPP_TYPE_SIMPLE_ACK:    /* BACnet-Simple-Ack-PDU */
-               offset = fSimpleAckPDU(tvb, bacapp_tree, offset);
-               break;
-       case BACAPP_TYPE_COMPLEX_ACK:   /* BACnet-Complex-Ack-PDU */
-               offset = fComplexAckPDU(tvb, bacapp_tree, offset);
-               break;
-       case BACAPP_TYPE_SEGMENT_ACK:   /* BACnet-SegmentAck-PDU */
-               offset = fSegmentAckPDU(tvb, bacapp_tree, offset);
-               break;
-       case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
-               offset = fErrorPDU(tvb, bacapp_tree, offset);
-               break;
-       case BACAPP_TYPE_REJECT:        /* BACnet-Reject-PDU */
-               offset = fRejectPDU(tvb, bacapp_tree, offset);
-               break;
-       case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
-               offset = fAbortPDU(tvb, bacapp_tree, offset);
-               break;
-       }
-    }
-
-       next_tvb = tvb_new_subset(tvb,offset,-1,tvb_length_remaining(tvb,offset));
-       call_dissector(data_handle,next_tvb, pinfo, tree);
+       pinfo->fragmented = save_fragmented;
+
+}
+
+static void
+bacapp_init_routine(void)
+{
+       fragment_table_init(&msg_fragment_table);
+       reassembled_table_init(&msg_reassembled_table);
+}
+
+static guint32
+fConvertXXXtoUTF8 (gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding)
+{
+       guint32 i;
+       GIConv icd;
+
+       if ((icd = g_iconv_open ("UTF-8", fromcoding)) != (GIConv) -1) {
+               i = (guint32) g_iconv (icd, &in, inbytesleft, &out, outbytesleft);
+               /* g_iconv incremented 'out'; now ensure it's NULL terminated */
+               out[0] = '\0';
+
+               g_iconv_close (icd);
+               return i;
+       }
+
+       uni_to_string(in,*inbytesleft,out);
+       out[*inbytesleft] = '\0';
+       *outbytesleft -= *inbytesleft;
+       *inbytesleft = 0;
+
+       return 0;
+}
+
+static void
+uni_to_string(char * data, gsize str_length, char *dest_buf)
+{
+       gint i;
+       guint16 c_char;
+       gsize length_remaining = 0;
+
+       length_remaining = str_length;
+       dest_buf[0] = '\0';
+       if(str_length == 0)
+       {
+               return;
+       }
+       for ( i = 0; i < (gint) str_length; i++ )
+       {
+               c_char = data[i];
+               if (c_char<0x20 || c_char>0x7e)
+               {
+                       if (c_char != 0x00)
+                       {
+                               c_char = '.';
+                               dest_buf[i] = c_char & 0xff;
+                       }
+                       else
+                       {
+                               i--;
+                               str_length--;
+                       }
+               }
+               else
+               {
+                       dest_buf[i] = c_char & 0xff;
+               }
+               length_remaining--;
+
+               if(length_remaining==0)
+               {
+                       dest_buf[i+1] = '\0';
+                       return;
+               }
+       }
+       if (i < 0) {
+               i = 0;
+       }
+       dest_buf[i] = '\0';
+       return;
 }
 
 void
@@ -5626,15 +9025,15 @@ proto_register_bacapp(void)
        static hf_register_info hf[] = {
                { &hf_bacapp_type,
                        { "APDU Type",           "bacapp.type",
-                       FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, "APDU Type", HFILL }
+                       FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
                },
                { &hf_bacapp_pduflags,
                        { "PDU Flags",                  "bacapp.pduflags",
-                       FT_UINT8, BASE_HEX, NULL, 0x0f, "PDU Flags", HFILL }
+                       FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
                },
                { &hf_bacapp_SEG,
                        { "Segmented Request",           "bacapp.segmented_request",
-                       FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, "Segmented Request", HFILL }
+                       FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
                },
                { &hf_bacapp_MOR,
                        { "More Segments",           "bacapp.more_segments",
@@ -5646,43 +9045,55 @@ proto_register_bacapp(void)
                },
                { &hf_bacapp_max_adpu_size,
                        { "Size of Maximum ADPU accepted",           "bacapp.max_adpu_size",
-                       FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, "Size of Maximum ADPU accepted", HFILL }
+                       FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
                },
                { &hf_bacapp_response_segments,
                        { "Max Response Segments accepted",           "bacapp.response_segments",
-                       FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, "Max Response Segments accepted", HFILL }
+                       FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
                },
                { &hf_bacapp_objectType,
                        { "Object Type",           "bacapp.objectType",
-                       FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, "Object Type", HFILL }
+                       FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
                },
                { &hf_bacapp_instanceNumber,
                        { "Instance Number",           "bacapp.instance_number",
-                       FT_UINT32, BASE_DEC, NULL, 0x003fffff, "Instance Number", HFILL }
+                       FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
+               },
+               { &hf_BACnetPropertyIdentifier,
+                       { "Property Identifier", "bacapp.property_identifier",
+                       FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
+               },
+               { &hf_BACnetVendorIdentifier,
+                       { "Vendor Identifier", "bacapp.vendor_identifier",
+                       FT_UINT16, BASE_DEC, VALS(BACnetVendorIdentifiers), 0, NULL, HFILL }
+               },
+               { &hf_BACnetRestartReason,
+                       { "Restart Reason", "bacapp.restart_reason",
+                       FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
                },
                { &hf_bacapp_invoke_id,
                        { "Invoke ID",           "bacapp.invoke_id",
-                       FT_UINT8, BASE_DEC, NULL, 0, "Invoke ID", HFILL }
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
                },
                { &hf_bacapp_sequence_number,
                        { "Sequence Number",           "bacapp.sequence_number",
-                       FT_UINT8, BASE_DEC, NULL, 0, "Sequence Number", HFILL }
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
                },
                { &hf_bacapp_window_size,
                        { "Proposed Window Size",           "bacapp.window_size",
-                       FT_UINT8, BASE_DEC, NULL, 0, "Proposed Window Size", HFILL }
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
                },
                { &hf_bacapp_service,
                        { "Service Choice",           "bacapp.confirmed_service",
-                       FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, "Service Choice", HFILL }
+                       FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
                },
                { &hf_bacapp_uservice,
                        { "Unconfirmed Service Choice",           "bacapp.unconfirmed_service",
-                       FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, "Unconfirmed Service Choice", HFILL }
+                       FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
                },
                { &hf_bacapp_NAK,
                        { "NAK",           "bacapp.NAK",
-                       FT_BOOLEAN, 8, NULL, 0x02, "negativ ACK", HFILL }
+                       FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
                },
                { &hf_bacapp_SRV,
                        { "SRV",           "bacapp.SRV",
@@ -5690,88 +9101,129 @@ proto_register_bacapp(void)
                },
                { &hf_BACnetRejectReason,
                        { "Reject Reason",           "bacapp.reject_reason",
-                       FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, "Reject Reason", HFILL }
+                       FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
                },
                { &hf_BACnetAbortReason,
                        { "Abort Reason",           "bacapp.abort_reason",
-                       FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, "Abort Reason", HFILL }
+                       FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
                },
                { &hf_bacapp_vpart,
                        { "BACnet APDU variable part:",           "bacapp.variable_part",
-                       FT_NONE, 0, NULL, 0, "BACnet APDU variable part", HFILL }
+                       FT_NONE, BASE_NONE, NULL, 0, "BACnet APDU variable part", HFILL }
                },
                { &hf_bacapp_tag,
                        { "BACnet Tag",
                        "bacapp.tag",
-                       FT_BYTES, BASE_HEX, NULL, 0,
-                       "BACnet Tag", HFILL }
+                       FT_BYTES, BASE_NONE, NULL, 0,
+                       NULL, HFILL }
                },
                { &hf_BACnetApplicationTagNumber,
                        { "Application Tag Number",
                        "bacapp.application_tag_number",
                        FT_UINT8, BASE_DEC, VALS(&BACnetApplicationTagNumber), 0xF0,
-                       "Application Tag Number", HFILL }
+                       NULL, HFILL }
                },
                { &hf_BACnetContextTagNumber,
                        { "Context Tag Number",
                        "bacapp.context_tag_number",
                        FT_UINT8, BASE_DEC, NULL, 0xF0,
-                       "Context Tag Number", HFILL }
+                       NULL, HFILL }
                },
                { &hf_BACnetExtendedTagNumber,
                        { "Extended Tag Number",
                        "bacapp.extended_tag_number",
                        FT_UINT8, BASE_DEC, NULL, 0,
-                       "Extended Tag Number", HFILL }
+                       NULL, HFILL }
                },
                { &hf_BACnetNamedTag,
                        { "Named Tag",
                        "bacapp.named_tag",
                        FT_UINT8, BASE_DEC, VALS(&BACnetTagNames), 0x07,
-                       "Named Tag", HFILL }
+                       NULL, HFILL }
                },
                { &hf_BACnetCharacterSet,
                        { "String Character Set",
                        "bacapp.string_character_set",
                        FT_UINT8, BASE_DEC, VALS(&BACnetCharacterSet),0,
-                       "String Character Set", HFILL }
+                       NULL, HFILL }
                },
                { &hf_BACnetTagClass,
                        { "Tag Class",           "bacapp.tag_class",
-                       FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, "Tag Class", HFILL }
+                       FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
                },
                { &hf_bacapp_tag_lvt,
                        { "Length Value Type",
                        "bacapp.LVT",
                        FT_UINT8, BASE_DEC, NULL, 0,
-                       "Length Value Type", HFILL }
+                       NULL, HFILL }
                },
                { &hf_bacapp_tag_value8,
                        { "Tag Value",
                        "bacapp.tag_value8",
                        FT_UINT8, BASE_DEC, NULL, 0,
-                       "Tag Value", HFILL }
+                       NULL, HFILL }
                },
                { &hf_bacapp_tag_value16,
                        { "Tag Value 16-bit",
                        "bacapp.tag_value16",
                        FT_UINT16, BASE_DEC, NULL, 0,
-                       "Tag Value 16-bit", HFILL }
+                       NULL, HFILL }
                },
                { &hf_bacapp_tag_value32,
                        { "Tag Value 32-bit",
                        "bacapp.tag_value32",
                        FT_UINT32, BASE_DEC, NULL, 0,
-                       "Tag Value 32-bit", HFILL }
+                       NULL, HFILL }
                },
                { &hf_bacapp_tag_ProcessId,
                        { "ProcessIdentifier",           "bacapp.processId",
                        FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
                },
+               { &hf_bacapp_tag_IPV4,
+                       { "IPV4",           "bacapp.IPV4",
+                       FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
+               },
+               { &hf_bacapp_tag_IPV6,
+               { "IPV6",           "bacapp.IPV6",
+                       FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
+               },
+               { &hf_bacapp_tag_PORT,
+                       { "Port",           "bacapp.Port",
+                       FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
+               },
                { &hf_bacapp_tag_initiatingObjectType,
                        { "ObjectType",           "bacapp.objectType",
                        FT_UINT16, BASE_DEC, VALS(BACnetObjectType), 0x00, "Object Type", HFILL }
                },
+               {&hf_msg_fragments,
+                       {"Message fragments", "bacapp.fragments",
+                       FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+               {&hf_msg_fragment,
+                       {"Message fragment", "bacapp.fragment",
+                       FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+               {&hf_msg_fragment_overlap,
+                       {"Message fragment overlap", "bacapp.fragment.overlap",
+                       FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+               {&hf_msg_fragment_overlap_conflicts,
+                       {"Message fragment overlapping with conflicting data",
+                       "bacapp.fragment.overlap.conflicts",
+                       FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+               {&hf_msg_fragment_multiple_tails,
+                       {"Message has multiple tail fragments",
+                       "bacapp.fragment.multiple_tails",
+                       FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+               {&hf_msg_fragment_too_long_fragment,
+                       {"Message fragment too long", "bacapp.fragment.too_long_fragment",
+                       FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+               {&hf_msg_fragment_error,
+                       {"Message defragmentation error", "bacapp.fragment.error",
+                       FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+               {&hf_msg_reassembled_in,
+                       {"Reassembled in", "bacapp.reassembled.in",
+                       FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+               {&hf_msg_reassembled_length,
+                       {"Reassembled BACapp length", "bacapp.reassembled.length",
+                       FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
        };
        static gint *ett[] = {
                &ett_bacapp,
@@ -5779,13 +9231,18 @@ proto_register_bacapp(void)
                &ett_bacapp_tag,
                &ett_bacapp_list,
                &ett_bacapp_value,
+               &ett_msg_fragment,
+               &ett_msg_fragments
+
        };
+
        proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
-           "BACapp", "bacapp");
+                                              "BACapp", "bacapp");
 
        proto_register_field_array(proto_bacapp, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
        register_dissector("bacapp", dissect_bacapp, proto_bacapp);
+       register_init_routine (&bacapp_init_routine);
 
 }
 
@@ -5795,33 +9252,3 @@ proto_reg_handoff_bacapp(void)
        data_handle = find_dissector("data");
 }
 
-guint32
-fConvertXXXtoUTF8 (const guint8 *in, size_t *inbytesleft, guint8 *out, size_t *outbytesleft, const gchar *fromcoding)
-{  /* I don't want to let in and out be modified */
-#ifdef HAVE_CONFIG_H
-#if HAVE_ICONV_H
-       guint32 i; 
-       iconv_t icd;
-       const guint8 *inp = in;
-       guint8 *outp = out;
-       const guint8 **inpp = &inp;
-       guint8 **outpp = &outp;
-     
-    if ((icd = iconv_open ("UTF-8", fromcoding)) != (iconv_t) -1) {
-        i = iconv (icd, (char**) inpp, inbytesleft, (char**) outpp, outbytesleft);
-               *outpp[0] = '\0';
-        iconv_close (icd);
-        return i;
-    }
-
-#endif
-#endif
-
-    memcpy (out, in, *inbytesleft);
-    out[*inbytesleft] = '\0';
-       *outbytesleft -= *inbytesleft;
-    *inbytesleft = 0;
-
-    return 0;
-}
-