c2b9f0511907b3dcdbf9a52a89d9f18a5bd3d46a
[metze/wireshark/wip.git] / epan / dissectors / packet-bacapp.c
1 /* packet-bacapp.c
2  * Routines for BACnet (APDU) dissection
3  * Copyright 2001, Hartmut Mueller <hartmut[AT]abmlinux.org>, FH Dortmund
4  * Enhanced by Steve Karg, 2005, <skarg[AT]users.sourceforge.net>, Atlanta
5  * Enhanced by Herbert Lischka, 2005, <lischka[AT]kieback-peter.de>, Berlin
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald[AT]wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * Copied from README.developer,v 1.23
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include <glib.h>
38
39 #include <epan/packet.h>
40 #include <epan/reassemble.h>
41 #include <epan/expert.h>
42
43 /* formerly bacapp.h  contains definitions and forward declarations */
44
45 #ifndef FAULT
46 #define FAULT                   proto_tree_add_text(subtree, tvb, offset, tvb_length(tvb) - offset, "something is going wrong here !!"); \
47         offset = tvb_length(tvb);
48 #endif
49
50 /* BACnet PDU Types */
51 #define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST 0
52 #define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST 1
53 #define BACAPP_TYPE_SIMPLE_ACK 2
54 #define BACAPP_TYPE_COMPLEX_ACK 3
55 #define BACAPP_TYPE_SEGMENT_ACK 4
56 #define BACAPP_TYPE_ERROR 5
57 #define BACAPP_TYPE_REJECT 6
58 #define BACAPP_TYPE_ABORT 7
59 #define MAX_BACAPP_TYPE 8
60
61 #define BACAPP_SEGMENTED_REQUEST 0x08
62 #define BACAPP_MORE_SEGMENTS 0x04
63 #define BACAPP_SEGMENTED_RESPONSE 0x02
64 #define BACAPP_SEGMENT_NAK 0x02
65 #define BACAPP_SENT_BY 0x01
66
67
68 /**
69  * dissect_bacapp ::= CHOICE {
70  *  confirmed-request-PDU       [0] BACnet-Confirmed-Request-PDU,
71  *  unconfirmed-request-PDU     [1] BACnet-Unconfirmed-Request-PDU,
72  *  simpleACK-PDU               [2] BACnet-SimpleACK-PDU,
73  *  complexACK-PDU              [3] BACnet-ComplexACK-PDU,
74  *  segmentACK-PDU              [4] BACnet-SegmentACK-PDU,
75  *  error-PDU                   [5] BACnet-Error-PDU,
76  *  reject-PDU                  [6] BACnet-Reject-PDU,
77  *  abort-PDU                   [7] BACnet-Abort-PDU
78  * }
79  * @param tvb
80  * @param pinfo
81  * @param tree
82  **/
83 static void
84 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
85
86 /**
87  * ConfirmedRequest-PDU ::= SEQUENCE {
88  *      pdu-type                                        [0] Unsigned (0..15), -- 0 for this PDU Type
89  *  segmentedMessage                    [1] BOOLEAN,
90  *  moreFollows                                 [2] BOOLEAN,
91  *  segmented-response-accepted [3] BOOLEAN,
92  *  reserved                                    [4] Unsigned (0..3), -- must be set zero
93  *  max-segments-accepted               [5] Unsigned (0..7), -- as per 20.1.2.4
94  *  max-APDU-length-accepted    [5] Unsigned (0..15), -- as per 20.1.2.5
95  *  invokeID                                    [6] Unsigned (0..255),
96  *  sequence-number                             [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
97  *  proposed-window-size                [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
98  *  service-choice                              [9] BACnetConfirmedServiceChoice,
99  *  service-request                             [10] BACnet-Confirmed-Service-Request OPTIONAL
100  * }
101  * @param tvb
102  * @param pinfo
103  * @param tree
104  * @param offset
105  * @return modified offset
106  */
107 static guint
108 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
109
110 /**
111  * @param tvb
112  * @param pinfo
113  * @param tree
114  * @param offset
115  * @param ack - indocates whether working on request or ack
116  * @param svc - output variable to return service choice
117  * @param tt  - output varable to return service choice item
118  * @return modified offset
119  */
120 static guint
121 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 ack,
122                                 gint *svc, proto_item **tt);
123
124 /**
125  * Unconfirmed-Request-PDU ::= SEQUENCE {
126  *      pdu-type                [0] Unsigned (0..15), -- 1 for this PDU type
127  *  reserved            [1] Unsigned (0..15), -- must be set zero
128  *  service-choice      [2] BACnetUnconfirmedServiceChoice,
129  *  service-request     [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
130  * }
131  * @param tvb
132  * @param pinfo
133  * @param tree
134  * @param offset
135  * @return modified offset
136  */
137 static guint
138 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
139
140 /**
141  * SimpleACK-PDU ::= SEQUENCE {
142  *      pdu-type                [0] Unsigned (0..15), -- 2 for this PDU type
143  *  reserved            [1] Unsigned (0..15), -- must be set zero
144  *  invokeID            [2] Unsigned (0..255),
145  *  service-ACK-choice  [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
146  * }
147  * @param tvb
148  * @param pinfo
149  * @param tree
150  * @param offset
151  * @return modified offset
152  */
153 static guint
154 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
155
156 /**
157  * ComplexACK-PDU ::= SEQUENCE {
158  *      pdu-type                                [0] Unsigned (0..15), -- 3 for this PDU Type
159  *  segmentedMessage            [1] BOOLEAN,
160  *  moreFollows                         [2] BOOLEAN,
161  *  reserved                            [3] Unsigned (0..3), -- must be set zero
162  *  invokeID                            [4] Unsigned (0..255),
163  *  sequence-number                     [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
164  *  proposed-window-size        [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
165  *  service-ACK-choice          [7] BACnetConfirmedServiceChoice,
166  *  service-ACK                         [8] BACnet-Confirmed-Service-Request  -- Context-specific tags 0..8 are NOT used in header encoding
167  * }
168  * @param tvb
169  * @param pinfo
170  * @param tree
171  * @param offset
172  * @return modified offset
173  */
174 static guint
175 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
176
177 /**
178  * SegmentACK-PDU ::= SEQUENCE {
179  *      pdu-type                                [0] Unsigned (0..15), -- 4 for this PDU Type
180  *  reserved                            [1] Unsigned (0..3), -- must be set zero
181  *  negative-ACK                        [2] BOOLEAN,
182  *  server                                      [3] BOOLEAN,
183  *  original-invokeID           [4] Unsigned (0..255),
184  *  sequence-number                     [5] Unsigned (0..255),
185  *  actual-window-size          [6] Unsigned (0..127)
186  * }
187  * @param tvb
188  * @param pinfo
189  * @param tree
190  * @param offset
191  * @return modified offset
192  */
193 static guint
194 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
195
196 /**
197  * Error-PDU ::= SEQUENCE {
198  *      pdu-type                                [0] Unsigned (0..15), -- 5 for this PDU Type
199  *  reserved                            [1] Unsigned (0..3), -- must be set zero
200  *  original-invokeID           [2] Unsigned (0..255),
201  *  error-choice                        [3] BACnetConfirmedServiceChoice,
202  *  error                                       [4] BACnet-Error
203  * }
204  * @param tvb
205  * @param pinfo
206  * @param tree
207  * @param offset
208  * @return modified offset
209  */
210 static guint
211 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
212
213 /**
214  * Reject-PDU ::= SEQUENCE {
215  *      pdu-type                                [0] Unsigned (0..15), -- 6 for this PDU Type
216  *  reserved                            [1] Unsigned (0..3), -- must be set zero
217  *  original-invokeID           [2] Unsigned (0..255),
218  *  reject-reason                       [3] BACnetRejectReason
219  * }
220  * @param tvb
221  * @param pinfo
222  * @param tree
223  * @param offset
224  * @return modified offset
225  */
226 static guint
227 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
228
229 /**
230  * Abort-PDU ::= SEQUENCE {
231  *      pdu-type                                [0] Unsigned (0..15), -- 7 for this PDU Type
232  *  reserved                            [1] Unsigned (0..3), -- must be set zero
233  *  server                                      [2] BOOLEAN,
234  *  original-invokeID           [3] Unsigned (0..255),
235  *  abort-reason                        [4] BACnetAbortReason
236  * }
237  * @param tvb
238  * @param pinfo
239  * @param tree
240  * @param offset
241  * @return modified offset
242  */
243 static guint
244 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
245
246 /**
247  * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
248  * @param tvb
249  * @param tree
250  * @param offset
251  * @param label
252  * @return modified offset
253  */
254 static guint
255 fUnsignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
256
257 /**
258  * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
259  * @param tvb
260  * @param tree
261  * @param offset
262  * @param label
263  * @return modified offset
264  */
265 static guint
266 fSignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
267
268 /**
269  * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
270  * @param tvb
271  * @param tree
272  * @param offset
273  * @param label
274  * @param lvt length of String
275  * @return modified offset
276  */
277 static guint
278 fOctetString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt);
279
280 /**
281  * 20.2.12, adds the label with Date Value to tree
282  * @param tvb
283  * @param tree
284  * @param offset
285  * @param label
286  * @return modified offset
287  */
288 static guint
289 fDate    (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
290
291 /**
292  * 20.2.13, adds the label with Time Value to tree
293  * @param tvb
294  * @param tree
295  * @param offset
296  * @param label
297  * @return modified offset
298  */
299 static guint
300 fTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
301
302 /**
303  * 20.2.14, adds Object Identifier to tree
304  * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
305  * @param tvb
306  * @param pinfo
307  * @param tree
308  * @param offset
309  * @return modified offset
310  */
311 static guint
312 fObjectIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
313
314 /**
315  * BACnet-Confirmed-Service-Request ::= CHOICE {
316  * }
317  * @param tvb
318  * @param pinfo
319  * @param tree
320  * @param offset
321  * @param service_choice
322  * @return offset
323  */
324 static guint
325 fConfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
326
327 /**
328  * BACnet-Confirmed-Service-ACK ::= CHOICE {
329  * }
330  * @param tvb
331  * @param pinfo
332  * @param tree
333  * @param offset
334  * @param service_choice
335  * @return offset
336  */
337 static guint
338 fConfirmedServiceAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
339
340 /**
341  * AcknowledgeAlarm-Request ::= SEQUENCE {
342  *      acknowledgingProcessIdentifier  [0]     Unsigned32,
343  *      eventObjectIdentifier   [1] BACnetObjectIdentifer,
344  *      eventStateAcknowledge   [2] BACnetEventState,
345  *      timeStamp       [3] BACnetTimeStamp,
346  *      acknowledgementSource   [4] Character String,
347  *  timeOfAcknowledgement       [5] BACnetTimeStamp
348  * }
349  * @param tvb
350  * @param pinfo
351  * @param tree
352  * @param offset
353  * @return modified offset
354  */
355 static guint
356 fAcknowledgeAlarmRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
357
358 /**
359  * ConfirmedCOVNotification-Request ::= SEQUENCE {
360  *      subscriberProcessIdentifier     [0]     Unsigned32,
361  *      initiatingDeviceIdentifier      [1] BACnetObjectIdentifer,
362  *      monitoredObjectIdentifier       [2] BACnetObjectIdentifer,
363  *      timeRemaining   [3] unsigned,
364  *      listOfValues    [4] SEQUENCE OF BACnetPropertyValues
365  * }
366  * @param tvb
367  * @param pinfo
368  * @param tree
369  * @param offset
370  * @return modified offset
371  */
372 static guint
373 fConfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
374
375 /**
376  * ConfirmedEventNotification-Request ::= SEQUENCE {
377  *      ProcessIdentifier       [0]     Unsigned32,
378  *      initiatingDeviceIdentifier      [1] BACnetObjectIdentifer,
379  *      eventObjectIdentifier   [2] BACnetObjectIdentifer,
380  *      timeStamp       [3] BACnetTimeStamp,
381  *      notificationClass       [4] unsigned,
382  *      priority        [5] unsigned8,
383  *      eventType       [6] BACnetEventType,
384  *      messageText     [7] CharacterString OPTIONAL,
385  *      notifyType      [8] BACnetNotifyType,
386  *      ackRequired     [9] BOOLEAN OPTIONAL,
387  *      fromState       [10] BACnetEventState OPTIONAL,
388  *      toState [11] BACnetEventState,
389  *      eventValues     [12] BACnetNotificationParameters OPTIONAL
390  * }
391  * @param tvb
392  * @param pinfo
393  * @param tree
394  * @param offset
395  * @return modified offset
396  */
397 static guint
398 fConfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo,  proto_tree *tree, guint offset);
399
400 /**
401  * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
402  *      objectIdentifier        BACnetObjectIdentifer,
403  *      alarmState      BACnetEventState,
404  *      acknowledgedTransitions  BACnetEventTransitionBits
405  * }
406  * @param tvb
407  * @param pinfo
408  * @param tree
409  * @param offset
410  * @return modified offset
411  */
412 static guint
413 fGetAlarmSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
414
415 /**
416  * GetEnrollmentSummary-Request ::= SEQUENCE {
417  *      acknowledgmentFilter    [0]     ENUMERATED {
418  *      all (0),
419  *      acked   (1),
420  *      not-acked   (2)
421  *      },
422  *      enrollmentFilter        [1] BACnetRecipientProcess OPTIONAL,
423  *      eventStateFilter        [2] ENUMERATED {
424  *      offnormal   (0),
425  *      fault   (1),
426  *      normal  (2),
427  *      all (3),
428  *      active  (4)
429  *      },
430  *      eventTypeFilter [3] BACnetEventType OPTIONAL,
431  *      priorityFilter  [4] SEQUENCE {
432  *      minPriority [0] Unsigned8,
433  *      maxPriority [1] Unsigned8
434  *      } OPTIONAL,
435  *  notificationClassFilter     [5] Unsigned OPTIONAL
436  * }
437  * @param tvb
438  * @param pinfo
439  * @param tree
440  * @param offset
441  * @return modified offset
442  */
443 static guint
444 fGetEnrollmentSummaryRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
445
446 /**
447  * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
448  *      objectIdentifier        BACnetObjectIdentifer,
449  *      eventType       BACnetEventType,
450  *      eventState      BACnetEventState,
451  *      priority    Unsigned8,
452  *  notificationClass   Unsigned OPTIONAL
453  * }
454  * @param tvb
455  * @param pinfo
456  * @param tree
457  * @param offset
458  * @return modified offset
459  */
460 static guint
461 fGetEnrollmentSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
462
463 /**
464  * GetEventInformation-Request ::= SEQUENCE {
465  *      lastReceivedObjectIdentifier    [0] BACnetObjectIdentifer
466  * }
467  * @param tvb
468  * @param pinfo
469  * @param tree
470  * @param offset
471  * @return modified offset
472  */
473 static guint
474 fGetEventInformationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
475
476 /**
477  * GetEventInformation-ACK ::= SEQUENCE {
478  *      listOfEventSummaries    [0] listOfEventSummaries,
479  *  moreEvents  [1] BOOLEAN
480  * }
481  * @param tvb
482  * @param pinfo
483  * @param tree
484  * @param offset
485  * @return modified offset
486  */
487 static guint
488 fGetEventInformationACK (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
489
490 /**
491  * LifeSafetyOperation-Request ::= SEQUENCE {
492  *      requestingProcessIdentifier     [0]     Unsigned32
493  *      requestingSource        [1] CharacterString
494  *      request [2] BACnetLifeSafetyOperation
495  *      objectIdentifier        [3] BACnetObjectIdentifier OPTIONAL
496  * }
497  * @param tvb
498  * @param pinfo
499  * @param tree
500  * @param offset
501  * @return modified offset
502  */
503 static guint
504 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
505
506 /**
507  * SubscribeCOV-Request ::= SEQUENCE {
508  *      subscriberProcessIdentifier     [0]     Unsigned32
509  *      monitoredObjectIdentifier       [1] BACnetObjectIdentifier
510  *      issueConfirmedNotifications     [2] BOOLEAN OPTIONAL
511  *      lifetime        [3] Unsigned OPTIONAL
512  * }
513  * @param tvb
514  * @param pinfo
515  * @param tree
516  * @param offset
517  * @param label
518  * @param src
519  * @return modified offset
520  */
521 static guint
522 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
523
524 /**
525  * SubscribeCOVProperty-Request ::= SEQUENCE {
526  *      subscriberProcessIdentifier     [0]     Unsigned32
527  *      monitoredObjectIdentifier       [1] BACnetObjectIdentifier
528  *      issueConfirmedNotifications     [2] BOOLEAN OPTIONAL
529  *      lifetime        [3] Unsigned OPTIONAL
530  *      monitoredPropertyIdentifier     [4] BACnetPropertyReference OPTIONAL
531  *      covIncrement    [5] Unsigned OPTIONAL
532  * }
533  * @param tvb
534  * @param pinfo
535  * @param tree
536  * @param offset
537  * @return modified offset
538  */
539 static guint
540 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
541
542 /**
543  * AtomicReadFile-Request ::= SEQUENCE {
544  *      fileIdentifier  BACnetObjectIdentifier,
545  *  accessMethod        CHOICE {
546  *      streamAccess    [0] SEQUENCE {
547  *              fileStartPosition       INTEGER,
548  *                      requestedOctetCount     Unsigned
549  *                      },
550  *              recordAccess    [1] SEQUENCE {
551  *                      fileStartRecord INTEGER,
552  *                      requestedRecordCount    Unsigned
553  *                      }
554  *              }
555  * }
556  * @param tvb
557  * @param pinfo
558  * @param tree
559  * @param offset
560  * @return modified offset
561  */
562 static guint
563 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
564
565 /**
566  * AtomicWriteFile-ACK ::= SEQUENCE {
567  *      endOfFile       BOOLEAN,
568  *  accessMethod        CHOICE {
569  *      streamAccess    [0] SEQUENCE {
570  *              fileStartPosition       INTEGER,
571  *                      fileData        OCTET STRING
572  *                      },
573  *              recordAccess    [1] SEQUENCE {
574  *                      fileStartRecord INTEGER,
575  *                      returnedRecordCount     Unsigned,
576  *                      fileRecordData  SEQUENCE OF OCTET STRING
577  *                      }
578  *              }
579  * }
580  * @param tvb
581  * @param pinfo
582  * @param tree
583  * @param offset
584  * @return modified offset
585  */
586 static guint
587 fAtomicReadFileAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
588
589 /**
590  * AtomicWriteFile-Request ::= SEQUENCE {
591  *      fileIdentifier  BACnetObjectIdentifier,
592  *  accessMethod        CHOICE {
593  *      streamAccess    [0] SEQUENCE {
594  *              fileStartPosition       INTEGER,
595  *                      fileData        OCTET STRING
596  *                      },
597  *              recordAccess    [1] SEQUENCE {
598  *                      fileStartRecord INTEGER,
599  *                      recordCount     Unsigned,
600  *                      fileRecordData  SEQUENCE OF OCTET STRING
601  *                      }
602  *              }
603  * }
604  * @param tvb
605  * @param pinfo
606  * @param tree
607  * @param offset
608  * @return modified offset
609  */
610 static guint
611 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
612
613 /**
614  * AtomicWriteFile-ACK ::= SEQUENCE {
615  *              fileStartPosition       [0] INTEGER,
616  *              fileStartRecord [1] INTEGER,
617  * }
618  * @param tvb
619  * @param tree
620  * @param offset
621  * @return modified offset
622  */
623 static guint
624 fAtomicWriteFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset);
625
626 /**
627  * AddListElement-Request ::= SEQUENCE {
628  *      objectIdentifier        [0] BACnetObjectIdentifier,
629  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
630  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
631  *  listOfElements  [3] ABSTRACT-SYNTAX.&Type
632  * }
633  * @param tvb
634  * @param pinfo
635  * @param tree
636  * @param offset
637  * @return modified offset
638  */
639 static guint
640 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
641
642 /**
643  * CreateObject-Request ::= SEQUENCE {
644  *      objectSpecifier [0] ObjectSpecifier,
645  *  listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
646  * }
647  * @param tvb
648  * @param pinfo
649  * @param tree
650  * @param offset
651  * @return modified offset
652  */
653 static guint
654 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
655
656 /**
657  * CreateObject-Request ::= BACnetObjectIdentifier
658  * @param tvb
659  * @param pinfo
660  * @param tree
661  * @param offset
662  * @return modified offset
663  */
664 static guint
665 fCreateObjectAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
666
667 /**
668  * DeleteObject-Request ::= SEQUENCE {
669  *      ObjectIdentifier        BACnetObjectIdentifer
670  * }
671  * @param tvb
672  * @param pinfo
673  * @param tree
674  * @param offset
675  * @return modified offset
676  */
677 static guint
678 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
679
680 /**
681  * ReadProperty-Request ::= SEQUENCE {
682  *      objectIdentifier        [0]     BACnetObjectIdentifier,
683  *      propertyIdentifier      [1] BACnetPropertyIdentifier,
684  *      propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
685  * }
686  * @param tvb
687  * @param pinfo
688  * @param tree
689  * @param offset
690  * @return modified offset
691  */
692 static guint
693 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
694
695 /**
696  * ReadProperty-ACK ::= SEQUENCE {
697  *      objectIdentifier        [0]     BACnetObjectIdentifier,
698  *      propertyIdentifier      [1] BACnetPropertyIdentifier,
699  *      propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
700  *      propertyValue   [3] ABSTRACT-SYNTAX.&Type
701  * }
702  * @param tvb
703  * @param pinfo
704  * @param tree
705  * @param offset
706  * @return modified offset
707  */
708 static guint
709 fReadPropertyAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
710
711 /**
712  * ReadPropertyConditional-Request ::= SEQUENCE {
713  *      objectSelectionCriteria [0] objectSelectionCriteria,
714  *      listOfPropertyReferences        [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
715  * }
716  * @param tvb
717  * @param pinfo
718  * @param tree
719  * @param offset
720  * @return modified offset
721  */
722 static guint
723 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
724
725 /**
726  * ReadPropertyConditional-ACK ::= SEQUENCE {
727  *      listOfPReadAccessResults        SEQUENCE OF ReadAccessResult OPTIONAL
728  * }
729  * @param tvb
730  * @param pinfo
731  * @param tree
732  * @param offset
733  * @return modified offset
734  */
735 static guint
736 fReadPropertyConditionalAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
737
738 /**
739  * ReadPropertyMultiple-Request ::= SEQUENCE {
740  *  listOfReadAccessSpecs       SEQUENCE OF ReadAccessSpecification
741  * }
742  * @param tvb
743  * @param pinfo
744  * @param tree
745  * @param offset
746  * @return offset modified
747  */
748 static guint
749 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
750
751 /**
752  * ReadPropertyMultiple-Ack ::= SEQUENCE {
753  *  listOfReadAccessResults     SEQUENCE OF ReadAccessResult
754  * }
755  * @param tvb
756  * @parma pinfo
757  * @param tree
758  * @param offset
759  * @return offset modified
760  */
761 static guint
762 fReadPropertyMultipleAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
763
764 /**
765  * ReadRange-Request ::= SEQUENCE {
766  *      objectIdentifier        [0] BACnetObjectIdentifier,
767  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
768  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
769  *      range   CHOICE {
770  *              byPosition      [3] SEQUENCE {
771  *                      referencedIndex Unsigned,
772  *                      count INTEGER
773  *                      },
774  *              byTime  [4] SEQUENCE {
775  *                      referenceTime BACnetDateTime,
776  *                      count INTEGER
777  *                      },
778  *              timeRange       [5] SEQUENCE {
779  *                      beginningTime BACnetDateTime,
780  *                      endingTime BACnetDateTime
781  *                      },
782  *              } OPTIONAL
783  * }
784  * @param tvb
785  * @param pinfo
786  * @param tree
787  * @param offset
788  * @return modified offset
789  */
790 static guint
791 fReadRangeRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
792
793 /**
794  * ReadRange-ACK ::= SEQUENCE {
795  *      objectIdentifier        [0] BACnetObjectIdentifier,
796  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
797  *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
798  *  resultFlags [3] BACnetResultFlags,
799  *  itemCount   [4] Unsigned,
800  *  itemData    [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
801  * }
802  * @param tvb
803  * @param pinfo
804  * @param tree
805  * @param offset
806  * @return modified offset
807  */
808 static guint
809 fReadRangeAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
810
811 /**
812  * RemoveListElement-Request ::= SEQUENCE {
813  *      objectIdentifier        [0]     BACnetObjectIdentifier,
814  *      propertyIdentifier      [1] BACnetPropertyIdentifier,
815  *      propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
816  *      listOfElements  [3] ABSTRACT-SYNTAX.&Type
817  * }
818  * @param tvb
819  * @param pinfo
820  * @param tree
821  * @param offset
822  * @return modified offset
823  */
824 static guint
825 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
826
827 /**
828  * WriteProperty-Request ::= SEQUENCE {
829  *      objectIdentifier        [0]     BACnetObjectIdentifier,
830  *      propertyIdentifier      [1] BACnetPropertyIdentifier,
831  *      propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
832  *      propertyValue   [3] ABSTRACT-SYNTAX.&Type
833  *  priority    [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
834  * }
835  * @param tvb
836  * @param pinfo
837  * @param tree
838  * @param offset
839  * @return modified offset
840  */
841 static guint
842 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
843
844 /**
845  * WritePropertyMultiple-Request ::= SEQUENCE {
846  *      listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
847  * }
848  * @param tvb
849  * @param pinfo
850  * @param tree
851  * @param offset
852  * @return modified offset
853  */
854 static guint
855 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
856
857 /**
858  * DeviceCommunicationControl-Request ::= SEQUENCE {
859  *      timeDuration    [0] Unsigned16 OPTIONAL,
860  *  enable-disable      [1] ENUMERATED {
861  *              enable (0),
862  *              disable (1)
863  *              },
864  *  password    [2] CharacterString (SIZE(1..20)) OPTIONAL
865  * }
866  * @param tvb
867  * @param tree
868  * @param offset
869  * @return modified offset
870  */
871 static guint
872 fDeviceCommunicationControlRequest(tvbuff_t *tvb, proto_tree *tree, guint offset);
873
874 /**
875  * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
876  *      vendorID        [0]     Unsigned,
877  *      serviceNumber   [1] Unsigned,
878  *      serviceParameters       [2] ABSTRACT-SYNTAX.&Type OPTIONAL
879  * }
880  * @param tvb
881  * @param pinfo
882  * @param tree
883  * @param offset
884  * @return modified offset
885  */
886 static guint
887 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
888
889 /**
890  * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
891  *      vendorID        [0]     Unsigned,
892  *      serviceNumber   [1] Unsigned,
893  *      resultBlock     [2] ABSTRACT-SYNTAX.&Type OPTIONAL
894  * }
895  * @param tvb
896  * @param pinfo
897  * @param tree
898  * @param offset
899  * @return modified offset
900  */
901 static guint
902 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
903
904 /**
905  * ConfirmedTextMessage-Request ::=  SEQUENCE {
906  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
907  *  messageClass [1] CHOICE {
908  *      numeric [0] Unsigned,
909  *      character [1] CharacterString
910  *      } OPTIONAL,
911  *  messagePriority [2] ENUMERATED {
912  *      normal (0),
913  *      urgent (1)
914  *      },
915  *  message [3] CharacterString
916  * }
917  * @param tvb
918  * @param pinfo
919  * @param tree
920  * @param offset
921  * @return modified offset
922  */
923 static guint
924 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
925
926 /**
927  * ReinitializeDevice-Request ::= SEQUENCE {
928  *  reinitializedStateOfDevice  [0] ENUMERATED {
929  *              coldstart (0),
930  *              warmstart (1),
931  *              startbackup (2),
932  *              endbackup (3),
933  *              startrestore (4),
934  *              endrestore (5),
935  *              abortrestor (6)
936  *              },
937  *  password    [1] CharacterString (SIZE(1..20)) OPTIONAL
938  * }
939  * @param tvb
940  * @param tree
941  * @param offset
942  * @return modified offset
943  */
944 static guint
945 fReinitializeDeviceRequest(tvbuff_t *tvb, proto_tree *tree, guint offset);
946
947 /**
948  * VTOpen-Request ::= SEQUENCE {
949  *  vtClass     BACnetVTClass,
950  *  localVTSessionIdentifier    Unsigned8
951  * }
952  * @param tvb
953  * @param pinfo
954  * @param tree
955  * @param offset
956  * @return modified offset
957  */
958 static guint
959 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
960
961 /**
962  * VTOpen-ACK ::= SEQUENCE {
963  *  remoteVTSessionIdentifier   Unsigned8
964  * }
965  * @param tvb
966  * @param pinfo
967  * @param tree
968  * @param offset
969  * @return modified offset
970  */
971 static guint
972 fVtOpenAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
973
974 /**
975  * VTClose-Request ::= SEQUENCE {
976  *  listOfRemoteVTSessionIdentifiers    SEQUENCE OF Unsigned8
977  * }
978  * @param tvb
979  * @param pinfo
980  * @param tree
981  * @param offset
982  * @return modified offset
983  */
984 static guint
985 fVtCloseRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
986
987 /**
988  * VTData-Request ::= SEQUENCE {
989  *  vtSessionIdentifier Unsigned8,
990  *  vtNewData   OCTET STRING,
991  *  vtDataFlag  Unsigned (0..1)
992  * }
993  * @param tvb
994  * @param pinfo
995  * @param tree
996  * @param offset
997  * @return modified offset
998  */
999 static guint
1000 fVtDataRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1001
1002 /**
1003  * VTData-ACK ::= SEQUENCE {
1004  *  allNewDataAccepted  [0] BOOLEAN,
1005  *  acceptedOctetCount  [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = FALSE
1006  * }
1007  * @param tvb
1008  * @param tree
1009  * @param offset
1010  * @return modified offset
1011  */
1012 static guint
1013 fVtDataAck (tvbuff_t *tvb, proto_tree *tree, guint offset);
1014
1015 /**
1016  * Authenticate-Request ::= SEQUENCE {
1017  *  pseudoRandomNumber  [0] Unsigned32,
1018  *  excpectedInvokeID   [1] Unsigned8 OPTIONAL,
1019  *  operatorName        [2] CharacterString OPTIONAL,
1020  *  operatorPassword    [3] CharacterString (SIZE(1..20)) OPTIONAL,
1021  *  startEncypheredSession      [4] BOOLEAN OPTIONAL
1022  * }
1023  * @param tvb
1024  * @param tree
1025  * @param offset
1026  * @return modified offset
1027  */
1028 static guint
1029 fAuthenticateRequest (tvbuff_t *tvb, proto_tree *tree, guint offset);
1030
1031 /**
1032  * Authenticate-ACK ::= SEQUENCE {
1033  *  modifiedRandomNumber        Unsigned32,
1034  * }
1035  * @param tvb
1036  * @param pinfo
1037  * @param tree
1038  * @param offset
1039  * @return modified offset
1040  */
1041 static guint
1042 fAuthenticateAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1043
1044 /**
1045  * RequestKey-Request ::= SEQUENCE {
1046  *  requestingDeviceIdentifier  BACnetObjectIdentifier,
1047  *  requestingDeviceAddress     BACnetAddress,
1048  *  remoteDeviceIdentifier      BACnetObjectIdentifier,
1049  *  remoteDeviceAddress BACnetAddress
1050  * }
1051  * @param tvb
1052  * @param pinfo
1053  * @param tree
1054  * @param offset
1055  * @return modified offset
1056  */
1057 static guint
1058 fRequestKeyRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1059
1060 /**
1061  * Unconfirmed-Service-Request ::= CHOICE {
1062  * }
1063  * @param tvb
1064  * @param pinfo
1065  * @param tree
1066  * @param offset
1067  * @param service_choice
1068  * @return modified offset
1069  */
1070 static guint
1071 fUnconfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
1072
1073 /**
1074  * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1075  *      subscriberProcessIdentifier     [0]     Unsigned32,
1076  *      initiatingDeviceIdentifier      [1] BACnetObjectIdentifer,
1077  *      monitoredObjectIdentifier       [2] BACnetObjectIdentifer,
1078  *      timeRemaining   [3] unsigned,
1079  *      listOfValues    [4] SEQUENCE OF BACnetPropertyValues
1080  * }
1081  * @param tvb
1082  * @param pinfo
1083  * @param tree
1084  * @param offset
1085  * @return modified offset
1086  */
1087 static guint
1088 fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1089
1090 /**
1091  * UnconfirmedEventNotification-Request ::= SEQUENCE {
1092  *      ProcessIdentifier       [0]     Unsigned32,
1093  *      initiatingDeviceIdentifier      [1] BACnetObjectIdentifer,
1094  *      eventObjectIdentifier   [2] BACnetObjectIdentifer,
1095  *      timeStamp       [3] BACnetTimeStamp,
1096  *      notificationClass       [4] unsigned,
1097  *      priority        [5] unsigned8,
1098  *      eventType       [6] BACnetEventType,
1099  *      messageText     [7] CharacterString OPTIONAL,
1100  *      notifyType      [8] BACnetNotifyType,
1101  *      ackRequired     [9] BOOLEAN OPTIONAL,
1102  *      fromState       [10] BACnetEventState OPTIONAL,
1103  *      toState [11] BACnetEventState,
1104  *      eventValues     [12] BACnetNotificationParameters OPTIONAL
1105  * }
1106  * @param tvb
1107  * @param pinfo
1108  * @param tree
1109  * @param offset
1110  * @return modified offset
1111  */
1112 static guint
1113 fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1114
1115 /**
1116  * I-Am-Request ::= SEQUENCE {
1117  *      aAmDeviceIdentifier     BACnetObjectIdentifier,
1118  *  maxAPDULengthAccepted       Unsigned,
1119  *      segmentationSupported   BACnetSegmentation,
1120  *      vendorID        Unsigned
1121  * }
1122  * @param tvb
1123  * @param pinfo
1124  * @param tree
1125  * @param offset
1126  * @return modified offset
1127  */
1128 static guint
1129 fIAmRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1130
1131
1132 /**
1133  * I-Have-Request ::= SEQUENCE {
1134  *      deviceIdentifier        BACnetObjectIdentifier,
1135  *  objectIdentifier    BACnetObjectIdentifier,
1136  *      objectName      CharacterString
1137  * }
1138  * @param tvb
1139  * @param pinfo
1140  * @param tree
1141  * @param offset
1142  * @return modified offset
1143  */
1144 static guint
1145 fIHaveRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1146
1147 /**
1148  * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1149  *      vendorID        [0]     Unsigned,
1150  *      serviceNumber   [1] Unsigned,
1151  *      serviceParameters       [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1152  * }
1153  * @param tvb
1154  * @param pinfo
1155  * @param tree
1156  * @param offset
1157  * @return modified offset
1158  */
1159 static guint
1160 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1161
1162 /**
1163  * UnconfirmedTextMessage-Request ::=  SEQUENCE {
1164  *  textMessageSourceDevice [0] BACnetObjectIdentifier,
1165  *  messageClass [1] CHOICE {
1166  *      numeric [0] Unsigned,
1167  *      character [1] CharacterString
1168  *      } OPTIONAL,
1169  *  messagePriority [2] ENUMERATED {
1170  *      normal (0),
1171  *      urgent (1)
1172  *      },
1173  *  message [3] CharacterString
1174  * }
1175  * @param tvb
1176  * @param pinfo
1177  * @param tree
1178  * @param offset
1179  * @return modified offset
1180  */
1181 static guint
1182 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1183
1184 /**
1185  * TimeSynchronization-Request ::=  SEQUENCE {
1186  *  BACnetDateTime
1187  * }
1188  * @param tvb
1189  * @param tree
1190  * @param offset
1191  * @return modified offset
1192  */
1193 static guint
1194 fTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset);
1195
1196 /**
1197  * UTCTimeSynchronization-Request ::=  SEQUENCE {
1198  *  BACnetDateTime
1199  * }
1200  * @param tvb
1201  * @param tree
1202  * @param offset
1203  * @return modified offset
1204  */
1205 static guint
1206 fUTCTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset);
1207
1208 /**
1209  * Who-Has-Request ::=  SEQUENCE {
1210  *  limits SEQUENCE {
1211  *      deviceInstanceRangeLowLimit [0] Unsigned (0..4194303),
1212  *      deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1213  *      } OPTIONAL,
1214  *  object CHOICE {
1215  *      objectIdentifier [2] BACnetObjectIdentifier,
1216  *      objectName [3] CharacterString
1217  *      }
1218  * }
1219  * @param tvb
1220  * @param pinfo
1221  * @param tree
1222  * @param offset
1223  * @return modified offset
1224  */
1225 static guint
1226 fWhoHas (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1227
1228 /**
1229  * Who-Is-Request ::= SEQUENCE {
1230  *      deviceInstanceRangeLowLimit     [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1231  *      deviceInstanceRangeHighLimit    [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1232  * }
1233  * @param tvb
1234  * @param tree
1235  * @param offset
1236  * @return modified offset
1237  */
1238 static guint
1239 fWhoIsRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1240
1241 /**
1242  * BACnet-Error ::= CHOICE {
1243  *  addListElement          [8] ChangeList-Error,
1244  *  removeListElement       [9] ChangeList-Error,
1245  *  writePropertyMultiple   [16] WritePropertyMultiple-Error,
1246  *  confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1247  *  vtClose                 [22] VTClose-Error,
1248  *  readRange               [26] ObjectAccessService-Error
1249  *                      [default] Error
1250  * }
1251  * @param tvb
1252  * @param pinfo
1253  * @param tree
1254  * @param offset
1255  * @param service
1256  * @return modified offset
1257  */
1258 static guint
1259 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service);
1260
1261 /**
1262  * Dissect a BACnetError in a context tag
1263  *
1264  * @param tvb
1265  * @param pinfo
1266  * @param tree
1267  * @param offset
1268  * @return modified offset
1269  */
1270 static guint fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1271
1272 /**
1273  * ChangeList-Error ::= SEQUENCE {
1274  *    errorType     [0] Error,
1275  *    firstFailedElementNumber  [1] Unsigned
1276  *    }
1277  * }
1278  * @param tvb
1279  * @param pinfo
1280  * @param tree
1281  * @param offset
1282  * @return modified offset
1283  */
1284 static guint
1285 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1286
1287 /**
1288  * CreateObject-Error ::= SEQUENCE {
1289  *    errorType     [0] Error,
1290  *    firstFailedElementNumber  [1] Unsigned
1291  *    }
1292  * }
1293  * @param tvb
1294  * @param pinfo
1295  * @param tree
1296  * @param offset
1297  * @return modified offset
1298  */
1299 static guint
1300 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1301
1302 /**
1303  * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1304  *    errorType     [0] Error,
1305  *    vendorID      [1] Unsigned,
1306  *    serviceNumber [2] Unsigned,
1307  *    errorParameters   [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1308  *    }
1309  * }
1310  * @param tvb
1311  * @param pinfo
1312  * @param tree
1313  * @param offset
1314  * @return modified offset
1315  */
1316 static guint
1317 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1318
1319 /**
1320  * WritePropertyMultiple-Error ::= SEQUENCE {
1321  *    errorType     [0] Error,
1322  *    firstFailedWriteAttempt  [1] Unsigned
1323  *    }
1324  * }
1325  * @param tvb
1326  * @pram pinfo
1327  * @param tree
1328  * @param offset
1329  * @return modified offset
1330  */
1331 static guint
1332 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1333
1334 /**
1335  * VTClose-Error ::= SEQUENCE {
1336  *    errorType     [0] Error,
1337  *    listOfVTSessionIdentifiers  [1] SEQUENCE OF Unsigned8 OPTIONAL
1338  *    }
1339  * }
1340  * @param tvb
1341  * @param pinfo
1342  * @param tree
1343  * @param offset
1344  * @return modified offset
1345  */
1346 static guint
1347 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1348
1349 /**
1350  * BACnet Application Types chapter 20.2.1
1351  * @param tvb
1352  * @param pinfo
1353  * @param tree
1354  * @param offset
1355  * @param label
1356  * @return modified offset
1357  */
1358 static guint
1359 fApplicationTypes   (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1360
1361 /**
1362  * BACnetActionCommand ::= SEQUENCE {
1363  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1364  *  objectIdentifier    [1] BACnetObjectIdentifier,
1365  *  propertyIdentifier  [2] BACnetPropertyIdentifier,
1366  *  propertyArrayIndex  [3] Unsigned OPTIONAL, -- used only with array datatype
1367  *  propertyValue       [4] ABSTRACT-SYNTAX.&Type,
1368  *  priority            [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1369  *  postDelay           [6] Unsigned OPTIONAL,
1370  *  quitOnFailure       [7] BOOLEAN,
1371  *  writeSuccessful     [8] BOOLEAN
1372  * }
1373  * @param tvb
1374  * @param pinfo
1375  * @param tree
1376  * @param offset
1377  * @param matching tag number
1378  * @return modified offset
1379  */
1380 static guint
1381 fActionCommand (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match);
1382
1383 /**
1384  * BACnetActionList ::= SEQUENCE {
1385  *  action  [0] SEQUENCE of BACnetActionCommand
1386  * }
1387  * @param tvb
1388  * @param pinfo
1389  * @param tree
1390  * @param offset
1391  * @return modified offset
1392  */
1393 static guint
1394 fActionList (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1395
1396 /** BACnetAddress ::= SEQUENCE {
1397  *  network-number  Unsigned16, -- A value 0 indicates the local network
1398  *  mac-address     OCTET STRING -- A string of length 0 indicates a broadcast
1399  * }
1400  * @param tvb
1401  * @param tree
1402  * @param offset
1403  * @return modified offset
1404  */
1405 static guint
1406 fAddress (tvbuff_t *tvb, proto_tree *tree, guint offset);
1407
1408 /**
1409  * BACnetAddressBinding ::= SEQUENCE {
1410  *      deviceObjectID  BACnetObjectIdentifier
1411  *      deviceAddress   BacnetAddress
1412  * }
1413  * @param tvb
1414  * @param pinfo
1415  * @param tree
1416  * @param offset
1417  * @return modified offset
1418  */
1419 static guint
1420 fAddressBinding (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1421
1422 /**
1423  * BACnetCalendaryEntry ::= CHOICE {
1424  *      date        [0] Date,
1425  *      dateRange   [1] BACnetDateRange,
1426  *  weekNDay    [2] BacnetWeekNday
1427  * }
1428  * @param tvb
1429  * @param tree
1430  * @param offset
1431  * @return modified offset
1432  */
1433 static guint
1434 fCalendaryEntry (tvbuff_t *tvb, proto_tree *tree, guint offset);
1435
1436 /**
1437  * BACnetClientCOV ::= CHOICE {
1438  *      real-increment  REAL,
1439  *      default-increment   NULL
1440  * }
1441  * @param tvb
1442  * @param tree
1443  * @param offset
1444  * @return modified offset
1445  */
1446 static guint
1447 fClientCOV (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1448
1449
1450 /**
1451  * BACnetDailySchedule ::= SEQUENCE {
1452  *  day-schedule    [0] SENQUENCE OF BACnetTimeValue
1453  * }
1454  * @param tvb
1455  * @param pinfo
1456  * @param tree
1457  * @param offset
1458  * @return modified offset
1459  */
1460 static guint
1461 fDailySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1462
1463 /**
1464  * BACnetWeeklySchedule ::= SEQUENCE {
1465  *  week-schedule    SENQUENCE SIZE (7) OF BACnetDailySchedule
1466  * }
1467  * @param tvb
1468  * @param pinfo
1469  * @param tree
1470  * @param offset
1471  * @return modified offset
1472  */
1473 static guint
1474 fWeeklySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1475
1476 /**
1477  * BACnetDateRange ::= SEQUENCE {
1478  *  StartDate   Date,
1479  *  EndDate     Date
1480  * }
1481  * @param tvb
1482  * @param tree
1483  * @param offset
1484  * @return modified offset
1485  */
1486 static guint
1487 fDateRange (tvbuff_t *tvb, proto_tree *tree, guint offset);
1488
1489 /**
1490  * BACnetDateTime ::= SEQUENCE {
1491  *  date   Date,
1492  *  time   Time
1493  * }
1494  * @param tvb
1495  * @param tree
1496  * @param offset
1497  * @param label
1498  * @return modified offset
1499  */
1500 static guint
1501 fDateTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
1502
1503 /**
1504  * BACnetDestination ::= SEQUENCE {
1505  *  validDays   BACnetDaysOfWeek,
1506  *  fromTime    Time,
1507  *  toTime      Time,
1508  *  recipient   BACnetRecipient,
1509  *  processIdentifier   Unsigned32,
1510  *  issueConfirmedNotifications BOOLEAN,
1511  *  transitions BACnetEventTransitionBits
1512  * }
1513  * @param tvb
1514  * @param pinfo
1515  * @param tree
1516  * @param offset
1517  * @return modified offset
1518  */
1519 static guint
1520 fDestination (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1521
1522 /**
1523  * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1524  *  objectIdentifier    [0] BACnetObjectIdentifier,
1525  *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1526  *  propertyArrayIndex  [2] Unsigend OPTIONAL,
1527  *  deviceIdentifier    [3] BACnetObjectIdentifier OPTIONAL
1528  * }
1529  * @param tvb
1530  * @param pinfo
1531  * @param tree
1532  * @param offset
1533  * @return modified offset
1534  */
1535 static guint
1536 fDeviceObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1537
1538 /**
1539  * BACnetDeviceObjectReference ::= SEQUENCE {
1540  *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1541  *  objectIdentifier    [1] BACnetObjectIdentifier
1542  * }
1543  * @param tvb
1544  * @param pinfo
1545  * @param tree
1546  * @param offset
1547  * @return modified offset
1548  */
1549 static guint
1550 fDeviceObjectReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1551
1552 #if 0
1553 /**
1554  * BACnetEventParameter ::= CHOICE {
1555  *      change-of-bitstring [0] SEQUENCE {
1556  *      time-delay [0] Unsigned,
1557  *      bitmask [1] BIT STRING,
1558  *      list-of-bitstring-values [2] SEQUENCE OF BIT STRING
1559  *      },
1560  *  change-of-state [1] SEQUENCE {
1561  *      time-delay [0] Unsigned,
1562  *      list-of-values [1] SEQUENCE OF BACnetPropertyStates
1563  *      },
1564  *   change-of-value [2] SEQUENCE {
1565  *      time-delay [0] Unsigned,
1566  *      cov-criteria [1] CHOICE {
1567  *              bitmask [0] BIT STRING,
1568  *              referenced-property-increment [1] REAL
1569  *                      }
1570  *              },
1571  *      command-failure [3] SEQUENCE {
1572  *              time-delay [0] Unsigned,
1573  *              feedback-property-reference [1] BACnetDeviceObjectPropertyReference
1574  *              },
1575  *      floating-limit [4] SEQUENCE {
1576  *              time-delay [0] Unsigned,
1577  *              setpoint-reference [1] BACnetDeviceObjectPropertyReference,
1578  *              low-diff-limit [2] REAL,
1579  *              high-diff-limit [3] REAL,
1580  *              deadband [4] REAL
1581  *              },
1582  *      out-of-range [5] SEQUENCE {
1583  *              time-delay [0] Unsigned,
1584  *              low-limit [1] REAL,
1585  *              high-limit [2] REAL,
1586  *              deadband [3] REAL
1587  *              },
1588  *      buffer-ready [7] SEQUENCE {
1589  *              notification-threshold [0] Unsigned,
1590  *              previous-notification-count [1] Unsigned32
1591  *              }
1592  *      change-of-life-safety [8] SEQUENCE {
1593  *              time-delay [0] Unsigned,
1594  *              list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1595  *              list-of-alarm-values [2] SEQUENCE OF BACnetLifeSafetyState,
1596  *              mode-property-reference [3] BACnetDeviceObjectPropertyReference
1597  *              }
1598  *      }
1599  * @param tvb
1600  * @param tree
1601  * @param offset
1602  * @return modified offset
1603  */
1604 static guint
1605 fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset);
1606 #endif
1607
1608
1609
1610 /**
1611  * BACnetLogRecord ::= SEQUENCE {
1612  *      timestamp [0] BACnetDateTime,
1613  *      logDatum [1] CHOICE {
1614  *              log-status [0] BACnetLogStatus,
1615  *              boolean-value [1] BOOLEAN,
1616  *              real-value [2] REAL,
1617  *              enum-value [3] ENUMERATED, -- Optionally limited to 32 bits
1618  *              unsigned-value [4] Unsigned, -- Optionally limited to 32 bits
1619  *              signed-value [5] INTEGER, -- Optionally limited to 32 bits
1620  *              bitstring-value [6] BIT STRING,-- Optionally limited to 32 bits
1621  *              null-value [7] NULL,
1622  *              failure [8] Error,
1623  *              time-change [9] REAL,
1624  *              any-value [10] ABSTRACT-SYNTAX.&Type -- Optional
1625  *              }
1626  *      statusFlags [2] BACnetStatusFlags OPTIONAL
1627  * }
1628  * @param tvb
1629  * @param pinfo
1630  * @param tree
1631  * @param offset
1632  * @return modified offset
1633  */
1634 static guint
1635 fLogRecord (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1636
1637
1638 /**
1639  * BACnetNotificationParameters ::= CHOICE {
1640  *      change-of-bitstring     [0]     SEQUENCE {
1641  *      referenced-bitstring    [0] BIT STRING,
1642  *      status-flags    [1] BACnetStatusFlags
1643  *      },
1644  *  change-of-state [1] SEQUENCE {
1645  *      new-state   [0] BACnetPropertyStatus,
1646  *      status-flags    [1] BACnetStatusFlags
1647  *      },
1648  *  change-of-value [2] SEQUENCE {
1649  *      new-value   [0] CHOICE {
1650  *          changed-bits   [0] BIT STRING,
1651  *          changed-value    [1] REAL
1652  *          },
1653  *      status-flags    [1] BACnetStatusFlags
1654  *      },
1655  *  command-failure [3] SEQUENCE {
1656  *      command-value   [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1657  *      status-flags    [1] BACnetStatusFlags
1658  *      feedback-value    [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1659  *      },
1660  *  floating-limit [4]  SEQUENCE {
1661  *      reference-value   [0] REAL,
1662  *      status-flags    [1] BACnetStatusFlags
1663  *      setpoint-value   [2] REAL,
1664  *      error-limit   [3] REAL
1665  *      },
1666  *  out-of-range [5]    SEQUENCE {
1667  *      exceeding-value   [0] REAL,
1668  *      status-flags    [1] BACnetStatusFlags
1669  *      deadband   [2] REAL,
1670  *      exceeded-limit   [0] REAL
1671  *      },
1672  *  complex-event-type  [6] SEQUENCE OF BACnetPropertyValue,
1673  *  buffer-ready [7]    SEQUENCE {
1674  *      buffer-device   [0] BACnetObjectIdentifier,
1675  *      buffer-object    [1] BACnetObjectIdentifier
1676  *      previous-notification   [2] BACnetDateTime,
1677  *      current-notification   [3] BACnetDateTime
1678  *      },
1679  *  change-of-life-safety [8]   SEQUENCE {
1680  *      new-state   [0] BACnetLifeSafetyState,
1681  *      new-mode    [1] BACnetLifeSafetyState
1682  *      status-flags   [2] BACnetStatusFlags,
1683  *      operation-expected   [3] BACnetLifeSafetyOperation
1684  *      }
1685  * }
1686  * @param tvb
1687  * @param pinfo
1688  * @param tree
1689  * @param offset
1690  * @return modified offset
1691  */
1692 static guint
1693 fNotificationParameters (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1694
1695 /**
1696  * BACnetObjectPropertyReference ::= SEQUENCE {
1697  *      objectIdentifier        [0] BACnetObjectIdentifier,
1698  *      propertyIdentifier      [1] BACnetPropertyIdentifier,
1699  *      propertyArrayIndex      [2] Unsigned OPTIONAL, -- used only with array datatype
1700  * }
1701  * @param tvb
1702  * @param pinfo
1703  * @param tree
1704  * @param offset
1705  * @return modified offset
1706  */
1707 static guint
1708 fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1709
1710 #if 0
1711 /**
1712  * BACnetObjectPropertyValue ::= SEQUENCE {
1713  *              objectIdentifier [0] BACnetObjectIdentifier,
1714  *              propertyIdentifier [1] BACnetPropertyIdentifier,
1715  *              propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1716  *                              -- if omitted with an array the entire array is referenced
1717  *              value [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1718  *              priority [4] Unsigned (1..16) OPTIONAL
1719  * }
1720  * @param tvb
1721  * @param tree
1722  * @param offset
1723  * @return modified offset
1724  */
1725 static guint
1726 fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset);
1727 #endif
1728
1729 /**
1730  * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1731  * @param tvb
1732  * @param pinfo
1733  * @param tree
1734  * @param offset
1735  * @return modified offset
1736  */
1737 static guint
1738 fPriorityArray (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1739
1740 static guint
1741 fPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list);
1742
1743 /**
1744  * BACnetPropertyReference ::= SEQUENCE {
1745  *      propertyIdentifier      [0] BACnetPropertyIdentifier,
1746  *      propertyArrayIndex      [1] Unsigned OPTIONAL, -- used only with array datatype
1747  * }
1748  * @param tvb
1749  * @param pinfo
1750  * @param tree
1751  * @param offset
1752  * @return modified offset
1753  */
1754 static guint
1755 fBACnetPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list);
1756
1757 /* static guint
1758 fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset); */
1759
1760 static guint
1761 fLOPR (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1762
1763 static guint
1764 fRestartReason (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1765
1766 /**
1767  * BACnetPropertyValue ::= SEQUENCE {
1768  *              PropertyIdentifier [0] BACnetPropertyIdentifier,
1769  *              propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1770  *                              -- if omitted with an array the entire array is referenced
1771  *              value [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1772  *              priority [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
1773  * }
1774  * @param tvb
1775  * @param pinfo
1776  * @param tree
1777  * @param offset
1778  * @return modified offset
1779  */
1780 static guint
1781 fBACnetPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1782
1783 static guint
1784 fPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset);
1785
1786 /**
1787  * BACnet Application PDUs chapter 21
1788  * BACnetRecipient::= CHOICE {
1789  *      device  [0] BACnetObjectIdentifier
1790  *      address [1] BACnetAddress
1791  * }
1792  * @param tvb
1793  * @param pinfo
1794  * @param tree
1795  * @param offset
1796  * @return modified offset
1797  */
1798 static guint
1799 fRecipient (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1800
1801 /**
1802  * BACnet Application PDUs chapter 21
1803  * BACnetRecipientProcess::= SEQUENCE {
1804  *      recipient       [0] BACnetRecipient
1805  *      processID       [1] Unsigned32
1806  * }
1807  * @param tvb
1808  * @param pinfo
1809  * @param tree
1810  * @param offset
1811  * @return modified offset
1812  */
1813 static guint
1814 fRecipientProcess (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1815
1816 static guint
1817 fCOVSubscription (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1818
1819 #if 0
1820 /**
1821  * BACnetSessionKey ::= SEQUENCE {
1822  *      sessionKey      OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
1823  *      peerAddress     BACnetAddress
1824  * }
1825  * @param tvb
1826  * @param tree
1827  * @param offset
1828  * @return modified offset
1829  * @todo check if checksum is displayed correctly
1830  */
1831 static guint
1832 fSessionKey (tvbuff_t *tvb, proto_tree *tree, guint offset);
1833 #endif
1834
1835 /**
1836  * BACnetSpecialEvent ::= SEQUENCE {
1837  *      period          CHOICE {
1838  *              calendarEntry           [0] BACnetCalendarEntry,
1839  *              calendarRefernce        [1] BACnetObjectIdentifier
1840  *              },
1841  *              listOfTimeValues        [2] SEQUENCE OF BACnetTimeValue,
1842  *              eventPriority           [3] Unsigned (1..16)
1843  * }
1844  * @param tvb
1845  * @param pinfo
1846  * @param tree
1847  * @param offset
1848  * @return modified offset
1849  */
1850 static guint
1851 fSpecialEvent (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1852
1853 /**
1854  * BACnetTimeStamp ::= CHOICE {
1855  *      time                    [0] Time,
1856  *      sequenceNumber  [1] Unsigned (0..65535),
1857  *      dateTime                [2] BACnetDateTime
1858  * }
1859  * @param tvb
1860  * @param tree
1861  * @param offset
1862  * @param label
1863  * @return modified offset
1864  */
1865 static guint
1866 fTimeStamp (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
1867
1868 /**
1869  * BACnetTimeValue ::= SEQUENCE {
1870  *      time    Time,
1871  *      value   ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
1872  * }
1873  * @param tvb
1874  * @param pinfo
1875  * @param tree
1876  * @param offset
1877  * @return modified offset
1878  */
1879 static guint
1880 fTimeValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1881
1882 #if 0
1883 /**
1884  * BACnetVTSession ::= SEQUENCE {
1885  *      local-vtSessionID       Unsigned8,
1886  *      remote-vtSessionID      Unsigned8,
1887  *      remote-vtAddress        BACnetAddress
1888  * }
1889  * @param tvb
1890  * @param tree
1891  * @param offset
1892  * @return modified offset
1893  */
1894 static guint
1895 fVTSession (tvbuff_t *tvb, proto_tree *tree, guint offset);
1896 #endif
1897
1898 /**
1899  * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
1900  * -- first octet month (1..12) January = 1, X'FF' = any month
1901  * -- second octet weekOfMonth where: 1 = days numbered 1-7
1902  * -- 2 = days numbered 8-14
1903  * -- 3 = days numbered 15-21
1904  * -- 4 = days numbered 22-28
1905  * -- 5 = days numbered 29-31
1906  * -- 6 = last 7 days of this month
1907  * -- X'FF' = any week of this month
1908  * -- third octet dayOfWeek (1..7) where 1 = Monday
1909  * -- 7 = Sunday
1910  * -- X'FF' = any day of week
1911  * @param tvb
1912  * @param tree
1913  * @param offset
1914  * @return modified offset
1915  */
1916 static guint
1917 fWeekNDay (tvbuff_t *tvb, proto_tree *tree, guint offset);
1918
1919 /**
1920  * ReadAccessResult ::= SEQUENCE {
1921  *      objectIdentifier        [0] BACnetObjectIdentifier,
1922  *      listOfResults   [1] SEQUENCE OF SEQUENCE {
1923  *              propertyIdentifier      [2] BACnetPropertyIdentifier,
1924  *              propertyArrayIndex      [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
1925  *              readResult      CHOICE {
1926  *                      propertyValue   [4] ABSTRACT-SYNTAX.&Type,
1927  *                      propertyAccessError     [5] Error
1928  *              }
1929  *  } OPTIONAL
1930  * }
1931  * @param tvb
1932  * @param pinfo
1933  * @param tree
1934  * @param offset
1935  * @return modified offset
1936  */
1937 static guint
1938 fReadAccessResult (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1939
1940 /**
1941  * ReadAccessSpecification ::= SEQUENCE {
1942  *      objectIdentifier        [0] BACnetObjectIdentifier,
1943  *      listOfPropertyReferences        [1] SEQUENCE OF BACnetPropertyReference
1944  * }
1945  * @param tvb
1946  * @param pinfo
1947  * @param tree
1948  * @param offset
1949  * @return modified offset
1950  */
1951 static guint
1952 fReadAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
1953
1954 /**
1955  * WriteAccessSpecification ::= SEQUENCE {
1956  *      objectIdentifier        [0] BACnetObjectIdentifier,
1957  *      listOfProperty  [1] SEQUENCE OF BACnetPropertyValue
1958  * }
1959  * @param tvb
1960  * @param pinfo
1961  * @param tree
1962  * @param offset
1963  * @return modified offset
1964  */
1965 static guint
1966 fWriteAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
1967
1968
1969 /********************************************************* Helper functions *******************************************/
1970
1971 /**
1972  * extracts the tag number from the tag header.
1973  * @param tvb "TestyVirtualBuffer"
1974  * @param offset in actual tvb
1975  * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
1976  */
1977 static guint
1978 fTagNo (tvbuff_t *tvb, guint offset);
1979
1980 /**
1981  * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
1982  * @param tvb = "TestyVirtualBuffer"
1983  * @param offset = offset in actual tvb
1984  * @return tag_no BACnet 20.2.1.2 Tag Number
1985  * @return class_tag BACnet 20.2.1.1 Class
1986  * @return lvt BACnet 20.2.1.3 Length/Value/Type
1987  * @return offs = length of this header
1988  */
1989
1990 static guint
1991 fTagHeader (tvbuff_t *tvb, guint offset, guint8 *tag_no, guint8* class_tag, guint32 *lvt);
1992
1993
1994 /**
1995  * adds processID with max 32Bit unsigned Integer Value to tree
1996  * @param tvb
1997  * @param tree
1998  * @param offset
1999  * @return modified offset
2000  */
2001 static guint
2002 fProcessId (tvbuff_t *tvb, proto_tree *tree, guint offset);
2003
2004 /**
2005  * adds timeSpan with max 32Bit unsigned Integer Value to tree
2006  * @param tvb
2007  * @param tree
2008  * @param offset
2009  * @return modified offset
2010  */
2011 static guint
2012 fTimeSpan (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
2013
2014 /**
2015  * BACnet Application PDUs chapter 21
2016  * BACnetPropertyIdentifier::= ENUMERATED {
2017  *       @see bacapp_property_identifier
2018  * }
2019  * @param tvb
2020  * @param pinfo
2021  * @param tree
2022  * @param offset
2023  * @param tt returnvalue of this item
2024  * @return modified offset
2025  */
2026 static guint
2027 fPropertyIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2028
2029 /**
2030  * BACnet Application PDUs chapter 21
2031  * BACnetPropertyArrayIndex::= ENUMERATED {
2032  *       @see bacapp_property_array_index
2033  * }
2034  * @param tvb
2035  * @param tree
2036  * @param offset
2037  * @param tt returnvalue of this item
2038  * @return modified offset
2039  */
2040 static guint
2041 fPropertyArrayIndex (tvbuff_t *tvb, proto_tree *tree, guint offset);
2042
2043 /**
2044  * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2045  *      objectIdentifier        [0] BACnetObjectIdentifier,
2046  *  eventState  [1] BACnetEventState,
2047  *  acknowledgedTransitions [2] BACnetEventTransitionBits,
2048  *  eventTimeStamps [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
2049  *  notifyType  [4] BACnetNotifyType,
2050  *  eventEnable [5] BACnetEventTransitionBits,
2051  *  eventPriorities [6] SEQUENCE SIZE (3) OF Unsigned
2052  * }
2053  * @param tvb
2054  * @param pinfo
2055  * @param tree
2056  * @param offset
2057  * @return modified offset
2058  */
2059 static guint
2060 flistOfEventSummaries (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2061
2062 /**
2063  * SelectionCriteria ::= SEQUENCE {
2064  *      propertyIdentifier      [0] BACnetPropertyIdentifier,
2065  *      propertyArrayIndex      [1] Unsigned OPTIONAL, -- used only with array datatype
2066  *  relationSpecifier   [2] ENUMERATED { bacapp_relationSpecifier },
2067  *  comparisonValue     [3] ABSTRACT-SYNTAX.&Type
2068  * }
2069  * @param tvb
2070  * @param pinfo
2071  * @param tree
2072  * @param offset
2073  * @return modified offset
2074  */
2075 static guint
2076 fSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2077
2078 /**
2079  * objectSelectionCriteria ::= SEQUENCE {
2080  *      selectionLogic  [0] ENUMERATED { bacapp_selectionLogic },
2081  *      listOfSelectionCriteria [1] SelectionCriteria
2082  * }
2083  * @param tvb
2084  * @param pinfo
2085  * @param tree
2086  * @param offset
2087  * @return modified offset
2088  */
2089 static guint
2090 fObjectSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2091
2092 /**
2093  * BACnet-Error ::= SEQUENCE {
2094  *    error-class ENUMERATED {},
2095  *    error-code  ENUMERATED {}
2096  *    }
2097  * }
2098  * @param tvb
2099  * @param pinfo
2100  * @param tree
2101  * @param offset
2102  * @return modified offset
2103  */
2104 static guint
2105 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2106
2107 /**
2108  * Generic handler for context tagged values.  Mostly for handling
2109  * vendor-defined properties and services.
2110  * @param tvb
2111  * @param tree
2112  * @param offset
2113  * @return modified offset
2114  * @todo beautify this ugly construct
2115  */
2116 static guint
2117 fContextTaggedValue(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
2118
2119 /**
2120  * realizes some ABSTRACT-SYNTAX.&Type
2121  * @param tvb
2122  * @param pinfo
2123  * @param tree
2124  * @param offset
2125  * @return modified offset
2126  * @todo beautify this ugly construct
2127  */
2128 static guint
2129 fAbstractSyntaxNType (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2130
2131
2132 static guint
2133 fBitStringTagVS (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
2134         const value_string *src);
2135
2136 /**
2137  * register_bacapp
2138  */
2139 void
2140 proto_register_bacapp(void);
2141
2142 /**
2143  * proto_reg_handoff_bacapp
2144  */
2145 void
2146 proto_reg_handoff_bacapp(void);
2147
2148 /**
2149  * converts XXX coded strings to UTF-8
2150  * else 'in' is copied to 'out'
2151  * @param in  -- pointer to string
2152  * @param inbytesleft
2153  * @param out -- pointer to string
2154  * @param outbytesleft
2155  * @param fromcoding
2156  * @return count of modified characters of returned string, -1 for errors
2157  */
2158 static guint32
2159 fConvertXXXtoUTF8(gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding);
2160
2161 static void
2162 uni_to_string(char * data, gsize str_length, char *dest_buf);
2163
2164 /* <<<< formerly bacapp.h */
2165
2166 /* some hashes for segmented messages */
2167 static GHashTable *msg_fragment_table = NULL;
2168 static GHashTable *msg_reassembled_table = NULL;
2169
2170 /* some necessary forward function prototypes */
2171 static guint
2172 fApplicationTypesEnumerated (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
2173         const gchar *label, const value_string *vs);
2174
2175 static const char *bacapp_unknown_service_str = "unknown service";
2176 static const char *ASHRAE_Reserved_Fmt = "(%d) Reserved for Use by ASHRAE";
2177 static const char *Vendor_Proprietary_Fmt = "(%d) Vendor Proprietary Value";
2178
2179 static const value_string
2180 BACnetTypeName[] = {
2181         {0, "Confirmed-REQ"},
2182         {1, "Unconfirmed-REQ"},
2183         {2, "Simple-ACK"},
2184         {3, "Complex-ACK"},
2185         {4, "Segment-ACK"},
2186         {5, "Error"},
2187         {6, "Reject"},
2188         {7, "Abort"},
2189         {0, NULL }
2190 };
2191
2192 static const true_false_string segments_follow = {
2193         "Segmented Request",
2194         "Unsegmented Request"
2195 };
2196
2197 static const true_false_string more_follow = {
2198         "More Segments Follow",
2199         "No More Segments Follow"
2200 };
2201
2202 static const true_false_string segmented_accept = {
2203         "Segmented Response accepted",
2204         "Segmented Response not accepted"
2205 };
2206
2207 static const true_false_string
2208 BACnetTagClass = {
2209         "Context Specific Tag",
2210         "Application Tag"
2211 };
2212
2213 static const value_string
2214 BACnetMaxSegmentsAccepted [] = {
2215         {0,"Unspecified"},
2216         {1,"2 segments"},
2217         {2,"4 segments"},
2218         {3,"8 segments"},
2219         {4,"16 segments"},
2220         {5,"32 segments"},
2221         {6,"64 segments"},
2222         {7,"Greater than 64 segments"},
2223         {0,NULL }
2224 };
2225
2226 static const value_string
2227 BACnetMaxAPDULengthAccepted [] = {
2228         {0,"Up to MinimumMessageSize (50 octets)"},
2229         {1,"Up to 128 octets"},
2230         {2,"Up to 206 octets (fits in a LonTalk frame)"},
2231         {3,"Up to 480 octets (fits in an ARCNET frame)"},
2232         {4,"Up to 1024 octets"},
2233         {5,"Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2234         {6,"reserved by ASHRAE"},
2235         {7,"reserved by ASHRAE"},
2236         {8,"reserved by ASHRAE"},
2237         {9,"reserved by ASHRAE"},
2238         {10,"reserved by ASHRAE"},
2239         {11,"reserved by ASHRAE"},
2240         {12,"reserved by ASHRAE"},
2241         {13,"reserved by ASHRAE"},
2242         {14,"reserved by ASHRAE"},
2243         {15,"reserved by ASHRAE"},
2244         {0,NULL}
2245 };
2246
2247 static const value_string
2248 BACnetRejectReason [] = {
2249         {0,"other"},
2250         {1,"buffer-overflow"},
2251         {2,"inconsistent-parameters"},
2252         {3,"invalid-parameter-data-type"},
2253         {4,"invalid-tag"},
2254         {5,"missing-required-parameter"},
2255         {6,"parameter-out-of-range"},
2256         {7,"too-many-arguments"},
2257         {8,"undefined-enumeration"},
2258         {9,"unrecognized-service"},
2259         {0,NULL}
2260 };
2261
2262 static const value_string
2263 BACnetRestartReason [] = {
2264         {0,"unknown"},
2265         {1,"coldstart"},
2266         {2,"warmstart"},
2267         {3,"detected-power-lost"},
2268         {4,"detected-powered-off"},
2269         {5,"hardware-watchdog"},
2270         {6,"software-watchdog"},
2271         {7,"suspended"},
2272         {0,NULL}
2273 };
2274
2275 static const value_string
2276 BACnetApplicationTagNumber [] = {
2277         {0,"Null"},
2278         {1,"Boolean"},
2279         {2,"Unsigned Integer"},
2280         {3,"Signed Integer (2's complement notation)"},
2281         {4,"Real (ANSI/IEE-754 floating point)"},
2282         {5,"Double (ANSI/IEE-754 double precision floating point)"},
2283         {6,"Octet String"},
2284         {7,"Character String"},
2285         {8,"Bit String"},
2286         {9,"Enumerated"},
2287         {10,"Date"},
2288         {11,"Time"},
2289         {12,"BACnetObjectIdentifier"},
2290         {13,"reserved by ASHRAE"},
2291         {14,"reserved by ASHRAE"},
2292         {15,"reserved by ASHRAE"},
2293         {0,NULL}
2294 };
2295
2296 static const value_string
2297 BACnetAction [] = {
2298         {0,"direct"},
2299         {1,"reverse"},
2300         {0,NULL}
2301 };
2302
2303 static const value_string
2304 BACnetFileAccessMethod [] = {
2305         {0,"record-access"},
2306         {1,"stream-access"},
2307         {0,NULL}
2308 };
2309
2310 /* For some reason, BACnet defines the choice parameter
2311    in the file read and write services backwards from the
2312    BACnetFileAccessMethod enumeration.
2313 */
2314 static const value_string
2315 BACnetFileAccessOption [] = {
2316         {0,"stream access"},
2317         {1,"record access"},
2318         {0,NULL}
2319 };
2320
2321 static const value_string
2322 BACnetFileStartOption [] = {
2323         {0, "File Start Position: "},
2324         {1, "File Start Record: "},
2325         {0, NULL}
2326 };
2327
2328 static const value_string
2329 BACnetFileRequestCount [] = {
2330         {0, "Requested Octet Count: "},
2331         {1, "Requested Record Count: "},
2332         {0, NULL}
2333 };
2334
2335 static const value_string
2336 BACnetFileWriteInfo [] = {
2337         {0, "File Data: "},
2338         {1, "Record Count: "},
2339         {0, NULL}
2340 };
2341
2342 static const value_string
2343 BACnetAbortReason [] = {
2344         {0,"other"},
2345         {1,"buffer-overflow"},
2346         {2,"invalid-apdu-in-this-state"},
2347         {3,"preempted-by-higher-priority-task"},
2348         {4,"segmentation-not-supported"},
2349         {0,NULL}
2350 };
2351
2352 static const value_string
2353 BACnetLifeSafetyMode [] = {
2354         {0,"off"},
2355         {1,"on"},
2356         {2,"test"},
2357         {3,"manned"},
2358         {4,"unmanned"},
2359         {5,"armed"},
2360         {6,"disarmed"},
2361         {7,"prearmed"},
2362         {8,"slow"},
2363         {9,"fast"},
2364         {10,"disconnected"},
2365         {11,"enabled"},
2366         {12,"disabled"},
2367         {13,"atomic-release-disabled"},
2368         {14,"default"},
2369         {0,NULL}
2370 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2371    Enumerated values 256-65535 may be used by others subject to
2372    procedures and constraints described in Clause 23. */
2373 };
2374
2375 static const value_string
2376 BACnetLifeSafetyOperation [] = {
2377         {0,"none"},
2378         {1,"silence"},
2379         {2,"silence-audible"},
2380         {3,"silence-visual"},
2381         {4,"reset"},
2382         {5,"reset-alarm"},
2383         {6,"reset-fault"},
2384         {7,"unsilence"},
2385         {8,"unsilence-audible"},
2386         {9,"unsilence-visual"},
2387         {0,NULL}
2388 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
2389    Enumerated values 64-65535 may be used by others subject to
2390    procedures and constraints described in Clause 23. */
2391 };
2392
2393 static const value_string
2394 BACnetLimitEnable [] = {
2395         {0,"lowLimitEnable"},
2396         {1,"highLimitEnable"},
2397         {0,NULL}
2398 };
2399
2400 static const value_string
2401 BACnetLifeSafetyState [] = {
2402         {0,"quiet"},
2403         {1,"pre-alarm"},
2404         {2,"alarm"},
2405         {3,"fault"},
2406         {4,"fault-pre-alarm"},
2407         {5,"fault-alarm"},
2408         {6,"not-ready"},
2409         {7,"active"},
2410         {8,"tamper"},
2411         {9,"test-alarm"},
2412         {10,"test-active"},
2413         {11,"test-fault"},
2414         {12,"test-fault-alarm"},
2415         {13,"holdup"},
2416         {14,"duress"},
2417         {15,"tamper-alarm"},
2418         {16,"abnormal"},
2419         {17,"emergency-power"},
2420         {18,"delayed"},
2421         {19,"blocked"},
2422         {20,"local-alarm"},
2423         {21,"general-alarm"},
2424         {22,"supervisory"},
2425         {23,"test-supervisory"},
2426         {0,NULL}
2427 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2428    Enumerated values 256-65535 may be used by others subject to
2429    procedures and constraints described in Clause 23. */
2430 };
2431
2432 static const value_string
2433 BACnetConfirmedServiceChoice [] = {
2434         {0,"acknowledgeAlarm"},
2435         {1,"confirmedCOVNotification"},
2436         {2,"confirmedEventNotification"},
2437         {3,"getAlarmSummary"},
2438         {4,"getEnrollmentSummary"},
2439         {5,"subscribeCOV"},
2440         {6,"atomicReadFile"},
2441         {7,"atomicWriteFile"},
2442         {8,"addListElement"},
2443         {9,"removeListElement"},
2444         {10,"createObject"},
2445         {11,"deleteObject"},
2446         {12,"readProperty"},
2447         {13,"readPropertyConditional"},
2448         {14,"readPropertyMultiple"},
2449         {15,"writeProperty"},
2450         {16,"writePropertyMultiple"},
2451         {17,"deviceCommunicationControl"},
2452         {18,"confirmedPrivateTransfer"},
2453         {19,"confirmedTextMessage"},
2454         {20,"reinitializeDevice"},
2455         {21,"vtOpen"},
2456         {22,"vtClose"},
2457         {23,"vtData"},
2458         {24,"authenticate"},
2459         {25,"requestKey"},
2460         {26,"readRange"},
2461         {27,"lifeSafetyOperation"},
2462         {28,"subscribeCOVProperty"},
2463         {29,"getEventInformation"},
2464         {30,"reserved by ASHRAE"},
2465         {0, NULL}
2466 };
2467
2468 static const value_string
2469 BACnetReliability [] = {
2470         {0,"no-fault-detected"},
2471         {1,"no-sensor"},
2472         {2,"over-range"},
2473         {3,"under-range"},
2474         {4,"open-loop"},
2475         {5,"shorted-loop"},
2476         {6,"no-output"},
2477         {7,"unreliable-other"},
2478         {8,"process-error"},
2479         {9,"multi-state-fault"},
2480         {0,NULL}
2481 };
2482
2483 static const value_string
2484 BACnetUnconfirmedServiceChoice [] = {
2485         {0,"i-Am"},
2486         {1,"i-Have"},
2487         {2,"unconfirmedCOVNotification"},
2488         {3,"unconfirmedEventNotification"},
2489         {4,"unconfirmedPrivateTransfer"},
2490         {5,"unconfirmedTextMessage"},
2491         {6,"timeSynchronization"},
2492         {7,"who-Has"},
2493         {8,"who-Is"},
2494         {9,"utcTimeSynchonization"},
2495         {0,NULL}
2496 };
2497
2498 static const value_string
2499 BACnetUnconfirmedServiceRequest [] = {
2500         {0,"i-Am-Request"},
2501         {1,"i-Have-Request"},
2502         {2,"unconfirmedCOVNotification-Request"},
2503         {3,"unconfirmedEventNotification-Request"},
2504         {4,"unconfirmedPrivateTransfer-Request"},
2505         {5,"unconfirmedTextMessage-Request"},
2506         {6,"timeSynchronization-Request"},
2507         {7,"who-Has-Request"},
2508         {8,"who-Is-Request"},
2509         {9,"utcTimeSynchonization-Request"},
2510         {0,NULL}
2511 };
2512
2513 static const value_string
2514 BACnetObjectType [] = {
2515         {0,"analog-input"},
2516         {1,"analog-output"},
2517         {2,"analog-value"},
2518         {3,"binary-input"},
2519         {4,"binary-output"},
2520         {5,"binary-value"},
2521         {6,"calendar"},
2522         {7,"command"},
2523         {8,"device"},
2524         {9,"event-enrollment"},
2525         {10,"file"},
2526         {11,"group"},
2527         {12,"loop"},
2528         {13,"multi-state-input"},
2529         {14,"multi-state-output"},
2530         {15,"notification-class"},
2531         {16,"program"},
2532         {17,"schedule"},
2533         {18,"averaging"},
2534         {19,"multi-state-value"},
2535         {20,"trend-log"},
2536         {21,"life-safety-point"},
2537         {22,"life-safety-zone"},
2538         {23,"accumulator"},
2539         {24,"pulse-converter"},
2540         {25,"event-log"},
2541         {26,"global-group"},
2542         {27,"trend-log-multiple"},
2543         {28,"load-control"},
2544         {29,"structured-view"},
2545         {30,"access-door"},             /* 30-37 added with addanda 135-2008j */
2546         {32,"access-credential"},
2547         {33,"access-point"},
2548         {34,"access-rights"},
2549         {35,"access-user"},
2550         {36,"access-zone"},
2551         {37,"credential-data-input"},
2552         {39,"bitstring-value"},         /* 39-50 added with addenda 135-2008w */
2553         {40,"characterstring-value"},
2554         {41,"date-pattern-value"},
2555         {42,"date-value"},
2556         {43,"datetime-pattern-value"},
2557         {44,"datetime-value"},
2558         {45,"integer-value"},
2559         {46,"large-analog-value"},
2560         {47,"octetstring-value"},
2561         {48,"positive-Integer-value"},
2562         {49,"time-pattern-value"},
2563         {50,"time-value"},
2564         {0, NULL}
2565 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
2566    Enumerated values 128-1023 may be used by others subject to
2567    the procedures and constraints described in Clause 23. */
2568 };
2569
2570 static const value_string
2571 BACnetEngineeringUnits [] = {
2572         {0,"Sq Meters"},
2573         {1,"Sq Feet"},
2574         {2,"Milliamperes"},
2575         {3,"Amperes"},
2576         {4,"Ohms"},
2577         {5,"Volts"},
2578         {6,"Kilovolts"},
2579         {7,"Megavolts"},
2580         {8,"Volt Amperes"},
2581         {9,"Kilovolt Amperes"},
2582         {10,"Megavolt Amperes"},
2583         {11,"Volt Amperes Reactive"},
2584         {12,"Kilovolt Amperes Reactive"},
2585         {13,"Megavolt Amperes Reactive"},
2586         {14,"Degrees Phase"},
2587         {15,"Power Factor"},
2588         {16,"Joules"},
2589         {17,"Kilojoules"},
2590         {18,"Watt Hours"},
2591         {19,"Kilowatt Hours"},
2592         {20,"BTUs"},
2593         {21,"Therms"},
2594         {22,"Ton Hours"},
2595         {23,"Joules Per Kg Dry Air"},
2596         {24,"BTUs Per Pound Dry Air"},
2597         {25,"Cycles Per Hour"},
2598         {26,"Cycles Per Minute"},
2599         {27,"Hertz"},
2600         {28,"Grams Of Water Per Kilogram Dry Air"},
2601         {29,"Relative Humidity"},
2602         {30,"Millimeters"},
2603         {31,"Meters"},
2604         {32,"Inches"},
2605         {33,"Feed"},
2606         {34,"Watts Per Sq Foot"},
2607         {35,"Watts Per Sq meter"},
2608         {36,"Lumens"},
2609         {37,"Lux"},
2610         {38,"Foot Candles"},
2611         {39,"Kilograms"},
2612         {40,"Pounds Mass"},
2613         {41,"Tons"},
2614         {42,"Kgs per Second"},
2615         {43,"Kgs Per Minute"},
2616         {44,"Kgs Per Hour"},
2617         {45,"Pounds Mass Per Minute"},
2618         {46,"Pounds Mass Per Hour"},
2619         {47,"Watt"},
2620         {48,"Kilowatts"},
2621         {49,"Megawatts"},
2622         {50,"BTUs Per Hour"},
2623         {51,"Horsepower"},
2624         {52,"Tons Refrigeration"},
2625         {53,"Pascals"},
2626         {54,"Kilopascals"},
2627         {55,"Bars"},
2628         {56,"Pounds Force Per Square Inch"},
2629         {57,"Centimeters Of Water"},
2630         {58,"Inches Of Water"},
2631         {59,"Millimeters Of Mercury"},
2632         {60,"Centimeters Of Mercury"},
2633         {61,"Inches Of Mercury"},
2634         {62,"Degrees Celsius"},
2635         {63,"Degrees Kelvin"},
2636         {64,"Degrees Fahrenheit"},
2637         {65,"Degree Days Celsius"},
2638         {66,"Degree Days Fahrenheit"},
2639         {67,"Years"},
2640         {68,"Months"},
2641         {69,"Weeks"},
2642         {70,"Days"},
2643         {71,"Hours"},
2644         {72,"Minutes"},
2645         {73,"Seconds"},
2646         {74,"Meters Per Second"},
2647         {75,"Kilometers Per Hour"},
2648         {76,"Feed Per Second"},
2649         {77,"Feet Per Minute"},
2650         {78,"Miles Per Hour"},
2651         {79,"Cubic Feet"},
2652         {80,"Cubic Meters"},
2653         {81,"Imperial Gallons"},
2654         {82,"Liters"},
2655         {83,"US Gallons"},
2656         {84,"Cubic Feet Per Minute"},
2657         {85,"Cubic Meters Per Second"},
2658         {86,"Imperial Gallons Per Minute"},
2659         {87,"Liters Per Second"},
2660         {88,"Liters Per Minute"},
2661         {89,"US Gallons Per Minute"},
2662         {90,"Degrees Angular"},
2663         {91,"Degrees Celsius Per Hour"},
2664         {92,"Degrees Celsius Per Minute"},
2665         {93,"Degrees Fahrenheit Per Hour"},
2666         {94,"Degrees Fahrenheit Per Minute"},
2667         {95,"No Units"},
2668         {96,"Parts Per Million"},
2669         {97,"Parts Per Billion"},
2670         {98,"Percent"},
2671         {99,"Pecent Per Second"},
2672         {100,"Per Minute"},
2673         {101,"Per Second"},
2674         {102,"Psi Per Degree Fahrenheit"},
2675         {103,"Radians"},
2676         {104,"Revolutions Per Min"},
2677         {105,"Currency1"},
2678         {106,"Currency2"},
2679         {107,"Currency3"},
2680         {108,"Currency4"},
2681         {109,"Currency5"},
2682         {110,"Currency6"},
2683         {111,"Currency7"},
2684         {112,"Currency8"},
2685         {113,"Currency9"},
2686         {114,"Currency10"},
2687         {115,"Sq Inches"},
2688         {116,"Sq Centimeters"},
2689         {117,"BTUs Per Pound"},
2690         {118,"Centimeters"},
2691         {119,"Pounds Mass Per Second"},
2692         {120,"Delta Degrees Fahrenheit"},
2693         {121,"Delta Degrees Kelvin"},
2694         {122,"Kilohms"},
2695         {123,"Megohms"},
2696         {124,"Millivolts"},
2697         {125,"Kilojoules Per Kg"},
2698         {126,"Megajoules"},
2699         {127,"Joules Per Degree Kelvin"},
2700         {128,"Joules Per Kg Degree Kelvin"},
2701         {129,"Kilohertz"},
2702         {130,"Megahertz"},
2703         {131,"Per Hour"},
2704         {132,"Milliwatts"},
2705         {133,"Hectopascals"},
2706         {134,"Millibars"},
2707         {135,"Cubic Meters Per Hour"},
2708         {136,"Liters Per Hour"},
2709         {137,"KWatt Hours Per Square Meter"},
2710         {138,"KWatt Hours Per Square Foot"},
2711         {139,"Megajoules Per Square Meter"},
2712         {140,"Megajoules Per Square Foot"},
2713         {141,"Watts Per Sq Meter Degree Kelvin"},
2714         {142,"Cubic Feet Per Second"},
2715         {143,"Percent Obstruction Per Foot"},
2716         {144,"Percent Obstruction Per Meter"},
2717         {145,"milliohms"},
2718         {146,"megawatt-hours"},
2719         {147,"kilo-btus"},
2720         {148,"mega-btus"},
2721         {149,"kilojoules-per-kilogram-dry-air"},
2722         {150,"megajoules-per-kilogram-dry-air"},
2723         {151,"kilojoules-per-degree-Kelvin"},
2724         {152,"megajoules-per-degree-Kelvin"},
2725         {153,"newton"},
2726         {154,"grams-per-second"},
2727         {155,"grams-per-minute"},
2728         {156,"tons-per-hour"},
2729         {157,"kilo-btus-per-hour"},
2730         {158,"hundredths-seconds"},
2731         {159,"milliseconds"},
2732         {160,"newton-meters"},
2733         {161,"millimeters-per-second"},
2734         {162,"millimeters-per-minute"},
2735         {163,"meters-per-minute"},
2736         {164,"meters-per-hour"},
2737         {165,"cubic-meters-per-minute"},
2738         {166,"meters-per-second-per-second"},
2739         {167,"amperes-per-meter"},
2740         {168,"amperes-per-square-meter"},
2741         {169,"ampere-square-meters"},
2742         {170,"farads"},
2743         {171,"henrys"},
2744         {172,"ohm-meters"},
2745         {173,"siemens"},
2746         {174,"siemens-per-meter"},
2747         {175,"teslas"},
2748         {176,"volts-per-degree-Kelvin"},
2749         {177,"volts-per-meter"},
2750         {178,"webers"},
2751         {179,"candelas"},
2752         {180,"candelas-per-square-meter"},
2753         {181,"degrees-Kelvin-per-hour"},
2754         {182,"degrees-Kelvin-per-minute"},
2755         {183,"joule-seconds"},
2756         {184,"radians-per-second"},
2757         {185,"square-meters-per-Newton"},
2758         {186,"kilograms-per-cubic-meter"},
2759         {187,"newton-seconds"},
2760         {188,"newtons-per-meter"},
2761         {189,"watts-per-meter-per-degree-Kelvin"},
2762         {0,NULL}
2763 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2764    Enumerated values 256-65535 may be used by others subject to
2765    the procedures and constraints described in Clause 23. */
2766 };
2767
2768 static const value_string
2769 BACnetErrorCode [] = {
2770         {0,"other"},
2771         {1,"authentication-failed"},
2772         {2,"configuration-in-progress"},
2773         {3,"device-busy"},
2774         {4,"dynamic-creation-not-supported"},
2775         {5,"file-access-denied"},
2776         {6,"incompatible-security-levels"},
2777         {7,"inconsistent-parameters"},
2778         {8,"inconsistent-selection-criterion"},
2779         {9,"invalid-data-type"},
2780         {10,"invalid-file-access-method"},
2781         {11,"invalid-file-start-position"},
2782         {12,"invalid-operator-name"},
2783         {13,"invalid-parameter-data-type"},
2784         {14,"invalid-time-stamp"},
2785         {15,"key-generation-error"},
2786         {16,"missing-required-parameter"},
2787         {17,"no-objects-of-specified-type"},
2788         {18,"no-space-for-object"},
2789         {19,"no-space-to-add-list-element"},
2790         {20,"no-space-to-write-property"},
2791         {21,"no-vt-sessions-available"},
2792         {22,"property-is-not-a-list"},
2793         {23,"object-deletion-not-permitted"},
2794         {24,"object-identifier-already-exists"},
2795         {25,"operational-problem"},
2796         {26,"password-failure"},
2797         {27,"read-access-denied"},
2798         {28,"security-not-supported"},
2799         {29,"service-request-denied"},
2800         {30,"timeout"},
2801         {31,"unknown-object"},
2802         {32,"unknown-property"},
2803         {33,"removed enumeration"},
2804         {34,"unknown-vt-class"},
2805         {35,"unknown-vt-session"},
2806         {36,"unsupported-object-type"},
2807         {37,"value-out-of-range"},
2808         {38,"vt-session-already-closed"},
2809         {39,"vt-session-termination-failure"},
2810         {40,"write-access-denied"},
2811         {41,"character-set-not-supported"},
2812         {42,"invalid-array-index"},
2813         {43,"cov-subscription-failed"},
2814         {44,"not-cov-property"},
2815         {45,"optional-functionality-not-supported"},
2816         {46,"invalid-configuration-data"},
2817         {47,"datatype-not-supported"},
2818         {48,"duplicate-name"},
2819         {49,"duplicate-object-id"},
2820         {50,"property-is-not-an-array"},
2821         {73,"invalid-event-state"},
2822         {74,"no-alarm-configured"},
2823         {0, NULL}
2824 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2825    Enumerated values 256-65535 may be used by others subject to the
2826    procedures and constraints described in Clause 23. */
2827 };
2828
2829 static const value_string
2830 BACnetPropertyIdentifier [] = {
2831         {0,"acked-transition"},
2832         {1,"ack-required"},
2833         {2,"action"},
2834         {3,"action-text"},
2835         {4,"active-text"},
2836         {5,"active-vt-session"},
2837         {6,"alarm-value"},
2838         {7,"alarm-values"},
2839         {8,"all"},
2840         {9,"all-write-successful"},
2841         {10,"apdu-segment-timeout"},
2842         {11,"apdu-timeout"},
2843         {12,"application-software-version"},
2844         {13,"archive"},
2845         {14,"bias"},
2846         {15,"change-of-state-count"},
2847         {16,"change-of-state-time"},
2848         {17,"notification-class"},
2849         {18,"the property in this place was deleted"},
2850         {19,"controlled-variable-reference"},
2851         {20,"controlled-variable-units"},
2852         {21,"controlled-variable-value"},
2853         {22,"cov-increment"},
2854         {23,"datelist"},
2855         {24,"daylights-savings-status"},
2856         {25,"deadband"},
2857         {26,"derivative-constant"},
2858         {27,"derivative-constant-units"},
2859         {28,"description"},
2860         {29,"description-of-halt"},
2861         {30,"device-address-binding"},
2862         {31,"device-type"},
2863         {32,"effective-period"},
2864         {33,"elapsed-active-time"},
2865         {34,"error-limit"},
2866         {35,"event-enable"},
2867         {36,"event-state"},
2868         {37,"event-type"},
2869         {38,"exception-schedule"},
2870         {39,"fault-values"},
2871         {40,"feedback-value"},
2872         {41,"file-access-method"},
2873         {42,"file-size"},
2874         {43,"file-type"},
2875         {44,"firmware-revision"},
2876         {45,"high-limit"},
2877         {46,"inactive-text"},
2878         {47,"in-progress"},
2879         {48,"instance-of"},
2880         {49,"integral-constant"},
2881         {50,"integral-constant-units"},
2882         {51,"issue-confirmed-notifications"},
2883         {52,"limit-enable"},
2884         {53,"list-of-group-members"},
2885         {54,"list-of-object-property-references"},
2886         {55,"list-of-session-keys"},
2887         {56,"local-date"},
2888         {57,"local-time"},
2889         {58,"location"},
2890         {59,"low-limit"},
2891         {60,"manipulated-variable-reference"},
2892         {61,"maximum-output"},
2893         {62,"max-apdu-length-accepted"},
2894         {63,"max-info-frames"},
2895         {64,"max-master"},
2896         {65,"max-pres-value"},
2897         {66,"minimum-off-time"},
2898         {67,"minimum-on-time"},
2899         {68,"minimum-output"},
2900         {69,"min-pres-value"},
2901         {70,"model-name"},
2902         {71,"modification-date"},
2903         {72,"notify-type"},
2904         {73,"number-of-APDU-retries"},
2905         {74,"number-of-states"},
2906         {75,"object-identifier"},
2907         {76,"object-list"},
2908         {77,"object-name"},
2909         {78,"object-property-reference"},
2910         {79,"object-type"},
2911         {80,"optional"},
2912         {81,"out-of-service"},
2913         {82,"output-units"},
2914         {83,"event-parameters"},
2915         {84,"polarity"},
2916         {85,"present-value"},
2917         {86,"priority"},
2918         {87,"priority-array"},
2919         {88,"priority-for-writing"},
2920         {89,"process-identifier"},
2921         {90,"program-change"},
2922         {91,"program-location"},
2923         {92,"program-state"},
2924         {93,"proportional-constant"},
2925         {94,"proportional-constant-units"},
2926         {95,"protocol-conformance-class"},
2927         {96,"protocol-object-types-supported"},
2928         {97,"protocol-services-supported"},
2929         {98,"protocol-version"},
2930         {99,"read-only"},
2931         {100,"reason-for-halt"},
2932         {101,"recipient"},
2933         {102,"recipient-list"},
2934         {103,"reliability"},
2935         {104,"relinquish-default"},
2936         {105,"required"},
2937         {106,"resolution"},
2938         {107,"segmentation-supported"},
2939         {108,"setpoint"},
2940         {109,"setpoint-reference"},
2941         {110,"state-text"},
2942         {111,"status-flags"},
2943         {112,"system-status"},
2944         {113,"time-delay"},
2945         {114,"time-of-active-time-reset"},
2946         {115,"time-of-state-count-reset"},
2947         {116,"time-synchronization-recipients"},
2948         {117,"units"},
2949         {118,"update-interval"},
2950         {119,"utc-offset"},
2951         {120,"vendor-identifier"},
2952         {121,"vendor-name"},
2953         {122,"vt-class-supported"},
2954         {123,"weekly-schedule"},
2955         {124,"attempted-samples"},
2956         {125,"average-value"},
2957         {126,"buffer-size"},
2958         {127,"client-cov-increment"},
2959         {128,"cov-resubscription-interval"},
2960         {129,"current-notify-time"},
2961         {130,"event-time-stamp"},
2962         {131,"log-buffer"},
2963         {132,"log-device-object-property"},
2964         {133,"enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
2965         {134,"log-interval"},
2966         {135,"maximum-value"},
2967         {136,"minimum-value"},
2968         {137,"notification-threshold"},
2969         {138,"previous-notify-time"},
2970         {139,"protocol-revision"},
2971         {140,"records-since-notification"},
2972         {141,"record-count"},
2973         {142,"start-time"},
2974         {143,"stop-time"},
2975         {144,"stop-when-full"},
2976         {145,"total-record-count"},
2977         {146,"valid-samples"},
2978         {147,"window-interval"},
2979         {148,"window-samples"},
2980         {149,"maximum-value-time-stamp"},
2981         {150,"minimum-value-time-stamp"},
2982         {151,"variance-value"},
2983         {152,"active-cov-subscriptions"},
2984         {153,"backup-failure-timeout"},
2985         {154,"configuration-files"},
2986         {155,"database-revision"},
2987         {156,"direct-reading"},
2988         {157,"last-restore-time"},
2989         {158,"maintenance-required"},
2990         {159,"member-of"},
2991         {160,"mode"},
2992         {161,"operation-expected"},
2993         {162,"setting"},
2994         {163,"silenced"},
2995         {164,"tracking-value"},
2996         {165,"zone-members"},
2997         {166,"life-safety-alarm-values"},
2998         {167,"max-segments-accepted"},
2999         {168,"profile-name"},
3000         {169,"auto-slave-discovery"},
3001         {170,"manual-slave-address-binding"},
3002         {171,"slave-address-binding"},
3003         {172,"slave-proxy-enable"},
3004         {173,"last-notify-record"},             /* bug 4117 */
3005         {174,"schedule-default"},
3006         {175,"accepted-modes"},
3007         {176,"adjust-value"},
3008         {177,"count"},
3009         {178,"count-before-change"},
3010         {179,"count-change-time"},
3011         {180,"cov-period"},
3012         {181,"input-reference"},
3013         {182,"limit-monitoring-interval"},
3014         {183,"logging-device"},
3015         {184,"logging-record"},
3016         {185,"prescale"},
3017         {186,"pulse-rate"},
3018         {187,"scale"},
3019         {188,"scale-factor"},
3020         {189,"update-time"},
3021         {190,"value-before-change"},
3022         {191,"value-set"},
3023         {192,"value-change-time"},
3024         {193,"align-intervals"},
3025         {194,"group-member-names"},
3026         {195,"interval-offset"},
3027         {196,"last-restart-reason"},
3028         {197,"logging-type"},
3029         {198,"member-status-flags"},
3030         {199,"notification-period"},
3031         {200,"previous-notify-record"},
3032         {201,"requested-update-interval"},
3033         {202,"restart-notification-recipients"},
3034         {203,"time-of-device-restart"},
3035         {204,"time-synchronization-recipients"},
3036         {205,"trigger"},
3037         {206,"UTC-time-synchronization-recipients"},
3038         {207,"node-subtype"},
3039         {208,"node-type"},
3040         {209,"structured-object-list"},
3041         {210,"subordinate-annotations"},
3042         {211,"subordinate-list"},
3043         {212,"actual-shed-level"},
3044         {213,"duty-window"},
3045         {214,"expected-shed-level"},
3046         {215,"full-duty-baseline"},
3047         {216,"node-subtype"},
3048         {217,"node-type"},
3049         {218,"requested-shed-level"},
3050         {219,"shed-duration"},
3051         {220,"shed-level-descriptions"},
3052         {221,"shed-levels"},
3053         {222,"state-description"},
3054         {226,"door-alarm-state"},
3055         {227,"door-extended-pulse-time"},
3056         {228,"door-members"},
3057         {229,"door-open-too-long-time"},
3058         {230,"door-pulse-time"},
3059         {231,"door-status"},
3060         {232,"door-unlock-delay-time"},
3061         {233,"lock-status"},
3062         {234,"masked-alarm-values"},
3063         {235,"secured-status"},
3064         {244,"absentee-limit"},         /* added with addenda 135-2008j */
3065         {245,"access-alarm-events"},
3066         {246,"access-doors"},
3067         {247,"access-event"},
3068         {248,"access-event-authentication-factor"},
3069         {249,"access-event-credential"},
3070         {250,"access-event-time"},
3071         {251,"access-transaction-events"},
3072         {252,"accompaniment"},
3073         {253,"accompaniment-time"},
3074         {254,"activation-time"},
3075         {255,"active-authentication-policy"},
3076         {256,"assigned-access-rights"},
3077         {257,"authentication-factors"},
3078         {258,"authentication-policy-list"},
3079         {259,"authentication-policy-names"},
3080         {260,"authentication-status"},
3081         {261,"authorization-mode"},
3082         {262,"belongs-to"},
3083         {263,"credential-disable"},
3084         {264,"credential-status"},
3085         {265,"credentials"},
3086         {266,"credentials-in-zone"},
3087         {267,"days-remaining"},
3088         {268,"entry-points"},
3089         {269,"exit-points"},
3090         {270,"expiry-time"},
3091         {271,"extended-time-enable"},
3092         {272,"failed-attempt-events"},
3093         {273,"failed-attempts"},
3094         {274,"failed-attempts-time"},
3095         {275,"last-access-event"},
3096         {276,"last-access-point"},
3097         {277,"last-credential-added"},
3098         {278,"last-credential-added-time"},
3099         {279,"last-credential-removed"},
3100         {280,"last-credential-removed-time"},
3101         {281,"last-use-time"},
3102         {282,"lockout"},
3103         {283,"lockout-relinquish-time"},
3104         {284,"master-exemption"},
3105         {285,"max-failed-attempts"},
3106         {286,"members"},
3107         {287,"muster-point"},
3108         {288,"negative-access-rules"},
3109         {289,"number-of-authentication-policies"},
3110         {290,"occupancy-count"},
3111         {291,"occupancy-count-adjust"},
3112         {292,"occupancy-count-enable"},
3113         {293,"occupancy-exemption"},
3114         {294,"occupancy-lower-limit"},
3115         {295,"occupancy-lower-limit-enforced"},
3116         {296,"occupancy-state"},
3117         {297,"occupancy-upper-limit"},
3118         {298,"occupancy-upper-limit-enforced"},
3119         {299,"passback-exemption"},
3120         {300,"passback-mode"},
3121         {301,"passback-timeout"},
3122         {302,"positive-access-rules"},
3123         {303,"reason-for-disable"},
3124         {304,"supported-formats"},
3125         {305,"supported-format-classes"},
3126         {306,"threat-authority"},
3127         {307,"threat-level"},
3128         {308,"trace-flag"},
3129         {309,"transaction-notification-class"},
3130         {310,"user-external-identifier"},
3131         {311,"user-information-reference"},
3132         /* enumeration values 312-316 reserved for future addenda */
3133         {317,"user-name"},
3134         {318,"user-type"},
3135         {319,"uses-remaining"},
3136         {320,"zone-from"},
3137         {321,"zone-to"},
3138         {322,"access-event-tag"},
3139         {323,"global-identifier"},
3140         /* enumeration values 324-325 reserved for future addenda */
3141         {326,"verification-time"},
3142         {342,"bit-mask"},               /* addenda 135-2008w */
3143         {343,"bit-text"},
3144         {344,"is-utc"},
3145         {0, NULL}
3146 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
3147    Enumerated values 512-4194303 may be used by others subject to
3148    the procedures and constraints described in Clause 23. */
3149 };
3150
3151 static const value_string
3152 BACnetBinaryPV [] = {
3153         {0,"inactive"},
3154         {1,"active"},
3155         {0,NULL}
3156 };
3157
3158
3159 #define ANSI_X34 0
3160 #define IBM_MS_DBCS 1
3161 #define JIS_C_6226 2
3162 #define ISO_10646_UCS4 3
3163 #define ISO_10646_UCS2 4
3164 #define ISO_18859_1 5
3165 static const value_string
3166 BACnetCharacterSet [] = {
3167         {ANSI_X34,      "ANSI X3.4 / UTF-8 (since 2010)"},
3168         {IBM_MS_DBCS,   "IBM/Microsoft DBCS"},
3169         {JIS_C_6226,    "JIS C 6226"},
3170         {ISO_10646_UCS4, "ISO 10646(UCS-4)"},
3171         {ISO_10646_UCS2, "ISO 10646(UCS-2)"},
3172         {ISO_18859_1,   "ISO 18859-1"},
3173         {0,             NULL}
3174 };
3175
3176 static const value_string
3177 BACnetStatusFlags [] = {
3178         {0,"in-alarm"},
3179         {1,"fault"},
3180         {2,"overridden"},
3181         {3,"out-of-service"},
3182         {0,NULL}
3183 };
3184
3185 static const value_string
3186 BACnetMessagePriority [] = {
3187         {0,"normal"},
3188         {1,"urgent"},
3189         {0,NULL}
3190 };
3191
3192 static const value_string
3193 BACnetAcknowledgementFilter [] = {
3194         {0,"all"},
3195         {1,"acked"},
3196         {2,"not-acked"},
3197         {0,NULL}
3198 };
3199
3200 static const value_string
3201 BACnetResultFlags [] = {
3202         {0,"firstitem"},
3203         {1,"lastitem"},
3204         {2,"moreitems"},
3205         {0,NULL}
3206 };
3207
3208 static const value_string
3209 BACnetRelationSpecifier [] = {
3210         {0,"equal"},
3211         {1,"not-equal"},
3212         {2,"less-than"},
3213         {3,"greater-than"},
3214         {4,"less-than-or-equal"},
3215         {5,"greater-than-or-equal"},
3216         {0,NULL}
3217 };
3218
3219 static const value_string
3220 BACnetSelectionLogic [] = {
3221         {0,"and"},
3222         {1,"or"},
3223         {2,"all"},
3224         {0,NULL}
3225 };
3226
3227 static const value_string
3228 BACnetEventStateFilter [] = {
3229         {0,"offnormal"},
3230         {1,"fault"},
3231         {2,"normal"},
3232         {3,"all"},
3233         {4,"active"},
3234         {0,NULL}
3235 };
3236
3237 static const value_string
3238 BACnetEventTransitionBits [] = {
3239         {0,"to-offnormal"},
3240         {1,"to-fault"},
3241         {2,"to-normal"},
3242         {0,NULL}
3243 };
3244
3245 static const value_string
3246 BACnetSegmentation [] = {
3247         {0,"segmented-both"},
3248         {1,"segmented-transmit"},
3249         {2,"segmented-receive"},
3250         {3,"no-segmentation"},
3251         {0,NULL}
3252 };
3253
3254 static const value_string
3255 BACnetSilencedState [] = {
3256         {0,"unsilenced"},
3257         {1,"audible-silenced"},
3258         {2,"visible-silenced"},
3259         {3,"all-silenced"},
3260         {0,NULL}
3261 };
3262
3263 static const value_string
3264 BACnetDeviceStatus [] = {
3265         {0,"operational"},
3266         {1,"operational-read-only"},
3267         {2,"download-required"},
3268         {3,"download-in-progress"},
3269         {4,"non-operational"},
3270         {5,"backup-in-progress"},
3271         {0,NULL}
3272 };
3273
3274 static const value_string
3275 BACnetEnableDisable [] = {
3276         {0,"enable"},
3277         {1,"disable"},
3278         {2,"disable-initiation"},
3279         {0,NULL}
3280 };
3281
3282 static const value_string
3283 months [] = {
3284         {1,"January" },
3285         {2,"February" },
3286         {3,"March" },
3287         {4,"April" },
3288         {5,"May" },
3289         {6,"June" },
3290         {7,"July" },
3291         {8,"August" },
3292         {9,"September" },
3293         {10,"October" },
3294         {11,"November" },
3295         {12,"December" },
3296         {255,"any month" },
3297         {0,NULL }
3298 };
3299
3300 static const value_string
3301 weekofmonth [] = {
3302         {1,"days numbered 1-7" },
3303         {2,"days numbered 8-14" },
3304         {3,"days numbered 15-21" },
3305         {4,"days numbered 22-28" },
3306         {5,"days numbered 29-31" },
3307         {6,"last 7 days of this month" },
3308         {255,"any week of this month" },
3309         {0,NULL }
3310 };
3311
3312 /* note: notification class object recipient-list uses
3313    different day-of-week enum */
3314 static const value_string
3315 day_of_week [] = {
3316         {1,"Monday" },
3317         {2,"Tuesday" },
3318         {3,"Wednesday" },
3319         {4,"Thursday" },
3320         {5,"Friday" },
3321         {6,"Saturday" },
3322         {7,"Sunday" },
3323         {255,"any day of week" },
3324         {0,NULL }
3325 };
3326
3327 static const value_string
3328 BACnetErrorClass [] = {
3329         {0,"device" },
3330         {1,"object" },
3331         {2,"property" },
3332         {3,"resources" },
3333         {4,"security" },
3334         {5,"services" },
3335         {6,"vt" },
3336         {0,NULL }
3337 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3338    Enumerated values64-65535 may be used by others subject to
3339    the procedures and constraints described in Clause 23. */
3340 };
3341
3342 static const value_string
3343 BACnetVTClass [] = {
3344         {0,"default-terminal" },
3345         {1,"ansi-x3-64" },
3346         {2,"dec-vt52" },
3347         {3,"dec-vt100" },
3348         {4,"dec-vt200" },
3349         {5,"hp-700-94" },
3350         {6,"ibm-3130" },
3351         {0,NULL }
3352 };
3353
3354 static const value_string
3355 BACnetEventType [] = {
3356         {0,"change-of-bitstring" },
3357         {1,"change-of-state" },
3358         {2,"change-of-value" },
3359         {3,"command-failure" },
3360         {4,"floating-limit" },
3361         {5,"out-of-range" },
3362         {6,"complex-event-type" },
3363         {7,"buffer-ready" },
3364         {8,"change-of-life-safety" },
3365         {9,"extended" },
3366         {10,"buffer-ready" },
3367         {11,"unsigned-range" },
3368         {14,"double-out-of-range"},             /* added with addenda 135-2008w */
3369         {15,"signed-out-of-range"},
3370         {16,"unsigned-out-of-range"},
3371         {17,"change-of-characterstring"},
3372         {0,NULL }
3373 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3374    Enumerated values 64-65535 may be used by others subject to
3375    the procedures and constraints described in Clause 23.
3376    It is expected that these enumerated values will correspond
3377    to the use of the complex-event-type CHOICE [6] of the
3378    BACnetNotificationParameters production. */
3379 };
3380
3381 static const value_string
3382 BACnetEventState [] = {
3383         {0,"normal" },
3384         {1,"fault" },
3385         {2,"offnormal" },
3386         {3,"high-limit" },
3387         {4,"low-limit" },
3388         {5,"life-safety-alarm" },
3389         {0,NULL }
3390 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3391    Enumerated values 64-65535 may be used by others subject to
3392    the procedures and constraints described in Clause 23.  */
3393 };
3394
3395 static const value_string
3396 BACnetLogStatus [] = {
3397         {0,"log-disabled" },
3398         {1,"buffer-purged" },
3399         {0,NULL }
3400 };
3401
3402 static const value_string
3403 BACnetMaintenance [] = {
3404         {0,"none" },
3405         {1,"periodic-test" },
3406         {2,"need-service-operational" },
3407         {3,"need-service-inoperative" },
3408         {0,NULL }
3409 };
3410
3411 static const value_string
3412 BACnetNotifyType [] = {
3413         {0,"alarm" },
3414         {1,"event" },
3415         {2,"ack-notification" },
3416         {0,NULL }
3417 };
3418
3419 static const value_string
3420 BACnetServicesSupported [] = {
3421         {0,"acknowledgeAlarm"},
3422         {1,"confirmedCOVNotification"},
3423         {2,"confirmedEventNotification"},
3424         {3,"getAlarmSummary"},
3425         {4,"getEnrollmentSummary"},
3426         {5,"subscribeCOV"},
3427         {6,"atomicReadFile"},
3428         {7,"atomicWriteFile"},
3429         {8,"addListElement"},
3430         {9,"removeListElement"},
3431         {10,"createObject"},
3432         {11,"deleteObject"},
3433         {12,"readProperty"},
3434         {13,"readPropertyConditional"},
3435         {14,"readPropertyMultiple"},
3436         {15,"writeProperty"},
3437         {16,"writePropertyMultiple"},
3438         {17,"deviceCommunicationControl"},
3439         {18,"confirmedPrivateTransfer"},
3440         {19,"confirmedTextMessage"},
3441         {20,"reinitializeDevice"},
3442         {21,"vtOpen"},
3443         {22,"vtClose"},
3444         {23,"vtData"},
3445         {24,"authenticate"},
3446         {25,"requestKey"},
3447         {26,"i-Am"},
3448         {27,"i-Have"},
3449         {28,"unconfirmedCOVNotification"},
3450         {29,"unconfirmedEventNotification"},
3451         {30,"unconfirmedPrivateTransfer"},
3452         {31,"unconfirmedTextMessage"},
3453         {32,"timeSynchronization"},
3454         {33,"who-Has"},
3455         {34,"who-Is"},
3456         {35,"readRange"},
3457         {36,"utcTimeSynchronization"},
3458         {37,"lifeSafetyOperation"},
3459         {38,"subscribeCOVProperty"},
3460         {39,"getEventInformation"},
3461         {0, NULL}
3462 };
3463
3464 static const value_string
3465 BACnetPropertyStates [] = {
3466         {0,"boolean-value"},
3467         {1,"binary-value"},
3468         {2,"event-type"},
3469         {3,"polarity"},
3470         {4,"program-change"},
3471         {5,"program-state"},
3472         {6,"reason-for-halt"},
3473         {7,"reliability"},
3474         {8,"state"},
3475         {9,"system-status"},
3476         {10,"units"},
3477         {11,"unsigned-value"},
3478         {12,"life-safety-mode"},
3479         {13,"life-safety-state"},
3480         {14,"door-alarm-state"},
3481         {0,NULL}
3482 /* Tag values 0-63 are reserved for definition by ASHRAE.
3483    Tag values of 64-254 may be used by others to accommodate
3484    vendor specific properties that have discrete or enumerated values,
3485    subject to the constraints described in Clause 23. */
3486 };
3487
3488 static const value_string
3489 BACnetProgramError [] = {
3490         {0,"normal"},
3491         {1,"load-failed"},
3492         {2,"internal"},
3493         {3,"program"},
3494         {4,"other"},
3495         {0,NULL}
3496 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3497    Enumerated values 64-65535 may be used by others subject to
3498    the procedures and constraints described in Clause 23. */
3499 };
3500
3501 static const value_string
3502 BACnetProgramRequest [] = {
3503         {0,"ready"},
3504         {1,"load"},
3505         {2,"run"},
3506         {3,"halt"},
3507         {4,"restart"},
3508         {4,"unload"},
3509         {0,NULL}
3510 };
3511
3512 static const value_string
3513 BACnetProgramState [] = {
3514         {0,"idle"},
3515         {1,"loading"},
3516         {2,"running"},
3517         {3,"waiting"},
3518         {4,"halted"},
3519         {4,"unloading"},
3520         {0,NULL}
3521 };
3522
3523 static const value_string
3524 BACnetReinitializedStateOfDevice [] = {
3525         {0,"coldstart"},
3526         {1,"warmstart"},
3527         {2,"startbackup"},
3528         {3,"endbackup"},
3529         {4,"startrestore"},
3530         {5,"endrestore"},
3531         {6,"abortrestore"},
3532         {0,NULL}
3533 };
3534
3535 static const value_string
3536 BACnetPolarity [] = {
3537         {0,"normal"},
3538         {1,"reverse"},
3539         {0,NULL}
3540 };
3541
3542 static const value_string
3543 BACnetTagNames[] = {
3544         { 5, "Extended Value" },
3545         { 6, "Opening Tag" },
3546         { 7, "Closing Tag" },
3547         { 0, NULL }
3548 };
3549
3550 static const value_string
3551 BACnetReadRangeOptions[] = {
3552         { 3, "range byPosition" },
3553         { 4, "range byTime" },
3554         { 5, "range timeRange" },
3555         { 6, "range bySequenceNumber" },
3556         { 7, "range byTime" },
3557         { 0, NULL }
3558 };
3559
3560 /* Present_Value for Load Control Object */
3561 static const value_string
3562 BACnetShedState[] = {
3563         { 0, "shed-inactive" },
3564         { 1, "shed-request-pending" },
3565         { 2, "shed-compliant" },
3566         { 3, "shed-non-compliant" },
3567         { 0, NULL }
3568 };
3569
3570 static const value_string
3571 BACnetVendorIdentifiers [] = {
3572         { 0, "ASHRAE" },
3573         { 1, "NIST" },
3574         { 2, "The Trane Company" },
3575         { 3, "McQuay International" },
3576         { 4, "PolarSoft" },
3577         { 5, "Johnson Controls, Inc." },
3578         { 6, "American Auto-Matrix" },
3579         { 7, "Siemens Building Technologies, Ltd., Landis & Staefa Division Europe" },
3580         { 8, "Delta Controls" },
3581         { 9, "Siemens Building Technologies, Inc." },
3582         { 10, "Tour Andover Controls Corporation" },
3583         { 11, "TAC" },
3584         { 12, "Orion Analysis Corporation" },
3585         { 13, "Teletrol Systems Inc." },
3586         { 14, "Cimetrics Technology" },
3587         { 15, "Cornell University" },
3588         { 16, "United Technologies Carrier" },
3589         { 17, "Honeywell Inc." },
3590         { 18, "Alerton / Honeywell" },
3591         { 19, "TAC AB" },
3592         { 20, "Hewlett-Packard Company" },
3593         { 21, "Dorsette's Inc." },
3594         { 22, "Cerberus AG" },
3595         { 23, "York Controls Group" },
3596         { 24, "Automated Logic Corporation" },
3597         { 25, "CSI Control Systems International" },
3598         { 26, "Phoenix Controls Corporation" },
3599         { 27, "Innovex Technologies, Inc." },
3600         { 28, "KMC Controls, Inc." },
3601         { 29, "Xn Technologies, Inc." },
3602         { 30, "Hyundai Information Technology Co., Ltd." },
3603         { 31, "Tokimec Inc." },
3604         { 32, "Simplex" },
3605         { 33, "North Communications Limited" },
3606         { 34, "Notifier" },
3607         { 35, "Reliable Controls Corporation" },
3608         { 36, "Tridium Inc." },
3609         { 37, "Sierra Monitor Corp." },
3610         { 38, "Silicon Energy" },
3611         { 39, "Kieback & Peter GmbH & Co KG" },
3612         { 40, "Anacon Systems, Inc." },
3613         { 41, "Systems Controls & Instruments, LLC" },
3614         { 42, "Lithonia Lighting" },
3615         { 43, "Micropower Manufacturing" },
3616         { 44, "Matrix Controls" },
3617         { 45, "METALAIRE" },
3618         { 46, "ESS Engineering" },
3619         { 47, "Sphere Systems Pty Ltd." },
3620         { 48, "Walker Technologies Corporation" },
3621         { 49, "H I Solutions, Inc." },
3622         { 50, "MBS GmbH" },
3623         { 51, "SAMSON AG" },
3624         { 52, "Badger Meter Inc." },
3625         { 53, "DAIKIN Industries Ltd." },
3626         { 54, "NARA Controls Inc." },
3627         { 55, "Mammoth Inc." },
3628         { 56, "Liebert Corporation" },
3629         { 57, "SEMCO Incorporated" },
3630         { 58, "Air Monitor Corporation" },
3631         { 59, "TRIATEK, Inc." },
3632         { 60, "NexLight" },
3633         { 61, "Multistack" },
3634         { 62, "TSI Incorporated" },
3635         { 63, "Weather-Rite, Inc." },
3636         { 64, "Dunham-Bush" },
3637         { 65, "Reliance Electric" },
3638         { 66, "LCS Inc." },
3639         { 67, "Regulator Australia PTY Ltd." },
3640         { 68, "Touch-Plate Lighting Controls" },
3641         { 69, "Amann GmbH" },
3642         { 70, "RLE Technologies" },
3643         { 71, "Cardkey Systems" },
3644         { 72, "SECOM Co., Ltd." },
3645         { 73, "ABB Gebaudetechnik AG Bereich NetServ" },
3646         { 74, "KNX Association cvba" },
3647         { 75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
3648         { 76, "Nohmi Bosai, Ltd." },
3649         { 77, "Carel S.p.A." },
3650         { 78, "AirSense Technology, Inc." },
3651         { 79, "Hochiki Corporation" },
3652         { 80, "Fr. Sauter AG" },
3653         { 81, "Matsushita Electric Works, Ltd." },
3654         { 82, "Mitsubishi Electric Corporation, Inazawa Works" },
3655         { 83, "Mitsubishi Heavy Industries, Ltd." },
3656         { 84, "ITT Bell & Gossett" },
3657         { 85, "Yamatake Building Systems Co., Ltd." },
3658         { 86, "The Watt Stopper, Inc." },
3659         { 87, "Aichi Tokei Denki Co., Ltd." },
3660         { 88, "Activation Technologies, LLC" },
3661         { 89, "Saia-Burgess Controls, Ltd." },
3662         { 90, "Hitachi, Ltd." },
3663         { 91, "Novar Corp./Trend Control Systems Ltd." },
3664         { 92, "Mitsubishi Electric Lighting Corporation" },
3665         { 93, "Argus Control Systems, Ltd." },
3666         { 94, "Kyuki Corporation" },
3667         { 95, "Richards-Zeta Building Intelligence, Inc." },
3668         { 96, "Scientech R&D, Inc." },
3669         { 97, "VCI Controls, Inc." },
3670         { 98, "Toshiba Corporation" },
3671         { 99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
3672         { 100, "Custom Mechanical Equipment, LLC" },
3673         { 101, "ClimateMaster" },
3674         { 102, "ICP Panel-Tec, Inc." },
3675         { 103, "D-Tek Controls" },
3676         { 104, "NEC Engineering, Ltd." },
3677         { 105, "PRIVA BV" },
3678         { 106, "Meidensha Corporation" },
3679         { 107, "JCI Systems Integration Services" },
3680         { 108, "Freedom Corporation" },
3681         { 109, "Neuberger Gebaudeautomation GmbH" },
3682         { 110, "Sitronix" },
3683         { 111, "Leviton Manufacturing" },
3684         { 112, "Fujitsu Limited" },
3685         { 113, "Emerson Network Power" },
3686         { 114, "S. A. Armstrong, Ltd." },
3687         { 115, "Visonet AG" },
3688         { 116, "M&M Systems, Inc." },
3689         { 117, "Custom Software Engineering" },
3690         { 118, "Nittan Company, Limited" },
3691         { 119, "Elutions Inc. (Wizcon Systems SAS)" },
3692         { 120, "Pacom Systems Pty., Ltd." },
3693         { 121, "Unico, Inc." },
3694         { 122, "Ebtron, Inc." },
3695         { 123, "Scada Engine" },
3696         { 124, "AC Technology Corporation" },
3697         { 125, "Eagle Technology" },
3698         { 126, "Data Aire, Inc." },
3699         { 127, "ABB, Inc." },
3700         { 128, "Transbit Sp. z o. o." },
3701         { 129, "Toshiba Carrier Corporation" },
3702         { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
3703         { 131, "Tokai Soft" },
3704         { 132, "Lumisys" },
3705         { 133, "Veris Industries" },
3706         { 134, "Centaurus Prime" },
3707         { 135, "Sand Network Systems" },
3708         { 136, "Regulvar, Inc." },
3709         { 137, "Fastek International, Ltd." },
3710         { 138, "PowerCold Comfort Air Solutions, Inc." },
3711         { 139, "I Controls" },
3712         { 140, "Viconics Electronics, Inc." },
3713         { 141, "Yaskawa Electric America, Inc." },
3714         { 142, "Plueth Regelsysteme" },
3715         { 143, "Digitale Mess- und Steuersysteme AG" },
3716         { 144, "Fujitsu General Limited" },
3717         { 145, "Project Engineering S.r.l." },
3718         { 146, "Sanyo Electric Co., Ltd." },
3719         { 147, "Integrated Information Systems, Inc." },
3720         { 148, "Temco Controls, Ltd." },
3721         { 149, "Airtek Technologies, Inc." },
3722         { 150, "Advantech Corporation" },
3723         { 151, "Titan Products, Ltd." },
3724         { 152, "Regel Partners" },
3725         { 153, "National Environmental Product" },
3726         { 154, "Unitec Corporation" },
3727         { 155, "Kanden Engineering Company" },
3728         { 156, "Messner Gebaudetechnik GmbH" },
3729         { 157, "Integrated.CH" },
3730         { 158, "EH Price Limited" },
3731         { 159, "SE-Elektronic GmbH" },
3732         { 160, "Rockwell Automation" },
3733         { 161, "Enflex Corp." },
3734         { 162, "ASI Controls" },
3735         { 163, "SysMik GmbH Dresden" },
3736         { 164, "HSC Regelungstechnik GmbH" },
3737         { 165, "Smart Temp Australia Pty. Ltd." },
3738         { 166, "PCI Lighting Control Systems" },
3739         { 167, "Duksan Mecasys Co., Ltd." },
3740         { 168, "Fuji IT Co., Ltd." },
3741         { 169, "Vacon Plc" },
3742         { 170, "Leader Controls" },
3743         { 171, "Cylon Controls, Ltd." },
3744         { 172, "Compas" },
3745         { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
3746         { 174, "Building Control Integrators" },
3747         { 175, "ITG Worldwide (M) Sdn Bhd" },
3748         { 176, "Lutron Electronics Co., Inc." },
3749         { 177, "Cooper-Atkins Corporation" },
3750         { 178, "LOYTEC Electronics GmbH" },
3751         { 179, "ProLon" },
3752         { 180, "Mega Controls Limited" },
3753         { 181, "Micro Control Systems, Inc." },
3754         { 182, "Kiyon, Inc." },
3755         { 183, "Dust Networks" },
3756         { 184, "Advanced Building Automation Systems" },
3757         { 185, "Hermos AG" },
3758         { 186, "CEZIM" },
3759         { 187, "Softing" },
3760         { 188, "Lynxspring" },
3761         { 189, "Schneider Toshiba Inverter Europe" },
3762         { 190, "Danfoss Drives A/S" },
3763         { 191, "Eaton Corporation" },
3764         { 192, "Matyca S.A." },
3765         { 193, "Botech AB" },
3766         { 194, "Noveo, Inc." },
3767         { 195, "AMEV" },
3768         { 196, "Yokogawa Electric Corporation" },
3769         { 197, "GFR Gesellschaft fur Regelungstechnik" },
3770         { 198, "Exact Logic" },
3771         { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
3772         { 200, "Kandenko Co., Ltd." },
3773         { 201, "DTF, Daten-Technik Fries" },
3774         { 202, "Klimasoft, Ltd." },
3775         { 203, "Toshiba Schneider Inverter Corporation" },
3776         { 204, "Control Applications, Ltd." },
3777         { 205, "KDT Systems Co., Ltd." },
3778         { 206, "Onicon Incorporated" },
3779         { 207, "Automation Displays, Inc." },
3780         { 208, "Control Solutions, Inc." },
3781         { 209, "Remsdaq Limited" },
3782         { 210, "NTT Facilities, Inc." },
3783         { 211, "VIPA GmbH" },
3784         { 212, "TSC21 Association of Japan" },
3785         { 213, "BBP Energie Ltee" },
3786         { 214, "HRW Limited" },
3787         { 215, "Lighting Control & Design, Inc." },
3788         { 216, "Mercy Electronic and Electrical Industries" },
3789         { 217, "Samsung SDS Co., Ltd" },
3790         { 218, "Impact Facility Solutions, Inc." },
3791         { 219, "Aircuity" },
3792         { 220, "Control Techniques, Ltd." },
3793         { 221, "Evolve Control Systems, LLC" },
3794         { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
3795         { 223, "Cerus Industrial" },
3796         { 224, "Chloride Power Protection Company" },
3797         { 225, "Computrols, Inc." },
3798         { 226, "Phoenix Contact GmbH & Co. KG" },
3799         { 227, "Grundfos Management A/S" },
3800         { 228, "Ridder Drive Systems" },
3801         { 229, "Soft Device SDN BHD" },
3802         { 230, "Integrated Control Technology Limited" },
3803         { 231, "AIRxpert Systems, Inc." },
3804         { 232, "Microtrol Limited" },
3805         { 233, "Red Lion Controls" },
3806         { 234, "Digital Electronics Corporation" },
3807         { 235, "Ennovatis GmbH" },
3808         { 236, "Serotonin Software Technologies, Inc." },
3809         { 237, "LS Industrial Systems Co., Ltd." },
3810         { 238, "Square D Company" },
3811         { 239, "S Squared Innovations, Inc." },
3812         { 240, "Aricent Ltd." },
3813         { 241, "EtherMetrics, LLC" },
3814         { 242, "Industrial Control Communications, Inc." },
3815         { 243, "Paragon Controls, Inc." },
3816         { 244, "A. O. Smith Corporation" },
3817         { 245, "Contemporary Control Systems, Inc." },
3818         { 246, "Intesis Software SL" },
3819         { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
3820         { 248, "Heat-Timer Corporation" },
3821         { 249, "Ingrasys Technology, Inc." },
3822         { 250, "Costerm Building Automation" },
3823         { 251, "Wilo AG" },
3824         { 252, "Embedia Technologies Corp." },
3825         { 253, "Technilog" },
3826         { 254, "HR Controls Ltd. & Co. KG" },
3827         { 255, "Lennox International, Inc." },
3828         { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
3829         { 257, "Thermomax, Ltd." },
3830         { 258, "ELCON Electronic Control, Ltd." },
3831         { 259, "Larmia Control AB" },
3832         { 260, "BACnet Stack at SourceForge" },
3833         { 261, "G4S Security Services A/S" },
3834         { 262, "Sitek S.p.A." },
3835         { 263, "Cristal Controles" },
3836         { 264, "Regin AB" },
3837         { 265, "Dimension Software, Inc. " },
3838         { 266, "SynapSense Corporation" },
3839         { 267, "Beijing Nantree Electronic Co., Ltd." },
3840         { 268, "Camus Hydronics Ltd." },
3841         { 269, "Kawasaki Heavy Industries, Ltd. " },
3842         { 270, "Critical Environment Technologies" },
3843         { 271, "ILSHIN IBS Co., Ltd." },
3844         { 272, "ELESTA Energy Control AG" },
3845         { 273, "KROPMAN Installatietechniek" },
3846         { 274, "Baldor Electric Company" },
3847         { 275, "INGA mbH" },
3848         { 276, "GE Consumer & Industrial" },
3849         { 277, "Functional Devices, Inc." },
3850         { 278, "ESAC" },
3851         { 279, "M-System Co., Ltd." },
3852         { 280, "Yokota Co., Ltd." },
3853         { 281, "Hitranse Technology Co., LTD" },
3854         { 282, "Federspiel Controls" },
3855         { 283, "Kele, Inc." },
3856         { 284, "Opera Electronics, Inc." },
3857         { 285, "Gentec" },
3858         { 286, "Embedded Science Labs, LLC" },
3859         { 287, "Parker Hannifin Corporation" },
3860         { 288, "MaCaPS International Limited" },
3861         { 289, "Link4 Corporation" },
3862         { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
3863         { 291, "Pribusin, Inc." },
3864         { 292, "Advantage Controls" },
3865         { 293, "Critical Room Control" },
3866         { 294, "LEGRAND" },
3867         { 295, "Tongdy Control Technology Co., Ltd." },
3868         { 296, "ISSARO Integrierte Systemtechnik" },
3869         { 297, "Pro-Dev Industries" },
3870         { 298, "DRI-STEEM" },
3871         { 299, "Creative Electronic GmbH" },
3872         { 300, "Swegon AB" },
3873         { 301, "Jan Brachacek" },
3874         { 302, "Hitachi Appliances, Inc." },
3875         { 303, "Real Time Automation, Inc." },
3876         { 304, "ITEC Hankyu-Hanshin Co." },
3877         { 305, "Cyrus E&M Engineering Co., Ltd." },
3878         { 306, "Racine Federated, Inc." },
3879         { 307, "Verari Systems, Inc." },
3880         { 308, "Elesta GmbH Building Automation" },
3881         { 309, "Securiton" },
3882         { 310, "OSlsoft, Inc." },
3883         { 311, "Hanazeder Electronic GmbH" },
3884         { 312, "Honeywell Security Deutschland, Novar GmbH" },
3885         { 313, "Siemens Energy & Automation, Inc." },
3886         { 314, "ETM Professional Control GmbH" },
3887         { 315, "Meitav-tec, Ltd." },
3888         { 316, "Janitza Electronics GmbH" },
3889         { 317, "MKS Nordhausen" },
3890         { 318, "De Gier Drive Systems B.V." },
3891         { 319, "Cypress Envirosystems" },
3892         { 320, "SMARTron s.r.o." },
3893         { 321, "Verari Systems, Inc." },
3894         { 322, "K-W Electronic Service, Inc." },
3895         { 323, "ALFA-SMART Energy Management" },
3896         { 324, "Telkonet, Inc." },
3897         { 325, "Securiton GmbH" },
3898         { 326, "Cemtrex, Inc." },
3899         { 327, "Performance Technologies, Inc." },
3900         { 328, "Xtralis (Aust) Pty Ltd" },
3901         { 329, "TROX GmbH" },
3902         { 330, "Beijing Hysine Technology Co., Ltd" },
3903         { 331, "RCK Controls, Inc." },
3904         { 332, "ACELIA" },
3905         { 333, "Novar/Honeywell" },
3906         { 334, "The S4 Group, Inc." },
3907         { 335, "Schneider Electric" },
3908         { 336, "LHA Systems" },
3909         { 337, "GHM engineering Group, Inc." },
3910         { 338, "Cllimalux S.A." },
3911         { 339, "VAISALA Oyj" },
3912         { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
3913         { 342, "POWERPEG NSI Limited" },
3914         { 343, "BACnet Interoperability Testing Services, Inc." },
3915         { 344, "Teco a.s." },
3916         { 0, NULL }
3917 };
3918
3919 static int proto_bacapp = -1;
3920 static int hf_bacapp_type = -1;
3921 static int hf_bacapp_pduflags = -1;
3922 static int hf_bacapp_SEG = -1;
3923 static int hf_bacapp_MOR = -1;
3924 static int hf_bacapp_SA = -1;
3925 static int hf_bacapp_response_segments = -1;
3926 static int hf_bacapp_max_adpu_size = -1;
3927 static int hf_bacapp_invoke_id = -1;
3928 static int hf_bacapp_objectType = -1;
3929 static int hf_bacapp_instanceNumber = -1;
3930 static int hf_bacapp_sequence_number = -1;
3931 static int hf_bacapp_window_size = -1;
3932 static int hf_bacapp_service = -1;
3933 static int hf_bacapp_NAK = -1;
3934 static int hf_bacapp_SRV = -1;
3935 static int hf_Device_Instance_Range_Low_Limit = -1;
3936 static int hf_Device_Instance_Range_High_Limit = -1;
3937 static int hf_BACnetRejectReason = -1;
3938 static int hf_BACnetAbortReason = -1;
3939 static int hf_BACnetApplicationTagNumber = -1;
3940 static int hf_BACnetContextTagNumber = -1;
3941 static int hf_BACnetExtendedTagNumber = -1;
3942 static int hf_BACnetNamedTag = -1;
3943 static int hf_BACnetTagClass = -1;
3944 static int hf_BACnetCharacterSet = -1;
3945 static int hf_bacapp_tag = -1;
3946 static int hf_bacapp_tag_lvt = -1;
3947 static int hf_bacapp_tag_value8 = -1;
3948 static int hf_bacapp_tag_value16 = -1;
3949 static int hf_bacapp_tag_value32 = -1;
3950 static int hf_bacapp_tag_ProcessId = -1;
3951 static int hf_bacapp_tag_initiatingObjectType = -1;
3952 static int hf_bacapp_vpart = -1;
3953 static int hf_bacapp_uservice = -1;
3954 static int hf_BACnetPropertyIdentifier = -1;
3955 static int hf_BACnetVendorIdentifier = -1;
3956 static int hf_BACnetRestartReason = -1;
3957 static int hf_bacapp_tag_IPV4 = -1;
3958 static int hf_bacapp_tag_IPV6 = -1;
3959 static int hf_bacapp_tag_PORT = -1;
3960 /* some more variables for segmented messages */
3961 static int hf_msg_fragments = -1;
3962 static int hf_msg_fragment = -1;
3963 static int hf_msg_fragment_overlap = -1;
3964 static int hf_msg_fragment_overlap_conflicts = -1;
3965 static int hf_msg_fragment_multiple_tails = -1;
3966 static int hf_msg_fragment_too_long_fragment = -1;
3967 static int hf_msg_fragment_error = -1;
3968 static int hf_msg_reassembled_in = -1;
3969 static int hf_msg_reassembled_length = -1;
3970
3971 static gint ett_msg_fragment = -1;
3972 static gint ett_msg_fragments = -1;
3973
3974 static gint ett_bacapp = -1;
3975 static gint ett_bacapp_control = -1;
3976 static gint ett_bacapp_tag = -1;
3977 static gint ett_bacapp_list = -1;
3978 static gint ett_bacapp_value = -1;
3979
3980 static dissector_handle_t data_handle;
3981 static gint32 propertyIdentifier = -1;
3982 static gint32 propertyArrayIndex = -1;
3983 static guint32 object_type = 4096;
3984
3985 static guint8 bacapp_flags = 0;
3986 static guint8 bacapp_seq = 0;
3987
3988 /* Defined to allow vendor identifier registration of private transfer dissectors */
3989 static dissector_table_t bacapp_dissector_table;
3990
3991 static const fragment_items msg_frag_items = {
3992         /* Fragment subtrees */
3993         &ett_msg_fragment,
3994         &ett_msg_fragments,
3995         /* Fragment fields */
3996         &hf_msg_fragments,
3997         &hf_msg_fragment,
3998         &hf_msg_fragment_overlap,
3999         &hf_msg_fragment_overlap_conflicts,
4000         &hf_msg_fragment_multiple_tails,
4001         &hf_msg_fragment_too_long_fragment,
4002         &hf_msg_fragment_error,
4003         /* Reassembled in field */
4004         &hf_msg_reassembled_in,
4005         /* Reassembled length field */
4006         &hf_msg_reassembled_length,
4007         /* Tag */
4008         "Message fragments"
4009 };
4010
4011 /* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
4012 static const guint MaxAPDUSize [] = { 50,128,206,480,1024,1476 };
4013
4014 static guint
4015 fGetMaxAPDUSize(guint8 idx)
4016 {
4017         /* only 16 values are defined, so use & 0x0f */
4018         /* check the size of the Array, deliver either the entry
4019            or the first entry if idx is outside of the array (bug 3736 comment#7) */
4020         if ((idx & 0x0f) >= (gint)(sizeof(MaxAPDUSize)/sizeof(guint)))
4021                 return MaxAPDUSize[0];
4022         else
4023                 return MaxAPDUSize[idx & 0x0f];
4024 }
4025
4026 /* Used when there are ranges of reserved and proprietary enumerations */
4027 static const char*
4028 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
4029         const char *fmt, const char *split_fmt)
4030 {
4031         if (val < split_val)
4032                 return val_to_str(val, vs, fmt);
4033         else
4034                 return val_to_str(val, vs, split_fmt);
4035 }
4036
4037 /* from clause 20.2.1.3.2 Constructed Data */
4038 /* returns true if the extended value is used */
4039 static gboolean
4040 tag_is_extended_value(guint8 tag)
4041 {
4042         return (tag & 0x07) == 5;
4043 }
4044
4045 static gboolean
4046 tag_is_opening(guint8 tag)
4047 {
4048         return (tag & 0x07) == 6;
4049 }
4050
4051 static gboolean
4052 tag_is_closing(guint8 tag)
4053 {
4054         return (tag & 0x07) == 7;
4055 }
4056
4057 /* from clause 20.2.1.1 Class
4058    class bit shall be one for context specific tags */
4059 /* returns true if the tag is context specific */
4060 static gboolean
4061 tag_is_context_specific(guint8 tag)
4062 {
4063         return (tag & 0x08) != 0;
4064 }
4065
4066 static gboolean
4067 tag_is_extended_tag_number(guint8 tag)
4068 {
4069         return ((tag & 0xF0) == 0xF0);
4070 }
4071
4072 static guint32
4073 object_id_type(guint32 object_identifier)
4074 {
4075         return ((object_identifier >> 22) & 0x3FF);
4076 }
4077
4078 static guint32
4079 object_id_instance(guint32 object_identifier)
4080 {
4081         return (object_identifier & 0x3FFFFF);
4082 }
4083
4084 static guint
4085 fTagNo (tvbuff_t *tvb, guint offset)
4086 {
4087         return (guint)(tvb_get_guint8(tvb, offset) >> 4);
4088 }
4089
4090 static gboolean
4091 fUnsigned32 (tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
4092 {
4093         gboolean valid = TRUE;
4094
4095         switch (lvt) {
4096                 case 1:
4097                         *val = tvb_get_guint8(tvb, offset);
4098                         break;
4099                 case 2:
4100                         *val = tvb_get_ntohs(tvb, offset);
4101                         break;
4102                 case 3:
4103                         *val = tvb_get_ntoh24(tvb, offset);
4104                         break;
4105                 case 4:
4106                         *val = tvb_get_ntohl(tvb, offset);
4107                         break;
4108                 default:
4109                         valid = FALSE;
4110                         break;
4111         }
4112
4113         return valid;
4114 }
4115
4116 static gboolean
4117 fUnsigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
4118 {
4119         gboolean valid = FALSE;
4120         gint64 value = 0;
4121         guint8 data, i;
4122
4123         if (lvt && (lvt <= 8)) {
4124                 valid = TRUE;
4125                 data = tvb_get_guint8(tvb, offset);
4126                 for (i = 0; i < lvt; i++) {
4127                         data = tvb_get_guint8(tvb, offset+i);
4128                         value = (value << 8) + data;
4129                 }
4130                 *val = value;
4131         }
4132
4133         return valid;
4134 }
4135
4136 /* BACnet Signed Value uses 2's complement notation, but with a twist:
4137    All signed integers shall be encoded in the smallest number of octets
4138    possible.  That is, the first octet of any multi-octet encoded value
4139    shall not be X'00' if the most significant bit (bit 7) of the second
4140    octet is 0, and the first octet shall not be X'FF' if the most
4141    significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
4142 static gboolean
4143 fSigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
4144 {
4145         gboolean valid = FALSE;
4146         gint64 value = 0;
4147         guint8 data;
4148         guint32 i;
4149
4150         /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
4151         if (lvt && (lvt <= 7)) {
4152                 valid = TRUE;
4153                 data = tvb_get_guint8(tvb, offset);
4154                 if ((data & 0x80) != 0)
4155                         value = (-1 << 8) | data;
4156                 else
4157                         value = data;
4158                 for (i = 1; i < lvt; i++) {
4159                         data = tvb_get_guint8(tvb, offset+i);
4160                         value = (value << 8) + data;
4161                 }
4162                 *val = value;
4163         }
4164
4165         return valid;
4166 }
4167
4168 static guint
4169 fTagHeaderTree (tvbuff_t *tvb, proto_tree *tree, guint offset,
4170         guint8 *tag_no, guint8* tag_info, guint32 *lvt)
4171 {
4172         guint8 tag;
4173         guint8 value;
4174         guint tag_len = 1;
4175         guint lvt_len = 1; /* used for tree display of lvt */
4176         guint lvt_offset; /* used for tree display of lvt */
4177         proto_item *ti;
4178         proto_tree *subtree;
4179
4180         lvt_offset = offset;
4181         tag = tvb_get_guint8(tvb, offset);
4182         *tag_info = 0;
4183         *lvt = tag & 0x07;
4184         /* To solve the problem of lvt values of 6/7 being indeterminate - it */
4185         /* can mean open/close tag or length of 6/7 after the length is */
4186         /* computed below - store whole tag info, not just context bit. */
4187         if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
4188         *tag_no = tag >> 4;
4189         if (tag_is_extended_tag_number(tag)) {
4190                 *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
4191         }
4192         if (tag_is_extended_value(tag)) {       /* length is more than 4 Bytes */
4193                 lvt_offset += tag_len;
4194                 value = tvb_get_guint8(tvb, lvt_offset);
4195                 tag_len++;
4196                 if (value == 254) { /* length is encoded with 16 Bits */
4197                         *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
4198                         tag_len += 2;
4199                         lvt_len += 2;
4200                 } else if (value == 255) { /* length is encoded with 32 Bits */
4201                         *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
4202                         tag_len += 4;
4203                         lvt_len += 4;
4204                 } else
4205                         *lvt = value;
4206         }
4207         if (tree)
4208         {
4209                 if (tag_is_opening(tag))
4210                         ti = proto_tree_add_text(tree, tvb, offset, tag_len, "{[%u]", *tag_no );
4211                 else if (tag_is_closing(tag))
4212                         ti = proto_tree_add_text(tree, tvb, offset, tag_len, "}[%u]", *tag_no );
4213                 else if (tag_is_context_specific(tag)) {
4214                         ti = proto_tree_add_text(tree, tvb, offset, tag_len,
4215                                 "Context Tag: %u, Length/Value/Type: %u",
4216                                 *tag_no, *lvt);
4217                 } else
4218                         ti = proto_tree_add_text(tree, tvb, offset, tag_len,
4219                                 "Application Tag: %s, Length/Value/Type: %u",
4220                                 val_to_str(*tag_no,
4221                                         BACnetApplicationTagNumber,
4222                                         ASHRAE_Reserved_Fmt),
4223                                         *lvt);
4224
4225                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4226                 /* details if needed */
4227                 proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, FALSE);
4228                 if (tag_is_extended_tag_number(tag)) {
4229                         proto_tree_add_uint_format(subtree,
4230                                         hf_BACnetContextTagNumber,
4231                                         tvb, offset, 1, tag,
4232                                         "Extended Tag Number");
4233                         proto_tree_add_item(subtree,
4234                                 hf_BACnetExtendedTagNumber,
4235                                 tvb, offset + 1, 1, FALSE);
4236                 } else {
4237                         if (tag_is_context_specific(tag))
4238                                 proto_tree_add_item(subtree,
4239                                         hf_BACnetContextTagNumber,
4240                                         tvb, offset, 1, FALSE);
4241                         else
4242                                 proto_tree_add_item(subtree,
4243                                         hf_BACnetApplicationTagNumber,
4244                                         tvb, offset, 1, FALSE);
4245                 }
4246                 if (tag_is_closing(tag) || tag_is_opening(tag))
4247                         proto_tree_add_item(subtree,
4248                                 hf_BACnetNamedTag,
4249                                 tvb, offset, 1, FALSE);
4250                 else if (tag_is_extended_value(tag)) {
4251                         proto_tree_add_item(subtree,
4252                                 hf_BACnetNamedTag,
4253                                 tvb, offset, 1, FALSE);
4254                         proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
4255                                 tvb, lvt_offset, lvt_len, *lvt);
4256                 } else
4257                         proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
4258                                 tvb, lvt_offset, lvt_len, *lvt);
4259         }
4260
4261         return tag_len;
4262 }
4263
4264 static guint
4265 fTagHeader (tvbuff_t *tvb, guint offset, guint8 *tag_no, guint8* tag_info,
4266         guint32 *lvt)
4267 {
4268         return fTagHeaderTree (tvb, NULL, offset, tag_no, tag_info, lvt);
4269 }
4270
4271 static guint
4272 fNullTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4273 {
4274         guint8 tag_no, tag_info;
4275         guint32 lvt;
4276         proto_item *ti;
4277         proto_tree *subtree;
4278
4279         ti = proto_tree_add_text(tree, tvb, offset, 1, "%sNULL", label);
4280         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4281         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4282
4283         return offset + 1;
4284 }
4285
4286 static guint
4287 fBooleanTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4288 {
4289         guint8 tag_no, tag_info;
4290         guint32 lvt = 0;
4291         guint tag_len;
4292         proto_item *ti;
4293         proto_tree *subtree;
4294         guint bool_len = 1;
4295
4296         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4297         if (tag_info && lvt == 1)
4298         {
4299                 lvt = tvb_get_guint8(tvb, offset+1);
4300                 ++bool_len;
4301         }
4302
4303         ti = proto_tree_add_text(tree, tvb, offset, bool_len,
4304                 "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
4305         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4306         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4307
4308         return offset + bool_len;
4309 }
4310
4311 static guint
4312 fUnsignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4313 {
4314         guint64 val = 0;
4315         guint8 tag_no, tag_info;
4316         guint32 lvt;
4317         guint tag_len;
4318         proto_item *ti;
4319         proto_tree *subtree;
4320
4321         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4322         /* only support up to an 8 byte (64-bit) integer */
4323         if (fUnsigned64 (tvb, offset + tag_len, lvt, &val))
4324                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4325                         "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
4326         else
4327                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4328                         "%s - %u octets (Unsigned)", label, lvt);
4329         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4330         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4331
4332         return offset+tag_len+lvt;
4333 }
4334
4335 static guint
4336 fDevice_Instance (tvbuff_t *tvb, proto_tree *tree, guint offset, int hf)
4337 {
4338         guint8 tag_no, tag_info;
4339         guint32 lvt;
4340         guint tag_len;
4341         proto_item *ti;
4342         proto_tree *subtree;
4343
4344         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4345         ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, lvt, TRUE);
4346         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4347         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4348
4349         return offset+tag_len+lvt;
4350 }
4351
4352 /* set split_val to zero when not needed */
4353 static guint
4354 fEnumeratedTagSplit (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
4355         const value_string *vs, guint32 split_val)
4356 {
4357         guint32 val = 0;
4358         guint8 tag_no, tag_info;
4359         guint32 lvt;
4360         guint tag_len;
4361         proto_item *ti;
4362         proto_tree *subtree;
4363
4364         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4365         /* only support up to a 4 byte (32-bit) enumeration */
4366         if (fUnsigned32 (tvb, offset+tag_len, lvt, &val)) {
4367                 if (vs)
4368                         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4369                                 "%s %s", label, val_to_split_str(val, split_val, vs,
4370                                 ASHRAE_Reserved_Fmt,Vendor_Proprietary_Fmt));
4371                 else
4372                         ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4373                                 "%s %u", label, val);
4374         } else {
4375                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4376                         "%s - %u octets (enumeration)", label, lvt);
4377         }
4378         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4379         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4380
4381         return offset+tag_len+lvt;
4382 }
4383
4384 static guint
4385 fEnumeratedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
4386                 const value_string *vs)
4387 {
4388         return fEnumeratedTagSplit (tvb, tree, offset, label, vs, 0);
4389 }
4390
4391 static guint
4392 fSignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4393 {
4394         gint64 val = 0;
4395         guint8 tag_no, tag_info;
4396         guint32 lvt;
4397         guint tag_len;
4398         proto_item *ti;
4399         proto_tree *subtree;
4400
4401         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4402         if (fSigned64 (tvb, offset + tag_len, lvt, &val))
4403                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4404                         "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
4405         else
4406                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4407                         "%s - %u octets (Signed)", label, lvt);
4408         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4409         fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4410
4411         return offset+tag_len+lvt;
4412 }
4413
4414 static guint
4415 fRealTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4416 {
4417         guint8 tag_no, tag_info;
4418         guint32 lvt;
4419         guint tag_len;
4420         gfloat f_val;
4421         proto_item *ti;
4422         proto_tree *subtree;
4423
4424         tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
4425         f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
4426         ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
4427                 "%s%f (Real)", label, f_val);
4428         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4429         fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4430
4431         return offset+tag_len+4;
4432 }
4433
4434 static guint
4435 fDoubleTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4436 {
4437         guint8 tag_no, tag_info;
4438         guint32 lvt;
4439         guint tag_len;
4440         gdouble d_val;
4441         proto_item *ti;
4442         proto_tree *subtree;
4443
4444         tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
4445         d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
4446         ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
4447                 "%s%f (Double)", label, d_val);
4448         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4449         fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4450
4451         return offset+tag_len+8;
4452 }
4453
4454 static guint
4455 fProcessId (tvbuff_t *tvb, proto_tree *tree, guint offset)
4456 {
4457         guint32 val = 0, lvt;
4458         guint8 tag_no, tag_info;
4459         proto_item *ti;
4460         proto_tree *subtree;
4461         guint tag_len;
4462
4463         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4464         if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
4465                 ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
4466                         tvb, offset, lvt+tag_len, val);
4467         else
4468                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4469                         "Process Identifier - %u octets (Signed)", lvt);
4470         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4471         fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4472         offset += tag_len + lvt;
4473
4474         return offset;
4475 }
4476
4477 static guint
4478 fTimeSpan (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4479 {
4480         guint32 val = 0, lvt;
4481         guint8 tag_no, tag_info;
4482         proto_item *ti;
4483         proto_tree *subtree;
4484         guint tag_len;
4485
4486         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4487         if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
4488                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4489                 "%s (hh.mm.ss): %d.%02d.%02d%s",
4490                 label,
4491                 (val / 3600), ((val % 3600) / 60), (val % 60),
4492                 val == 0 ? " (indefinite)" : "");
4493         else
4494                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4495                         "%s - %u octets (Signed)", label, lvt);
4496         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4497         fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4498
4499         return offset+tag_len+lvt;
4500 }
4501
4502 static guint
4503 fWeekNDay (tvbuff_t *tvb, proto_tree *tree, guint offset)
4504 {
4505         guint32 month, weekOfMonth, dayOfWeek;
4506         guint8 tag_no, tag_info;
4507         guint32 lvt;
4508         guint tag_len;
4509         proto_item *ti;
4510         proto_tree *subtree;
4511
4512         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4513         month = tvb_get_guint8(tvb, offset+tag_len);
4514         weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
4515         dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
4516         ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
4517                                  val_to_str(month, months, "month (%d) not found"),
4518                                  val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
4519                                  val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
4520         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4521         fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4522
4523         return offset+tag_len+lvt;
4524 }
4525
4526 static guint
4527 fDate (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4528 {
4529         guint32 year, month, day, weekday;
4530         guint8 tag_no, tag_info;
4531         guint32 lvt;
4532         guint tag_len;
4533         proto_item *ti;
4534         proto_tree *subtree;
4535
4536         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4537         year = tvb_get_guint8(tvb, offset+tag_len);
4538         month = tvb_get_guint8(tvb, offset+tag_len+1);
4539         day = tvb_get_guint8(tvb, offset+tag_len+2);
4540         weekday = tvb_get_guint8(tvb, offset+tag_len+3);
4541         if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255))
4542         {
4543                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4544                         "%sany", label);
4545         }
4546         else if (year != 255)
4547         {
4548                 year += 1900;
4549                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4550                         "%s%s %d, %d, (Day of Week = %s)",
4551                         label, val_to_str(month,
4552                                 months,
4553                                 "month (%d) not found"),
4554                         day, year, val_to_str(weekday,
4555                                 day_of_week,
4556                                 "(%d) not found"));
4557         }
4558         else
4559         {
4560                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4561                         "%s%s %d, any year, (Day of Week = %s)",
4562                         label, val_to_str(month, months, "month (%d) not found"),
4563                         day, val_to_str(weekday, day_of_week, "(%d) not found"));
4564         }
4565         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4566         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4567
4568         return offset+tag_len+lvt;
4569 }
4570
4571 static guint
4572 fTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4573 {
4574         guint32 hour, minute, second, msec, lvt;
4575         guint8 tag_no, tag_info;
4576         guint tag_len;
4577         proto_item *ti;
4578         proto_tree *subtree;
4579
4580         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4581         hour = tvb_get_guint8(tvb, offset+tag_len);
4582         minute = tvb_get_guint8(tvb, offset+tag_len+1);
4583         second = tvb_get_guint8(tvb, offset+tag_len+2);
4584         msec = tvb_get_guint8(tvb, offset+tag_len+3);
4585         if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
4586                 ti = proto_tree_add_text(tree, tvb, offset,
4587                         lvt+tag_len, "%sany", label);
4588         else
4589                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
4590                         "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
4591                         label,
4592                         hour > 12 ? hour - 12 : hour,
4593                         minute, second, msec,
4594                         hour >= 12 ? "P.M." : "A.M.",
4595                         hour, minute, second, msec);
4596         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4597         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4598
4599         return offset+tag_len+lvt;
4600 }
4601
4602 static guint
4603 fDateTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
4604 {
4605         proto_tree *subtree = tree;
4606         proto_item *tt;
4607
4608         if (label != NULL) {
4609                 tt = proto_tree_add_text (subtree, tvb, offset, 1, "%s", label);
4610                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4611         }
4612         offset = fDate (tvb,subtree,offset,"Date: ");
4613         return fTime (tvb,subtree,offset,"Time: ");
4614 }
4615
4616 static guint
4617 fTimeValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
4618 {
4619         guint lastoffset = 0;
4620         guint8 tag_no, tag_info;
4621         guint32 lvt;
4622
4623         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
4624                 lastoffset = offset;
4625                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4626                 if (tag_is_closing(tag_info)) {   /* closing Tag, but not for me */
4627                         return offset;
4628                 }
4629                 offset = fTime    (tvb,tree,offset,"Time: ");
4630                 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
4631
4632                 if (offset==lastoffset) break;    /* exit loop if nothing happens inside */
4633         }
4634         return offset;
4635 }
4636
4637 static guint
4638 fCalendaryEntry (tvbuff_t *tvb, proto_tree *tree, guint offset)
4639 {
4640         guint8 tag_no, tag_info;
4641         guint32 lvt;
4642
4643         switch (fTagNo(tvb, offset)) {
4644         case 0: /* Date */
4645                 offset = fDate    (tvb, tree, offset, "Date: ");
4646                 break;
4647         case 1: /* dateRange */
4648                 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
4649                 offset = fDateRange (tvb, tree, offset);
4650                 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
4651                 break;
4652         case 2: /* BACnetWeekNDay */
4653                 offset = fWeekNDay (tvb, tree, offset);
4654                 break;
4655         default:
4656                 return offset;
4657         }
4658
4659         return offset;
4660 }
4661
4662 static guint fTimeStamp (tvbuff_t *tvb, proto_tree *tree,
4663         guint offset, const gchar *label)
4664 {
4665         guint8 tag_no = 0, tag_info = 0;
4666         guint32 lvt = 0;
4667
4668         if (tvb_reported_length_remaining(tvb, offset) > 0) {   /* don't loop, it's a CHOICE */
4669                 switch (fTagNo(tvb, offset)) {
4670                 case 0: /* time */
4671                         offset = fTime (tvb, tree, offset, label?label:"timestamp: ");
4672                         break;
4673                 case 1: /* sequenceNumber */
4674                         offset = fUnsignedTag (tvb, tree, offset,
4675                                 label?label:"sequence Number: ");
4676                         break;
4677                 case 2: /* dateTime */
4678                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
4679                         offset = fDateTime (tvb, tree, offset, label?label:"timestamp: ");
4680                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
4681                         break;
4682                 default:
4683                         return offset;
4684                 }
4685         }
4686
4687         return offset;
4688 }
4689
4690
4691 static guint
4692 fClientCOV (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
4693 {
4694         if (tvb_reported_length_remaining(tvb, offset) > 0) {
4695                 offset = fApplicationTypes(tvb,pinfo,tree,offset, "increment: ");
4696         }
4697         return offset;
4698 }
4699
4700 static const value_string
4701 BACnetDaysOfWeek [] = {
4702         {0,"Monday" },
4703         {1,"Tuesday" },
4704         {2,"Wednesday" },
4705         {3,"Thursday" },
4706         {4,"Friday" },
4707         {5,"Saturday" },
4708         {6,"Sunday" },
4709         {0,NULL }
4710 };
4711
4712 static guint
4713 fDestination (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
4714 {
4715         if (tvb_reported_length_remaining(tvb, offset) > 0) {
4716                 offset = fApplicationTypesEnumerated(tvb,pinfo,tree,offset,
4717                         "valid Days: ", BACnetDaysOfWeek);
4718                 offset = fTime (tvb,tree,offset,"from time: ");
4719                 offset = fTime (tvb,tree,offset,"to time: ");
4720                 offset = fRecipient (tvb,pinfo,tree,offset);
4721                 offset = fProcessId (tvb,tree,offset);
4722                 offset = fApplicationTypes (tvb,pinfo,tree,offset,
4723                         "issue confirmed notifications: ");
4724                 offset = fBitStringTagVS (tvb,tree,offset,
4725                         "transitions: ", BACnetEventTransitionBits);
4726         }
4727         return offset;
4728 }
4729
4730
4731 static guint
4732 fOctetString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
4733 {
4734         gchar *tmp;
4735         guint start = offset;
4736         guint8 tag_no, tag_info;
4737         proto_tree* subtree = tree;
4738         proto_item* ti = 0;
4739
4740         offset += fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4741
4742         if (lvt > 0)
4743         {
4744                 tmp = tvb_bytes_to_str(tvb, offset, lvt);
4745                 ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
4746                 offset += lvt;
4747         }
4748
4749         if (ti)
4750                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4751
4752         fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
4753
4754         return offset;
4755 }
4756
4757 static guint
4758 fMacAddress (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
4759 {
4760         gchar *tmp;
4761         guint start = offset;
4762         guint8 tag_no, tag_info;
4763         proto_tree* subtree = tree;
4764         proto_item* ti = 0;
4765
4766         offset += fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4767
4768         ti = proto_tree_add_text(tree, tvb, offset, 6, "%s", label); /* just add the label, with the tagHeader information in its subtree */
4769
4770         if (lvt > 0)
4771         {
4772                 if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
4773
4774                         guint32 ip = tvb_get_ipv4(tvb, offset);
4775                         guint16 port =  tvb_get_ntohs(tvb, offset+4);
4776
4777                         proto_tree_add_ipv4(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ip);
4778                         proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, port);
4779
4780                 } else {
4781                         if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
4782                         struct e_in6_addr addr;
4783                         guint16 port =  tvb_get_ntohs(tvb, offset+16);
4784                         tvb_get_ipv6(tvb, offset, &addr);
4785
4786                         proto_tree_add_ipv6(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, (const guint8 *) &addr);
4787                         proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, port);
4788
4789                         } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
4790                                 tmp = tvb_bytes_to_str(tvb, offset, lvt);
4791                                 ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s", tmp);
4792                         }
4793                 }
4794                 offset += lvt;
4795         }
4796
4797         if (ti)
4798                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4799
4800         fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
4801
4802         return offset;
4803 }
4804
4805 static guint
4806 fAddress (tvbuff_t *tvb, proto_tree *tree, guint offset)
4807 {
4808         guint8 tag_no, tag_info;
4809         guint32 lvt;
4810         guint offs;
4811
4812         offset = fUnsignedTag (tvb, tree, offset, "network-number");
4813         offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4814         if (lvt == 0) {
4815                 proto_tree_add_text(tree, tvb, offset, offs, "MAC-address: broadcast");
4816                 offset += offs;
4817         } else
4818                 offset = fMacAddress (tvb, tree, offset, "MAC-address: ", lvt);
4819
4820         return offset;
4821 }
4822
4823 static guint
4824 fSessionKey (tvbuff_t *tvb, proto_tree *tree, guint offset)
4825 {
4826         offset = fOctetString (tvb,tree,offset,"session key: ", 8);
4827         return fAddress (tvb,tree,offset);
4828 }
4829
4830 static guint
4831 fObjectIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
4832 {
4833         guint8  tag_no, tag_info;
4834         guint32 lvt;
4835         guint tag_length;
4836         proto_item *ti;
4837         proto_tree *subtree;
4838         guint32 object_id;
4839
4840         tag_length = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
4841         object_id = tvb_get_ntohl(tvb,offset+tag_length);
4842         object_type = object_id_type(object_id);
4843         ti = proto_tree_add_text(tree, tvb, offset, tag_length + 4,
4844                 "ObjectIdentifier: %s, %u",
4845                 val_to_split_str(object_type,
4846                         128,
4847                         BACnetObjectType,
4848                         ASHRAE_Reserved_Fmt,
4849                         Vendor_Proprietary_Fmt),
4850                 object_id_instance(object_id));
4851         if (col_get_writable(pinfo->cinfo))
4852                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
4853                         val_to_split_str(object_type,
4854                                 128,
4855                                 BACnetObjectType,
4856                                 ASHRAE_Reserved_Fmt,
4857                                 Vendor_Proprietary_Fmt),
4858                                 object_id_instance(object_id));
4859
4860         /* here are the details of how we arrived at the above text */
4861         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
4862         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4863         offset += tag_length;
4864         proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, FALSE);
4865         proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, FALSE);
4866         offset += 4;
4867
4868         return offset;
4869 }
4870
4871 static guint
4872 fRecipient (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
4873 {
4874         guint8  tag_no, tag_info;
4875         guint32 lvt;
4876
4877         fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
4878         if (tag_no < 2) {
4879                 if (tag_no == 0) { /* device */
4880                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
4881                 }
4882                 else {  /* address */
4883                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
4884                         offset = fAddress (tvb, tree, offset);
4885                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
4886                 }
4887         }
4888         return offset;
4889 }
4890
4891 static guint
4892 fRecipientProcess (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
4893 {
4894         guint lastoffset = 0;
4895         guint8  tag_no, tag_info;
4896         guint32 lvt;
4897         proto_tree* orgtree = tree;
4898         proto_item* tt;
4899         proto_tree* subtree;
4900
4901         /* beginning of new item - indent and label */
4902         tt = proto_tree_add_text(orgtree, tvb, offset, 1, "Recipient Process" );
4903         tree = proto_item_add_subtree(tt, ett_bacapp_value);
4904
4905         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
4906                 lastoffset = offset;
4907
4908                 switch (fTagNo(tvb, offset)) {
4909                 case 0: /* recipient */
4910                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
4911                         tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient");    /* add tree label and indent */
4912                         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4913                         offset = fRecipient (tvb, pinfo, subtree, offset);
4914                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
4915                         break;
4916                 case 1: /* processId */
4917                         offset = fProcessId (tvb, tree, offset);
4918                         lastoffset = offset;
4919                         break;
4920                 default:
4921                         break;
4922                 }
4923                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
4924         }
4925         return offset;
4926 }
4927
4928 static guint
4929 fCOVSubscription (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
4930 {
4931         guint lastoffset = 0, len;
4932         guint8  tag_no, tag_info;
4933         guint32 lvt;
4934         proto_tree* subtree;
4935         proto_item *tt;
4936         proto_tree* orgtree = tree;
4937         guint itemno = 1;
4938
4939         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
4940                 lastoffset = offset;
4941                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4942                 if (tag_is_closing(tag_info) ) {
4943                         return offset;
4944                 }
4945                 switch (tag_no) {
4946
4947                 case 0: /* recipient */
4948                                 /* beginning of new item in list */
4949                                 tt = proto_tree_add_text(orgtree, tvb, offset, 1, "Subscription %d",itemno);    /* add tree label and indent */
4950                                 itemno = itemno + 1;
4951                                 tree = proto_item_add_subtree(tt, ett_bacapp_value);
4952
4953                                 tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient");    /* add tree label and indent */
4954                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4955                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
4956                                 offset = fRecipientProcess (tvb, pinfo, subtree, offset);
4957                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);      /* show context close */
4958                                 subtree = tree; /* done with this level - return to previous tree */
4959                         break;
4960                 case 1: /* MonitoredPropertyReference */
4961                                 tt = proto_tree_add_text(tree, tvb, offset, 1, "Monitored Property Reference");
4962                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4963                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4964                                 offset = fBACnetObjectPropertyReference (tvb, pinfo, subtree, offset);
4965                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4966                                 subtree = tree;
4967                         break;
4968                 case 2: /* IssueConfirmedNotifications - boolean */
4969                         offset = fBooleanTag (tvb, tree, offset, "Issue Confirmed Notifications: ");
4970                         break;
4971                 case 3: /* TimeRemaining */
4972                         offset = fUnsignedTag (tvb, tree, offset, "Time Remaining: ");
4973                         break;
4974                 case 4: /* COVIncrement */
4975                         offset = fRealTag (tvb, tree, offset, "COV Increment: ");
4976                         break;
4977                 default:
4978                         break;
4979                 }
4980                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
4981         }
4982         return offset;
4983 }
4984
4985 static guint
4986 fAddressBinding (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
4987 {
4988         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
4989         return fAddress (tvb, tree, offset);
4990 }
4991
4992 static guint
4993 fActionCommand (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match)
4994 {
4995         guint lastoffset = 0, len;
4996         guint8 tag_no, tag_info;
4997         guint32 lvt;
4998         proto_tree *subtree = tree;
4999
5000         /* set the optional global properties to indicate not-used */
5001         propertyArrayIndex = -1;
5002         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
5003                 lastoffset = offset;
5004                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5005                 if (tag_is_closing(tag_info) ) {
5006                         if (tag_no == tag_match) {
5007                                 return offset;
5008                         }
5009                         offset += len;
5010                         subtree = tree;
5011                         continue;
5012                 }
5013                 switch (tag_no) {
5014
5015                 case 0: /* deviceIdentifier */
5016                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
5017                         break;
5018                 case 1: /* objectIdentifier */
5019                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
5020                         break;
5021                 case 2: /* propertyIdentifier */
5022                         offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
5023                         break;
5024                 case 3: /* propertyArrayIndex */
5025                         offset = fPropertyArrayIndex (tvb, subtree, offset);
5026                         break;
5027                 case 4: /* propertyValue */
5028                         offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
5029                         break;
5030                 case 5: /* priority */
5031                         offset = fUnsignedTag (tvb,subtree,offset,"Priority: ");
5032                         break;
5033                 case 6: /* postDelay */
5034                         offset = fUnsignedTag (tvb,subtree,offset,"Post Delay: ");
5035                         break;
5036                 case 7: /* quitOnFailure */
5037                         offset = fBooleanTag(tvb, subtree, offset,
5038                                 "Quit On Failure: ");
5039                         break;
5040                 case 8: /* writeSuccessful */
5041                         offset = fBooleanTag(tvb, subtree, offset,
5042                                 "Write Successful: ");
5043                         break;
5044                 default:
5045                         return offset;
5046                 }
5047                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
5048         }
5049         return offset;
5050 }
5051
5052 /* BACnetActionList ::= SEQUENCE{
5053       action [0] SEQUENCE OF BACnetActionCommand
5054       }
5055 */
5056 static guint
5057 fActionList (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5058 {
5059         guint lastoffset = 0, len;
5060         guint8 tag_no, tag_info;
5061         guint32 lvt;
5062         proto_tree *subtree = tree;
5063         proto_item *ti;
5064
5065         while (tvb_reported_length_remaining(tvb, offset)) {
5066                 lastoffset = offset;
5067                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5068                 if (tag_is_closing(tag_info)) {
5069                         offset += len;
5070                         subtree = tree;
5071                         continue;
5072                 }
5073                 if (tag_is_opening(tag_info)) {
5074                         ti = proto_tree_add_text(tree, tvb, offset, 1, "Action List");
5075                         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5076                         offset += fTagHeaderTree (tvb, subtree, offset,
5077                                 &tag_no, &tag_info, &lvt);
5078                 }
5079                 switch (tag_no) {
5080                         case 0: /* BACnetActionCommand */
5081                                 offset = fActionCommand (tvb, pinfo, subtree, offset, tag_no);
5082                                 break;
5083                         default:
5084                                 break;
5085                 }
5086                 if (offset == lastoffset) break;    /* nothing happened, exit loop */
5087         }
5088         return offset;
5089 }
5090
5091 static guint
5092 fPropertyIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5093 {
5094         guint8 tag_no, tag_info;
5095         guint32 lvt;
5096         guint tag_len;
5097         proto_item *ti;
5098         proto_tree *subtree;
5099         const gchar *label = "Property Identifier";
5100
5101         propertyIdentifier = 0; /* global Variable */
5102         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5103         /* can we decode this value? */
5104         if (fUnsigned32 (tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
5105                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5106                         "%s: %s (%u)", label,
5107                         val_to_split_str(propertyIdentifier, 512,
5108                                 BACnetPropertyIdentifier,
5109                                 ASHRAE_Reserved_Fmt,
5110                                 Vendor_Proprietary_Fmt), propertyIdentifier);
5111                 if (col_get_writable(pinfo->cinfo))
5112                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
5113                                 val_to_split_str(propertyIdentifier, 512,
5114                                         BACnetPropertyIdentifier,
5115                                         ASHRAE_Reserved_Fmt,
5116                                         Vendor_Proprietary_Fmt));
5117         } else {
5118                 /* property identifiers cannot be larger than 22-bits */
5119                 return offset;
5120         }
5121         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5122         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
5123         proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
5124                 offset+tag_len, lvt, FALSE);
5125
5126         return offset+tag_len+lvt;
5127 }
5128
5129 static guint
5130 fPropertyArrayIndex (tvbuff_t *tvb, proto_tree *tree, guint offset)
5131 {
5132         guint8 tag_no, tag_info;
5133         guint32 lvt;
5134         guint tag_len;
5135         proto_item *ti;
5136         proto_tree *subtree;
5137
5138         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5139         if (fUnsigned32 (tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
5140                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5141                         "property Array Index (Unsigned) %u", propertyArrayIndex);
5142         else
5143                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5144                         "property Array Index - %u octets (Unsigned)", lvt);
5145         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5146         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
5147
5148         return offset+tag_len+lvt;
5149 }
5150
5151 static guint
5152 fCharacterString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
5153 {
5154         guint8 tag_no, tag_info, character_set;
5155         guint32 lvt, l;
5156         gsize inbytesleft, outbytesleft = 512;
5157         guint offs, extra = 1;
5158         guint8 *str_val;
5159         const char *coding;
5160         guint8 bf_arr[512], *out = &bf_arr[0];
5161         proto_item *ti;
5162         proto_tree *subtree;
5163         guint start = offset;
5164
5165         if (tvb_reported_length_remaining(tvb, offset) > 0) {
5166
5167                 offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5168
5169                 character_set = tvb_get_guint8(tvb, offset+offs);
5170                 /* Account for code page if DBCS */
5171                 if (character_set == 1)
5172                 {
5173                     extra = 3;
5174                 }
5175                 offset += (offs+extra);
5176                 lvt -= (extra);
5177
5178                 do {
5179                         inbytesleft = l = MIN(lvt, 255);
5180                         /*
5181                          * XXX - are we guaranteed that these encoding
5182                          * names correspond, on *all* platforms with
5183                          * iconv(), to the encodings we want?
5184                          * If not (and perhaps even if so), we should
5185                          * perhaps have our own iconv() implementation,
5186                          * with a different name, so that we control the
5187                          * encodings it supports and the names of those
5188                          * encodings.
5189                          *
5190                          * We should also handle that in the general
5191                          * string handling code, rather than making it
5192                          * specific to the BACAPP dissector, as many
5193                          * other dissectors need to handle various
5194                          * character encodings.
5195                          */
5196                         str_val = tvb_get_ephemeral_string(tvb, offset, l);
5197                         /** this decoding may be not correct for multi-byte characters, Lka */
5198                         switch (character_set) {
5199                         case ANSI_X34:
5200                                 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ANSI_X3.4");
5201                                 coding = "ANSI X3.4";
5202                                 break;
5203                         case IBM_MS_DBCS:
5204                                 out = str_val;
5205                                 coding = "IBM MS DBCS";
5206                                 break;
5207                         case JIS_C_6226:
5208                                 out = str_val;
5209                                 coding = "JIS C 6226";
5210                                 break;
5211                         case ISO_10646_UCS4:
5212                                 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-4BE");
5213                                 coding = "ISO 10646 UCS-4";
5214                                 break;
5215                         case ISO_10646_UCS2:
5216                                 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-2BE");
5217                                 coding = "ISO 10646 UCS-2";
5218                                 break;
5219                         case ISO_18859_1:
5220                                 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ISO8859-1");
5221                                 coding = "ISO 8859-1";
5222                                 break;
5223                         default:
5224                                 out = str_val;
5225                                 coding = "unknown";
5226                                 break;
5227                         }
5228                         ti = proto_tree_add_text(tree, tvb, offset, l, "%s%s'%s'", label, coding, out);
5229                         lvt-=l;
5230                         offset+=l;
5231                 } while (lvt > 0);
5232
5233                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5234
5235                 fTagHeaderTree (tvb, subtree, start, &tag_no, &tag_info, &lvt);
5236                 proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, FALSE);
5237
5238                 if (character_set == 1)
5239                 {
5240                     proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
5241                 }
5242         }
5243         return offset;
5244 }
5245
5246 static guint
5247 fBitStringTagVS (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
5248         const value_string *src)
5249 {
5250         guint8 tag_no, tag_info, tmp;
5251         gint j, unused, skip;
5252         guint start = offset;
5253         guint offs;
5254         guint32 lvt, i, numberOfBytes;
5255         guint8 bf_arr[256];
5256         proto_tree* subtree = tree;
5257         proto_item* ti = 0;
5258
5259         offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5260         numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
5261         offset+=offs;
5262         unused = tvb_get_guint8(tvb, offset); /* get the unused Bits */
5263         ti = proto_tree_add_text(tree, tvb, start, offs+lvt,
5264                                 "%s(Bit String)",
5265                                 label);
5266         if (ti) {
5267                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5268         }
5269         fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
5270         proto_tree_add_text(subtree, tvb, offset, 1,
5271                                 "Unused bits: %u",
5272                                 unused);
5273         skip = 0;
5274         for (i = 0; i < numberOfBytes; i++) {
5275                 tmp = tvb_get_guint8(tvb, (offset)+i+1);
5276                 if (i == numberOfBytes-1) { skip = unused; }
5277                 for (j = 0; j < 8-skip; j++) {
5278                         if (src != NULL) {
5279                                 if (tmp & (1 << (7 - j)))
5280                                         proto_tree_add_text(subtree, tvb,
5281                                                 offset+i+1, 1,
5282                                                 "%s = TRUE",
5283                                                 val_to_str((guint) (i*8 +j),
5284                                                         src,
5285                                                         ASHRAE_Reserved_Fmt));
5286                                 else
5287                                         proto_tree_add_text(subtree, tvb,
5288                                                 offset+i+1, 1,
5289                                                 "%s = FALSE",
5290                                                 val_to_str((guint) (i*8 +j),
5291                                                         src,
5292                                                         ASHRAE_Reserved_Fmt));
5293                         } else {
5294                                 bf_arr[MIN(255,(i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
5295                         }
5296                 }
5297         }
5298
5299         if (src == NULL)
5300         {
5301                 bf_arr[MIN(255,numberOfBytes*8-unused)] = 0;
5302                 proto_tree_add_text(subtree, tvb, offset, lvt, "B'%s'", bf_arr);
5303         }
5304
5305         offset+=lvt;
5306
5307         return offset;
5308 }
5309
5310 static guint
5311 fBitStringTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
5312 {
5313         return fBitStringTagVS (tvb, tree, offset, label, NULL);
5314 }
5315
5316 /* handles generic application types, as well as enumerated and enumerations
5317    with reserved and proprietarty ranges (split) */
5318 static guint
5319 fApplicationTypesEnumeratedSplit (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
5320         const gchar *label, const value_string *src, guint32 split_val)
5321 {
5322         guint8 tag_no, tag_info;
5323         guint32 lvt;
5324         guint tag_len;
5325
5326         if (tvb_reported_length_remaining(tvb, offset) > 0) {
5327
5328                 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5329                 if (!tag_is_context_specific(tag_info))
5330                 {
5331                         switch (tag_no) {
5332                                 case 0: /** NULL 20.2.2 */
5333                                         offset = fNullTag(tvb, tree, offset, label);
5334                                         break;
5335                                 case 1: /** BOOLEAN 20.2.3 */
5336                                         offset = fBooleanTag(tvb, tree, offset, label);
5337                                         break;
5338                                 case 2: /** Unsigned Integer 20.2.4 */
5339                                         offset = fUnsignedTag(tvb, tree, offset, label);
5340                                         break;
5341                                 case 3: /** Signed Integer 20.2.5 */
5342                                         offset = fSignedTag(tvb, tree, offset, label);
5343                                         break;
5344                                 case 4: /** Real 20.2.6 */
5345                                         offset = fRealTag(tvb, tree, offset, label);
5346                                         break;
5347                                 case 5: /** Double 20.2.7 */
5348                                         offset = fDoubleTag(tvb, tree, offset, label);
5349                                         break;
5350                                 case 6: /** Octet String 20.2.8 */
5351                                         offset = fOctetString (tvb, tree, offset, label, lvt);
5352                                         break;
5353                                 case 7: /** Character String 20.2.9 */
5354                                         offset = fCharacterString (tvb,tree,offset,label);
5355                                         break;
5356                                 case 8: /** Bit String 20.2.10 */
5357                                         offset = fBitStringTagVS (tvb, tree, offset, label, src);
5358                                         break;
5359                                 case 9: /** Enumerated 20.2.11 */
5360                                         offset = fEnumeratedTagSplit (tvb, tree, offset, label, src, split_val);
5361                                         break;
5362                                 case 10: /** Date 20.2.12 */
5363                                         offset = fDate (tvb, tree, offset, label);
5364                                         break;
5365                                 case 11: /** Time 20.2.13 */
5366                                         offset = fTime (tvb, tree, offset, label);
5367                                         break;
5368                                 case 12: /** BACnetObjectIdentifier 20.2.14 */
5369                                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
5370                                         break;
5371                                 case 13: /* reserved for ASHRAE */
5372                                 case 14:
5373                                 case 15:
5374                                         proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
5375                                         offset+=lvt+tag_len;
5376                                         break;
5377                                 default:
5378                                         break;
5379                         }
5380
5381                 }
5382         }
5383         return offset;
5384 }
5385
5386 static guint
5387 fShedLevel (tvbuff_t *tvb, proto_tree *tree, guint offset)
5388 {
5389         guint lastoffset = 0;
5390
5391         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
5392                 lastoffset = offset;
5393
5394                 switch (fTagNo(tvb,offset)) {
5395                 case 0: /* percent */
5396                         offset = fUnsignedTag (tvb, tree, offset, "shed percent: ");
5397                         break;
5398                 case 1: /* level */
5399                         offset = fUnsignedTag (tvb, tree, offset, "shed level: ");
5400                         break;
5401                 case 2: /* amount */
5402                         offset = fRealTag(tvb, tree, offset, "shed amount: ");
5403                         break;
5404                 default:
5405                         return offset;
5406                 }
5407                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
5408         }
5409         return offset;
5410 }
5411
5412 static guint
5413 fApplicationTypesEnumerated (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
5414         const gchar *label, const value_string *vs)
5415 {
5416         return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
5417 }
5418
5419 static guint
5420 fApplicationTypes (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
5421         const gchar *label)
5422 {
5423         return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
5424 }
5425
5426 static guint
5427 fContextTaggedValue(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
5428 {
5429         guint8 tag_no, tag_info;
5430         guint32 lvt;
5431         guint tag_len;
5432         proto_item *ti;
5433         proto_tree *subtree;
5434         gint tvb_len;
5435
5436         (void)label;
5437         tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
5438         /* cap the the suggested length in case of bad data */
5439         tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
5440         if ((tvb_len >= 0) && ((guint32)tvb_len < lvt))
5441         {
5442                 lvt = tvb_len;
5443         }
5444         ti = proto_tree_add_text(tree, tvb, offset+tag_len, lvt,
5445                 "Context Value (as %u DATA octets)", lvt);
5446
5447         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5448         fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
5449
5450         return offset + tag_len + lvt;
5451 }
5452
5453 static guint
5454 fAbstractSyntaxNType (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5455 {
5456         guint8 tag_no, tag_info;
5457         guint32 lvt;
5458         guint lastoffset = 0, depth = 0;
5459         char ar[256];
5460
5461         if (propertyIdentifier >= 0)
5462         {
5463                 g_snprintf (ar, sizeof(ar), "%s: ",
5464                         val_to_split_str(propertyIdentifier, 512,
5465                                 BACnetPropertyIdentifier,
5466                                 ASHRAE_Reserved_Fmt,
5467                                 Vendor_Proprietary_Fmt));
5468         }
5469         else
5470         {
5471                 g_snprintf (ar, sizeof(ar), "Abstract Type: ");
5472         }
5473         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
5474                 lastoffset = offset;
5475                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5476                 if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
5477                         if (depth <= 0) return offset;
5478                 }
5479
5480                 /* Application Tags */
5481                 switch (propertyIdentifier) {
5482                 case 2: /* action */
5483                         /* loop object is application tagged,
5484                                 command object is context tagged */
5485                         if (tag_is_context_specific(tag_info)) {
5486                                 /* BACnetActionList */
5487                                 offset = fActionList (tvb, pinfo, tree,offset);
5488                         } else {
5489                                 /* BACnetAction */
5490                                 offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
5491                                         BACnetAction);
5492                         }
5493                         break;
5494                 case 30: /* BACnetAddressBinding */
5495                         offset = fAddressBinding (tvb,pinfo,tree,offset);
5496                         break;
5497                 case 54: /* list of object property reference */
5498                         offset = fLOPR (tvb, pinfo, tree,offset);
5499                         break;
5500                 case 55: /* list-of-session-keys */
5501                         fSessionKey (tvb, tree, offset);
5502                         break;
5503                 case 79: /* object-type */
5504                 case 96: /* protocol-object-types-supported */
5505                         offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset, ar,
5506                                 BACnetObjectType, 128);
5507                         break;
5508                 case 97: /* Protocol-Services-Supported */
5509                         offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
5510                                 BACnetServicesSupported);
5511                         break;
5512                 case 102: /* recipient-list */
5513                         offset = fDestination (tvb, pinfo, tree, offset);
5514                         break;
5515                 case 107: /* segmentation-supported */
5516                         offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
5517                                 BACnetSegmentation);
5518                         break;
5519                 case 111: /* Status-Flags */
5520                         offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
5521                                 BACnetStatusFlags);
5522                         break;
5523                 case 112: /* System-Status */
5524                         offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
5525                                 BACnetDeviceStatus);
5526                         break;
5527                 case 117: /* units */
5528                         offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
5529                                 BACnetEngineeringUnits);
5530                         break;
5531                 case 87:        /* priority-array -- accessed as a BACnetARRAY */
5532                         if (propertyArrayIndex == 0) {
5533                                 /* BACnetARRAY index 0 refers to the length
5534                                 of the array, not the elements of the array */
5535                                 offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
5536                         } else {
5537                                 offset = fPriorityArray (tvb, pinfo, tree, offset);
5538                         }
5539                         break;
5540                 case 38:        /* exception-schedule */
5541                         if (object_type < 128)
5542                         {
5543                                 if (propertyArrayIndex == 0) {
5544                                         /* BACnetARRAY index 0 refers to the length
5545                                         of the array, not the elements of the array */
5546                                         offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
5547                                 } else {
5548                                         offset = fSpecialEvent (tvb,pinfo,tree,offset);
5549                                 }
5550                         }
5551                         break;
5552                 case 19:  /* controlled-variable-reference */
5553                 case 60:  /* manipulated-variable-reference */
5554                 case 109: /* Setpoint-Reference */
5555                 case 132: /* log-device-object-property */
5556                         offset = fDeviceObjectPropertyReference (tvb, pinfo, tree, offset);
5557                         break;
5558                 case 123:       /* weekly-schedule -- accessed as a BACnetARRAY */
5559                         if (object_type < 128)
5560                         {
5561                                 if (propertyArrayIndex == 0) {
5562                                         /* BACnetARRAY index 0 refers to the length
5563                                         of the array, not the elements of the array */
5564                                         offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
5565                                 } else {
5566                                         offset = fWeeklySchedule (tvb, pinfo, tree, offset);
5567                                 }
5568                         }
5569                         break;
5570                 case 127:       /* client COV increment */
5571                         offset = fClientCOV (tvb, pinfo, tree, offset);
5572                         break;
5573                 case 131:  /* log-buffer */
5574                         offset = fLogRecord (tvb, pinfo, tree, offset);
5575                         break;
5576                 case 159: /* member-of */
5577                 case 165: /* zone-members */
5578                         offset = fDeviceObjectReference (tvb, pinfo, tree, offset);
5579                         break;
5580                 case 196: /* last-restart-reason */
5581                         offset = fRestartReason (tvb, pinfo, tree, offset);
5582                         break;
5583                 case 212: /* actual-shed-level */
5584                 case 214: /* expected-shed-level */
5585                 case 218: /* requested-shed-level */
5586                         offset = fShedLevel (tvb, tree, offset);
5587                         break;
5588                 case 152: /* active-cov-subscriptions */
5589                         offset = fCOVSubscription (tvb, pinfo, tree, offset);
5590                         break;
5591                 default:
5592                         if (tag_info)
5593                         {
5594                                 if (tag_is_opening(tag_info))
5595                                 {
5596                                         ++depth;
5597                                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
5598                                 }
5599                                 else if (tag_is_closing(tag_info))
5600                                 {
5601                                         --depth;
5602                                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
5603                                 }
5604                                 else
5605                                 {
5606                                         offset = fContextTaggedValue(tvb, tree, offset, ar);
5607                                 }
5608                         }
5609                         else
5610                         {
5611                                 offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
5612                         }
5613                         break;
5614                 }
5615                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
5616         }
5617         return offset;
5618
5619 }
5620
5621 static guint
5622 fPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_info)
5623 {
5624         guint8 tag_no;
5625         guint32 lvt;
5626
5627         if (tag_is_opening(tag_info)) {
5628                 offset += fTagHeaderTree(tvb, tree, offset,
5629                         &tag_no, &tag_info, &lvt);
5630                 offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
5631                 if (tvb_length_remaining(tvb, offset) > 0) {
5632                         offset += fTagHeaderTree(tvb, tree, offset,
5633                                 &tag_no, &tag_info, &lvt);
5634                 }
5635         } else {
5636                 proto_tree_add_text(tree, tvb, offset, tvb_length(tvb) - offset,
5637                         "expected Opening Tag!"); \
5638                 offset = tvb_length(tvb);
5639         }
5640
5641         return offset;
5642 }
5643
5644
5645 static guint
5646 fPropertyIdentifierValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset)
5647 {
5648         guint lastoffset = offset;
5649         guint8 tag_no, tag_info;
5650         guint32 lvt;
5651
5652         offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
5653         if (offset > lastoffset)
5654         {
5655                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5656                 if (tag_no == tagoffset+2) {  /* Value - might not be present in ReadAccessResult */
5657                         offset = fPropertyValue (tvb, pinfo, tree, offset, tag_info);
5658                 }
5659         }
5660         return offset;
5661 }
5662
5663 static guint
5664 fBACnetPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5665 {
5666         guint lastoffset = 0;
5667         guint8 tag_no, tag_info;
5668         guint32 lvt;
5669
5670         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
5671                 lastoffset = offset;
5672                 offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
5673                 if (offset > lastoffset)
5674                 {
5675                         /* detect optional priority
5676                         by looking to see if the next tag is context tag number 3 */
5677                         fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5678                         if (tag_is_context_specific(tag_info) && (tag_no == 3))
5679                                 offset = fUnsignedTag (tvb,tree,offset,"Priority: ");
5680                 }
5681                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
5682         }
5683         return offset;
5684 }
5685
5686 static guint
5687 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5688 {
5689         guint lastoffset = 0, len;
5690         guint8 tag_no, tag_info;
5691         guint32 lvt;
5692         proto_tree *subtree = tree;
5693         proto_item *tt;
5694
5695         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
5696                 lastoffset = offset;
5697                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5698                 if (tag_is_closing(tag_info)) {
5699                         offset += len;
5700                         subtree = tree;
5701                         continue;
5702                 }
5703
5704                 switch (tag_no) {
5705                 case 0: /* ProcessId */
5706                         offset = fUnsignedTag (tvb, tree, offset, "subscriber Process Id: ");
5707                         break;
5708                 case 1: /* monitored ObjectId */
5709                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
5710                         break;
5711                 case 2: /* issueConfirmedNotifications */
5712                         offset = fBooleanTag (tvb, tree, offset, "issue Confirmed Notifications: ");
5713                         break;
5714                 case 3: /* life time */
5715                         offset = fTimeSpan (tvb,tree,offset,"life time");
5716                         break;
5717                 case 4: /* monitoredPropertyIdentifier */
5718                         if (tag_is_opening(tag_info)) {
5719                                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "monitoredPropertyIdentifier");
5720                                 if (tt) {
5721                                         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
5722                                 }
5723                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
5724                                 offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
5725                                 break;
5726                         }
5727                         FAULT;
5728                         break;
5729                 case 5: /* covIncrement */
5730                         offset = fRealTag (tvb, tree, offset, "COV Increment: ");
5731                         break;
5732                 default:
5733                         return offset;
5734                 }
5735                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
5736         }
5737         return offset;
5738 }
5739
5740 static guint
5741 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5742 {
5743         return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
5744 }
5745
5746 static guint
5747 fWhoHas (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5748 {
5749         guint lastoffset = 0;
5750
5751         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
5752                 lastoffset = offset;
5753
5754                 switch (fTagNo(tvb, offset)) {
5755                 case 0: /* deviceInstanceLowLimit */
5756                         offset = fUnsignedTag (tvb, tree, offset, "device Instance Low Limit: ");
5757                         break;
5758                 case 1: /* deviceInstanceHighLimit */
5759                         offset = fUnsignedTag (tvb, tree, offset, "device Instance High Limit: ");
5760                         break;
5761                 case 2: /* BACnetObjectId */
5762                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
5763                         break;
5764                 case 3: /* messageText */
5765                         offset = fCharacterString (tvb,tree,offset, "Object Name: ");
5766                         break;
5767                 default:
5768                         return offset;
5769                 }
5770                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
5771         }
5772         return offset;
5773 }
5774
5775
5776 static guint
5777 fDailySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
5778 {
5779         guint lastoffset = 0;
5780         guint8 tag_no, tag_info;
5781         guint32 lvt;
5782
5783         fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5784         if (tag_is_opening(tag_info) && tag_no == 0)
5785         {
5786                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
5787                 while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
5788                         lastoffset = offset;
5789                         fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5790                         if (tag_is_closing(tag_info)) {
5791                                 /* should be closing context tag 0 */
5792                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
5793                                 return offset;
5794                         }
5795
5796                         offset = fTimeValue (tvb, pinfo, subtree, offset);
5797                         if (offset == lastoffset) break;    /* nothing happened, exit loop */
5798                 }
5799         }
5800         else if (tag_no == 0 && lvt == 0)
5801         {
5802                 /* not sure null (empty array element) is legal */
5803                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
5804         }
5805         return offset;
5806 }
5807
5808 static guint
5809 fWeeklySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5810 {
5811         guint lastoffset = 0;
5812         guint8 tag_no, tag_info;
5813         guint32 lvt;
5814         guint i = 1; /* day of week array index */
5815         proto_tree *subtree = tree;
5816         proto_item *tt;
5817
5818         if (propertyArrayIndex > 0) {
5819                 /* BACnetARRAY index 0 refers to the length
5820                 of the array, not the elements of the array.
5821                 BACnetARRAY index -1 is our internal flag that
5822                 the optional index was not used.
5823                 BACnetARRAY refers to this as all elements of the array.
5824                 If the optional index is specified for a BACnetARRAY,
5825                 then that specific array element is referenced. */
5826                 i = propertyArrayIndex;
5827         }
5828         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
5829                 lastoffset = offset;
5830                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5831                 if (tag_is_closing(tag_info)) {
5832                         return offset; /* outer encoding will print out closing tag */
5833                 }
5834                 tt = proto_tree_add_text(tree, tvb, offset, 0, "%s", val_to_str(i++, day_of_week, "day of week (%d) not found"));
5835                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
5836                 offset = fDailySchedule (tvb, pinfo, subtree, offset);
5837                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
5838         }
5839         return offset;
5840 }
5841
5842
5843 static guint
5844 fUTCTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
5845 {
5846         if (tvb_reported_length_remaining(tvb, offset) <= 0)
5847                 return offset;
5848
5849         return fDateTime (tvb, tree, offset, "UTC-Time: ");
5850 }
5851
5852 static guint
5853 fTimeSynchronizationRequest  (tvbuff_t *tvb, proto_tree *tree, guint offset)
5854 {
5855         if (tvb_reported_length_remaining(tvb, offset) <= 0)
5856                 return offset;
5857
5858         return fDateTime (tvb, tree, offset, NULL);
5859 }
5860
5861 static guint
5862 fDateRange  (tvbuff_t *tvb, proto_tree *tree, guint offset)
5863 {
5864         if (tvb_reported_length_remaining(tvb, offset) <= 0)
5865                 return offset;
5866         offset = fDate (tvb,tree,offset,"Start Date: ");
5867         return fDate (tvb, tree, offset, "End Date: ");
5868 }
5869
5870 static guint
5871 fVendorIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5872 {
5873         guint32 val = 0;
5874         guint8 tag_no, tag_info;
5875         guint32 lvt;
5876         guint tag_len;
5877         proto_item *ti;
5878         proto_tree *subtree;
5879         const gchar *label = "Vendor ID";
5880
5881         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5882         if (fUnsigned32 (tvb, offset + tag_len, lvt, &val))
5883                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5884                         "%s: %s (%u)", label,
5885                         val_to_str(val,BACnetVendorIdentifiers,"Unknown Vendor"), val);
5886         else
5887                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5888                         "%s - %u octets (Unsigned)", label, lvt);
5889         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5890         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
5891
5892         if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1  and <= 2 are supported */
5893                 proto_item *expert_item;
5894                 expert_item = proto_tree_add_text(tree, tvb, 0, lvt, "Wrong length indicated. Expected 1 or 2, got %u", lvt);
5895                 expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1 or 2, got %u", lvt);
5896                 PROTO_ITEM_SET_GENERATED(expert_item);
5897                 return offset+tag_len+lvt;
5898         }
5899
5900         proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
5901                 offset+tag_len, lvt, FALSE);
5902
5903         return offset+tag_len+lvt;
5904 }
5905
5906 static guint
5907 fRestartReason (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5908 {
5909         guint32 val = 0;
5910         guint8 tag_no, tag_info;
5911         guint32 lvt;
5912         guint tag_len;
5913         proto_item *ti;
5914         proto_tree *subtree;
5915         const gchar *label = "Restart Reason";
5916
5917         tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5918         if (fUnsigned32 (tvb, offset + tag_len, lvt, &val))
5919                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5920                         "%s: %s (%u)", label,
5921                         val_to_str(val,BACnetRestartReason,"Unknown reason"), val);
5922         else
5923                 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5924                         "%s - %u octets (Unsigned)", label, lvt);
5925         subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5926         fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
5927
5928         if (lvt != 1) {
5929                 proto_item *expert_item;
5930                 expert_item = proto_tree_add_text(tree, tvb, 0, lvt, "Wrong length indicated. Expected 1, got %u", lvt);
5931                 expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", lvt);
5932                 PROTO_ITEM_SET_GENERATED(expert_item);
5933                 return offset+tag_len+lvt;
5934         }
5935
5936         proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
5937                 offset+tag_len, lvt, FALSE);
5938
5939         return offset+tag_len+lvt;
5940 }
5941
5942 static guint
5943 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5944 {
5945         guint lastoffset = 0;
5946
5947         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
5948                 lastoffset = offset;
5949                 switch (fTagNo(tvb, offset)) {
5950
5951                 case 0: /* textMessageSourceDevice */
5952                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
5953                         break;
5954                 case 1: /* messageClass */
5955                         switch (fTagNo(tvb, offset)) {
5956                         case 0: /* numeric */
5957                                 offset = fUnsignedTag (tvb, tree, offset, "message Class: ");
5958                                 break;
5959                         case 1: /* character */
5960                                 offset = fCharacterString (tvb, tree, offset, "message Class: ");
5961                                 break;
5962                         }
5963                         break;
5964                 case 2: /* messagePriority */
5965                         offset = fEnumeratedTag (tvb, tree, offset, "message Priority: ",
5966                                 BACnetMessagePriority);
5967                         break;
5968                 case 3: /* message */
5969                         offset = fCharacterString (tvb, tree, offset, "message: ");
5970                         break;
5971                 default:
5972                         return offset;
5973                 }
5974                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
5975         }
5976         return offset;
5977 }
5978
5979 static guint
5980 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5981 {
5982         return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
5983 }
5984
5985 static guint
5986 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5987 {
5988         guint lastoffset = 0, len;
5989         guint8 tag_no, tag_info;
5990         guint32 lvt;
5991         proto_tree *subtree = tree;
5992         proto_item *tt;
5993         tvbuff_t *next_tvb;
5994         guint vendor_identifier = 0;
5995         guint service_number = 0;
5996
5997         lastoffset = offset;
5998         len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
5999         fUnsigned32(tvb, offset+len, lvt, &vendor_identifier);
6000         if (col_get_writable(pinfo->cinfo))
6001                 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
6002         offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
6003
6004         next_tvb = tvb_new_subset_remaining(tvb,offset);
6005         if (dissector_try_uint(bacapp_dissector_table,
6006             vendor_identifier, next_tvb, pinfo, tree))
6007         {
6008                 /* we parsed it so skip over length and we are done */
6009                 offset += tvb_length(next_tvb);
6010                 return offset;
6011         }
6012
6013         /* Not handled by vendor dissector */
6014
6015         /* exit loop if nothing happens inside */
6016         while (tvb_reported_length_remaining(tvb, offset)) {
6017                 lastoffset = offset;
6018                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
6019                 if (tag_is_closing(tag_info)) {
6020                         if (tag_no == 2) /* Make sure it's the expected tag */
6021                         {
6022                                 offset += len;
6023                                 subtree = tree;
6024                                 continue;
6025                         }
6026                         else
6027                         {
6028                                 break; /* End loop if incorrect closing tag */
6029                         }
6030                 }
6031                 switch (tag_no) {
6032
6033                         /* vendorID is now parsed above */
6034                 case 1: /* serviceNumber */
6035                         fUnsigned32(tvb, offset+len, lvt, &service_number);
6036                         if (col_get_writable(pinfo->cinfo))
6037                                 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",       service_number);
6038                         offset = fUnsignedTag (tvb, subtree, offset, "service Number: ");
6039                         break;
6040                 case 2: /*serviceParameters */
6041                         if (tag_is_opening(tag_info)) {
6042                                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "service Parameters");
6043                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6044                                 propertyIdentifier = -1;
6045                                 offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
6046                                 break;
6047                         }
6048                         FAULT;
6049                         break;
6050                 default:
6051                         return offset;
6052                 }
6053                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
6054         }
6055
6056         return offset;
6057 }
6058
6059 static guint
6060 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6061 {
6062         return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
6063 }
6064
6065 static guint
6066 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6067 {
6068         return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
6069 }
6070
6071 static guint
6072 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6073 {
6074         guint lastoffset = 0;
6075         guint8 tag_no, tag_info;
6076         guint32 lvt;
6077         proto_tree *subtree = tree;
6078         proto_item *tt;
6079
6080         if (label != NULL) {
6081                 tt = proto_tree_add_text (subtree, tvb, offset, 1, "%s", label);
6082                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6083         }
6084
6085         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6086                 lastoffset = offset;
6087                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
6088
6089                 switch (tag_no) {
6090                 case 0: /* subscriberProcessId */
6091                         offset = fUnsignedTag (tvb, subtree, offset, "requesting Process Id: ");
6092                         break;
6093                 case 1: /* requestingSource */
6094                         offset = fCharacterString (tvb, tree, offset, "requesting Source: ");
6095                         break;
6096                 case 2: /* request */
6097                         offset = fEnumeratedTagSplit (tvb, tree, offset,
6098                                 "request: ", BACnetLifeSafetyOperation, 64);
6099                         break;
6100                 case 3: /* objectId */
6101                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
6102                         break;
6103                 default:
6104                         return offset;
6105                 }
6106                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
6107         }
6108         return offset;
6109 }
6110
6111 static guint
6112 fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset)
6113 {
6114         switch (fTagNo(tvb, offset))
6115         {
6116         case 0:
6117                 offset = fBooleanTag (tvb, tree, offset, "boolean-value: ");
6118                 break;
6119         case 1:
6120                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6121                         "binary-value: ", BACnetBinaryPV, 2);
6122                 break;
6123         case 2:
6124                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6125                         "event-type: ", BACnetEventType, 12);
6126                 break;
6127         case 3:
6128                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6129                         "polarity: ", BACnetPolarity, 2);
6130                 break;
6131         case 4:
6132                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6133                         "program-change: ", BACnetProgramRequest, 5);
6134                 break;
6135         case 5:
6136                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6137                         "program-state: ", BACnetProgramState, 5);
6138                 break;
6139         case 6:
6140                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6141                         "reason-for-halt: ", BACnetProgramError, 5);
6142                 break;
6143         case 7:
6144                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6145                         "reliability: ", BACnetReliability, 10);
6146                 break;
6147         case 8:
6148                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6149                         "state: ", BACnetEventState, 64);
6150                 break;
6151         case 9:
6152                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6153                         "system-status: ", BACnetDeviceStatus, 64);
6154                 break;
6155         case 10:
6156                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6157                         "units: ", BACnetEngineeringUnits, 2);
6158                 break;
6159         case 11:
6160                 offset = fUnsignedTag(tvb, tree, offset, "unsigned-value: ");
6161                 break;
6162         case 12:
6163                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6164                         "life-safety-mode: ", BACnetLifeSafetyMode, 64);
6165                 break;
6166         case 13:
6167                 offset = fEnumeratedTagSplit (tvb, tree, offset,
6168                         "life-safety-state: ", BACnetLifeSafetyState, 64);
6169                 break;
6170         default:
6171                 break;
6172         }
6173         return offset;
6174 }
6175
6176
6177 /*
6178 BACnetDeviceObjectPropertyValue ::= SEQUENCE {
6179       deviceIdentifier       [0]      BACnetObjectIdentifier,
6180       objectIdentifier       [1]      BACnetObjectIdentifier,
6181       propertyIdentifier     [2]      BACnetPropertyIdentifier,
6182       arrayIndex             [3]      Unsigned OPTIONAL,
6183       value                  [4]      ABSTRACT-SYNTAX.&Type
6184       }
6185 */
6186 static guint
6187 fDeviceObjectPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6188 {
6189         guint lastoffset = 0;
6190         guint8 tag_no, tag_info;
6191         guint32 lvt;
6192
6193         while (tvb_reported_length_remaining(tvb, offset)) {
6194                 lastoffset = offset;
6195                 /* check the tag.  A closing tag means we are done */
6196                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
6197                 if (tag_is_closing(tag_info)) {
6198                         return offset;
6199                 }
6200                 switch (tag_no) {
6201                 case 0: /* deviceIdentifier */
6202                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
6203                         break;
6204                 case 1: /* objectIdentifier */
6205                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
6206                         break;
6207                 case 2: /* propertyIdentifier */
6208                         offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
6209                         break;
6210                 case 3: /* arrayIndex - OPTIONAL */
6211                         offset = fUnsignedTag (tvb, tree, offset,
6212                                 "arrayIndex: ");
6213                         break;
6214                 case 4: /* value */
6215                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
6216                         offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
6217                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
6218                         break;
6219                 default:
6220                         return offset;
6221                 }
6222                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
6223         }
6224         return offset;
6225 }
6226
6227
6228 /*
6229 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
6230       objectIdentifier       [0]      BACnetObjectIdentifier,
6231       propertyIdentifier     [1]      BACnetPropertyIdentifier,
6232       propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
6233                                                                 -- if omitted with an array then
6234                                                                 -- the entire array is referenced
6235       deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
6236       }
6237 */
6238 static guint
6239 fDeviceObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6240 {
6241         guint lastoffset = 0;
6242         guint8 tag_no, tag_info;
6243         guint32 lvt;
6244
6245         while (tvb_reported_length_remaining(tvb, offset)) {
6246                 lastoffset = offset;
6247                 /* check the tag.  A closing tag means we are done */
6248                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
6249                 if (tag_is_closing(tag_info)) {
6250                         return offset;
6251                 }
6252                 switch (tag_no) {
6253                 case 0: /* objectIdentifier */
6254                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
6255                         break;
6256                 case 1: /* propertyIdentifier */
6257                         offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
6258                         break;
6259                 case 2: /* arrayIndex - OPTIONAL */
6260                         offset = fUnsignedTag (tvb, tree, offset,
6261                                 "arrayIndex: ");
6262                         break;
6263                 case 3: /* deviceIdentifier - OPTIONAL */
6264                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
6265                         break;
6266                 default:
6267                         return offset;
6268                 }
6269                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
6270         }
6271         return offset;
6272 }
6273
6274 static guint
6275 fNotificationParameters (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6276 {
6277         guint lastoffset = offset;
6278         guint8 tag_no, tag_info;
6279         guint32 lvt;
6280         proto_tree *subtree = tree;
6281         proto_item *tt;
6282
6283         fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
6284         tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters (%d) %s",
6285                 tag_no, val_to_str(tag_no, BACnetEventType, "invalid type"));
6286         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6287         /* Opening tag for parameter choice */
6288         offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6289
6290         switch (tag_no) {
6291         case 0: /* change-of-bitstring */
6292                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6293                         lastoffset = offset;
6294                         switch (fTagNo(tvb, offset)) {
6295                         case 0:
6296                                 offset = fBitStringTag (tvb, subtree, offset,
6297                                         "referenced-bitstring: ");
6298                                 break;
6299                         case 1:
6300                                 offset = fBitStringTagVS (tvb, subtree, offset,
6301                                         "status-flags: ", BACnetStatusFlags);
6302                         lastoffset = offset;
6303                                 break;
6304                         default:
6305                                 break;
6306                         }
6307                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6308                 }
6309                 break;
6310         case 1: /* change-of-state */
6311                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6312                         lastoffset = offset;
6313                         switch (fTagNo(tvb, offset)) {
6314                         case 0:
6315                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6316                                 offset = fBACnetPropertyStates(tvb, subtree, offset);
6317                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6318                                 break;
6319                         case 1:
6320                                 offset = fBitStringTagVS (tvb, subtree, offset,
6321                                         "status-flags: ", BACnetStatusFlags);
6322                         lastoffset = offset;
6323                                 break;
6324                         default:
6325                                 break;
6326                         }
6327                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6328                 }
6329                 break;
6330         case 2: /* change-of-value */
6331                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6332                         lastoffset = offset;
6333                         switch (fTagNo(tvb, offset)) {
6334                         case 0:
6335                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6336                                 switch (fTagNo(tvb, offset)) {
6337                                 case 0:
6338                                         offset = fBitStringTag (tvb, subtree, offset,
6339                                                 "changed-bits: ");
6340                                         break;
6341                                 case 1:
6342                                         offset = fRealTag (tvb, subtree, offset,
6343                                                 "changed-value: ");
6344                                         break;
6345                                 default:
6346                                         break;
6347                                 }
6348                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6349                                 break;
6350                         case 1:
6351                                 offset = fBitStringTagVS (tvb, subtree, offset,
6352                                         "status-flags: ", BACnetStatusFlags);
6353                         lastoffset = offset;
6354                                 break;
6355                         default:
6356                                 break;
6357                         }
6358                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6359                 }
6360                 break;
6361         case 3: /* command-failure */
6362                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6363                         lastoffset = offset;
6364                         switch (fTagNo(tvb, offset)) {
6365                         case 0: /* "command-value: " */
6366                                 /* from BACnet Table 13-3,
6367                                         Standard Object Property Values Returned in Notifications */
6368                                 propertyIdentifier = 85; /* PRESENT_VALUE */
6369                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6370                                 offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
6371                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6372                                 break;
6373                         case 1:
6374                                 offset = fBitStringTagVS (tvb, subtree, offset,
6375                                         "status-flags: ", BACnetStatusFlags);
6376                                 break;
6377                         case 2: /* "feedback-value: " */
6378                                 propertyIdentifier = 40; /* FEEDBACK_VALUE */
6379                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6380                                 offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
6381                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6382                         lastoffset = offset;
6383                                 break;
6384                         default:
6385                                 break;
6386                         }
6387                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6388                 }
6389                 break;
6390         case 4: /* floating-limit */
6391                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6392                         lastoffset = offset;
6393                         switch (fTagNo(tvb, offset)) {
6394                         case 0:
6395                                 offset = fRealTag (tvb, subtree, offset, "reference-value: ");
6396                                 break;
6397                         case 1:
6398                                 offset = fBitStringTagVS (tvb, subtree, offset,
6399                                         "status-flags: ", BACnetStatusFlags);
6400                                 break;
6401                         case 2:
6402                                 offset = fRealTag (tvb, subtree, offset, "setpoint-value: ");
6403                                 break;
6404                         case 3:
6405                                 offset = fRealTag (tvb, subtree, offset, "error-limit: ");
6406                         lastoffset = offset;
6407                                 break;
6408                         default:
6409                                 break;
6410                         }
6411                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6412                 }
6413                 break;
6414         case 5: /* out-of-range */
6415                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6416                         lastoffset = offset;
6417                         switch (fTagNo(tvb, offset)) {
6418                         case 0:
6419                                 offset = fRealTag (tvb, subtree, offset, "exceeding-value: ");
6420                                 break;
6421                         case 1:
6422                                 offset = fBitStringTagVS (tvb, subtree, offset,
6423                                         "status-flags: ", BACnetStatusFlags);
6424                                 break;
6425                         case 2:
6426                                 offset = fRealTag (tvb, subtree, offset, "deadband: ");
6427                                 break;
6428                         case 3:
6429                                 offset = fRealTag (tvb, subtree, offset, "exceeded-limit: ");
6430                         lastoffset = offset;
6431                                 break;
6432                         default:
6433                                 break;
6434                         }
6435                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6436                 }
6437             break;
6438         case 6:
6439                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6440                         lastoffset = offset;
6441                         offset =fBACnetPropertyValue (tvb,pinfo,subtree,offset);
6442                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6443                 }
6444                 break;
6445         case 7: /* buffer-ready */
6446                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6447                         lastoffset = offset;
6448                         switch (fTagNo(tvb, offset)) {
6449                         case 0:
6450                                 offset = fObjectIdentifier (tvb, pinfo, subtree, offset); /* buffer-device */
6451                                 break;
6452                         case 1:
6453                                 offset = fObjectIdentifier (tvb, pinfo, subtree, offset); /* buffer-object */
6454                                 break;
6455                         case 2:
6456                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6457                                 offset = fDateTime (tvb, subtree, offset, "previous-notification: ");
6458                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6459                                 break;
6460                         case 3:
6461                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6462                                 offset = fDateTime (tvb, subtree, offset, "current-notification: ");
6463                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6464                         lastoffset = offset;
6465                                 break;
6466                         default:
6467                                 break;
6468                         }
6469                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6470                 }
6471                 break;
6472         case 8: /* change-of-life-safety */
6473                 while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6474                         lastoffset = offset;
6475                         switch (fTagNo(tvb, offset)) {
6476                         case 0:
6477                                 offset = fEnumeratedTagSplit (tvb, subtree, offset,
6478                                         "new-state: ", BACnetLifeSafetyState, 256);
6479                                 break;
6480                         case 1:
6481                                 offset = fEnumeratedTagSplit (tvb, subtree, offset,
6482                                         "new-mode: ", BACnetLifeSafetyMode, 256);
6483                                 break;
6484                         case 2:
6485                                 offset = fBitStringTagVS (tvb, subtree, offset,
6486                                         "status-flags: ", BACnetStatusFlags);
6487                                 break;
6488                         case 3:
6489                                 offset = fEnumeratedTagSplit (tvb, subtree, offset,
6490                                         "operation-expected: ", BACnetLifeSafetyOperation, 64);
6491                         lastoffset = offset;
6492                                 break;
6493                         default:
6494                                 break;
6495                         }
6496                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6497                 }
6498                 break;
6499         case 9: /* extended */
6500                 while (tvb_reported_length_remaining(tvb, offset)) {
6501                         lastoffset = offset;
6502                         switch (fTagNo(tvb, offset)) {
6503                         case 0:
6504                                 offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
6505                                 break;
6506                         case 1:
6507                                 offset = fUnsignedTag (tvb, subtree, offset,
6508                                         "extended-event-type: ");
6509                                 break;
6510                         case 2: /* parameters */
6511                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6512                                 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
6513                                 offset = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
6514                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6515                         lastoffset = offset;
6516                                 break;
6517                         default:
6518                                 break;
6519                         }
6520                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6521                 }
6522                 break;
6523         case 10: /* buffer ready */
6524                 while (tvb_reported_length_remaining(tvb, offset)) {
6525                         lastoffset = offset;
6526                         switch (fTagNo(tvb, offset)) {
6527                         case 0: /* buffer-property */
6528                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6529                                 offset = fDeviceObjectPropertyReference (tvb, pinfo, subtree, offset);
6530                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6531                                 break;
6532                         case 1:
6533                                 offset = fUnsignedTag (tvb, subtree, offset,
6534                                         "previous-notification: ");
6535                                 break;
6536                         case 2:
6537                                 offset = fUnsignedTag (tvb, subtree, offset,
6538                                         "current-notification: ");
6539                         lastoffset = offset;
6540                                 break;
6541                         default:
6542                                 break;
6543                         }
6544                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6545                 }
6546                 break;
6547         case 11: /* unsigned range */
6548                 while (tvb_reported_length_remaining(tvb, offset)) {
6549                         lastoffset = offset;
6550                         switch (fTagNo(tvb, offset)) {
6551                         case 0:
6552                                 offset = fUnsignedTag (tvb, subtree, offset,
6553                                         "exceeding-value: ");
6554                                 break;
6555                         case 1:
6556                                 offset = fBitStringTagVS (tvb, subtree, offset,
6557                                         "status-flags: ", BACnetStatusFlags);
6558                                 break;
6559                         case 2:
6560                                 offset = fUnsignedTag (tvb, subtree, offset,
6561                                         "exceeded-limit: ");
6562                         lastoffset = offset;
6563                                 break;
6564                         default:
6565                                 break;
6566                         }
6567                         if (offset == lastoffset) break;     /* nothing happened, exit loop */
6568                 }
6569                 break;
6570         default:
6571                 break;
6572         }
6573
6574         /* Closing tag for parameter choice */
6575         offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6576
6577         return offset;
6578 }
6579
6580 #if 0
6581 static guint
6582 fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
6583 {
6584         guint lastoffset = 0;
6585
6586         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6587                 lastoffset = offset;
6588                 switch (fTagNo(tvb, offset)) {
6589                 case 0: /* change-of-bitstring */
6590                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6591                                 lastoffset = offset;
6592                                 switch (fTagNo(tvb, offset)) {
6593                                 case 0:
6594                                         offset = fTimeSpan (tvb, tree, offset, "Time Delay");
6595                                         break;
6596                                 case 1:
6597                                         offset = fBitStringTag (tvb, tree, offset, "bitmask: ");
6598                                         break;
6599                                 case 2: /* SEQUENCE OF BIT STRING */
6600                                         offset = fBitStringTagVS (tvb, tree, offset,
6601                                                 "bitstring value: ", BACnetEventTransitionBits);
6602                                         break;
6603                                 default:
6604                                         return offset;
6605                                 }
6606                         }
6607                         break;
6608                 case 1: /* change-of-state */
6609                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6610                                 lastoffset = offset;
6611                                 switch (fTagNo(tvb, offset)) {
6612                                 case 0:
6613                                         offset = fTimeSpan (tvb, tree, offset, "Time Delay");
6614                                         break;
6615                                 case 1: /* SEQUENCE OF BACnetPropertyStates */
6616                                         offset = fEnumeratedTagSplit (tvb, tree, offset,
6617                                                 "value: ", BACnetPropertyStates, 64);
6618                                         break;
6619                                 default:
6620                                         return offset;
6621                                 }
6622                         }
6623                         break;
6624                 case 2: /* change-of-value */
6625                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6626                                 lastoffset = offset;
6627                                 switch (fTagNo(tvb, offset)) {
6628                                 case 0:
6629                                         offset = fTimeSpan   (tvb, tree, offset, "Time Delay");
6630                                         break;
6631                                 case 1: /* don't loop it, it's a CHOICE */
6632                                         switch (fTagNo(tvb, offset)) {
6633                                         case 0:
6634                                                 offset = fBitStringTag (tvb, tree, offset, "bitmask: ");
6635                                                 break;
6636                                         case 1:
6637                                                 offset = fRealTag (tvb, tree, offset,
6638                                                         "referenced Property Increment: ");
6639                                                 break;
6640                                         default:
6641                                                 return offset;
6642                                         }
6643                                 default:
6644                                         return offset;
6645                                 }
6646                         }
6647                         break;
6648                 case 3: /* command-failure */
6649                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6650                                 lastoffset = offset;
6651                                 switch (fTagNo(tvb, offset)) {
6652                                 case 0:
6653                                         offset = fTimeSpan   (tvb, tree, offset, "Time Delay");
6654                                         break;
6655                                 case 1:
6656                                         offset = fDeviceObjectPropertyReference (tvb,pinfo,tree,offset);
6657                                 default:
6658                                         return offset;
6659                                 }
6660                         }
6661                         break;
6662                 case 4: /* floating-limit */
6663                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6664                                 lastoffset = offset;
6665                                 switch (fTagNo(tvb, offset)) {
6666                                 case 0:
6667                                         offset = fTimeSpan   (tvb, tree, offset, "Time Delay");
6668                                         break;
6669                                 case 1:
6670                                         offset = fDeviceObjectPropertyReference (tvb,pinfo,tree,offset);
6671                                         break;
6672                                 case 2:
6673                                         offset = fRealTag (tvb, tree, offset, "low diff limit: ");
6674                                         break;
6675                                 case 3:
6676                                         offset = fRealTag (tvb, tree, offset, "high diff limit: ");
6677                                         break;
6678                                 case 4:
6679                                         offset = fRealTag (tvb, tree, offset, "deadband: ");
6680                                         break;
6681                                 default:
6682                                         return offset;
6683                                 }
6684                         }
6685                         break;
6686                 case 5: /* out-of-range */
6687                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6688                                 lastoffset = offset;
6689                                 switch (fTagNo(tvb, offset)) {
6690                                 case 0:
6691                                         offset = fTimeSpan (tvb, tree, offset, "Time Delay");
6692                                         break;
6693                                 case 1:
6694                                         offset = fRealTag (tvb, tree, offset, "low limit: ");
6695                                         break;
6696                                 case 2:
6697                                         offset = fRealTag (tvb, tree, offset, "high limit: ");
6698                                         break;
6699                                 case 3:
6700                                         offset = fRealTag (tvb, tree, offset, "deadband: ");
6701                                         break;
6702                                 default:
6703                                         return offset;
6704                                 }
6705                         }
6706                         break;
6707                 case 6:
6708                         offset = fBACnetPropertyValue (tvb,pinfo,tree,offset);
6709                         break;
6710                 case 7: /* buffer-ready */
6711                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6712                                 lastoffset = offset;
6713                                 switch (fTagNo(tvb, offset)) {
6714                                 case 0:
6715                                         offset = fUnsignedTag (tvb,tree,offset,"notification threshold");
6716                                         break;
6717                                 case 1:
6718                                         offset = fUnsignedTag (tvb,tree,offset,
6719                                                 "previous notification count: ");
6720                                         break;
6721                                 default:
6722                                         return offset;
6723                                 }
6724                         }
6725                         break;
6726                 case 8: /* change-of-life-safety */
6727                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
6728                                 lastoffset = offset;
6729                                 switch (fTagNo(tvb, offset)) {
6730                                 case 0:
6731                                         offset = fTimeSpan (tvb, tree, offset, "Time Delay");
6732                                         break;
6733                                 case 1:
6734                                         offset = fEnumeratedTagSplit (tvb, tree, offset,
6735                                                 "life safety alarm value: ", BACnetLifeSafetyState, 256);
6736                                         break;
6737                                 case 2:
6738                                         offset = fEnumeratedTagSplit (tvb, tree, offset,
6739                                                 "alarm value: ", BACnetLifeSafetyState, 256);
6740                                         break;
6741                                 case 3:
6742                                         offset = fDeviceObjectPropertyReference (tvb, pinfo, tree, offset);
6743                                         break;
6744                                 default:
6745                                         return offset;
6746                                 }
6747                         }
6748                         break;
6749                 default:
6750                         return offset;
6751                 }
6752         }
6753         return offset;
6754 }
6755 #endif
6756
6757 static guint
6758 fLogRecord (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6759 {
6760         guint lastoffset = 0;
6761         guint8 tag_no, tag_info;
6762         guint32 lvt;
6763
6764         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6765                 lastoffset = offset;
6766                 switch (fTagNo(tvb, offset)) {
6767                 case 0: /* timestamp */
6768                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6769                         offset = fDate (tvb,tree,offset,"Date: ");
6770                         offset = fTime (tvb,tree,offset,"Time: ");
6771                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6772                         break;
6773                 case 1: /* logDatum: don't loop, it's a CHOICE */
6774                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6775                         switch (fTagNo(tvb, offset)) {
6776                         case 0: /* logStatus */
6777                                 offset = fEnumeratedTag (tvb, tree, offset,
6778                                         "log status: ", BACnetLogStatus);
6779                                 break;
6780                         case 1:
6781                                 offset = fBooleanTag (tvb, tree, offset, "boolean-value: ");
6782                                 break;
6783                         case 2:
6784                                 offset = fRealTag (tvb, tree, offset, "real value: ");
6785                                 break;
6786                         case 3:
6787                                 offset = fUnsignedTag (tvb, tree, offset, "enum value: ");
6788                                 break;
6789                         case 4:
6790                                 offset = fUnsignedTag (tvb, tree, offset, "unsigned value: ");
6791                                 break;
6792                         case 5:
6793                                 offset = fSignedTag (tvb, tree, offset, "signed value: ");
6794                                 break;
6795                         case 6:
6796                                 offset = fBitStringTag (tvb, tree, offset, "bitstring value: ");
6797                                 break;
6798                         case 7:
6799                                 offset = fNullTag(tvb, tree, offset, "null value: ");
6800                                 break;
6801                         case 8:
6802                                 offset = fError (tvb, pinfo, tree, offset);
6803                                 break;
6804                         case 9:
6805                                 offset = fRealTag (tvb, tree, offset, "time change: ");
6806                                 break;
6807                         case 10:        /* any Value */
6808                                 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6809                                 offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
6810                                 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6811                                 break;
6812                         default:
6813                                 return offset;
6814                         }
6815                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6816                         break;
6817                 case 2:
6818                         offset = fEnumeratedTag (tvb, tree, offset,
6819                                 "Status Flags: ", BACnetStatusFlags);
6820                         break;
6821                 default:
6822                         return offset;
6823                 }
6824                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
6825         }
6826         return offset;
6827 }
6828
6829
6830 static guint
6831 fConfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6832 {
6833         guint lastoffset = 0;
6834         guint8 tag_no, tag_info;
6835         guint32 lvt;
6836
6837         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6838                 lastoffset = offset;
6839
6840                 switch (fTagNo(tvb,offset)) {
6841                 case 0: /* ProcessId */
6842                         offset = fProcessId (tvb,tree,offset);
6843                         break;
6844                 case 1: /* initiating ObjectId */
6845                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
6846                         break;
6847                 case 2: /* event ObjectId */
6848                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
6849                         break;
6850                 case 3: /* time stamp */
6851                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6852                         offset = fTimeStamp (tvb, tree, offset, NULL);
6853                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6854                         break;
6855                 case 4: /* notificationClass */
6856                         offset = fUnsignedTag (tvb, tree, offset, "Notification Class: ");
6857                         break;
6858                 case 5: /* Priority */
6859                         offset = fUnsignedTag (tvb, tree, offset, "Priority: ");
6860                         break;
6861                 case 6: /* EventType */
6862                         offset = fEnumeratedTagSplit (tvb, tree, offset,
6863                                 "Event Type: ", BACnetEventType, 64);
6864                         break;
6865                 case 7: /* messageText */
6866                         offset = fCharacterString (tvb, tree, offset, "message Text: ");
6867                         break;
6868                 case 8: /* NotifyType */
6869                         offset = fEnumeratedTag (tvb, tree, offset,
6870                                 "Notify Type: ", BACnetNotifyType);
6871                         break;
6872                 case 9: /* ackRequired */
6873                         offset = fBooleanTag (tvb, tree, offset, "ack Required: ");
6874                         break;
6875                 case 10: /* fromState */
6876                         offset = fEnumeratedTagSplit (tvb, tree, offset,
6877                                 "from State: ", BACnetEventState, 64);
6878                         break;
6879                 case 11: /* toState */
6880                         offset = fEnumeratedTagSplit (tvb, tree, offset,
6881                                 "to State: ", BACnetEventState, 64);
6882                         break;
6883                 case 12: /* NotificationParameters */
6884                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6885                         offset = fNotificationParameters (tvb, pinfo, tree, offset);
6886                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
6887                         break;
6888                 default:
6889                         break;
6890                 }
6891                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
6892         }
6893         return offset;
6894 }
6895
6896 static guint
6897 fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6898 {
6899         return fConfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
6900 }
6901
6902 static guint
6903 fConfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6904 {
6905         guint lastoffset = 0, len;
6906         guint8 tag_no, tag_info;
6907         guint32 lvt;
6908         proto_tree *subtree = tree;
6909         proto_item *tt;
6910
6911         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6912                 lastoffset = offset;
6913                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
6914                 if (tag_is_closing(tag_info)) {
6915                         offset += len;
6916                         subtree = tree;
6917                         continue;
6918                 }
6919
6920                 switch (tag_no) {
6921                 case 0: /* ProcessId */
6922                         offset = fProcessId (tvb,tree,offset);
6923                         break;
6924                 case 1: /* initiating DeviceId */
6925                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
6926                         break;
6927                 case 2: /* monitored ObjectId */
6928                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
6929                         break;
6930                 case 3: /* time remaining */
6931                         offset = fTimeSpan (tvb, tree, offset, "Time remaining");
6932                         break;
6933                 case 4: /* List of Values */
6934                         if (tag_is_opening(tag_info)) {
6935                                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "list of Values");
6936                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6937                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
6938                                 offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
6939                                 break;
6940                         }
6941                         FAULT;
6942                         break;
6943                 default:
6944                         return offset;
6945                 }
6946                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
6947         }
6948         return offset;
6949 }
6950
6951 static guint
6952 fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6953 {
6954         return fConfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
6955 }
6956
6957 static guint
6958 fAcknowledgeAlarmRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6959 {
6960         guint lastoffset = 0;
6961         guint8 tag_no = 0, tag_info = 0;
6962         guint32 lvt = 0;
6963
6964         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
6965                 lastoffset = offset;
6966                 switch (fTagNo(tvb, offset)) {
6967                 case 0: /* acknowledgingProcessId */
6968                         offset = fUnsignedTag (tvb, tree, offset, "acknowledging Process Id: ");
6969                         break;
6970                 case 1: /* eventObjectId */
6971                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
6972                         break;
6973                 case 2: /* eventStateAcknowledged */
6974                         offset = fEnumeratedTagSplit (tvb, tree, offset,
6975                                 "event State Acknowledged: ", BACnetEventState, 64);
6976                         break;
6977                 case 3: /* timeStamp */
6978                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
6979                         offset = fTimeStamp(tvb, tree, offset, NULL);
6980                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
6981                         break;
6982                 case 4: /* acknowledgementSource */
6983                         offset = fCharacterString (tvb, tree, offset, "acknowledgement Source: ");
6984                         break;
6985                 case 5: /* timeOfAcknowledgement */
6986                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
6987                         offset = fTimeStamp(tvb, tree, offset, "acknowledgement timestamp: ");
6988                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
6989                         break;
6990                 default:
6991                         return offset;
6992                 }
6993                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
6994         }
6995         return offset;
6996 }
6997
6998 static guint
6999 fGetAlarmSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7000 {
7001         guint lastoffset = 0;
7002
7003         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7004                 lastoffset = offset;
7005                 offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
7006                 offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
7007                         "alarm State: ", BACnetEventState, 64);
7008                 offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
7009                         "acknowledged Transitions: ", BACnetEventTransitionBits);
7010                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7011         }
7012         return  offset;
7013 }
7014
7015 static guint
7016 fGetEnrollmentSummaryRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7017 {
7018         guint lastoffset = 0;
7019         guint8 tag_no, tag_info;
7020         guint32 lvt;
7021
7022         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7023                 lastoffset = offset;
7024                 switch (fTagNo(tvb, offset)) {
7025                 case 0: /* acknowledgmentFilter */
7026                         offset = fEnumeratedTag (tvb, tree, offset,
7027                                 "acknowledgment Filter: ", BACnetAcknowledgementFilter);
7028                         break;
7029                 case 1: /* eventObjectId - OPTIONAL */
7030                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
7031                         offset = fRecipientProcess (tvb, pinfo, tree, offset);
7032                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
7033                         break;
7034                 case 2: /* eventStateFilter */
7035                         offset = fEnumeratedTag (tvb, tree, offset,
7036                                 "event State Filter: ", BACnetEventStateFilter);
7037                         break;
7038                 case 3: /* eventTypeFilter - OPTIONAL */
7039                         offset = fEnumeratedTag (tvb, tree, offset,
7040                                 "event Type Filter: ", BACnetEventType);
7041                         break;
7042                 case 4: /* priorityFilter */
7043                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
7044                         offset = fUnsignedTag (tvb, tree, offset, "min Priority: ");
7045                         offset = fUnsignedTag (tvb, tree, offset, "max Priority: ");
7046                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
7047                         break;
7048                 case 5: /* notificationClassFilter - OPTIONAL */
7049                         offset = fUnsignedTag (tvb, tree, offset, "notification Class Filter: ");
7050                         break;
7051                 default:
7052                         return offset;
7053                 }
7054                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7055         }
7056         return offset;
7057 }
7058
7059 static guint
7060 fGetEnrollmentSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7061 {
7062         guint lastoffset = 0;
7063
7064         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7065                 lastoffset = offset;
7066                 offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
7067                 offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
7068                         "event Type: ", BACnetEventType, 64);
7069                 offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
7070                         "event State: ", BACnetEventState);
7071                 offset = fApplicationTypes (tvb, pinfo, tree, offset, "Priority: ");
7072                 offset = fApplicationTypes (tvb, pinfo, tree, offset, "Notification Class: ");
7073                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7074         }
7075
7076         return  offset;
7077 }
7078
7079 static guint
7080 fGetEventInformationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7081 {
7082         if (tvb_reported_length_remaining(tvb, offset) > 0) {
7083                 if (fTagNo(tvb, offset) == 0) {
7084                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
7085                 }
7086         }
7087         return offset;
7088 }
7089
7090 static guint
7091 flistOfEventSummaries (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7092 {
7093         guint lastoffset = 0;
7094         guint8 tag_no, tag_info;
7095         guint32 lvt;
7096         proto_tree* subtree = tree;
7097         proto_item* ti = 0;
7098
7099         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7100                 lastoffset = offset;
7101                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7102                 /* we are finished here if we spot a closing tag */
7103                 if (tag_is_closing(tag_info)) {
7104                         break;
7105                 }
7106                 switch (tag_no) {
7107                 case 0: /* ObjectId */
7108                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
7109                         break;
7110                 case 1: /* eventState */
7111                         offset = fEnumeratedTag (tvb, tree, offset,
7112                                 "event State: ", BACnetEventState);
7113                         break;
7114                 case 2: /* acknowledgedTransitions */
7115                         offset = fBitStringTagVS (tvb, tree, offset,
7116                                 "acknowledged Transitions: ", BACnetEventTransitionBits);
7117                         break;
7118                 case 3: /* eventTimeStamps */
7119                         ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
7120                         if (ti) {
7121                                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7122                         }
7123                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7124                         offset = fTimeStamp (tvb, subtree, offset,"TO-OFFNORMAL timestamp: ");
7125                         offset = fTimeStamp (tvb, subtree, offset,"TO-FAULT timestamp: ");
7126                         offset = fTimeStamp (tvb, subtree, offset,"TO-NORMAL timestamp: ");
7127                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7128                         break;
7129                 case 4: /* notifyType */
7130                         offset = fEnumeratedTag (tvb, tree, offset,
7131                                 "Notify Type: ", BACnetNotifyType);
7132                         break;
7133                 case 5: /* eventEnable */
7134                         offset = fBitStringTagVS (tvb, tree, offset,
7135                                 "event Enable: ", BACnetEventTransitionBits);
7136                         break;
7137                 case 6: /* eventPriorities */
7138                         ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventPriorities");
7139                         if (ti) {
7140                                 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7141                         }
7142                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7143                         offset = fUnsignedTag (tvb, subtree, offset, "TO-OFFNORMAL Priority: ");
7144                         offset = fUnsignedTag (tvb, subtree, offset, "TO-FAULT Priority: ");
7145                         offset = fUnsignedTag (tvb, subtree, offset, "TO-NORMAL Priority: ");
7146                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7147                         break;
7148                 default:
7149                         return offset;
7150                 }
7151                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7152         }
7153         return offset;
7154 }
7155
7156 static guint
7157 fLOPR (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7158 {
7159         guint lastoffset = 0;
7160         guint8 tag_no, tag_info;
7161         guint32 lvt;
7162
7163         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
7164         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7165                 lastoffset = offset;
7166                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7167                 /* we are finished here if we spot a closing tag */
7168                 if (tag_is_closing(tag_info)) {
7169                         break;
7170                 }
7171                 offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
7172                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7173         }
7174         return offset;
7175 }
7176
7177 static guint
7178 fGetEventInformationACK (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7179 {
7180         guint lastoffset = 0;
7181         guint8 tag_no, tag_info;
7182         guint32 lvt;
7183
7184         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7185                 lastoffset = offset;
7186                 switch (fTagNo(tvb, offset)) {
7187                 case 0: /* listOfEventSummaries */
7188                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
7189                         offset = flistOfEventSummaries (tvb, pinfo, tree, offset);
7190                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
7191                         break;
7192                 case 1: /* moreEvents */
7193                         offset = fBooleanTag (tvb, tree, offset, "more Events: ");
7194                         break;
7195                 default:
7196                         return offset;
7197                 }
7198                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7199         }
7200         return offset;
7201 }
7202
7203 static guint
7204 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7205 {
7206         guint lastoffset = 0, len;
7207         guint8 tag_no, tag_info;
7208         guint32 lvt;
7209         proto_tree *subtree = tree;
7210         proto_item *tt;
7211
7212         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
7213
7214         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7215                 lastoffset = offset;
7216                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7217                 if (tag_is_closing(tag_info)) {
7218                         offset += len;
7219                         subtree = tree;
7220                         continue;
7221                 }
7222
7223                 switch (tag_no) {
7224                 case 0: /* ObjectId */
7225                         offset = fBACnetObjectPropertyReference (tvb, pinfo, subtree, offset);
7226                         break;
7227                 case 3: /* listOfElements */
7228                         if (tag_is_opening(tag_info)) {
7229                                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfElements");
7230                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7231                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7232                                 offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
7233                                 break;
7234                         }
7235                         FAULT;
7236                         break;
7237                 default:
7238                         return offset;
7239                 }
7240                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7241         }
7242         return offset;
7243 }
7244
7245 static guint
7246 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7247 {
7248         return fObjectIdentifier (tvb, pinfo, tree, offset);
7249 }
7250
7251 static guint
7252 fDeviceCommunicationControlRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
7253 {
7254         guint lastoffset = 0;
7255
7256         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7257                 lastoffset = offset;
7258
7259                 switch (fTagNo(tvb, offset)) {
7260                 case 0: /* timeDuration */
7261                         offset = fUnsignedTag (tvb,tree,offset,"time Duration: ");
7262                         break;
7263                 case 1: /* enable-disable */
7264                         offset = fEnumeratedTag (tvb, tree, offset, "enable-disable: ",
7265                                 BACnetEnableDisable);
7266                         break;
7267                 case 2: /* password - OPTIONAL */
7268                         offset = fCharacterString (tvb, tree, offset, "Password: ");
7269                         break;
7270                 default:
7271                         return offset;
7272                 }
7273                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7274         }
7275         return offset;
7276 }
7277
7278 static guint
7279 fReinitializeDeviceRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
7280 {
7281         guint lastoffset = 0;
7282
7283         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7284                 lastoffset = offset;
7285
7286                 switch (fTagNo(tvb, offset)) {
7287                 case 0: /* reinitializedStateOfDevice */
7288                         offset = fEnumeratedTag (tvb, tree, offset,
7289                                 "reinitialized State Of Device: ",
7290                                 BACnetReinitializedStateOfDevice);
7291                         break;
7292                 case 1: /* password - OPTIONAL */
7293                         offset = fCharacterString (tvb, tree, offset, "Password: ");
7294                         break;
7295                 default:
7296                         return offset;
7297                 }
7298                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7299         }
7300         return offset;
7301 }
7302
7303 static guint
7304 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7305 {
7306         offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
7307                 "vtClass: ", BACnetVTClass);
7308         return fApplicationTypes (tvb, pinfo, tree,offset,"local VT Session ID: ");
7309 }
7310
7311 static guint
7312 fVtOpenAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7313 {
7314         return fApplicationTypes (tvb, pinfo, tree,offset,"remote VT Session ID: ");
7315 }
7316
7317 static guint
7318 fVtCloseRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7319 {
7320         guint lastoffset = 0;
7321
7322         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7323                 lastoffset = offset;
7324                 offset= fApplicationTypes (tvb, pinfo, tree,offset,"remote VT Session ID: ");
7325                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7326         }
7327         return offset;
7328 }
7329
7330 static guint
7331 fVtDataRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7332 {
7333         offset= fApplicationTypes (tvb, pinfo, tree,offset,"VT Session ID: ");
7334         offset = fApplicationTypes (tvb, pinfo, tree, offset, "VT New Data: ");
7335         return fApplicationTypes (tvb, pinfo, tree,offset,"VT Data Flag: ");;
7336 }
7337
7338 static guint
7339 fVtDataAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
7340 {
7341         guint lastoffset = 0;
7342
7343         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7344                 lastoffset = offset;
7345
7346                 switch (fTagNo(tvb,offset)) {
7347                 case 0: /* BOOLEAN */
7348                         offset = fBooleanTag (tvb, tree, offset, "all New Data Accepted: ");
7349                         break;
7350                 case 1: /* Unsigned OPTIONAL */
7351                         offset = fUnsignedTag (tvb, tree, offset, "accepted Octet Count: ");
7352                         break;
7353                 default:
7354                         return offset;
7355                 }
7356                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7357         }
7358         return offset;
7359 }
7360
7361 static guint
7362 fAuthenticateRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
7363 {
7364         guint lastoffset = 0;
7365
7366         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7367                 lastoffset = offset;
7368
7369                 switch (fTagNo(tvb,offset)) {
7370                 case 0: /* Unsigned32 */
7371                         offset = fUnsignedTag (tvb, tree, offset, "pseudo Random Number: ");
7372                         break;
7373                 case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
7374                         proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
7375                         break;
7376                 case 2: /* Chararacter String OPTIONAL */
7377                         offset = fCharacterString (tvb, tree, offset, "operator Name: ");
7378                         break;
7379                 case 3: /* Chararacter String OPTIONAL */
7380                         offset = fCharacterString (tvb, tree, offset, "operator Password: ");
7381                         break;
7382                 case 4: /* Boolean OPTIONAL */
7383                         offset = fBooleanTag (tvb, tree, offset, "start Encyphered Session: ");
7384                         break;
7385                 default:
7386                         return offset;
7387                 }
7388                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7389         }
7390         return offset;
7391 }
7392
7393 static guint
7394 fAuthenticateAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7395 {
7396         return fApplicationTypes (tvb, pinfo, tree, offset, "modified Random Number: ");
7397 }
7398
7399 static guint
7400 fRequestKeyRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7401 {
7402         offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* Requesting Device Identifier */
7403         offset = fAddress (tvb, tree, offset);
7404         offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* Remote Device Identifier */
7405         return fAddress (tvb, tree, offset);
7406 }
7407
7408 static guint
7409 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7410 {
7411         /* Same as AddListElement request after service choice */
7412         return fAddListElementRequest(tvb, pinfo, tree, offset);
7413 }
7414
7415 static guint
7416 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7417 {
7418         return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
7419 }
7420
7421 static guint
7422 fReadPropertyAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7423 {
7424         guint lastoffset = 0, len;
7425         guint8 tag_no, tag_info;
7426         guint32 lvt;
7427         proto_tree *subtree = tree;
7428
7429         /* set the optional global properties to indicate not-used */
7430         propertyArrayIndex = -1;
7431         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7432                 lastoffset = offset;
7433                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7434                 if (tag_is_closing(tag_info)) {
7435                         offset += len;
7436                         subtree = tree;
7437                         continue;
7438                 }
7439                 switch (tag_no) {
7440                 case 0: /* objectIdentifier */
7441                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
7442                         break;
7443                 case 1: /* propertyIdentifier */
7444                         offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
7445                         break;
7446                 case 2: /* propertyArrayIndex */
7447                         offset = fPropertyArrayIndex (tvb, subtree, offset);
7448                         break;
7449                 case 3: /* propertyValue */
7450                         offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
7451                         break;
7452                 default:
7453                         break;
7454                 }
7455                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7456         }
7457         return offset;
7458 }
7459
7460 static guint
7461 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7462 {
7463         guint lastoffset = 0;
7464         guint8 tag_no, tag_info;
7465         guint32 lvt;
7466         proto_tree *subtree = tree;
7467
7468         /* set the optional global properties to indicate not-used */
7469         propertyArrayIndex = -1;
7470         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7471                 lastoffset = offset;
7472                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7473                 /* quit loop if we spot a closing tag */
7474                 if (tag_is_closing(tag_info)) {
7475                         subtree = tree;
7476                         break;
7477                 }
7478
7479                 switch (tag_no) {
7480                 case 0: /* objectIdentifier */
7481                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
7482                         break;
7483                 case 1: /* propertyIdentifier */
7484                         offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
7485                         break;
7486                 case 2: /* propertyArrayIndex */
7487                         offset = fPropertyArrayIndex (tvb, subtree, offset);
7488                         break;
7489                 case 3: /* propertyValue */
7490                         offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
7491                         break;
7492                 case 4: /* Priority (only used for write) */
7493                         offset = fUnsignedTag (tvb, subtree, offset, "Priority: ");
7494                         break;
7495                 default:
7496                         return offset;
7497                 }
7498                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7499         }
7500         return offset;
7501 }
7502
7503 static guint
7504 fWriteAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
7505 {
7506         guint lastoffset = 0, len;
7507         guint8 tag_no, tag_info;
7508         guint32 lvt;
7509
7510         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7511                 lastoffset = offset;
7512                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7513                 /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
7514                 if (tag_is_closing(tag_info)) {
7515                         offset += len;
7516                         continue;
7517                 }
7518
7519                 switch (tag_no) {
7520                 case 0: /* objectIdentifier */
7521                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
7522                         break;
7523                 case 1: /* listOfPropertyValues */
7524                         if (tag_is_opening(tag_info)) {
7525                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7526                                 offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
7527                                 break;
7528                         }
7529                         FAULT;
7530                         break;
7531                 default:
7532                         return offset;
7533                 }
7534                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7535         }
7536         return offset;
7537 }
7538
7539 static guint
7540 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7541 {
7542         if (offset >= tvb_reported_length(tvb))
7543                 return offset;
7544
7545         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
7546         return fWriteAccessSpecification (tvb, pinfo, tree, offset);
7547 }
7548
7549 static guint
7550 fPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
7551 {
7552         guint lastoffset = 0;
7553         guint8 tag_no, tag_info;
7554         guint32 lvt;
7555
7556         /* set the optional global properties to indicate not-used */
7557         propertyArrayIndex = -1;
7558         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7559                 lastoffset = offset;
7560                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7561                 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
7562                         return offset;
7563                 } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
7564                         return offset;
7565                 }
7566                 switch (tag_no-tagoffset) {
7567                 case 0: /* PropertyIdentifier */
7568                         offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
7569                         break;
7570                 case 1: /* propertyArrayIndex */
7571                         offset = fPropertyArrayIndex (tvb, tree, offset);
7572                         if (list != 0) break; /* Continue decoding if this may be a list */
7573                 default:
7574                         lastoffset = offset; /* Set loop end condition */
7575                         break;
7576                 }
7577                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7578         }
7579         return offset;
7580 }
7581
7582 static guint
7583 fBACnetPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list)
7584 {
7585         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
7586         return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
7587 }
7588
7589 static guint
7590 fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7591 {
7592         guint lastoffset = 0;
7593
7594         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7595                 lastoffset = offset;
7596
7597                 switch (fTagNo(tvb,offset)) {
7598                 case 0: /* ObjectIdentifier */
7599                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
7600                         break;
7601                 case 1: /* PropertyIdentifier and propertyArrayIndex */
7602                         offset = fPropertyReference (tvb, pinfo, tree, offset, 1, 0);
7603                         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
7604                 default:
7605                         lastoffset = offset; /* Set loop end condition */
7606                         break;
7607                 }
7608                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7609         }
7610         return offset;
7611 }
7612
7613 #if 0
7614 static guint
7615 fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
7616 {
7617         guint lastoffset = 0;
7618         guint8 tag_no, tag_info;
7619         guint32 lvt;
7620         proto_tree* subtree = tree;
7621         proto_item* tt;
7622
7623         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
7624                 lastoffset = offset;
7625                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7626                 if (tag_is_closing(tag_info)) {
7627                         offset += fTagHeaderTree (tvb, subtree, offset,
7628                                 &tag_no, &tag_info, &lvt);
7629                         continue;
7630                 }
7631                 switch (tag_no) {
7632                 case 0: /* ObjectIdentifier */
7633                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
7634                         break;
7635                 case 1: /* PropertyIdentifier */
7636                         offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
7637                         break;
7638                 case 2: /* propertyArrayIndex */
7639                         offset = fUnsignedTag (tvb, subtree, offset, "property Array Index: ");
7640                         break;
7641                 case 3:  /* Value */
7642                         offset = fPropertyValue (tvb, subtree, offset, tag_info);
7643                         break;
7644                 case 4:  /* Priority */
7645                         offset = fUnsignedTag (tvb, subtree, offset, "Priority: ");
7646                         break;
7647                 default:
7648                         break;
7649                 }
7650         }
7651         return offset;
7652 }
7653 #endif
7654
7655 static guint
7656 fPriorityArray (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7657 {
7658         char i = 1, ar[256];
7659         guint lastoffset = 0;
7660
7661         if (propertyArrayIndex > 0) {
7662                 /* BACnetARRAY index 0 refers to the length
7663                 of the array, not the elements of the array.
7664                 BACnetARRAY index -1 is our internal flag that
7665                 the optional index was not used.
7666                 BACnetARRAY refers to this as all elements of the array.
7667                 If the optional index is specified for a BACnetARRAY,
7668                 then that specific array element is referenced. */
7669                 i = propertyArrayIndex;
7670         }
7671         while (tvb_reported_length_remaining(tvb, offset)) {
7672                 /* exit loop if nothing happens inside */
7673                 lastoffset = offset;
7674                 g_snprintf (ar, sizeof(ar), "%s[%d]: ",
7675                         val_to_split_str(87 , 512,
7676                                 BACnetPropertyIdentifier,
7677                                 ASHRAE_Reserved_Fmt,
7678                                 Vendor_Proprietary_Fmt),
7679                         i++);
7680                 /* DMR Should be fAbstractNSyntax, but that's where we came from! */
7681                 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
7682                 /* there are only 16 priority array elements */
7683                 if (i > 16) {
7684                         break;
7685                 }
7686                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7687         }
7688
7689         return offset;
7690 }
7691
7692 static guint
7693 fDeviceObjectReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7694 {
7695         guint lastoffset = 0;
7696
7697         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7698                 lastoffset = offset;
7699
7700                 switch (fTagNo(tvb,offset)) {
7701                 case 0: /* deviceIdentifier - OPTIONAL */
7702                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
7703                         break;
7704                 case 1: /* ObjectIdentifier */
7705                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
7706                         break;
7707                 default:
7708                         return offset;
7709                 }
7710                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7711         }
7712         return offset;
7713 }
7714
7715 static guint
7716 fSpecialEvent (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
7717 {
7718         guint8 tag_no, tag_info;
7719         guint32 lvt;
7720         guint lastoffset = 0, len;
7721
7722         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7723                 lastoffset = offset;
7724                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7725                 /* maybe a SEQUENCE of SpecialEvents if we spot a closing tag */
7726                 if (tag_is_closing(tag_info)) {
7727                         offset += len;
7728                         continue;
7729                 }
7730
7731                 switch (tag_no) {
7732                 case 0: /* calendaryEntry */
7733                         if (tag_is_opening(tag_info))
7734                         {
7735                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7736                                 offset = fCalendaryEntry (tvb, subtree, offset);
7737                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7738                         }
7739                         break;
7740                 case 1: /* calendarReference */
7741                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
7742                         break;
7743                 case 2: /* list of BACnetTimeValue */
7744                         if (tag_is_opening(tag_info)) {
7745                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7746                                 offset = fTimeValue (tvb, pinfo, subtree, offset);
7747                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7748                                 break;
7749                         }
7750                         FAULT;
7751                         break;
7752                 case 3: /* eventPriority */
7753                         offset = fUnsignedTag (tvb, subtree, offset, "event priority: ");
7754                         break;
7755                 default:
7756                         return offset;
7757                 }
7758                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7759         }
7760         return offset;
7761 }
7762
7763 static guint
7764 fSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7765 {
7766         guint lastoffset = 0, len;
7767         guint8 tag_no, tag_info;
7768         guint32 lvt;
7769
7770         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7771                 lastoffset = offset;
7772                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7773                 /* maybe a listOfSelectionCriteria if we spot a closing tag */
7774                 if (tag_is_closing(tag_info)) {
7775                         offset += len;
7776                         continue;
7777                 }
7778
7779                 switch (fTagNo(tvb,offset)) {
7780                 case 0: /* propertyIdentifier */
7781                         offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
7782                         break;
7783                 case 1: /* propertyArrayIndex */
7784                         offset = fPropertyArrayIndex (tvb, tree, offset);
7785                         break;
7786                 case 2: /* relationSpecifier */
7787                         offset = fEnumeratedTag (tvb, tree, offset,
7788                                 "relation Specifier: ", BACnetRelationSpecifier);
7789                         break;
7790                 case 3: /* comparisonValue */
7791                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
7792                         offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
7793                         offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
7794                         break;
7795                 default:
7796                         return offset;
7797                 }
7798                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7799         }
7800         return offset;
7801 }
7802
7803 static guint
7804 fObjectSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
7805 {
7806         guint lastoffset = 0;
7807         guint8 tag_no, tag_info;
7808         guint32 lvt;
7809
7810         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7811                 lastoffset = offset;
7812                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7813                 /* quit loop if we spot a closing tag */
7814                 if (tag_is_closing(tag_info)) {
7815                         break;
7816                 }
7817
7818                 switch (tag_no) {
7819                 case 0: /* selectionLogic */
7820                         offset = fEnumeratedTag (tvb, subtree, offset,
7821                                 "selection Logic: ", BACnetSelectionLogic);
7822                         break;
7823                 case 1: /* listOfSelectionCriteria */
7824                         if (tag_is_opening(tag_info)) {
7825                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7826                                 offset = fSelectionCriteria (tvb, pinfo, subtree, offset);
7827                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7828                                 break;
7829                         }
7830                         FAULT;
7831                         break;
7832                 default:
7833                         return offset;
7834                 }
7835                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7836         }
7837         return offset;
7838 }
7839
7840
7841 static guint
7842 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, guint offset)
7843 {
7844         guint lastoffset = 0;
7845         guint8 tag_no, tag_info;
7846         guint32 lvt;
7847
7848         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7849                 lastoffset = offset;
7850                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7851
7852                 if (tag_is_opening(tag_info) && tag_no < 2) {
7853                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7854                         switch (tag_no) {
7855                         case 0: /* objectSelectionCriteria */
7856                                 offset = fObjectSelectionCriteria (tvb, pinfo, subtree, offset);
7857                                 break;
7858                         case 1: /* listOfPropertyReferences */
7859                                 offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
7860                                 break;
7861                         default:
7862                                 return offset;
7863                         }
7864                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7865                 }
7866                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7867         }
7868         return offset;
7869 }
7870
7871 static guint
7872 fReadAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7873 {
7874         guint lastoffset = 0;
7875         guint8 tag_no, tag_info;
7876         guint32 lvt;
7877         proto_item *tt;
7878         proto_tree *subtree = tree;
7879
7880         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7881                 lastoffset = offset;
7882                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7883                 switch (tag_no) {
7884                 case 0: /* objectIdentifier */
7885                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
7886                         break;
7887                 case 1: /* listOfPropertyReferences */
7888                         if (tag_is_opening(tag_info)) {
7889                                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfPropertyReferences");
7890                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7891                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7892                                 offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
7893                         } else if (tag_is_closing(tag_info)) {
7894                                 offset += fTagHeaderTree (tvb, subtree, offset,
7895                                         &tag_no, &tag_info, &lvt);
7896                                 subtree = tree;
7897                         } else {
7898                                 /* error condition: let caller handle */
7899                                 return offset;
7900                         }
7901                         break;
7902                 default:
7903                         return offset;
7904                 }
7905                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7906         }
7907         return offset;
7908 }
7909
7910 static guint
7911 fReadAccessResult (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7912 {
7913         guint lastoffset = 0, len;
7914         guint8 tag_no;
7915         guint8 tag_info;
7916         guint32 lvt;
7917         proto_tree *subtree = tree;
7918         proto_item *tt;
7919
7920         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7921                 lastoffset = offset;
7922                 len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7923                 /* maybe a listOfReadAccessResults if we spot a closing tag here */
7924                 if (tag_is_closing(tag_info)) {
7925                         offset += len;
7926                         if ((tag_no == 4 || tag_no == 5) && (subtree != tree)) subtree = subtree->parent; /* Value and error have extra subtree */
7927                         continue;
7928                 }
7929
7930                 switch (tag_no) {
7931                 case 0: /* objectSpecifier */
7932                         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
7933                         break;
7934                 case 1: /* list of Results */
7935                         if (tag_is_opening(tag_info)) {
7936                                 tt = proto_tree_add_text(tree, tvb, offset, 1, "listOfResults");
7937                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7938                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7939                                 break;
7940                         }
7941                         FAULT;
7942                         break;
7943                 case 2: /* propertyIdentifier */
7944                         offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
7945                         break;
7946                 case 5: /* propertyAccessError */
7947                         if (tag_is_opening(tag_info)) {
7948                                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyAccessError");
7949                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7950                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7951                                 /* Error Code follows */
7952                                 offset = fError(tvb, pinfo, subtree, offset);
7953                                 break;
7954                         }
7955                         FAULT;
7956                         break;
7957                 default:
7958                         return offset;
7959                 }
7960                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
7961         }
7962         return offset;
7963 }
7964
7965
7966 static guint
7967 fReadPropertyConditionalAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7968 {
7969         /* listOfReadAccessResults */
7970         return fReadAccessResult (tvb, pinfo, tree, offset);
7971 }
7972
7973
7974 static guint
7975 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
7976 {
7977         guint lastoffset = 0;
7978         guint8 tag_no, tag_info;
7979         guint32 lvt;
7980
7981         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
7982                 lastoffset = offset;
7983                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
7984
7985                 if (tag_no < 2)
7986                 {
7987                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
7988                         switch (tag_no) {
7989                         case 0: /* objectSpecifier */
7990                                 switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
7991                                 case 0: /* objectType */
7992                                         offset = fEnumeratedTagSplit (tvb, subtree, offset, "Object Type: ", BACnetObjectType, 128);
7993                                         break;
7994                                 case 1: /* objectIdentifier */
7995                                         offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
7996                                         break;
7997                                 default:
7998                                         break;
7999                                 }
8000                                 break;
8001                         case 1: /* propertyValue */
8002                                 if (tag_is_opening(tag_info)) {
8003                                         offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
8004                                         break;
8005                                 }
8006                                 FAULT;
8007                                 break;
8008                         default:
8009                                 break;
8010                         }
8011                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8012                 }
8013                 if (offset == lastoffset) break;    /* nothing happened, exit loop */
8014         }
8015         return offset;
8016 }
8017
8018 static guint
8019 fCreateObjectAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8020 {
8021         return fObjectIdentifier (tvb, pinfo, tree, offset);
8022 }
8023
8024 static guint
8025 fReadRangeRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8026 {
8027         guint8 tag_no, tag_info;
8028         guint32 lvt;
8029         proto_tree *subtree = tree;
8030         proto_item *tt;
8031
8032         offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
8033
8034         if (tvb_reported_length_remaining(tvb, offset) > 0) {
8035                 /* optional range choice */
8036                 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
8037                 if (tag_is_opening(tag_info)) {
8038                         tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetReadRangeOptions, "unknown range option"));
8039                         subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8040                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8041                         switch (tag_no) {
8042                         case 3: /* range byPosition */
8043                         case 6: /* range bySequenceNumber, 2004 spec */
8044                                 offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Index: ");
8045                                 offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Count: ");
8046                                 break;
8047                         case 4: /* range byTime - deprecated in 2004 */
8048                         case 7: /* 2004 spec */
8049                                 offset = fDateTime(tvb, subtree, offset, "reference Date/Time: ");
8050                                 offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Count: ");
8051                                 break;
8052                         case 5: /* range timeRange - deprecated in 2004 */
8053                                 offset = fDateTime(tvb, subtree, offset, "beginning Time: ");
8054                                 offset = fDateTime(tvb, subtree, offset, "ending Time: ");
8055                                 break;
8056                         default:
8057                                 break;
8058                         }
8059                         offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8060                 }
8061         }
8062         return offset;
8063 }
8064
8065 static guint
8066 fReadRangeAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8067 {
8068         guint8 tag_no, tag_info;
8069         guint32 lvt;
8070         proto_tree *subtree = tree;
8071         proto_item *tt;
8072
8073         /* set the optional global properties to indicate not-used */
8074         propertyArrayIndex = -1;
8075         /* objectIdentifier, propertyIdentifier, and
8076            OPTIONAL propertyArrayIndex */
8077         offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
8078         /* resultFlags => BACnetResultFlags ::= BIT STRING */
8079         offset = fBitStringTagVS (tvb, tree, offset,
8080                 "resultFlags: ",
8081                 BACnetResultFlags);
8082         /* itemCount */
8083         offset = fUnsignedTag (tvb, subtree, offset, "item Count: ");
8084         /* itemData */
8085         fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
8086         if (tag_is_opening(tag_info)) {
8087                 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
8088                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
8089                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8090                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8091                 offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
8092                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8093         }
8094         /* firstSequenceNumber - OPTIONAL */
8095         if (tvb_reported_length_remaining(tvb, offset) > 0) {
8096                 offset = fUnsignedTag (tvb, subtree, offset, "first Sequence Number: ");
8097         }
8098
8099         return offset;
8100 }
8101
8102 static guint
8103 fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8104 {
8105         guint lastoffset = 0;
8106         guint32 lvt;
8107         guint8 tag_no, tag_info;
8108         proto_item* tt;
8109         proto_tree* subtree = NULL;
8110
8111         fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
8112
8113         if (tag_is_opening(tag_info))
8114         {
8115                 tt = proto_tree_add_text(tree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetFileAccessOption, "invalid access method"));
8116                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8117                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8118                 offset = fApplicationTypes (tvb, pinfo, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "invalid option"));
8119                 offset = fApplicationTypes (tvb, pinfo, subtree, offset, val_to_str(tag_no, BACnetFileWriteInfo, "unknown option"));
8120
8121                 if (tag_no == 1)
8122                 {
8123                         while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset))
8124                         {  /* exit loop if nothing happens inside */
8125                                 lastoffset = offset;
8126                                 offset = fApplicationTypes (tvb, pinfo, subtree, offset, "Record Data: ");
8127                         }
8128                 }
8129
8130                 if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0)
8131                 {
8132                         /* More Flag is not set, so we can look for closing tag in this segment */
8133                         fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
8134                         if (tag_is_closing(tag_info)) {
8135                                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8136                         }
8137                 }
8138         }
8139         return offset;
8140 }
8141
8142 static guint
8143 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8144 {
8145         guint8 tag_no, tag_info;
8146         guint32 lvt;
8147         proto_tree *subtree = tree;
8148         proto_item *tt;
8149
8150         offset = fObjectIdentifier (tvb, pinfo, tree, offset);
8151
8152         fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
8153
8154         if (tag_is_opening(tag_info))
8155         {
8156                 tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetFileAccessOption, "unknown access method"));
8157                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8158                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8159                 offset = fSignedTag (tvb, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "unknown option"));
8160                 offset = fUnsignedTag (tvb, subtree, offset, val_to_str(tag_no, BACnetFileRequestCount, "unknown option"));
8161                 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8162         }
8163         return offset;
8164 }
8165
8166 static guint
8167 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8168 {
8169
8170         offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* file Identifier */
8171         offset = fAccessMethod(tvb, pinfo, tree, offset);
8172
8173         return offset;
8174 }
8175
8176 static guint
8177 fAtomicWriteFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
8178 {
8179         guint tag_no = fTagNo(tvb, offset);
8180         return fSignedTag (tvb, tree, offset, val_to_str(tag_no, BACnetFileStartOption, "unknown option"));
8181 }
8182
8183 static guint
8184 fAtomicReadFileAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8185 {
8186         offset = fApplicationTypes (tvb, pinfo, tree, offset, "End Of File: ");
8187         offset = fAccessMethod(tvb,pinfo, tree, offset);
8188
8189         return offset;
8190 }
8191
8192 static guint
8193 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
8194 {
8195         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
8196         return fReadAccessSpecification (tvb,pinfo,subtree,offset);
8197 }
8198
8199 static guint
8200 fReadPropertyMultipleAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8201 {
8202         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
8203         return fReadAccessResult (tvb,pinfo,tree,offset);
8204 }
8205
8206 static guint
8207 fConfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
8208 {
8209         if (tvb_reported_length_remaining(tvb,offset) <= 0)
8210                 return offset;
8211
8212         switch (service_choice) {
8213         case 0: /* acknowledgeAlarm */
8214                 offset = fAcknowledgeAlarmRequest (tvb, pinfo, tree, offset);
8215                 break;
8216         case 1: /* confirmedCOVNotification */
8217                 offset = fConfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
8218                 break;
8219         case 2: /* confirmedEventNotification */
8220                 offset = fConfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
8221                 break;
8222         case 3: /* confirmedGetAlarmSummary conveys no parameters */
8223                 break;
8224         case 4: /* getEnrollmentSummaryRequest */
8225                 offset = fGetEnrollmentSummaryRequest (tvb, pinfo, tree, offset);
8226                 break;
8227         case 5: /* subscribeCOVRequest */
8228                 offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
8229                 break;
8230         case 6: /* atomicReadFile-Request */
8231                 offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
8232                 break;
8233         case 7: /* atomicWriteFile-Request */
8234                 offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
8235                 break;
8236         case 8: /* AddListElement-Request */
8237                 offset = fAddListElementRequest(tvb, pinfo, tree, offset);
8238                 break;
8239         case 9: /* removeListElement-Request */
8240                 offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
8241                 break;
8242         case 10: /* createObjectRequest */
8243                 offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
8244                 break;
8245         case 11: /* deleteObject */
8246                 offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
8247                 break;
8248         case 12:
8249                 offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
8250                 break;
8251         case 13:
8252                 offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
8253                 break;
8254         case 14:
8255                 offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
8256                 break;
8257         case 15:
8258                 offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
8259                 break;
8260         case 16:
8261                 offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
8262                 break;
8263         case 17:
8264                 offset = fDeviceCommunicationControlRequest(tvb, tree, offset);
8265                 break;
8266         case 18:
8267                 offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
8268                 break;
8269         case 19:
8270                 offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
8271                 break;
8272         case 20:
8273                 offset = fReinitializeDeviceRequest(tvb, tree, offset);
8274                 break;
8275         case 21:
8276                 offset = fVtOpenRequest(tvb, pinfo, tree, offset);
8277                 break;
8278         case 22:
8279                 offset = fVtCloseRequest (tvb, pinfo, tree, offset);
8280                 break;
8281         case 23:
8282                 offset = fVtDataRequest (tvb, pinfo, tree, offset);
8283                 break;
8284         case 24:
8285                 offset = fAuthenticateRequest (tvb, tree, offset);
8286                 break;
8287         case 25:
8288                 offset = fRequestKeyRequest (tvb, pinfo, tree, offset);
8289                 break;
8290         case 26:
8291                 offset = fReadRangeRequest (tvb, pinfo, tree, offset);
8292                 break;
8293         case 27:
8294                 offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
8295                 break;
8296         case 28:
8297                 offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
8298                 break;
8299         case 29:
8300                 offset = fGetEventInformationRequest (tvb, pinfo, tree, offset);
8301                 break;
8302         default:
8303                 return offset;
8304         }
8305         return offset;
8306 }
8307
8308 static guint
8309 fConfirmedServiceAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
8310 {
8311         if (tvb_reported_length_remaining(tvb,offset) <= 0)
8312                 return offset;
8313
8314         switch (service_choice) {
8315         case 3: /* confirmedEventNotificationAck */
8316                 offset = fGetAlarmSummaryAck (tvb, pinfo, tree, offset);
8317                 break;
8318         case 4: /* getEnrollmentSummaryAck */
8319                 offset = fGetEnrollmentSummaryAck (tvb, pinfo, tree, offset);
8320                 break;
8321         case 6: /* atomicReadFile */
8322                 offset = fAtomicReadFileAck (tvb, pinfo, tree, offset);
8323                 break;
8324         case 7: /* atomicReadFileAck */
8325                 offset = fAtomicWriteFileAck (tvb, tree, offset);
8326                 break;
8327         case 10: /* createObject */
8328                 offset = fCreateObjectAck (tvb, pinfo, tree, offset);
8329                 break;
8330         case 12:
8331                 offset = fReadPropertyAck (tvb, pinfo, tree, offset);
8332                 break;
8333         case 13:
8334                 offset = fReadPropertyConditionalAck (tvb, pinfo, tree, offset);
8335                 break;
8336         case 14:
8337                 offset = fReadPropertyMultipleAck (tvb, pinfo, tree, offset);
8338                 break;
8339         case 18:
8340                 offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
8341                 break;
8342         case 21:
8343                 offset = fVtOpenAck (tvb, pinfo, tree, offset);
8344                 break;
8345         case 23:
8346                 offset = fVtDataAck (tvb, tree, offset);
8347                 break;
8348         case 24:
8349                 offset = fAuthenticateAck (tvb, pinfo, tree, offset);
8350                 break;
8351         case 26:
8352                 offset = fReadRangeAck (tvb, pinfo, tree, offset);
8353                 break;
8354         case 29:
8355                 offset = fGetEventInformationACK (tvb, pinfo, tree, offset);
8356                 break;
8357         default:
8358                 return offset;
8359         }
8360         return offset;
8361 }
8362
8363 static guint
8364 fIAmRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8365 {
8366         /* BACnetObjectIdentifier */
8367         offset = fApplicationTypes (tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
8368
8369         /* MaxAPDULengthAccepted */
8370         offset = fApplicationTypes (tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
8371
8372         /* segmentationSupported */
8373         offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
8374                 "Segmentation Supported: ", BACnetSegmentation);
8375
8376         /* vendor ID */
8377         return fVendorIdentifier (tvb, pinfo, tree, offset);
8378 }
8379
8380 static guint
8381 fIHaveRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8382 {
8383         /* BACnetDeviceIdentifier */
8384         offset = fApplicationTypes (tvb, pinfo, tree, offset, "Device Identifier: ");
8385
8386         /* BACnetObjectIdentifier */
8387         offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
8388
8389         /* ObjectName */
8390         return fApplicationTypes (tvb, pinfo, tree, offset, "Object Name: ");
8391
8392 }
8393
8394 static guint
8395 fWhoIsRequest  (tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, guint offset)
8396 {
8397         guint lastoffset = 0;
8398         guint val;
8399         guint8 tag_len;
8400
8401         guint8 tag_no, tag_info;
8402         guint32 lvt;
8403
8404         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
8405                 lastoffset = offset;
8406
8407                 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
8408
8409                 switch (tag_no) {
8410                 case 0:
8411                         /* DeviceInstanceRangeLowLimit Optional */
8412                         fUnsigned32(tvb, offset+tag_len, lvt, &val);
8413                         if (col_get_writable(pinfo->cinfo))
8414                                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
8415                         offset = fDevice_Instance (tvb, tree, offset,
8416                                 hf_Device_Instance_Range_Low_Limit);
8417                         break;
8418                 case 1:
8419                         /* DeviceInstanceRangeHighLimit Optional but
8420                                 required if DeviceInstanceRangeLowLimit is there */
8421                         fUnsigned32(tvb, offset+tag_len, lvt, &val);
8422                         if (col_get_writable(pinfo->cinfo))
8423                                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
8424                         offset = fDevice_Instance (tvb, tree, offset,
8425                                 hf_Device_Instance_Range_High_Limit);
8426                         break;
8427                 default:
8428                         return offset;
8429                 }
8430                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
8431         }
8432         return offset;
8433 }
8434
8435 static guint
8436 fUnconfirmedServiceRequest  (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
8437 {
8438         if (tvb_reported_length_remaining(tvb,offset) <= 0)
8439                 return offset;
8440
8441         switch (service_choice) {
8442         case 0: /* I-Am-Request */
8443                 offset = fIAmRequest  (tvb, pinfo, tree, offset);
8444                 break;
8445         case 1: /* i-Have Request */
8446                 offset = fIHaveRequest  (tvb, pinfo, tree, offset);
8447         break;
8448         case 2: /* unconfirmedCOVNotification */
8449                 offset = fUnconfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
8450                 break;
8451         case 3: /* unconfirmedEventNotification */
8452                 offset = fUnconfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
8453                 break;
8454         case 4: /* unconfirmedPrivateTransfer */
8455                 offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
8456                 break;
8457         case 5: /* unconfirmedTextMessage */
8458                 offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
8459                 break;
8460         case 6: /* timeSynchronization */
8461                 offset = fTimeSynchronizationRequest  (tvb, tree, offset);
8462                 break;
8463         case 7: /* who-Has */
8464                 offset = fWhoHas (tvb, pinfo, tree, offset);
8465                 break;
8466         case 8: /* who-Is */
8467                 offset = fWhoIsRequest  (tvb, pinfo, tree, offset);
8468                 break;
8469         case 9: /* utcTimeSynchronization */
8470                 offset = fUTCTimeSynchronizationRequest  (tvb, tree, offset);
8471                 break;
8472         default:
8473                 break;
8474         }
8475         return offset;
8476 }
8477
8478 static guint
8479 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset, guint8 ack,
8480                                 gint *svc, proto_item **tt)
8481 {
8482         proto_item *tc;
8483         proto_tree *bacapp_tree_control;
8484         gint tmp, bacapp_type;
8485         guint extra = 2;
8486
8487         bacapp_seq = 0;
8488         tmp = (gint) tvb_get_guint8(tvb, offset);
8489         bacapp_type = (tmp >> 4) & 0x0f;
8490         bacapp_flags = tmp & 0x0f;
8491
8492         if (ack == 0) {
8493                 extra = 3;
8494         }
8495         *svc = (gint) tvb_get_guint8(tvb, offset+extra);
8496         if (bacapp_flags & 0x08)
8497                 *svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
8498
8499         proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
8500         tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, TRUE);
8501         bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
8502
8503         proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, TRUE);
8504         proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, TRUE);
8505         if (ack == 0) /* The following are for ConfirmedRequest, not Complex ack */
8506         {
8507             proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, TRUE);
8508                 proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
8509                                                         offset, 1, TRUE);
8510                 proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
8511                                                         offset, 1, TRUE);
8512         }
8513         offset++;
8514         proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
8515         if (bacapp_flags & 0x08) {
8516                 bacapp_seq = tvb_get_guint8(tvb, offset);
8517                 proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
8518                     offset++, 1, TRUE);
8519                 proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
8520                     offset++, 1, TRUE);
8521         }
8522         *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
8523                                   offset++, 1, TRUE);
8524         return offset;
8525 }
8526
8527 static guint
8528 fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
8529 {       /* BACnet-Confirmed-Request */
8530         /* ASHRAE 135-2001 20.1.2 */
8531
8532         return fConfirmedServiceRequest (tvb, pinfo, bacapp_tree, offset, svc);
8533 }
8534
8535 static guint
8536 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
8537 {       /* BACnet-Confirmed-Request */
8538         /* ASHRAE 135-2001 20.1.2 */
8539         gint svc;
8540         proto_item *tt = 0;
8541
8542         offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
8543         return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
8544 }
8545
8546 static guint
8547 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
8548 {       /* BACnet-Unconfirmed-Request-PDU */
8549         /* ASHRAE 135-2001 20.1.3 */
8550
8551         gint tmp;
8552
8553         proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
8554
8555         tmp = tvb_get_guint8(tvb, offset);
8556         proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
8557             offset++, 1, TRUE);
8558         /* Service Request follows... Variable Encoding 20.2ff */
8559         return fUnconfirmedServiceRequest  (tvb, pinfo, bacapp_tree, offset, tmp);
8560 }
8561
8562 static guint
8563 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
8564 {       /* BACnet-Simple-Ack-PDU */
8565         /* ASHRAE 135-2001 20.1.4 */
8566
8567         proto_item *tc;
8568
8569         tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
8570
8571         proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
8572                             offset++, 1, TRUE);
8573         proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
8574                             offset++, 1, TRUE);
8575
8576         return offset;
8577 }
8578
8579 static guint
8580 fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
8581 {       /* BACnet-Complex-Ack-PDU */
8582         /* ASHRAE 135-2001 20.1.5 */
8583
8584         /* Service ACK follows... */
8585         return fConfirmedServiceAck (tvb, pinfo, bacapp_tree, offset, svc);
8586 }
8587
8588 static guint
8589 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
8590 {       /* BACnet-Complex-Ack-PDU */
8591         /* ASHRAE 135-2001 20.1.5 */
8592         gint svc;
8593         proto_item *tt = 0;
8594
8595         offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
8596         return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
8597 }
8598
8599 static guint
8600 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
8601 {       /* BACnet-SegmentAck-PDU */
8602         /* ASHRAE 135-2001 20.1.6 */
8603
8604         proto_item *tc;
8605         proto_tree *bacapp_tree_control;
8606
8607         tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
8608         bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
8609
8610         proto_tree_add_item(bacapp_tree, hf_bacapp_NAK, tvb, offset, 1, TRUE);
8611         proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
8612         proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
8613                             offset++, 1, TRUE);
8614         proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
8615                             offset++, 1, TRUE);
8616         proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
8617                             offset++, 1, TRUE);
8618         return offset;
8619 }
8620
8621 static guint
8622 fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8623 {
8624         guint8 tag_info = 0;
8625         guint8 parsed_tag = 0;
8626         guint32 lvt = 0;
8627         offset += fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
8628         offset = fError(tvb, pinfo, tree, offset);
8629         return offset + fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
8630 }
8631
8632 static guint
8633 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8634 {
8635         guint lastoffset = 0;
8636         guint8 tag_no = 0, tag_info = 0;
8637         guint32 lvt = 0;
8638         proto_tree *subtree = tree;
8639         proto_item *tt;
8640
8641         guint vendor_identifier = 0;
8642         guint service_number = 0;
8643         guint8 tag_len = 0;
8644
8645         while (tvb_reported_length_remaining(tvb, offset)) {
8646                 /* exit loop if nothing happens inside */
8647                 lastoffset = offset;
8648                 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
8649                 switch (tag_no) {
8650                 case 0: /* errorType */
8651                         offset = fContextTaggedError(tvb, pinfo, subtree, offset);
8652                         break;
8653                 case 1: /* vendorID */
8654                         fUnsigned32(tvb, offset+tag_len, lvt, &vendor_identifier);
8655                         if (col_get_writable(pinfo->cinfo))
8656                                 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ",        vendor_identifier);
8657                         offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
8658                         break;
8659                 case 2: /* serviceNumber */
8660                         fUnsigned32(tvb, offset+tag_len, lvt, &service_number);
8661                         if (col_get_writable(pinfo->cinfo))
8662                                 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",       service_number);
8663                         offset = fUnsignedTag (tvb, subtree, offset, "service Number: ");
8664                         break;
8665                 case 3: /* errorParameters */
8666                         if (tag_is_opening(tag_info)) {
8667                                 tt = proto_tree_add_text(subtree, tvb, offset, 1,
8668                                         "error Parameters");
8669                                 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8670                                 propertyIdentifier = -1;
8671                                 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
8672                                 offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
8673                         } else if (tag_is_closing(tag_info)) {
8674                                 offset += fTagHeaderTree (tvb, subtree, offset,
8675                                         &tag_no, &tag_info, &lvt);
8676                                 subtree = tree;
8677                         } else {
8678                                 /* error condition: let caller handle */
8679                                 return offset;
8680                         }
8681                         break;
8682                 default:
8683                         return offset;
8684                 }
8685                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
8686         }
8687         return offset;
8688 }
8689
8690 static guint
8691 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8692 {
8693         guint lastoffset = 0;
8694
8695         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
8696                 lastoffset = offset;
8697                 switch (fTagNo(tvb, offset)) {
8698                 case 0: /* errorType */
8699                         offset = fContextTaggedError(tvb, pinfo, tree, offset);
8700                         break;
8701                 case 1: /* firstFailedElementNumber */
8702                         offset = fUnsignedTag (tvb,tree,offset,"first failed element number: ");
8703                         break;
8704                 default:
8705                         return offset;
8706                 }
8707                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
8708         }
8709         return offset;
8710 }
8711
8712 static guint
8713 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8714 {
8715         /* Identical to CreateObjectError */
8716         return fCreateObjectError(tvb, pinfo, tree, offset);
8717 }
8718
8719 static guint
8720 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8721 {
8722         guint8 tag_no = 0, tag_info = 0;
8723         guint32 lvt = 0;
8724
8725         if (fTagNo(tvb, offset) == 0)
8726         {
8727                 /* errorType */
8728                 offset = fContextTaggedError(tvb, pinfo, tree,offset);
8729                 if (fTagNo(tvb, offset) == 1)
8730                 {
8731                         /* listOfVTSessionIdentifiers [OPTIONAL] */
8732                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
8733                         offset = fVtCloseRequest (tvb, pinfo, tree, offset);
8734                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
8735                 }
8736         }
8737         /* should report bad packet if initial tag wasn't 0 */
8738         return offset;
8739 }
8740
8741 static guint
8742 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8743 {
8744         guint lastoffset = 0;
8745         guint8 tag_no = 0, tag_info = 0;
8746         guint32 lvt = 0;
8747
8748         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
8749         while (tvb_reported_length_remaining(tvb, offset)) {  /* exit loop if nothing happens inside */
8750                 lastoffset = offset;
8751                 switch (fTagNo(tvb, offset)) {
8752                 case 0: /* errorType */
8753                         offset = fContextTaggedError(tvb, pinfo, tree, offset);
8754                         break;
8755                 case 1: /* firstFailedWriteAttempt */
8756                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
8757                         offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
8758                         offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
8759                         break;
8760                 default:
8761                         return offset;
8762                 }
8763                 if (offset == lastoffset) break;     /* nothing happened, exit loop */
8764         }
8765         return offset;
8766 }
8767
8768 static guint
8769 fError (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8770 {
8771         offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
8772                                                    "error Class: ", BACnetErrorClass, 64);
8773         return fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
8774                                                  "error Code: ", BACnetErrorCode, 256);
8775 }
8776
8777 static guint
8778 fBACnetError (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service)
8779 {
8780         switch (service) {
8781         case 8:  /* no break here !!!! */
8782         case 9:
8783                 offset = fChangeListError (tvb, pinfo, tree, offset);
8784                 break;
8785         case 10:
8786                 offset = fCreateObjectError (tvb, pinfo, tree, offset);
8787                 break;
8788         case 16:
8789                 offset = fWritePropertyMultipleError (tvb, pinfo, tree, offset);
8790                 break;
8791         case 18:
8792                 offset = fConfirmedPrivateTransferError (tvb,pinfo,tree,offset);
8793                 break;
8794         case 22:
8795                 offset = fVTCloseError (tvb, pinfo, tree, offset);
8796                 break;
8797         default:
8798                 return fError (tvb, pinfo, tree, offset);
8799         }
8800         return offset;
8801 }
8802
8803 static guint
8804 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
8805 {       /* BACnet-Error-PDU */
8806         /* ASHRAE 135-2001 20.1.7 */
8807
8808         proto_item *tc, *tt;
8809         proto_tree *bacapp_tree_control;
8810         guint8 tmp;
8811
8812         tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
8813         bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
8814
8815         proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
8816                             offset++, 1, TRUE);
8817         tmp = tvb_get_guint8(tvb, offset);
8818         tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
8819                                  offset++, 1, TRUE);
8820         /* Error Handling follows... */
8821         return fBACnetError (tvb, pinfo, bacapp_tree, offset, tmp);
8822 }
8823
8824 static guint
8825 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
8826 {       /* BACnet-Reject-PDU */
8827         /* ASHRAE 135-2001 20.1.8 */
8828
8829         proto_item *tc;
8830         proto_tree *bacapp_tree_control;
8831
8832         tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
8833                                  bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
8834
8835         proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
8836                             offset++, 1, TRUE);
8837         proto_tree_add_item(bacapp_tree, hf_BACnetRejectReason, tvb,
8838                             offset++, 1, TRUE);
8839         return offset;
8840 }
8841
8842 static guint
8843 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
8844 {       /* BACnet-Abort-PDU */
8845         /* ASHRAE 135-2001 20.1.9 */
8846
8847         proto_item *tc;
8848         proto_tree *bacapp_tree_control;
8849
8850         tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
8851         bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
8852
8853         proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
8854         proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
8855                             offset++, 1, TRUE);
8856         proto_tree_add_item(bacapp_tree, hf_BACnetAbortReason, tvb,
8857                             offset++, 1, TRUE);
8858         return offset;
8859 }
8860
8861 static guint
8862 do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
8863 {
8864         guint8 flag, bacapp_type;
8865         guint offset = 0;
8866
8867         flag = (gint) tvb_get_guint8(tvb, 0);
8868         bacapp_type = (flag >> 4) & 0x0f;
8869
8870         if (tvb == NULL || tree == NULL) {
8871                 return 0;
8872         }
8873
8874         /* ASHRAE 135-2001 20.1.1 */
8875         switch (bacapp_type) {
8876         case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:     /* BACnet-Confirmed-Service-Request */
8877                 offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
8878                 break;
8879         case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:   /* BACnet-Unconfirmed-Request-PDU */
8880                 offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
8881                 break;
8882         case BACAPP_TYPE_SIMPLE_ACK:    /* BACnet-Simple-Ack-PDU */
8883                 offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
8884                 break;
8885         case BACAPP_TYPE_COMPLEX_ACK:   /* BACnet-Complex-Ack-PDU */
8886                 offset = fComplexAckPDU(tvb, pinfo, tree, offset);
8887                 break;
8888         case BACAPP_TYPE_SEGMENT_ACK:   /* BACnet-SegmentAck-PDU */
8889                 offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
8890                 break;
8891         case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
8892                 offset = fErrorPDU(tvb, pinfo, tree, offset);
8893                 break;
8894         case BACAPP_TYPE_REJECT:        /* BACnet-Reject-PDU */
8895                 offset = fRejectPDU(tvb, pinfo, tree, offset);
8896                 break;
8897         case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
8898                 offset = fAbortPDU(tvb, pinfo, tree, offset);
8899                 break;
8900         }
8901         return offset;
8902 }
8903
8904 static void
8905 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
8906 {
8907         guint8 flag, bacapp_type;
8908         guint save_fragmented = FALSE, data_offset = 0, bacapp_apdu_size = fGetMaxAPDUSize(0), fragment = FALSE;
8909         tvbuff_t* new_tvb = NULL;
8910         guint offset = 0;
8911         guint8 bacapp_seqno = 0;
8912         guint8 bacapp_service, bacapp_reason, bacapp_prop_win_size;
8913         guint8 bacapp_invoke_id = 0;
8914         proto_item *ti;
8915         proto_tree *bacapp_tree = NULL;
8916
8917         gint svc = 0;
8918         proto_item *tt = 0;
8919         gint8 ack = 0;
8920
8921         col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
8922         col_clear (pinfo->cinfo, COL_INFO);
8923
8924         flag = tvb_get_guint8(tvb, 0);
8925         bacapp_type = (flag >> 4) & 0x0f;
8926
8927         /* show some descriptive text in the INFO column */
8928         col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
8929                 val_to_str(bacapp_type, BACnetTypeName, "# unknown APDU #"));
8930
8931         switch (bacapp_type)
8932         {
8933                 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
8934                         /* segmented messages have 2 additional bytes */
8935                         if (flag & BACAPP_SEGMENTED_REQUEST)
8936                         {
8937                                 fragment = TRUE;
8938                                 ack = 0;
8939                                 bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_guint8(tvb, offset + 1)); /* has 16 values, reserved are 50 Bytes */
8940                                 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
8941                                 bacapp_seqno = tvb_get_guint8(tvb, offset + 3);
8942                                 bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 4);
8943                                 bacapp_service = tvb_get_guint8(tvb, offset + 5);
8944                                 data_offset = 6;
8945                         }
8946                         else
8947                         {
8948                                 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
8949                                 bacapp_service = tvb_get_guint8(tvb, offset + 3);
8950                         }
8951                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
8952                                 val_to_str(bacapp_service,
8953                                         BACnetConfirmedServiceChoice,
8954                                         bacapp_unknown_service_str),bacapp_invoke_id);
8955                         break;
8956                 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
8957                         bacapp_service = tvb_get_guint8(tvb, offset + 1);
8958                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
8959                                 val_to_str(bacapp_service,
8960                                         BACnetUnconfirmedServiceChoice,
8961                                         bacapp_unknown_service_str));
8962                         break;
8963                 case BACAPP_TYPE_SIMPLE_ACK:
8964                         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
8965                         bacapp_service = tvb_get_guint8(tvb, offset + 2);
8966                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
8967                                 val_to_str(bacapp_service,
8968                                         BACnetConfirmedServiceChoice,
8969                                         bacapp_unknown_service_str), bacapp_invoke_id);
8970                         break;
8971                 case BACAPP_TYPE_COMPLEX_ACK:
8972                         /* segmented messages have 2 additional bytes */
8973                         if (flag & BACAPP_SEGMENTED_REQUEST)
8974                         {
8975                                 fragment = TRUE;
8976                                 ack = 1;
8977                                 bacapp_apdu_size = fGetMaxAPDUSize(0); /* has minimum of 50 Bytes */
8978                                 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
8979                                 bacapp_seqno = tvb_get_guint8(tvb, offset + 2);
8980                                 bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 3);
8981                                 bacapp_service = tvb_get_guint8(tvb, offset + 4);
8982                                 data_offset = 5;
8983                         }
8984                         else
8985                         {
8986                                 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
8987                                 bacapp_service = tvb_get_guint8(tvb, offset + 2);
8988                         }
8989                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
8990                                 val_to_str(bacapp_service,
8991                                         BACnetConfirmedServiceChoice,
8992                                         bacapp_unknown_service_str), bacapp_invoke_id);
8993                         break;
8994                 case BACAPP_TYPE_SEGMENT_ACK:
8995                         /* nothing more to add */
8996                         break;
8997                 case BACAPP_TYPE_ERROR:
8998                         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
8999                         bacapp_service = tvb_get_guint8(tvb, offset + 2);
9000                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
9001                                 val_to_str(bacapp_service,
9002                                         BACnetConfirmedServiceChoice,
9003                                         bacapp_unknown_service_str), bacapp_invoke_id);
9004                         break;
9005                 case BACAPP_TYPE_REJECT:
9006                         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
9007                         bacapp_reason = tvb_get_guint8(tvb, offset + 2);
9008                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
9009                                 val_to_split_str(bacapp_reason,
9010                                         64,
9011                                         BACnetRejectReason,
9012                                         ASHRAE_Reserved_Fmt,
9013                                         Vendor_Proprietary_Fmt), bacapp_invoke_id);
9014                         break;
9015                 case BACAPP_TYPE_ABORT:
9016                         bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
9017                         bacapp_reason = tvb_get_guint8(tvb, offset + 2);
9018                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
9019                                 val_to_split_str(bacapp_reason,
9020                                         64,
9021                                         BACnetAbortReason,
9022                                         ASHRAE_Reserved_Fmt,
9023                                         Vendor_Proprietary_Fmt), bacapp_invoke_id);
9024                         break;
9025                 /* UNKNOWN */
9026                 default:
9027                         /* nothing more to add */
9028                         break;
9029         }
9030
9031         save_fragmented = pinfo->fragmented;
9032
9033         if (tree) {
9034
9035                 ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE);
9036                 bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
9037
9038                 if (!fragment)
9039                         offset = do_the_dissection(tvb,pinfo,bacapp_tree);
9040                 else
9041                         fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
9042                         /* not resetting the offset so the remaining can be done */
9043         }
9044
9045         if (fragment) { /* fragmented */
9046                 fragment_data *frag_msg = NULL;
9047
9048                 new_tvb = NULL;
9049                 pinfo->fragmented = TRUE;
9050
9051                 frag_msg = fragment_add_seq_check(tvb, data_offset, pinfo,
9052                         bacapp_invoke_id, /* ID for fragments belonging together */
9053                         msg_fragment_table, /* list of message fragments */
9054                         msg_reassembled_table, /* list of reassembled messages */
9055                         bacapp_seqno, /* fragment sequence number */
9056                         tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
9057                         flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
9058                 new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
9059                                 "Reassembled BACapp", frag_msg, &msg_frag_items,
9060                                 NULL, tree);
9061
9062                 if (new_tvb) { /* Reassembled */
9063                         col_append_str(pinfo->cinfo, COL_INFO,
9064                                 " (Message Reassembled)");
9065                 } else { /* Not last packet of reassembled Short Message */
9066                         col_append_fstr(pinfo->cinfo, COL_INFO,
9067                         " (Message fragment %u)", bacapp_seqno);
9068                 }
9069                 if (new_tvb) { /* take it all */
9070                         switch (bacapp_type)
9071                         {
9072                                 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
9073                                         fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
9074                                 break;
9075                                 case BACAPP_TYPE_COMPLEX_ACK:
9076                                         fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
9077                                 break;
9078                                 default:
9079                                         /* do nothing */
9080                                 break;
9081                         }
9082                         /* } */
9083                 }
9084         }
9085
9086         pinfo->fragmented = save_fragmented;
9087
9088 }
9089
9090 static void
9091 bacapp_init_routine(void)
9092 {
9093         fragment_table_init(&msg_fragment_table);
9094         reassembled_table_init(&msg_reassembled_table);
9095 }
9096
9097 static guint32
9098 fConvertXXXtoUTF8 (gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding)
9099 {
9100         guint32 i;
9101         GIConv icd;
9102
9103         if ((icd = g_iconv_open ("UTF-8", fromcoding)) != (GIConv) -1) {
9104                 i = (guint32) g_iconv (icd, &in, inbytesleft, &out, outbytesleft);
9105                 /* g_iconv incremented 'out'; now ensure it's NULL terminated */
9106                 out[0] = '\0';
9107
9108                 g_iconv_close (icd);
9109                 return i;
9110         }
9111
9112         uni_to_string(in,*inbytesleft,out);
9113         out[*inbytesleft] = '\0';
9114         *outbytesleft -= *inbytesleft;
9115         *inbytesleft = 0;
9116
9117         return 0;
9118 }
9119
9120 static void
9121 uni_to_string(char * data, gsize str_length, char *dest_buf)
9122 {
9123         gint i;
9124         guint16 c_char;
9125         gsize length_remaining = 0;
9126
9127         length_remaining = str_length;
9128         dest_buf[0] = '\0';
9129         if(str_length == 0)
9130         {
9131                 return;
9132         }
9133         for ( i = 0; i < (gint) str_length; i++ )
9134         {
9135                 c_char = data[i];
9136                 if (c_char<0x20 || c_char>0x7e)
9137                 {
9138                         if (c_char != 0x00)
9139                         {
9140                                 c_char = '.';
9141                                 dest_buf[i] = c_char & 0xff;
9142                         }
9143                         else
9144                         {
9145                                 i--;
9146                                 str_length--;
9147                         }
9148                 }
9149                 else
9150                 {
9151                         dest_buf[i] = c_char & 0xff;
9152                 }
9153                 length_remaining--;
9154
9155                 if(length_remaining==0)
9156                 {
9157                         dest_buf[i+1] = '\0';
9158                         return;
9159                 }
9160         }
9161         if (i < 0) {
9162                 i = 0;
9163         }
9164         dest_buf[i] = '\0';
9165         return;
9166 }
9167
9168 void
9169 proto_register_bacapp(void)
9170 {
9171         static hf_register_info hf[] = {
9172                 { &hf_bacapp_type,
9173                         { "APDU Type",           "bacapp.type",
9174                         FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
9175                 },
9176                 { &hf_bacapp_pduflags,
9177                         { "PDU Flags",                  "bacapp.pduflags",
9178                         FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
9179                 },
9180                 { &hf_bacapp_SEG,
9181                         { "Segmented Request",           "bacapp.segmented_request",
9182                         FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
9183                 },
9184                 { &hf_bacapp_MOR,
9185                         { "More Segments",           "bacapp.more_segments",
9186                         FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
9187                 },
9188                 { &hf_bacapp_SA,
9189                         { "SA",           "bacapp.SA",
9190                         FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
9191                 },
9192                 { &hf_bacapp_max_adpu_size,
9193                         { "Size of Maximum ADPU accepted",           "bacapp.max_adpu_size",
9194                         FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
9195                 },
9196                 { &hf_bacapp_response_segments,
9197                         { "Max Response Segments accepted",           "bacapp.response_segments",
9198                         FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
9199                 },
9200                 { &hf_bacapp_objectType,
9201                         { "Object Type",           "bacapp.objectType",
9202                         FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
9203                 },
9204                 { &hf_bacapp_instanceNumber,
9205                         { "Instance Number",           "bacapp.instance_number",
9206                         FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
9207                 },
9208                 { &hf_BACnetPropertyIdentifier,
9209                         { "Property Identifier", "bacapp.property_identifier",
9210                         FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
9211                 },
9212                 { &hf_BACnetVendorIdentifier,
9213                         { "Vendor Identifier", "bacapp.vendor_identifier",
9214                         FT_UINT16, BASE_DEC, VALS(BACnetVendorIdentifiers), 0, NULL, HFILL }
9215                 },
9216                 { &hf_BACnetRestartReason,
9217                         { "Restart Reason", "bacapp.restart_reason",
9218                         FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
9219                 },
9220                 { &hf_bacapp_invoke_id,
9221                         { "Invoke ID",           "bacapp.invoke_id",
9222                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
9223                 },
9224                 { &hf_bacapp_sequence_number,
9225                         { "Sequence Number",           "bacapp.sequence_number",
9226                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
9227                 },
9228                 { &hf_bacapp_window_size,
9229                         { "Proposed Window Size",           "bacapp.window_size",
9230                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
9231                 },
9232                 { &hf_bacapp_service,
9233                         { "Service Choice",           "bacapp.confirmed_service",
9234                         FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
9235                 },
9236                 { &hf_bacapp_uservice,
9237                         { "Unconfirmed Service Choice",           "bacapp.unconfirmed_service",
9238                         FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
9239                 },
9240                 { &hf_bacapp_NAK,
9241                         { "NAK",           "bacapp.NAK",
9242                         FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
9243                 },
9244                 { &hf_bacapp_SRV,
9245                         { "SRV",           "bacapp.SRV",
9246                         FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
9247                 },
9248                 { &hf_Device_Instance_Range_Low_Limit,
9249                         { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
9250                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
9251                 },
9252                 { &hf_Device_Instance_Range_High_Limit,
9253                         { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
9254                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
9255                 },
9256                 { &hf_BACnetRejectReason,
9257                         { "Reject Reason",           "bacapp.reject_reason",
9258                         FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
9259                 },
9260                 { &hf_BACnetAbortReason,
9261                         { "Abort Reason",           "bacapp.abort_reason",
9262                         FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
9263                 },
9264                 { &hf_bacapp_vpart,
9265                         { "BACnet APDU variable part:",           "bacapp.variable_part",
9266                         FT_NONE, BASE_NONE, NULL, 0, "BACnet APDU variable part", HFILL }
9267                 },
9268                 { &hf_bacapp_tag,
9269                         { "BACnet Tag",
9270                         "bacapp.tag",
9271                         FT_BYTES, BASE_NONE, NULL, 0,
9272                         NULL, HFILL }
9273                 },
9274                 { &hf_BACnetApplicationTagNumber,
9275                         { "Application Tag Number",
9276                         "bacapp.application_tag_number",
9277                         FT_UINT8, BASE_DEC, VALS(&BACnetApplicationTagNumber), 0xF0,
9278                         NULL, HFILL }
9279                 },
9280                 { &hf_BACnetContextTagNumber,
9281                         { "Context Tag Number",
9282                         "bacapp.context_tag_number",
9283                         FT_UINT8, BASE_DEC, NULL, 0xF0,
9284                         NULL, HFILL }
9285                 },
9286                 { &hf_BACnetExtendedTagNumber,
9287                         { "Extended Tag Number",
9288                         "bacapp.extended_tag_number",
9289                         FT_UINT8, BASE_DEC, NULL, 0,
9290                         NULL, HFILL }
9291                 },
9292                 { &hf_BACnetNamedTag,
9293                         { "Named Tag",
9294                         "bacapp.named_tag",
9295                         FT_UINT8, BASE_DEC, VALS(&BACnetTagNames), 0x07,
9296                         NULL, HFILL }
9297                 },
9298                 { &hf_BACnetCharacterSet,
9299                         { "String Character Set",
9300                         "bacapp.string_character_set",
9301                         FT_UINT8, BASE_DEC, VALS(&BACnetCharacterSet),0,
9302                         NULL, HFILL }
9303                 },
9304                 { &hf_BACnetTagClass,
9305                         { "Tag Class",           "bacapp.tag_class",
9306                         FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
9307                 },
9308                 { &hf_bacapp_tag_lvt,
9309                         { "Length Value Type",
9310                         "bacapp.LVT",
9311                         FT_UINT8, BASE_DEC, NULL, 0,
9312                         NULL, HFILL }
9313                 },
9314                 { &hf_bacapp_tag_value8,
9315                         { "Tag Value",
9316                         "bacapp.tag_value8",
9317                         FT_UINT8, BASE_DEC, NULL, 0,
9318                         NULL, HFILL }
9319                 },
9320                 { &hf_bacapp_tag_value16,
9321                         { "Tag Value 16-bit",
9322                         "bacapp.tag_value16",
9323                         FT_UINT16, BASE_DEC, NULL, 0,
9324                         NULL, HFILL }
9325                 },
9326                 { &hf_bacapp_tag_value32,
9327                         { "Tag Value 32-bit",
9328                         "bacapp.tag_value32",
9329                         FT_UINT32, BASE_DEC, NULL, 0,
9330                         NULL, HFILL }
9331                 },
9332                 { &hf_bacapp_tag_ProcessId,
9333                         { "ProcessIdentifier",           "bacapp.processId",
9334                         FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
9335                 },
9336                 { &hf_bacapp_tag_IPV4,
9337                         { "IPV4",           "bacapp.IPV4",
9338                         FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
9339                 },
9340                 { &hf_bacapp_tag_IPV6,
9341                 { "IPV6",           "bacapp.IPV6",
9342                         FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
9343                 },
9344                 { &hf_bacapp_tag_PORT,
9345                         { "Port",           "bacapp.Port",
9346                         FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
9347                 },
9348                 { &hf_bacapp_tag_initiatingObjectType,
9349                         { "ObjectType",           "bacapp.objectType",
9350                         FT_UINT16, BASE_DEC, VALS(BACnetObjectType), 0x00, "Object Type", HFILL }
9351                 },
9352                 {&hf_msg_fragments,
9353                         {"Message fragments", "bacapp.fragments",
9354                         FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
9355                 {&hf_msg_fragment,
9356                         {"Message fragment", "bacapp.fragment",
9357                         FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
9358                 {&hf_msg_fragment_overlap,
9359                         {"Message fragment overlap", "bacapp.fragment.overlap",
9360                         FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
9361                 {&hf_msg_fragment_overlap_conflicts,
9362                         {"Message fragment overlapping with conflicting data",
9363                         "bacapp.fragment.overlap.conflicts",
9364                         FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
9365                 {&hf_msg_fragment_multiple_tails,
9366                         {"Message has multiple tail fragments",
9367                         "bacapp.fragment.multiple_tails",
9368                         FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
9369                 {&hf_msg_fragment_too_long_fragment,
9370                         {"Message fragment too long", "bacapp.fragment.too_long_fragment",
9371                         FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
9372                 {&hf_msg_fragment_error,
9373                         {"Message defragmentation error", "bacapp.fragment.error",
9374                         FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
9375                 {&hf_msg_reassembled_in,
9376                         {"Reassembled in", "bacapp.reassembled.in",
9377                         FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
9378                 {&hf_msg_reassembled_length,
9379                         {"Reassembled BACapp length", "bacapp.reassembled.length",
9380                         FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
9381         };
9382         static gint *ett[] = {
9383                 &ett_bacapp,
9384                 &ett_bacapp_control,
9385                 &ett_bacapp_tag,
9386                 &ett_bacapp_list,
9387                 &ett_bacapp_value,
9388                 &ett_msg_fragment,
9389                 &ett_msg_fragments
9390
9391         };
9392
9393         proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
9394                                                "BACapp", "bacapp");
9395
9396         proto_register_field_array(proto_bacapp, hf, array_length(hf));
9397         proto_register_subtree_array(ett, array_length(ett));
9398         register_dissector("bacapp", dissect_bacapp, proto_bacapp);
9399         register_init_routine (&bacapp_init_routine);
9400
9401         bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
9402                                                           "BACapp Vendor Identifier",
9403                                                           FT_UINT8, BASE_HEX);
9404
9405 }
9406
9407 void
9408 proto_reg_handoff_bacapp(void)
9409 {
9410         data_handle = find_dissector("data");
9411 }
9412