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