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