2 * Routines for BACnet (APDU) dissection
3 * Copyright 2001, Hartmut Mueller <hartmut@abmlinux.org>, FH Dortmund
4 * Enhanced by Steve Karg, 2005, <skarg@users.sourceforge.net>, Atlanta
5 * Enhanced by Herbert Lischka, 2005, <lischka@kieback-peter.de>, Berlin
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * Copied from README.developer,v 1.23
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include "packet-bacapp.h"
32 /* some necessary forward function prototypes */
34 fApplicationTypesEnumerated (tvbuff_t *tvb, proto_tree *tree, guint offset,
35 const gchar *label, const value_string *vs);
37 static const char *bacapp_unknown_service_str = "unknown service";
38 static const char *ASHRAE_Reserved_Fmt = "(%d) Reserved for Use by ASHRAE";
39 static const char *Vendor_Proprietary_Fmt = "(%d) Vendor Proprietary Value";
41 static const value_string
43 {0, "Confirmed-Request "},
44 {1, "Unconfirmed-Request "},
54 static const true_false_string segments_follow = {
59 static const true_false_string more_follow = {
60 "More Segments Follow",
61 "No More Segments Follow"
64 static const true_false_string segmented_accept = {
65 "Segmented Response accepted",
66 "Segmented Response not accepted"
69 static const true_false_string
71 "Context Specific Tag",
75 static const value_string
76 BACnetMaxSegmentsAccepted [] = {
84 {7,"Greater than 64 segments"},
88 static const value_string
89 BACnetMaxAPDULengthAccepted [] = {
90 {0,"Up to MinimumMessageSize (50 octets)"},
91 {1,"Up to 128 octets"},
92 {2,"Up to 206 octets (fits in a LonTalk frame)"},
93 {3,"Up to 480 octets (fits in an ARCNET frame)"},
94 {4,"Up to 1024 octets"},
95 {5,"Up to 1476 octets (fits in an ISO 8802-3 frame)"},
96 {6,"reserved by ASHRAE"},
97 {7,"reserved by ASHRAE"},
98 {8,"reserved by ASHRAE"},
99 {9,"reserved by ASHRAE"},
100 {10,"reserved by ASHRAE"},
101 {11,"reserved by ASHRAE"},
102 {12,"reserved by ASHRAE"},
103 {13,"reserved by ASHRAE"},
104 {14,"reserved by ASHRAE"},
105 {15,"reserved by ASHRAE"},
109 static const value_string
110 BACnetRejectReason [] = {
112 {1,"buffer-overflow"},
113 {2,"inconsistent-parameters"},
114 {3,"invalid-parameter-data-type"},
116 {5,"missing-required-parameter"},
117 {6,"parameter-out-of-range"},
118 {7,"too-many-arguments"},
119 {8,"undefined-enumeration"},
120 {9,"unrecognized-service"},
124 static const value_string
125 BACnetApplicationTagNumber [] = {
128 {2,"Unsigned Integer"},
129 {3,"Signed Integer (2's complement notation)"},
130 {4,"Real (ANSI/IEE-754 floating point)"},
131 {5,"Double (ANSI/IEE-754 double precision floating point)"},
133 {7,"Character String"},
138 {12,"BACnetObjectIdentifier"},
139 {13,"reserved by ASHRAE"},
140 {14,"reserved by ASHRAE"},
141 {15,"reserved by ASHRAE"},
145 static const value_string
152 static const value_string
153 BACnetFileAccessMethod [] = {
159 /* For some reason, BACnet defines the choice parameter
160 in the file read and write services backwards from the
161 BACnetFileAccessMethod enumeration.
163 static const value_string
164 BACnetFileAccessOption [] = {
170 static const value_string
171 BACnetFileStartOption [] = {
172 {0, "File Start Position: "},
173 {1, "File Start Record: "},
177 static const value_string
178 BACnetFileRequestCount [] = {
179 {0, "Requested Octet Count: "},
180 {1, "Requested Record Count: "},
184 static const value_string
185 BACnetFileWriteInfo [] = {
187 {1, "Record Count: "},
191 static const value_string
192 BACnetAbortReason [] = {
194 {1,"buffer-overflow"},
195 {2,"invalid-apdu-in-this-state"},
196 {3,"preempted-by-higher-priority-task"},
197 {4,"segmentation-not-supported"},
201 static const value_string
202 BACnetLifeSafetyMode [] = {
216 {13,"atomic-release-disabled"},
219 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
220 Enumerated values 256-65535 may be used by others subject to
221 procedures and constraints described in Clause 23. */
224 static const value_string
225 BACnetLifeSafetyOperation [] = {
228 {2,"silence-audible"},
229 {3,"silence-visual"},
234 {8,"unsilence-audible"},
235 {9,"unsilence-visual"},
237 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
238 Enumerated values 64-65535 may be used by others subject to
239 procedures and constraints described in Clause 23. */
242 static const value_string
243 BACnetLimitEnable [] = {
244 {0,"lowLimitEnable"},
245 {1,"highLimitEnable"},
249 static const value_string
250 BACnetLifeSafetyState [] = {
255 {4,"fault-pre-alarm"},
263 {12,"test-fault-alarm"},
268 {17,"emergency-power"},
272 {21,"general-alarm"},
274 {23,"test-supervisory"},
276 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
277 Enumerated values 256-65535 may be used by others subject to
278 procedures and constraints described in Clause 23. */
281 static const value_string
282 BACnetConfirmedServiceChoice [] = {
283 {0,"acknowledgeAlarm"},
284 {1,"confirmedCOVNotification"},
285 {2,"confirmedEventNotification"},
286 {3,"getAlarmSummary"},
287 {4,"getEnrollmentSummary"},
289 {6,"atomicReadFile"},
290 {7,"atomicWriteFile"},
291 {8,"addListElement"},
292 {9,"removeListElement"},
296 {13,"readPropertyConditional"},
297 {14,"readPropertyMultiple"},
298 {15,"writeProperty"},
299 {16,"writePropertyMultiple"},
300 {17,"deviceCommunicationControl"},
301 {18,"confirmedPrivateTransfer"},
302 {19,"confirmedTextMessage"},
303 {20,"reinitializeDevice"},
310 {27,"lifeSafetyOperation"},
311 {28,"subscribeCOVProperty"},
312 {29,"getEventInformation"},
313 {30,"reserved by ASHRAE"},
317 static const value_string
318 BACnetReliability [] = {
319 {0,"no-fault-detected"},
326 {7,"unreliable-other"},
328 {9,"multi-state-fault"},
332 static const value_string
333 BACnetUnconfirmedServiceChoice [] = {
336 {2,"unconfirmedCOVNotification"},
337 {3,"unconfirmedEventNotification"},
338 {4,"unconfirmedPrivateTransfer"},
339 {5,"unconfirmedTextMessage"},
340 {6,"timeSynchronization"},
343 {9,"utcTimeSynchonization"},
347 static const value_string
348 BACnetUnconfirmedServiceRequest [] = {
350 {1,"i-Have-Request"},
351 {2,"unconfirmedCOVNotification-Request"},
352 {3,"unconfirmedEventNotification-Request"},
353 {4,"unconfirmedPrivateTransfer-Request"},
354 {5,"unconfirmedTextMessage-Request"},
355 {6,"timeSynchronization-Request"},
356 {7,"who-Has-Request"},
357 {8,"who-Is-Request"},
358 {9,"utcTimeSynchonization-Request"},
362 static const value_string
363 BACnetObjectType [] = {
364 {0,"analog-input object"},
365 {1,"analog-output object"},
366 {2,"analog-value object"},
367 {3,"binary-input object"},
368 {4,"binary-output object"},
369 {5,"binary-value object"},
370 {6,"calendar object"},
371 {7,"command object"},
373 {9,"event-enrollment object"},
377 {13,"multi-state-input object"},
378 {14,"multi-state-output object"},
379 {15,"notification-class object"},
380 {16,"program object"},
381 {17,"schedule object"},
382 {18,"averaging object"},
383 {19,"multi-state-value object"},
384 {20,"trend-log object"},
385 {21,"life-safety-point object"},
386 {22,"life-safety-zone object"},
387 {23,"accumulator object"},
388 {24,"pulse-converter object"},
389 {25,"event-log object"},
390 {26,"global-group object"},
391 {27,"trend-log-multiple object"},
392 {28,"load-control object"},
393 {29,"structured-view object"},
395 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
396 Enumerated values 128-1023 may be used by others subject to
397 the procedures and constraints described in Clause 23. */
400 static const value_string
401 BACnetEngineeringUnits [] = {
411 {9,"Kilovolt Amperes"},
412 {10,"Megavolt Amperes"},
413 {11,"Volt Amperes Reactive"},
414 {12,"Kilovolt Amperes Reactive"},
415 {13,"Megavolt Amperes Ractive"},
416 {14,"Degrees Phase"},
421 {19,"Kilowatt Hours"},
425 {23,"Joules Per Kg Dry Air"},
426 {24,"BTUs Per Pound Dry Air"},
427 {25,"Cycles Per Hour"},
428 {26,"Cycles Per Minute"},
430 {28,"Gramms Of Water Per Kilogram Dry Air"},
431 {29,"Relative Humidity"},
436 {34,"Watts Per Sq Foot"},
437 {35,"Watts Per Sq meter"},
444 {42,"Kgs per Second"},
445 {43,"Kgs Per Minute"},
447 {45,"Pounds Mass Per Minute"},
448 {46,"Pounds Mass Per Hour"},
452 {50,"BTUs Per Hour"},
454 {52,"Tons Refrigeration"},
458 {56,"Pounds Force Per Square Inch"},
459 {57,"Centimeters Of Water"},
460 {58,"Inches Of Water"},
461 {59,"Millimeters Of Mercury"},
462 {60,"Centimeters Of Mercury"},
463 {61,"Inches Of Mercury"},
464 {62,"Degrees Celsius"},
465 {63,"Degress Kelvin"},
466 {64,"Degrees Fahrenheit"},
467 {65,"Degree Days Celsius"},
468 {66,"Degree Days Fahrenheit"},
476 {74,"Meters Per Second"},
477 {75,"Kilometers Per Hour"},
478 {76,"Feed Per Second"},
479 {77,"Feet Per Minute"},
480 {78,"Miles Per Hour"},
483 {81,"Imperial Gallons"},
486 {84,"Cubic Feet Per Minute"},
487 {85,"Cubic Meters Per Second"},
488 {86,"Imperial Gallons Per Minute"},
489 {87,"Liters Per Second"},
490 {88,"Liters Per Minute"},
491 {89,"US Gallons Per Minute"},
492 {90,"Degrees Angular"},
493 {91,"Degrees Celsius Per Hour"},
494 {92,"Degrees Celsius Per Minute"},
495 {93,"Degrees Fahrenheit Per Hour"},
496 {94,"Degrees Fahrenheit Per Minute"},
498 {96,"Parts Per Million"},
499 {97,"Parts Per Billion"},
501 {99,"Pecent Per Second"},
504 {102,"Psi Per Degree Fahrenheit"},
506 {104,"Revolutions Per Min"},
518 {116,"Sq Centimeters"},
519 {117,"BTUs Per Pound"},
521 {119,"Pounds Mass Per Second"},
522 {120,"Delta Degrees Fahrenheit"},
523 {121,"Delta Degrees Kelvin"},
527 {125,"Kilojoules Per Kg"},
529 {127,"Joules Per Degree Kelvin"},
530 {128,"Joules Per Kg Degree Kelvin"},
535 {133,"Hectopascals"},
537 {135,"Cubic Meters Per Hour"},
538 {136,"Liters Per Hour"},
539 {137,"KWatt Hours Per Square Meter"},
540 {138,"KWatt Hours Per Square Foot"},
541 {139,"Megajoules Per Square Meter"},
542 {140,"Megajoules Per Square Foot"},
543 {141,"Watts Per Sq Meter Degree Kelvin"},
544 {142,"Cubic Feet Per Second"},
545 {143,"Percent Obstruction Per Foot"},
546 {144,"Percent Obstruction Per Meter"},
548 {146,"megawatt-hours"},
551 {149,"kilojoules-per-kilogram-dry-air"},
552 {150,"megajoules-per-kilogram-dry-air"},
553 {151,"kilojoules-per-degree-Kelvin"},
554 {152,"megajoules-per-degree-Kelvin"},
556 {154,"grams-per-second"},
557 {155,"grams-per-minute"},
558 {156,"tons-per-hour"},
559 {157,"kilo-btus-per-hour"},
560 {158,"hundredths-seconds"},
561 {159,"milliseconds"},
562 {160,"newton-meters"},
563 {161,"millimeters-per-second"},
564 {162,"millimeters-per-minute"},
565 {163,"meters-per-minute"},
566 {164,"meters-per-hour"},
567 {165,"cubic-meters-per-minute"},
568 {166,"meters-per-second-per-second"},
569 {167,"amperes-per-meter"},
570 {168,"amperes-per-square-meter"},
571 {169,"ampere-square-meters"},
576 {174,"siemens-per-meter"},
578 {176,"volts-per-degree-Kelvin"},
579 {177,"volts-per-meter"},
582 {180,"candelas-per-square-meter"},
583 {181,"degrees-Kelvin-per-hour"},
584 {182,"degrees-Kelvin-per-minute"},
585 {183,"joule-seconds"},
586 {184,"radians-per-second"},
587 {185,"square-meters-per-Newton"},
588 {186,"kilograms-per-cubic-meter"},
589 {187,"newton-seconds"},
590 {188,"newtons-per-meter"},
591 {189,"watts-per-meter-per-degree-Kelvin"},
593 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
594 Enumerated values 256-65535 may be used by others subject to
595 the procedures and constraints described in Clause 23. */
598 static const value_string
599 BACnetErrorCode [] = {
601 {1,"authentication-failed"},
602 {2,"character-set-not-supported"},
603 {3,"configuration-in-progress"},
605 {5,"file-access-denied"},
606 {6,"incompatible-security-levels"},
607 {7,"inconsistent-parameters"},
608 {8,"inconsistent-selection-criterion"},
609 {9,"invalid-data-type"},
610 {10,"invalid-file-access-method"},
611 {11,"invalid-file-start-position"},
612 {12,"invalid-operator-name"},
613 {13,"invalid-parameter-data-type"},
614 {14,"invalid-time-stamp"},
615 {15,"key-generation-error"},
616 {16,"missing-required-parameter"},
617 {17,"no-objects-of-specified-type"},
618 {18,"no-space-for-object"},
619 {19,"no-space-to-add-list-element"},
620 {20,"no-space-to-write-property"},
621 {21,"no-vt-sessions-available"},
622 {22,"property-is-not-a-list"},
623 {23,"object-deletion-not-permitted"},
624 {24,"object-identifier-already-exists"},
625 {25,"operational-problem"},
626 {26,"password-failure"},
627 {27,"read-access-denied"},
628 {28,"security-not-supported"},
629 {29,"service-request-denied"},
631 {31,"unknown-object"},
632 {32,"unknown-property"},
633 {33,"removed enumeration"},
634 {34,"unknown-vt-class"},
635 {35,"unknown-vt-session"},
636 {36,"unsupported-object-type"},
637 {37,"value-out-of-range"},
638 {38,"vt-session-already-closed"},
639 {39,"vt-session-termination-failure"},
640 {40,"write-access-denied"},
641 {41,"character-set-not-supported"},
642 {42,"invalid-array-index"},
643 {43,"cov-subscription-failed"},
644 {44,"not-cov-property"},
645 {45,"optional-functionaltity-not-supported"},
646 {46,"invalid-configuration-data"},
647 {47,"datatype-not-supported"},
648 {48,"duplicate-name"},
649 {49,"duplicate-object-id"},
650 {50,"property-is-not-an-array"},
652 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
653 Enumerated values 256-65535 may be used by others subject to the
654 procedures and constraints described in Clause 23. */
657 static const value_string
658 BACnetPropertyIdentifier [] = {
659 {0,"acked-transition"},
664 {5,"active-vt-session"},
668 {9,"all-write-successful"},
669 {10,"apdu-segment-timeout"},
671 {12,"application-software-version"},
674 {15,"change-of-state-count"},
675 {16,"change-of-state-time"},
676 {17,"notification-class"},
677 {18,"the property in this place was deleted"},
678 {19,"controlled-variable-reference"},
679 {20,"controlled-variable-units"},
680 {21,"controlled-variable-value"},
681 {22,"cov-increment"},
683 {24,"daylights-savings-status"},
685 {26,"derivative-constant"},
686 {27,"derivative-constant-units"},
688 {29,"description-of-halt"},
689 {30,"device-address-binding"},
691 {32,"effective-period"},
692 {33,"elapsed-active-time"},
697 {38,"exception-schedule"},
699 {40,"feedback-value"},
700 {41,"file-access-method"},
703 {44,"firmware-revision"},
705 {46,"inactive-text"},
708 {49,"integral-constant"},
709 {50,"integral-constant-units"},
710 {51,"issue-confirmed-notifications"},
712 {53,"list-of-group-members"},
713 {54,"list-of-object-property-references"},
714 {55,"list-of-session-keys"},
719 {60,"manipulated-variable-reference"},
720 {61,"maximum-output"},
721 {62,"max-apdu-length-accepted"},
722 {63,"max-info-frames"},
724 {65,"max-pres-value"},
725 {66,"minimum-off-time"},
726 {67,"minimum-on-time"},
727 {68,"minimum-output"},
728 {69,"min-pres-value"},
730 {71,"modification-date"},
732 {73,"number-of-APDU-retries"},
733 {74,"number-of-states"},
734 {75,"object-identifier"},
737 {78,"object-property-reference"},
740 {81,"out-of-service"},
742 {83,"event-parameters"},
744 {85,"present-value"},
746 {87,"priority-array"},
747 {88,"priority-for-writing"},
748 {89,"process-identifier"},
749 {90,"program-change"},
750 {91,"program-location"},
751 {92,"program-state"},
752 {93,"proportional-constant"},
753 {94,"proportional-constant-units"},
754 {95,"protocol-conformance-class"},
755 {96,"protocol-object-types-supported"},
756 {97,"protocol-services-supported"},
757 {98,"protocol-version"},
759 {100,"reason-for-halt"},
761 {102,"recipient-list"},
763 {104,"relinquish-default"},
766 {107,"segmentation-supported"},
768 {109,"setpoint-reference"},
770 {111,"status-flags"},
771 {112,"system-status"},
773 {114,"time-of-active-time-reset"},
774 {115,"time-of-state-count-reset"},
775 {116,"time-synchronization-recipients"},
777 {118,"update-interval"},
779 {120,"vendor-identifier"},
781 {122,"vt-class-supported"},
782 {123,"weekly-schedule"},
783 {124,"attempted-samples"},
784 {125,"average-value"},
786 {127,"client-cov-increment"},
787 {128,"cov-resubscription-interval"},
788 {129,"current-notify-time"},
789 {130,"event-time-stamp"},
791 {132,"log-device-object-property"},
792 {133,"enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
793 {134,"log-interval"},
794 {135,"maximum-value"},
795 {136,"minimum-value"},
796 {137,"notification-threshold"},
797 {138,"previous-notify-time"},
798 {139,"protocol-revision"},
799 {140,"records-since-notification"},
800 {141,"record-count"},
803 {144,"stop-when-full"},
804 {145,"total-record-count"},
805 {146,"valid-samples"},
806 {147,"window-interval"},
807 {148,"window-samples"},
808 {149,"maximum-value-time-stamp"},
809 {150,"minimum-value-time-stamp"},
810 {151,"variance-value"},
811 {152,"active-cov-subscriptions"},
812 {153,"backup-failure-timeout"},
813 {154,"configuration-files"},
814 {155,"database-revision"},
815 {156,"direct-reading"},
816 {157,"last-restore-time"},
817 {158,"maintenance-required"},
820 {161,"operation-expected"},
823 {164,"tracking-value"},
824 {165,"zone-members"},
825 {166,"life-safety-alarm-values"},
826 {167,"max-segments-accepted"},
827 {168,"profile-name"},
828 {169,"auto-slave-discovery"},
829 {170,"manual-slave-address-binding"},
830 {171,"slave-address-binding"},
831 {172,"slave-proxy-enable"},
832 {173,"last-notify-time"},
833 {174,"schedule-default"},
834 {175,"accepted-modes"},
835 {176,"adjust-value"},
837 {178,"count-before-change"},
838 {179,"count-change-time"},
840 {181,"input-reference"},
841 {182,"limit-monitoring-interval"},
842 {183,"logging-device"},
843 {184,"logging-record"},
847 {188,"scale-factor"},
849 {190,"value-before-change"},
851 {192,"value-change-time"},
852 {193,"align-intervals"},
853 {194,"group-member-names"},
854 {195,"interval-offset"},
855 {196,"last-restart-reason"},
856 {197,"logging-type"},
857 {198,"member-status-flags"},
858 {199,"notification-period"},
859 {200,"previous-notify-record"},
860 {201,"requested-update-interval"},
861 {202,"restart-notification-recipients"},
862 {203,"time-of-device-restart"},
863 {204,"time-synchronization-recipients"},
865 {206,"UTC-time-synchronization-recipients"},
866 /* enumerations 207-211 are used in Addendum d to
867 ANSI/ASHRAE 135-2004 */
868 {207,"node-subtype"},
870 {209,"structured-object-list"},
871 {210,"subordinate-annotations"},
872 {211,"subordinate-list"},
874 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
875 Enumerated values 512-4194303 may be used by others subject to
876 the procedures and constraints described in Clause 23. */
879 static const value_string
880 BACnetBinaryPV [] = {
887 static const value_string
888 BACnetCharacterSet [] = {
890 {1,"IBM/Microsoft DBCS"},
892 {3,"ISO 10646(UCS-4)"},
893 {4,"ISO 10646(UCS-2)"},
898 static const value_string
899 BACnetStatusFlags [] = {
903 {3,"out-of-service"},
907 static const value_string
908 BACnetMessagePriority [] = {
914 static const value_string
915 BACnetAcknowledgementFilter [] = {
922 static const value_string
923 BACnetResultFlags [] = {
930 static const value_string
931 BACnetRelationSpecifier [] = {
936 {4,"less-than-or-equal"},
937 {5,"greater-than-or-equal"},
941 static const value_string
942 BACnetSelectionLogic [] = {
949 static const value_string
950 BACnetEventStateFilter [] = {
959 static const value_string
960 BACnetEventTransitionBits [] = {
967 static const value_string
968 BACnetSegmentation [] = {
969 {0,"segmented-both"},
970 {1,"segmented-transmit"},
971 {2,"segmented-receive"},
972 {3,"no-segmentation"},
976 static const value_string
977 BACnetSilencedState [] = {
979 {1,"audible-silenced"},
980 {2,"visible-silenced"},
985 static const value_string
986 BACnetDeviceStatus [] = {
988 {1,"operational-read-only"},
989 {2,"download-required"},
990 {3,"download-in-progress"},
991 {4,"non-operational"},
992 {5,"backup-in-progress"},
996 static const value_string
997 BACnetEnableDisable [] = {
1000 {2,"disable-initiation"},
1004 static const value_string
1022 static const value_string
1024 {1,"days numbered 1-7" },
1025 {2,"days numbered 8-14" },
1026 {3,"days numbered 15-21" },
1027 {4,"days numbered 22-28" },
1028 {5,"days numbered 29-31" },
1029 {6,"last 7 days of this month" },
1030 {255,"any week of this month" },
1034 static const value_string
1043 {255,"any day of week" },
1047 static const value_string
1048 BACnetErrorClass [] = {
1057 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
1058 Enumerated values64-65535 may be used by others subject to
1059 the procedures and constraints described in Clause 23. */
1062 static const value_string
1063 BACnetVTClass [] = {
1064 {0,"default-terminal" },
1074 static const value_string
1075 BACnetEventType [] = {
1076 {0,"change-of-bitstring" },
1077 {1,"change-of-state" },
1078 {2,"change-of-value" },
1079 {3,"command-failure" },
1080 {4,"floating-limit" },
1081 {5,"out-of-range" },
1082 {6,"complex-event-type" },
1083 {7,"buffer-ready" },
1084 {8,"change-of-life-safety" },
1086 {10,"buffer-ready" },
1087 {11,"unsigned-range" },
1089 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
1090 Enumerated values 64-65535 may be used by others subject to
1091 the procedures and constraints described in Clause 23.
1092 It is expected that these enumerated values will correspond
1093 to the use of the complex-event-type CHOICE [6] of the
1094 BACnetNotificationParameters production. */
1097 static const value_string
1098 BACnetEventState [] = {
1104 {5,"life-safety-alarm" },
1106 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
1107 Enumerated values 64-65535 may be used by others subject to
1108 the procedures and constraints described in Clause 23. */
1111 static const value_string
1112 BACnetLogStatus [] = {
1113 {0,"log-disabled" },
1114 {1,"buffer-purged" },
1118 static const value_string
1119 BACnetMaintenance [] = {
1121 {1,"periodic-test" },
1122 {2,"need-service-operational" },
1123 {3,"need-service-inoperative" },
1127 static const value_string
1128 BACnetNotifyType [] = {
1131 {2,"ack-notification" },
1135 static const value_string
1136 BACnetServicesSupported [] = {
1137 {0,"acknowledgeAlarm"},
1138 {1,"confirmedCOVNotification"},
1139 {2,"confirmedEventNotification"},
1140 {3,"getAlarmSummary"},
1141 {4,"getEnrollmentSummary"},
1143 {6,"atomicReadFile"},
1144 {7,"atomicWriteFile"},
1145 {8,"addListElement"},
1146 {9,"removeListElement"},
1147 {10,"createObject"},
1148 {11,"deleteObject"},
1149 {12,"readProperty"},
1150 {13,"readPropertyConditional"},
1151 {14,"readPropertyMultiple"},
1152 {15,"writeProperty"},
1153 {16,"writePropertyMultiple"},
1154 {17,"deviceCommunicationControl"},
1155 {18,"confirmedPrivateTransfer"},
1156 {19,"confirmedTextMessage"},
1157 {20,"reinitializeDevice"},
1161 {24,"authenticate"},
1165 {28,"unconfirmedCOVNotification"},
1166 {29,"unconfirmedEventNotification"},
1167 {30,"unconfirmedPrivateTransfer"},
1168 {31,"unconfirmedTextMessage"},
1169 {32,"timeSynchronization"},
1173 {36,"utcTimeSynchronization"},
1174 {37,"lifeSafetyOperation"},
1175 {38,"subscribeCOVProperty"},
1176 {39,"getEventInformation"},
1180 static const value_string
1181 BACnetPropertyStates [] = {
1182 {0,"boolean-value"},
1186 {4,"program-change"},
1187 {5,"program-state"},
1188 {6,"reason-for-halt"},
1191 {9,"system-status"},
1193 {11,"unsigned-value"},
1194 {12,"life-safety-mode"},
1195 {13,"life-safety-state"},
1197 /* Tag values 0-63 are reserved for definition by ASHRAE.
1198 Tag values of 64-254 may be used by others to accommodate
1199 vendor specific properties that have discrete or enumerated values,
1200 subject to the constraints described in Clause 23. */
1203 static const value_string
1204 BACnetProgramError [] = {
1211 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
1212 Enumerated values 64-65535 may be used by others subject to
1213 the procedures and constraints described in Clause 23. */
1216 static const value_string
1217 BACnetProgramRequest [] = {
1227 static const value_string
1228 BACnetProgramState [] = {
1238 static const value_string
1239 BACnetReinitializedStateOfDevice [] = {
1250 static const value_string
1251 BACnetPolarity [] = {
1257 static const value_string
1258 BACnetTagNames[] = {
1259 { 5, "Extended Value" },
1260 { 6, "Opening Tag" },
1261 { 7, "Closing Tag" },
1265 static const value_string
1266 BACnetReadRangeOptions[] = {
1267 { 3, "range byPosition" },
1268 { 4, "range byTime" },
1269 { 5, "range timeRange" },
1270 { 6, "range bySequenceNumber" },
1271 { 7, "range byTime" },
1275 static int proto_bacapp = -1;
1276 static int hf_bacapp_type = -1;
1277 static int hf_bacapp_pduflags = -1;
1278 static int hf_bacapp_SEG = -1;
1279 static int hf_bacapp_MOR = -1;
1280 static int hf_bacapp_SA = -1;
1281 static int hf_bacapp_response_segments = -1;
1282 static int hf_bacapp_max_adpu_size = -1;
1283 static int hf_bacapp_invoke_id = -1;
1284 static int hf_bacapp_objectType = -1;
1285 static int hf_bacapp_instanceNumber = -1;
1286 static int hf_bacapp_sequence_number = -1;
1287 static int hf_bacapp_window_size = -1;
1288 static int hf_bacapp_service = -1;
1289 static int hf_bacapp_NAK = -1;
1290 static int hf_bacapp_SRV = -1;
1291 static int hf_BACnetRejectReason = -1;
1292 static int hf_BACnetAbortReason = -1;
1293 static int hf_BACnetApplicationTagNumber = -1;
1294 static int hf_BACnetContextTagNumber = -1;
1295 static int hf_BACnetExtendedTagNumber = -1;
1296 static int hf_BACnetNamedTag = -1;
1297 static int hf_BACnetTagClass = -1;
1298 static int hf_BACnetCharacterSet = -1;
1299 static int hf_bacapp_tag = -1;
1300 static int hf_bacapp_tag_lvt = -1;
1301 static int hf_bacapp_tag_value8 = -1;
1302 static int hf_bacapp_tag_value16 = -1;
1303 static int hf_bacapp_tag_value32 = -1;
1304 static int hf_bacapp_tag_ProcessId = -1;
1305 static int hf_bacapp_tag_initiatingObjectType = -1;
1306 static int hf_bacapp_vpart = -1;
1308 static int hf_bacapp_uservice = -1;
1311 static gint ett_bacapp = -1;
1312 static gint ett_bacapp_control = -1;
1313 static gint ett_bacapp_tag = -1;
1314 static gint ett_bacapp_list = -1;
1315 static gint ett_bacapp_value = -1;
1317 static dissector_handle_t data_handle;
1318 static gint32 propertyIdentifier = -1;
1319 static guint32 object_type = 4096;
1321 static guint8 bacapp_flags = 0;
1322 static guint8 bacapp_seq = 0;
1324 /* Used when there are ranges of reserved and proprietary enumerations */
1326 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
1327 const char *fmt, const char *split_fmt)
1329 if (val < split_val)
1330 return val_to_str(val, vs, fmt);
1332 return val_to_str(val, vs, split_fmt);
1335 /* from clause 20.2.1.3.2 Constructed Data */
1336 /* returns true if the extended value is used */
1337 static gboolean tag_is_extended_value(guint8 tag)
1339 return (tag & 0x07) == 5;
1342 static gboolean tag_is_opening(guint8 tag)
1344 return (tag & 0x07) == 6;
1347 static gboolean tag_is_closing(guint8 tag)
1349 return (tag & 0x07) == 7;
1352 /* from clause 20.2.1.1 Class
1353 class bit shall be one for context specific tags */
1354 /* returns true if the tag is context specific */
1355 static gboolean tag_is_context_specific(guint8 tag)
1357 return (tag & 0x08) != 0;
1360 static gboolean tag_is_extended_tag_number(guint8 tag)
1362 return ((tag & 0xF0) == 0xF0);
1365 static guint32 object_id_type(guint32 object_identifier)
1367 return ((object_identifier >> 22) & 0x3FF);
1370 static guint32 object_id_instance(guint32 object_identifier)
1372 return (object_identifier & 0x3FFFFF);
1376 fTagNo (tvbuff_t *tvb, guint offset)
1378 return (guint)(tvb_get_guint8(tvb, offset) >> 4);
1382 fUnsigned32 (tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
1384 gboolean valid = TRUE;
1388 *val = tvb_get_guint8(tvb, offset);
1391 *val = tvb_get_ntohs(tvb, offset);
1394 *val = tvb_get_ntoh24(tvb, offset);
1397 *val = tvb_get_ntohl(tvb, offset);
1408 fUnsigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
1410 gboolean valid = FALSE;
1414 if (lvt && (lvt <= 8)) {
1416 data = tvb_get_guint8(tvb, offset);
1417 for (i = 0; i < lvt; i++) {
1418 data = tvb_get_guint8(tvb, offset+i);
1419 value = (value << 8) + data;
1427 /* BACnet Signed Value uses 2's compliment notation, but with a twist:
1428 All signed integers shall be encoded in the smallest number of octets
1429 possible. That is, the first octet of any multi-octet encoded value
1430 shall not be X'00' if the most significant bit (bit 7) of the second
1431 octet is 0, and the first octet shall not be X'FF' if the most
1432 significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
1434 fSigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
1436 gboolean valid = FALSE;
1440 /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
1441 if (lvt && (lvt <= 7)) {
1443 data = tvb_get_guint8(tvb, offset);
1444 if ((data & 0x80) != 0)
1445 value = (-1 << 8) | data;
1448 for (i = 1; i < lvt; i++) {
1449 data = tvb_get_guint8(tvb, offset+i);
1450 value = (value << 8) + data;
1459 fTagHeaderTree (tvbuff_t *tvb, proto_tree *tree, guint offset,
1460 guint8 *tag_no, guint8* tag_info, guint32 *lvt)
1465 guint lvt_len = 1; /* used for tree display of lvt */
1466 guint lvt_offset; /* used for tree display of lvt */
1468 proto_tree *subtree;
1470 lvt_offset = offset;
1471 tag = tvb_get_guint8(tvb, offset);
1474 /* To solve the problem of lvt values of 6/7 being indeterminate - it */
1475 /* can mean open/close tag or length of 6/7 after the length is */
1476 /* computed below - store whole tag info, not just context bit. */
1477 if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
1479 if (tag_is_extended_tag_number(tag)) {
1480 *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
1482 if (tag_is_extended_value(tag)) { /* length is more than 4 Bytes */
1483 lvt_offset += tag_len;
1484 value = tvb_get_guint8(tvb, lvt_offset);
1486 if (value == 254) { /* length is encoded with 16 Bits */
1487 *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
1490 } else if (value == 255) { /* length is encoded with 32 Bits */
1491 *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
1499 if (tag_is_closing(tag) || tag_is_opening(tag))
1500 ti = proto_tree_add_text(tree, tvb, offset, tag_len,
1501 "%s: %u", match_strval(
1502 tag & 0x07, BACnetTagNames),
1504 else if (tag_is_context_specific(tag)) {
1505 ti = proto_tree_add_text(tree, tvb, offset, tag_len,
1506 "Context Tag: %u, Length/Value/Type: %u",
1509 ti = proto_tree_add_text(tree, tvb, offset, tag_len,
1510 "Application Tag: %s, Length/Value/Type: %u",
1512 BACnetApplicationTagNumber,
1513 ASHRAE_Reserved_Fmt),
1515 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1516 /* details if needed */
1517 proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, FALSE);
1518 if (tag_is_extended_tag_number(tag)) {
1519 proto_tree_add_uint_format(subtree,
1520 hf_BACnetContextTagNumber,
1521 tvb, offset, 1, tag,
1522 "Extended Tag Number");
1523 proto_tree_add_item(subtree,
1524 hf_BACnetExtendedTagNumber,
1525 tvb, offset + 1, 1, FALSE);
1527 if (tag_is_context_specific(tag))
1528 proto_tree_add_item(subtree,
1529 hf_BACnetContextTagNumber,
1530 tvb, offset, 1, FALSE);
1532 proto_tree_add_item(subtree,
1533 hf_BACnetApplicationTagNumber,
1534 tvb, offset, 1, FALSE);
1536 if (tag_is_closing(tag) || tag_is_opening(tag))
1537 proto_tree_add_item(subtree,
1539 tvb, offset, 1, FALSE);
1540 else if (tag_is_extended_value(tag)) {
1541 proto_tree_add_item(subtree,
1543 tvb, offset, 1, FALSE);
1544 proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
1545 tvb, lvt_offset, lvt_len, *lvt);
1547 proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
1548 tvb, lvt_offset, lvt_len, *lvt);
1555 fTagHeader (tvbuff_t *tvb, guint offset, guint8 *tag_no, guint8* tag_info,
1558 return fTagHeaderTree (tvb, NULL, offset, tag_no, tag_info, lvt);
1562 fNullTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1564 guint8 tag_no, tag_info;
1567 proto_tree *subtree;
1569 ti = proto_tree_add_text(tree, tvb, offset, 1, "%sNULL", label);
1570 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1571 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1577 fBooleanTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1579 guint8 tag_no, tag_info;
1583 proto_tree *subtree;
1586 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1587 if (tag_info && lvt == 1)
1589 lvt = tvb_get_guint8(tvb, offset+1);
1593 ti = proto_tree_add_text(tree, tvb, offset, bool_len,
1594 "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
1595 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1596 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1598 return offset + bool_len;
1602 fUnsignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1605 guint8 tag_no, tag_info;
1609 proto_tree *subtree;
1611 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1612 /* only support up to an 8 byte (64-bit) integer */
1613 if (fUnsigned64 (tvb, offset + tag_len, lvt, &val))
1614 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1615 "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
1617 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1618 "%s - %u octets (Unsigned)", label, lvt);
1619 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1620 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1622 return offset+tag_len+lvt;
1625 /* set split_val to zero when not needed */
1627 fEnumeratedTagSplit (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
1628 const value_string *vs, guint32 split_val)
1631 guint8 tag_no, tag_info;
1635 proto_tree *subtree;
1637 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1638 /* only support up to a 4 byte (32-bit) enumeration */
1639 if (fUnsigned32 (tvb, offset+tag_len, lvt, &val)) {
1641 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1642 "%s %s", label, val_to_split_str(val, split_val, vs,
1643 ASHRAE_Reserved_Fmt,Vendor_Proprietary_Fmt));
1645 ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1646 "%s %u", label, val);
1648 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1649 "%s - %u octets (enumeration)", label, lvt);
1651 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1652 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1654 return offset+tag_len+lvt;
1658 fEnumeratedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
1659 const value_string *vs)
1661 return fEnumeratedTagSplit (tvb, tree, offset, label, vs, 0);
1665 fSignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1668 guint8 tag_no, tag_info;
1672 proto_tree *subtree;
1674 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1675 if (fSigned64 (tvb, offset + tag_len, lvt, &val))
1676 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1677 "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
1679 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1680 "%s - %u octets (Signed)", label, lvt);
1681 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1682 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1684 return offset+tag_len+lvt;
1688 fRealTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1690 guint8 tag_no, tag_info;
1695 proto_tree *subtree;
1697 tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
1698 f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
1699 ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
1700 "%s%f (Real)", label, f_val);
1701 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1702 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1704 return offset+tag_len+4;
1708 fDoubleTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1710 guint8 tag_no, tag_info;
1715 proto_tree *subtree;
1717 tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
1718 d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
1719 ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
1720 "%s%lf (Double)", label, d_val);
1721 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1722 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1724 return offset+tag_len+8;
1728 fProcessId (tvbuff_t *tvb, proto_tree *tree, guint offset)
1730 guint32 val = 0, lvt;
1731 guint8 tag_no, tag_info;
1733 proto_tree *subtree;
1736 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1737 if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
1738 ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
1739 tvb, offset, lvt+tag_len, val);
1741 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1742 "Process Identifier - %u octets (Signed)", lvt);
1743 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1744 offset += tag_len + lvt;
1750 fTimeSpan (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1752 guint32 val = 0, lvt;
1753 guint8 tag_no, tag_info;
1755 proto_tree *subtree;
1758 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1759 if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
1760 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1761 "%s (hh.mm.ss): %d.%02d.%02d%s",
1763 (val / 3600), ((val % 3600) / 60), (val % 60),
1764 val == 0 ? " (indefinite)" : "");
1766 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1767 "%s - %u octets (Signed)", label, lvt);
1768 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1769 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1771 return offset+tag_len+lvt;
1775 fWeekNDay (tvbuff_t *tvb, proto_tree *tree, guint offset)
1777 guint32 month, weekOfMonth, dayOfWeek;
1778 guint8 tag_no, tag_info;
1782 proto_tree *subtree;
1784 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1785 month = tvb_get_guint8(tvb, offset+tag_len);
1786 weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
1787 dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
1788 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
1789 val_to_str(month, months, "month (%d) not found"),
1790 val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
1791 val_to_str(dayOfWeek, days, "day of week (%d) not found"));
1792 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1793 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1795 return offset+tag_len+lvt;
1799 fDate (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1801 guint32 year, month, day, weekday;
1802 guint8 tag_no, tag_info;
1806 proto_tree *subtree;
1808 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1809 year = tvb_get_guint8(tvb, offset+tag_len);
1810 month = tvb_get_guint8(tvb, offset+tag_len+1);
1811 day = tvb_get_guint8(tvb, offset+tag_len+2);
1812 weekday = tvb_get_guint8(tvb, offset+tag_len+3);
1813 if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255))
1815 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1818 else if (year != 255)
1821 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1822 "%s%s %d, %d, (Day of Week = %s)",
1823 label, val_to_str(month,
1825 "month (%d) not found"),
1826 day, year, val_to_str(weekday,
1832 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1833 "%s%s %d, any year, (Day of Week = %s)",
1834 label, val_to_str(month, months, "month (%d) not found"),
1835 day, val_to_str(weekday, days, "(%d) not found"));
1837 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1838 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1840 return offset+tag_len+lvt;
1844 fTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1846 guint32 hour, minute, second, msec, lvt;
1847 guint8 tag_no, tag_info;
1850 proto_tree *subtree;
1852 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1853 hour = tvb_get_guint8(tvb, offset+tag_len);
1854 minute = tvb_get_guint8(tvb, offset+tag_len+1);
1855 second = tvb_get_guint8(tvb, offset+tag_len+2);
1856 msec = tvb_get_guint8(tvb, offset+tag_len+3);
1857 if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
1858 ti = proto_tree_add_text(tree, tvb, offset,
1859 lvt+tag_len, "%sany", label);
1861 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1862 "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
1864 hour > 12 ? hour - 12 : hour,
1865 minute, second, msec,
1866 hour > 12 ? "P.M." : "A.M.",
1867 hour, minute, second, msec);
1868 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1869 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1871 return offset+tag_len+lvt;
1875 fDateTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1877 proto_tree *subtree = tree;
1880 if (label != NULL) {
1881 tt = proto_tree_add_text (subtree, tvb, offset, 1, "%s", label);
1882 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
1884 offset = fDate (tvb,subtree,offset,"Date: ");
1885 return fTime (tvb,subtree,offset,"Time: ");
1889 fTimeValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
1891 guint lastoffset = 0;
1892 guint8 tag_no, tag_info;
1895 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
1896 lastoffset = offset;
1897 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1898 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
1901 offset = fTime (tvb,tree,offset,"Time: ");
1902 offset = fApplicationTypes(tvb, tree, offset, "Value: ");
1908 fCalendaryEntry (tvbuff_t *tvb, proto_tree *tree, guint offset)
1910 guint8 tag_no, tag_info;
1913 switch (fTagNo(tvb, offset)) {
1915 offset = fDate (tvb, tree, offset, "Date: ");
1917 case 1: /* dateRange */
1918 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
1919 offset = fDateRange (tvb, tree, offset);
1920 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
1922 case 2: /* BACnetWeekNDay */
1923 offset = fWeekNDay (tvb, tree, offset);
1934 fTimeStamp (tvbuff_t *tvb, proto_tree *tree, guint offset)
1936 guint8 tag_no = 0, tag_info = 0;
1939 if (tvb_length_remaining(tvb, offset) > 0) { /* don't loop, it's a CHOICE */
1940 switch (fTagNo(tvb, offset)) {
1942 offset = fTime (tvb, tree, offset, "timestamp: ");
1944 case 1: /* sequenceNumber */
1945 offset = fUnsignedTag (tvb, tree, offset, "sequence Number: ");
1947 case 2: /* dateTime */
1948 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
1949 offset = fDateTime (tvb, tree, offset, "timestamp: ");
1950 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
1962 fSetpointReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
1964 guint lastoffset = 0;
1966 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
1967 lastoffset = offset;
1969 switch (fTagNo(tvb, offset)) {
1970 case 0: /* setpointReference */
1971 offset = fBACnetObjectPropertyReference (tvb,tree,offset);
1984 fClientCOV (tvbuff_t *tvb, proto_tree *tree, guint offset)
1986 if (tvb_length_remaining(tvb, offset) > 0) {
1987 offset = fApplicationTypes(tvb,tree,offset, "increment: ");
1993 fDestination (tvbuff_t *tvb, proto_tree *tree, guint offset)
1995 if (tvb_length_remaining(tvb, offset) > 0) {
1996 offset = fApplicationTypesEnumerated(tvb,tree,offset,
1997 "valid Days: ", days);
1998 offset = fTime (tvb,tree,offset,"from time: ");
1999 offset = fTime (tvb,tree,offset,"to time: ");
2000 offset = fRecipient (tvb,tree,offset);
2001 offset = fProcessId (tvb,tree,offset);
2002 offset = fApplicationTypes (tvb,tree,offset,
2003 "issue confirmed notifications: ");
2004 offset = fApplicationTypesEnumerated (tvb,tree,offset,
2005 "transitions: ", BACnetEventTransitionBits);
2013 fOctetString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
2016 guint start = offset;
2017 guint8 tag_no, tag_info;
2018 proto_tree* subtree = tree;
2021 offset += fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2025 tmp = tvb_bytes_to_str(tvb, offset, lvt);
2026 ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
2031 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
2033 fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
2039 fAddress (tvbuff_t *tvb, proto_tree *tree, guint offset)
2041 guint8 tag_no, tag_info;
2045 offset = fUnsignedTag (tvb, tree, offset, "network-number");
2046 offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2048 proto_tree_add_text(tree, tvb, offset, offs, "mac-address: broadcast");
2051 offset = fOctetString (tvb, tree, offset, "mac-address: ", lvt);
2056 fSessionKey (tvbuff_t *tvb, proto_tree *tree, guint offset)
2058 offset = fOctetString (tvb,tree,offset,"session key: ", 8);
2059 return fAddress (tvb,tree,offset);
2063 fObjectIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
2065 guint8 tag_no, tag_info;
2069 proto_tree *subtree;
2072 tag_length = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
2073 object_id = tvb_get_ntohl(tvb,offset+tag_length);
2074 object_type = object_id_type(object_id);
2075 ti = proto_tree_add_text(tree, tvb, offset, tag_length + 4,
2076 "ObjectIdentifier: %s, %u",
2077 val_to_split_str(object_type,
2080 ASHRAE_Reserved_Fmt,
2081 Vendor_Proprietary_Fmt),
2082 object_id_instance(object_id));
2083 /* here are the details of how we arrived at the above text */
2084 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
2085 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2086 offset += tag_length;
2087 proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, FALSE);
2088 proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, FALSE);
2095 fRecipient (tvbuff_t *tvb, proto_tree *tree, guint offset)
2097 guint8 tag_no, tag_info;
2100 fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
2102 if (tag_no == 0) { /* device */
2103 offset = fObjectIdentifier (tvb, tree, offset);
2105 else { /* address */
2106 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
2107 offset = fAddress (tvb, tree, offset);
2108 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
2115 fRecipientProcess (tvbuff_t *tvb, proto_tree *tree, guint offset)
2117 guint lastoffset = 0;
2118 guint8 tag_no, tag_info;
2121 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2122 lastoffset = offset;
2124 switch (fTagNo(tvb, offset)) {
2125 case 0: /* recipient */
2126 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
2127 offset = fRecipient (tvb, tree, offset);
2128 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
2130 case 1: /* processId */
2131 offset = fProcessId (tvb, tree, offset);
2132 lastoffset = offset;
2142 fAddressBinding (tvbuff_t *tvb, proto_tree *tree, guint offset)
2144 offset = fObjectIdentifier (tvb, tree, offset);
2145 return fAddress (tvb, tree, offset);
2149 fActionCommand (tvbuff_t *tvb, proto_tree *tree, guint offset)
2151 guint lastoffset = 0;
2152 guint8 tag_no, tag_info;
2154 proto_tree *subtree = tree;
2157 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2158 lastoffset = offset;
2159 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2160 if (tag_is_closing(tag_info)) {
2161 offset += fTagHeaderTree (tvb, subtree, offset,
2162 &tag_no, &tag_info, &lvt);
2168 case 0: /* deviceIdentifier */
2169 offset = fObjectIdentifier (tvb, subtree, offset);
2171 case 1: /* objectIdentifier */
2172 offset = fObjectIdentifier (tvb, subtree, offset);
2174 case 2: /* propertyIdentifier */
2175 offset = fPropertyIdentifier (tvb, subtree, offset);
2177 case 3: /* propertyArrayIndex */
2178 offset = fUnsignedTag (tvb,subtree,offset,"Property Array Index: ");
2180 case 4: /* propertyValue */
2181 if (tag_is_opening(tag_info)) {
2182 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
2183 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2184 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2185 offset = fAbstractSyntaxNType (tvb, subtree, offset);
2190 case 5: /* priority */
2191 offset = fUnsignedTag (tvb,subtree,offset,"Priority: ");
2193 case 6: /* postDelay */
2194 offset = fUnsignedTag (tvb,subtree,offset,"Post Delay: ");
2196 case 7: /* quitOnFailure */
2197 offset = fBooleanTag(tvb, subtree, offset,
2198 "Quit On Failure: ");
2200 case 8: /* writeSuccessful */
2201 offset = fBooleanTag(tvb, subtree, offset,
2202 "Write Successful: ");
2212 fActionList (tvbuff_t *tvb, proto_tree *tree, guint offset)
2214 return fActionCommand (tvb,tree,offset);
2218 fPropertyIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
2220 guint8 tag_no, tag_info;
2224 proto_tree *subtree;
2226 propertyIdentifier = 0; /* global Variable */
2227 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2228 if (fUnsigned32 (tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier))
2229 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
2230 "property Identifier: %s",
2231 val_to_split_str(propertyIdentifier, 512,
2232 BACnetPropertyIdentifier,
2233 ASHRAE_Reserved_Fmt,
2234 Vendor_Proprietary_Fmt));
2236 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
2237 "Property Identifier - %u octets", lvt);
2238 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
2239 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2241 return offset+tag_len+lvt;
2245 fCharacterString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
2247 guint8 tag_no, tag_info, character_set;
2249 size_t inbytesleft, outbytesleft = 512;
2250 guint offs, extra = 1;
2252 guint8 bf_arr[512], *out = &bf_arr[0];
2254 proto_tree *subtree;
2255 guint start = offset;
2257 if (tvb_length_remaining(tvb, offset) > 0) {
2259 offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2261 character_set = tvb_get_guint8(tvb, offset+offs);
2262 /* Account for code page if DBCS */
2263 if (character_set == 1)
2267 offset += (offs+extra);
2271 l = inbytesleft = min(lvt, 255);
2273 * XXX - are we guaranteed that these encoding
2274 * names correspond, on *all* platforms with
2275 * iconv(), to the encodings we want?
2276 * If not (and perhaps even if so), we should
2277 * perhaps have our own iconv() implementation,
2278 * with a different name, so that we control the
2279 * encodings it supports and the names of those
2282 * We should also handle that in the general
2283 * string handling code, rather than making it
2284 * specific to the BACAPP dissector, as many
2285 * other dissectors need to handle various
2286 * character encodings.
2288 str_val = tvb_get_ephemeral_string(tvb, offset, l);
2289 /** this decoding may be not correct for multi-byte characters, Lka */
2290 switch (character_set) {
2291 case 0x00: /* ANSI_X3.4 */
2292 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ANSI_X3.4");
2294 case 1: /* IBM/MICROSOFT DBCS */
2297 case 2: /* JIS C 6226 */
2301 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-4BE");
2304 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-2BE");
2306 case 5: /* ISO8859-1 */
2307 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ISO8859-1");
2313 ti = proto_tree_add_text(tree, tvb, offset, l, "%s'%s'", label, out);
2318 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
2320 fTagHeaderTree (tvb, subtree, start, &tag_no, &tag_info, &lvt);
2321 proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, FALSE);
2322 if (character_set == 1)
2324 proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
2331 fBitStringTagVS (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
2332 const value_string *src)
2334 guint8 tag_no, tag_info, tmp;
2335 gint j, unused, skip;
2337 guint32 lvt, i, numberOfBytes;
2340 offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2341 numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
2343 unused = tvb_get_guint8(tvb, offset); /* get the unused Bits */
2345 for (i = 0; i < numberOfBytes; i++) {
2346 tmp = tvb_get_guint8(tvb, (offset)+i+1);
2347 if (i == numberOfBytes-1) { skip = unused; }
2348 for (j = 0; j < 8-skip; j++) {
2350 if (tmp & (1 << (7 - j)))
2351 proto_tree_add_text(tree, tvb,
2355 val_to_str((guint) (i*8 +j),
2357 ASHRAE_Reserved_Fmt));
2359 proto_tree_add_text(tree, tvb,
2363 val_to_str((guint) (i*8 +j),
2365 ASHRAE_Reserved_Fmt));
2368 bf_arr[min(255,(i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
2375 bf_arr[min(255,numberOfBytes*8-unused)] = 0;
2376 proto_tree_add_text(tree, tvb, offset, lvt, "%sB'%s'", label, bf_arr);
2385 fBitStringTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
2387 return fBitStringTagVS (tvb, tree, offset, label, NULL);
2390 /* handles generic application types, as well as enumerated and enumerations
2391 with reserved and proprietarty ranges (split) */
2393 fApplicationTypesEnumeratedSplit (tvbuff_t *tvb, proto_tree *tree, guint offset,
2394 const gchar *label, const value_string *src, guint32 split_val)
2396 guint8 tag_no, tag_info;
2400 if (tvb_length_remaining(tvb, offset) > 0) {
2402 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2403 if (!tag_is_context_specific(tag_info))
2406 case 0: /** NULL 20.2.2 */
2407 offset = fNullTag(tvb, tree, offset, label);
2409 case 1: /** BOOLEAN 20.2.3 */
2410 offset = fBooleanTag(tvb, tree, offset, label);
2412 case 2: /** Unsigned Integer 20.2.4 */
2413 offset = fUnsignedTag(tvb, tree, offset, label);
2415 case 3: /** Signed Integer 20.2.5 */
2416 offset = fSignedTag(tvb, tree, offset, label);
2418 case 4: /** Real 20.2.6 */
2419 offset = fRealTag(tvb, tree, offset, label);
2421 case 5: /** Double 20.2.7 */
2422 offset = fDoubleTag(tvb, tree, offset, label);
2424 case 6: /** Octet String 20.2.8 */
2425 offset = fOctetString (tvb, tree, offset, label, lvt);
2427 case 7: /** Character String 20.2.9 */
2428 offset = fCharacterString (tvb,tree,offset,label);
2430 case 8: /** Bit String 20.2.10 */
2431 offset = fBitStringTagVS (tvb, tree, offset, label, src);
2433 case 9: /** Enumerated 20.2.11 */
2434 offset = fEnumeratedTagSplit (tvb, tree, offset, label, src, split_val);
2436 case 10: /** Date 20.2.12 */
2437 offset = fDate (tvb, tree, offset, label);
2439 case 11: /** Time 20.2.13 */
2440 offset = fTime (tvb, tree, offset, label);
2442 case 12: /** BACnetObjectIdentifier 20.2.14 */
2443 offset = fObjectIdentifier (tvb, tree, offset);
2445 case 13: /* reserved for ASHRAE */
2448 proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
2449 offset+=lvt+tag_len;
2461 fApplicationTypesEnumerated (tvbuff_t *tvb, proto_tree *tree, guint offset,
2462 const gchar *label, const value_string *vs)
2464 return fApplicationTypesEnumeratedSplit(tvb, tree, offset, label, vs, 0);
2468 fApplicationTypes (tvbuff_t *tvb, proto_tree *tree, guint offset,
2471 return fApplicationTypesEnumeratedSplit(tvb, tree, offset, label, NULL, 0);
2475 fContextTaggedValue(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
2477 guint8 tag_no, tag_info;
2481 proto_tree *subtree;
2485 tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
2486 /* cap the the suggested length in case of bad data */
2487 tvb_len = tvb_length_remaining(tvb, offset+tag_len);
2488 if ((tvb_len >= 0) && ((guint32)tvb_len < lvt))
2492 ti = proto_tree_add_text(tree, tvb, offset+tag_len, lvt,
2493 "Context Value (as %u DATA octets)", lvt);
2495 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
2496 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2498 return offset + tag_len + lvt;
2502 fAbstractSyntaxNType (tvbuff_t *tvb, proto_tree *tree, guint offset)
2504 guint8 tag_no, tag_info;
2506 guint lastoffset = 0, depth = 0;
2509 if (propertyIdentifier >= 0)
2511 g_snprintf (ar, sizeof(ar), "%s: ",
2512 val_to_split_str(propertyIdentifier, 512,
2513 BACnetPropertyIdentifier,
2514 ASHRAE_Reserved_Fmt,
2515 Vendor_Proprietary_Fmt));
2519 g_snprintf (ar, sizeof(ar), "Abstract Type: ");
2521 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2522 lastoffset = offset;
2523 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2524 if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
2525 if (depth <= 0) return offset;
2528 /* Application Tags */
2529 switch (propertyIdentifier) {
2530 case 2: /* BACnetActionList */
2531 offset = fActionList (tvb,tree,offset);
2533 case 30: /* BACnetAddressBinding */
2534 offset = fAddressBinding (tvb,tree,offset);
2536 case 55: /* list-of-session-keys */
2537 fSessionKey (tvb, tree, offset);
2539 case 79: /* object-type */
2540 case 96: /* protocol-object-types-supported */
2541 offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, ar,
2542 BACnetObjectType, 128);
2544 case 97: /* Protocol-Services-Supported */
2545 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2546 BACnetServicesSupported);
2548 case 107: /* segmentation-supported */
2549 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2550 BACnetSegmentation);
2552 case 111: /* Status-Flags */
2553 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2556 case 112: /* System-Status */
2557 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2558 BACnetDeviceStatus);
2560 case 117: /* units */
2561 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2562 BACnetEngineeringUnits);
2564 case 87: /* priority-array */
2565 offset = fPriorityArray (tvb, tree, offset);
2567 case 38: /* exception-schedule */
2568 if (object_type < 128)
2570 offset = fSpecialEvent (tvb,tree,offset);
2573 case 123: /* weekly-schedule */
2574 if (object_type < 128)
2576 offset = fWeeklySchedule (tvb,tree,offset);
2579 case 159: /* member-of */
2580 case 165: /* zone-members */
2581 fDeviceObjectReference (tvb, tree, offset);
2586 if (tag_is_opening(tag_info))
2589 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
2591 else if (tag_is_closing(tag_info))
2594 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
2598 offset = fContextTaggedValue(tvb, tree, offset, ar);
2603 offset = fApplicationTypes (tvb, tree, offset, ar);
2613 fPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 tagoffset)
2615 guint lastoffset = offset;
2617 proto_tree *subtree;
2618 guint8 tag_no, tag_info;
2621 offset = fPropertyReference(tvb, tree, offset, tagoffset, 0);
2622 if (offset > lastoffset)
2624 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2625 if (tag_no == tagoffset+2) { /* Value - might not be present in ReadAccessResult */
2626 if (tag_is_opening(tag_info)) {
2627 tt = proto_tree_add_text(tree, tvb, offset, 1, "propertyValue");
2628 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2629 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2630 offset = fAbstractSyntaxNType (tvb, subtree, offset);
2631 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2639 fBACnetPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
2641 guint lastoffset = 0;
2642 guint8 tag_no, tag_info;
2645 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2646 lastoffset = offset;
2647 offset = fPropertyValue(tvb, tree, offset, 0);
2648 if (offset > lastoffset)
2650 /* detect optional priority
2651 by looking to see if the next tag is context tag number 3 */
2652 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2653 if (tag_is_context_specific(tag_info) && (tag_no == 3))
2654 offset = fUnsignedTag (tvb,tree,offset,"Priority: ");
2661 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2663 guint lastoffset = 0;
2665 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2666 lastoffset = offset;
2668 switch (fTagNo(tvb,offset)) {
2669 case 0: /* ProcessId */
2670 offset = fUnsignedTag (tvb, tree, offset, "subscriber Process Id: ");
2672 case 1: /* monitored ObjectId */
2673 offset = fObjectIdentifier (tvb, tree, offset);
2675 case 2: /* issueConfirmedNotifications */
2676 offset = fBooleanTag (tvb, tree, offset, "issue Confirmed Notifications: ");
2678 case 3: /* life time */
2679 offset = fTimeSpan (tvb,tree,offset,"life time");
2681 case 4: /* monitoredPropertyIdentifier */
2682 offset = fBACnetPropertyReference (tvb, tree, offset, 0);
2684 case 5: /* covIncrement */
2685 offset = fRealTag (tvb, tree, offset, "COV Increment: ");
2696 fSubscribeCOVRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2698 return fSubscribeCOVPropertyRequest(tvb, tree, offset);
2702 fWhoHas (tvbuff_t *tvb, proto_tree *tree, guint offset)
2704 guint lastoffset = 0;
2706 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2707 lastoffset = offset;
2709 switch (fTagNo(tvb, offset)) {
2710 case 0: /* deviceInstanceLowLimit */
2711 offset = fUnsignedTag (tvb, tree, offset, "device Instance Low Limit: ");
2713 case 1: /* deviceInstanceHighLimit */
2714 offset = fUnsignedTag (tvb, tree, offset, "device Instance High Limit: ");
2716 case 2: /* BACnetObjectId */
2717 offset = fObjectIdentifier (tvb, tree, offset);
2719 case 3: /* messageText */
2720 offset = fCharacterString (tvb,tree,offset, "Object Name: ");
2731 fDailySchedule (tvbuff_t *tvb, proto_tree *subtree, guint offset)
2733 guint lastoffset = 0;
2734 guint8 tag_no, tag_info;
2737 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2738 if (tag_is_opening(tag_info) && tag_no == 0)
2740 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
2741 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2742 lastoffset = offset;
2743 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2744 if (tag_is_closing(tag_info)) {
2745 /* should be closing context tag 0 */
2746 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2750 offset = fTimeValue (tvb, subtree, offset);
2753 else if (tag_no == 0 && lvt == 0)
2755 /* not sure null (empty array element) is legal */
2756 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2762 fWeeklySchedule (tvbuff_t *tvb, proto_tree *tree, guint offset)
2764 guint lastoffset = 0;
2765 guint8 tag_no, tag_info;
2768 proto_tree *subtree = tree;
2771 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2772 lastoffset = offset;
2773 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2774 if (tag_is_closing(tag_info)) {
2775 return offset; /* outer encoding will print out closing tag */
2777 tt = proto_tree_add_text(tree, tvb, offset, 0, val_to_str(i++, days, "day of week (%d) not found"));
2778 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2779 offset = fDailySchedule (tvb,subtree,offset);
2786 fUTCTimeSynchronizationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
2788 if (tvb_length_remaining(tvb, offset) <= 0)
2791 return fDateTime (tvb, tree, offset, "UTC-Time: ");
2795 fTimeSynchronizationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
2797 if (tvb_length_remaining(tvb, offset) <= 0)
2800 return fDateTime (tvb, tree, offset, NULL);
2804 fDateRange (tvbuff_t *tvb, proto_tree *tree, guint offset)
2806 if (tvb_length_remaining(tvb, offset) <= 0)
2808 offset = fDate (tvb,tree,offset,"Start Date: ");
2809 return fDate (tvb, tree, offset, "End Date: ");
2813 fConfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2815 guint lastoffset = 0;
2817 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2818 lastoffset = offset;
2819 switch (fTagNo(tvb, offset)) {
2821 case 0: /* textMessageSourceDevice */
2822 offset = fObjectIdentifier (tvb, tree, offset);
2824 case 1: /* messageClass */
2825 switch (fTagNo(tvb, offset)) {
2826 case 0: /* numeric */
2827 offset = fUnsignedTag (tvb, tree, offset, "message Class: ");
2829 case 1: /* character */
2830 offset = fCharacterString (tvb, tree, offset, "message Class: ");
2834 case 2: /* messagePriority */
2835 offset = fEnumeratedTag (tvb, tree, offset, "message Priority: ",
2836 BACnetMessagePriority);
2838 case 3: /* message */
2839 offset = fCharacterString (tvb, tree, offset, "message: ");
2850 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2852 return fConfirmedTextMessageRequest(tvb, tree, offset);
2856 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2858 guint lastoffset = 0;
2859 guint8 tag_no, tag_info;
2861 proto_tree *subtree = tree;
2864 /* exit loop if nothing happens inside */
2865 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
2866 lastoffset = offset;
2867 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2868 if (tag_is_closing(tag_info)) {
2869 if (tag_no == 2) /* Make sure it's the expected tag */
2871 offset += fTagHeaderTree (tvb, subtree, offset,
2872 &tag_no, &tag_info, &lvt);
2878 break; /* End loop if incorrect closing tag */
2883 case 0: /* vendorID */
2884 offset = fUnsignedTag (tvb, subtree, offset, "vendor ID: ");
2886 case 1: /* serviceNumber */
2887 offset = fUnsignedTag (tvb, subtree, offset, "service Number: ");
2889 case 2: /*serviceParameters */
2890 if (tag_is_opening(tag_info)) {
2891 tt = proto_tree_add_text(subtree, tvb, offset, 1, "service Parameters");
2892 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2893 propertyIdentifier = -1;
2894 offset = fAbstractSyntaxNType (tvb, subtree, offset);
2907 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2909 return fConfirmedPrivateTransferRequest(tvb, tree, offset);
2913 fConfirmedPrivateTransferAck(tvbuff_t *tvb, proto_tree *tree, guint offset)
2915 return fConfirmedPrivateTransferRequest(tvb, tree, offset);
2919 fLifeSafetyOperationRequest(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
2921 guint lastoffset = 0;
2922 guint8 tag_no, tag_info;
2924 proto_tree *subtree = tree;
2927 if (label != NULL) {
2928 tt = proto_tree_add_text (subtree, tvb, offset, 1, "%s", label);
2929 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2932 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2933 lastoffset = offset;
2934 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2937 case 0: /* subscriberProcessId */
2938 offset = fUnsignedTag (tvb, subtree, offset, "requesting Process Id: ");
2940 case 1: /* requestingSource */
2941 offset = fCharacterString (tvb, tree, offset, "requesting Source: ");
2943 case 2: /* request */
2944 offset = fEnumeratedTagSplit (tvb, tree, offset,
2945 "request: ", BACnetLifeSafetyOperation, 64);
2947 case 3: /* objectId */
2948 offset = fObjectIdentifier (tvb, subtree, offset);
2958 static guint fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset)
2960 switch (fTagNo(tvb, offset))
2963 offset = fBooleanTag (tvb, tree, offset, "boolean-value: ");
2966 offset = fEnumeratedTagSplit (tvb, tree, offset,
2967 "binary-value: ", BACnetBinaryPV, 2);
2970 offset = fEnumeratedTagSplit (tvb, tree, offset,
2971 "event-type: ", BACnetEventType, 12);
2974 offset = fEnumeratedTagSplit (tvb, tree, offset,
2975 "polarity: ", BACnetPolarity, 2);
2978 offset = fEnumeratedTagSplit (tvb, tree, offset,
2979 "program-change: ", BACnetProgramRequest, 5);
2982 offset = fEnumeratedTagSplit (tvb, tree, offset,
2983 "program-state: ", BACnetProgramState, 5);
2986 offset = fEnumeratedTagSplit (tvb, tree, offset,
2987 "reason-for-halt: ", BACnetProgramError, 5);
2990 offset = fEnumeratedTagSplit (tvb, tree, offset,
2991 "reliability: ", BACnetReliability, 10);
2994 offset = fEnumeratedTagSplit (tvb, tree, offset,
2995 "state: ", BACnetEventState, 64);
2998 offset = fEnumeratedTagSplit (tvb, tree, offset,
2999 "system-status: ", BACnetDeviceStatus, 64);
3002 offset = fEnumeratedTagSplit (tvb, tree, offset,
3003 "units: ", BACnetEngineeringUnits, 2);
3006 offset = fUnsignedTag(tvb, tree, offset, "unsigned-value: ");
3009 offset = fEnumeratedTagSplit (tvb, tree, offset,
3010 "life-safety-mode: ", BACnetLifeSafetyMode, 64);
3013 offset = fEnumeratedTagSplit (tvb, tree, offset,
3014 "life-safety-state: ", BACnetLifeSafetyState, 64);
3023 fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
3025 guint lastoffset = offset;
3026 guint8 tag_no, tag_info;
3028 proto_tree *subtree = tree;
3031 tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters");
3032 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
3033 /* Opeing tag for parameter choice */
3034 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3037 case 0: /* change-of-bitstring */
3038 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3039 lastoffset = offset;
3040 switch (fTagNo(tvb, offset)) {
3042 offset = fBitStringTag (tvb, subtree, offset,
3043 "referenced-bitstring: ");
3046 offset = fBitStringTagVS (tvb, subtree, offset,
3047 "status-flags: ", BACnetStatusFlags);
3054 case 1: /* change-of-state */
3055 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3056 lastoffset = offset;
3057 switch (fTagNo(tvb, offset)) {
3059 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3060 offset = fBACnetPropertyStates(tvb, subtree, offset);
3061 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3063 offset = fBitStringTagVS (tvb, subtree, offset,
3064 "status-flags: ", BACnetStatusFlags);
3065 lastoffset = offset;
3072 case 2: /* change-of-value */
3073 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3074 lastoffset = offset;
3075 switch (fTagNo(tvb, offset)) {
3077 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3078 switch (fTagNo(tvb, offset)) {
3080 offset = fBitStringTag (tvb, subtree, offset,
3084 offset = fRealTag (tvb, subtree, offset,
3090 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3093 offset = fBitStringTagVS (tvb, subtree, offset,
3094 "status-flags: ", BACnetStatusFlags);
3101 case 3: /* command-failure */
3102 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3103 lastoffset = offset;
3104 switch (fTagNo(tvb, offset)) {
3105 case 0: /* "command-value: " */
3106 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3107 offset = fAbstractSyntaxNType (tvb, subtree, offset);
3108 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3111 offset = fBitStringTagVS (tvb, subtree, offset,
3112 "status-flags: ", BACnetStatusFlags);
3113 case 2: /* "feedback-value: " */
3114 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3115 offset = fAbstractSyntaxNType (tvb, subtree, offset);
3116 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3122 case 4: /* floating-limit */
3123 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3124 lastoffset = offset;
3125 switch (fTagNo(tvb, offset)) {
3127 offset = fRealTag (tvb, subtree, offset, "reference-value: ");
3130 offset = fBitStringTagVS (tvb, subtree, offset,
3131 "status-flags: ", BACnetStatusFlags);
3134 offset = fRealTag (tvb, subtree, offset, "setpoint-value: ");
3137 offset = fRealTag (tvb, subtree, offset, "error-limit: ");
3143 case 5: /* out-of-range */
3144 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3145 lastoffset = offset;
3146 switch (fTagNo(tvb, offset)) {
3148 offset = fRealTag (tvb, subtree, offset, "exceeding-value: ");
3151 offset = fBitStringTagVS (tvb, subtree, offset,
3152 "status-flags: ", BACnetStatusFlags);
3155 offset = fRealTag (tvb, subtree, offset, "deadband: ");
3158 offset = fRealTag (tvb, subtree, offset, "exceeded-limit: ");
3165 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3166 lastoffset = offset;
3167 offset =fBACnetPropertyValue (tvb,subtree,offset);
3170 case 7: /* buffer-ready */
3171 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3172 lastoffset = offset;
3173 switch (fTagNo(tvb, offset)) {
3175 offset = fObjectIdentifier (tvb, subtree, offset); /* buffer-device */
3178 offset = fObjectIdentifier (tvb, subtree, offset); /* buffer-object */
3181 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3182 offset = fDateTime (tvb, subtree, offset, "previous-notification: ");
3183 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3186 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3187 offset = fDateTime (tvb, subtree, offset, "current-notification: ");
3188 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3194 case 8: /* change-of-life-safety */
3195 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3196 lastoffset = offset;
3197 switch (fTagNo(tvb, offset)) {
3199 offset = fEnumeratedTagSplit (tvb, subtree, offset,
3200 "new-state: ", BACnetLifeSafetyState, 256);
3203 offset = fEnumeratedTagSplit (tvb, subtree, offset,
3204 "new-mode: ", BACnetLifeSafetyState, 256);
3207 offset = fBitStringTagVS (tvb, subtree, offset,
3208 "status-flags: ", BACnetStatusFlags);
3210 offset = fEnumeratedTagSplit (tvb, subtree, offset,
3211 "operation-expected: ", BACnetLifeSafetyOperation, 64);
3220 /* Closing tag for parameter choice */
3221 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3228 fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
3230 guint lastoffset = 0;
3232 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3233 lastoffset = offset;
3234 switch (fTagNo(tvb, offset)) {
3235 case 0: /* change-of-bitstring */
3236 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3237 lastoffset = offset;
3238 switch (fTagNo(tvb, offset)) {
3240 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3243 offset = fBitStringTag (tvb, tree, offset, "bitmask: ");
3245 case 2: /* SEQUENCE OF BIT STRING */
3246 offset = fBitStringTagVS (tvb, tree, offset,
3247 "bitstring value: ", BACnetEventTransitionBits);
3254 case 1: /* change-of-state */
3255 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3256 lastoffset = offset;
3257 switch (fTagNo(tvb, offset)) {
3259 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3261 case 1: /* SEQUENCE OF BACnetPropertyStates */
3262 offset = fEnumeratedTagSplit (tvb, tree, offset,
3263 "value: ", BACnetPropertyStates, 64);
3270 case 2: /* change-of-value */
3271 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3272 lastoffset = offset;
3273 switch (fTagNo(tvb, offset)) {
3275 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3277 case 1: /* don't loop it, it's a CHOICE */
3278 switch (fTagNo(tvb, offset)) {
3280 offset = fBitStringTag (tvb, tree, offset, "bitmask: ");
3283 offset = fRealTag (tvb, tree, offset,
3284 "referenced Property Increment: ");
3294 case 3: /* command-failure */
3295 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3296 lastoffset = offset;
3297 switch (fTagNo(tvb, offset)) {
3299 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3302 offset = fDeviceObjectPropertyReference (tvb,tree,offset);
3308 case 4: /* floating-limit */
3309 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3310 lastoffset = offset;
3311 switch (fTagNo(tvb, offset)) {
3313 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3316 offset = fDeviceObjectPropertyReference (tvb,tree,offset);
3319 offset = fRealTag (tvb, tree, offset, "low diff limit: ");
3322 offset = fRealTag (tvb, tree, offset, "high diff limit: ");
3325 offset = fRealTag (tvb, tree, offset, "deadband: ");
3332 case 5: /* out-of-range */
3333 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3334 lastoffset = offset;
3335 switch (fTagNo(tvb, offset)) {
3337 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3340 offset = fRealTag (tvb, tree, offset, "low limit: ");
3343 offset = fRealTag (tvb, tree, offset, "high limit: ");
3346 offset = fRealTag (tvb, tree, offset, "deadband: ");
3354 offset = fBACnetPropertyValue (tvb,tree,offset);
3356 case 7: /* buffer-ready */
3357 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3358 lastoffset = offset;
3359 switch (fTagNo(tvb, offset)) {
3361 offset = fUnsignedTag (tvb,tree,offset,"notification threshold");
3364 offset = fUnsignedTag (tvb,tree,offset,
3365 "previous notification count: ");
3372 case 8: /* change-of-life-safety */
3373 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3374 lastoffset = offset;
3375 switch (fTagNo(tvb, offset)) {
3377 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3380 offset = fEnumeratedTagSplit (tvb, tree, offset,
3381 "life safety alarm value: ", BACnetLifeSafetyState, 256);
3384 offset = fEnumeratedTagSplit (tvb, tree, offset,
3385 "alarm value: ", BACnetLifeSafetyState, 256);
3388 offset = fDeviceObjectPropertyReference (tvb, tree, offset);
3403 fLogRecord (tvbuff_t *tvb, proto_tree *tree, guint offset)
3405 guint lastoffset = 0;
3406 guint8 tag_no, tag_info;
3409 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3410 lastoffset = offset;
3411 switch (fTagNo(tvb, offset)) {
3412 case 0: /* timestamp */
3413 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3414 offset = fDateTime (tvb,tree,offset,NULL);
3415 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3417 case 1: /* logDatum: don't loop, it's a CHOICE */
3418 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3419 switch (fTagNo(tvb, offset)) {
3420 case 0: /* logStatus */
3421 offset = fEnumeratedTag (tvb, tree, offset,
3422 "log status: ", BACnetLogStatus);
3425 offset = fBooleanTag (tvb, tree, offset, "boolean-value: ");
3428 offset = fRealTag (tvb, tree, offset, "real value: ");
3431 offset = fUnsignedTag (tvb, tree, offset, "enum value: ");
3434 offset = fUnsignedTag (tvb, tree, offset, "unsigned value: ");
3437 offset = fSignedTag (tvb, tree, offset, "signed value: ");
3440 offset = fBitStringTag (tvb, tree, offset, "bitstring value: ");
3443 offset = fNullTag(tvb, tree, offset, "null value: ");
3446 offset = fError (tvb,tree,offset);
3449 offset = fRealTag (tvb, tree, offset, "time change: ");
3451 case 10: /* any Value */
3452 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3453 offset = fAbstractSyntaxNType (tvb, tree, offset);
3454 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3459 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3462 offset = fEnumeratedTag (tvb, tree, offset,
3463 "status Flags: ", BACnetStatusFlags);
3474 fConfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3476 guint lastoffset = 0;
3477 guint8 tag_no, tag_info;
3480 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3481 lastoffset = offset;
3483 switch (fTagNo(tvb,offset)) {
3484 case 0: /* ProcessId */
3485 offset = fProcessId (tvb,tree,offset);
3487 case 1: /* initiating ObjectId */
3488 offset = fObjectIdentifier (tvb, tree, offset);
3490 case 2: /* event ObjectId */
3491 offset = fObjectIdentifier (tvb, tree, offset);
3493 case 3: /* time stamp */
3494 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3495 offset = fTimeStamp (tvb, tree, offset);
3496 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3498 case 4: /* notificationClass */
3499 offset = fUnsignedTag (tvb, tree, offset, "Notification Class: ");
3501 case 5: /* Priority */
3502 offset = fUnsignedTag (tvb, tree, offset, "Priority: ");
3504 case 6: /* EventType */
3505 offset = fEnumeratedTagSplit (tvb, tree, offset,
3506 "Event Type: ", BACnetEventType, 64);
3508 case 7: /* messageText */
3509 offset = fCharacterString (tvb, tree, offset, "message Text: ");
3511 case 8: /* NotifyType */
3512 offset = fEnumeratedTag (tvb, tree, offset,
3513 "Notify Type: ", BACnetNotifyType);
3515 case 9: /* ackRequired */
3516 offset = fBooleanTag (tvb, tree, offset, "ack Required: ");
3518 case 10: /* fromState */
3519 offset = fEnumeratedTagSplit (tvb, tree, offset,
3520 "from State: ", BACnetEventState, 64);
3522 case 11: /* toState */
3523 offset = fEnumeratedTagSplit (tvb, tree, offset,
3524 "to State: ", BACnetEventState, 64);
3526 case 12: /* NotificationParameters */
3527 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3528 offset = fNotificationParameters (tvb, tree, offset);
3529 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3539 fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3541 return fConfirmedEventNotificationRequest (tvb, tree, offset);
3545 fConfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3547 guint lastoffset = 0;
3548 guint8 tag_no, tag_info;
3550 proto_tree *subtree = tree;
3553 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3554 lastoffset = offset;
3555 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
3556 if (tag_is_closing(tag_info)) {
3557 offset += fTagHeaderTree (tvb, subtree, offset,
3558 &tag_no, &tag_info, &lvt);
3559 lastoffset = offset;
3565 case 0: /* ProcessId */
3566 offset = fProcessId (tvb,tree,offset);
3568 case 1: /* initiating DeviceId */
3569 offset = fObjectIdentifier (tvb, subtree, offset);
3571 case 2: /* monitored ObjectId */
3572 offset = fObjectIdentifier (tvb, subtree, offset);
3574 case 3: /* time remaining */
3575 offset = fTimeSpan (tvb, tree, offset, "Time remaining");
3577 case 4: /* List of Values */
3578 if (tag_is_opening(tag_info)) {
3579 tt = proto_tree_add_text(subtree, tvb, offset, 1, "list of Values");
3580 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
3581 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3582 offset = fBACnetPropertyValue (tvb, subtree, offset);
3596 fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3598 return fConfirmedCOVNotificationRequest (tvb, tree, offset);
3602 fAcknowledgeAlarmRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3604 guint lastoffset = 0;
3605 guint8 tag_no = 0, tag_info = 0;
3608 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3609 lastoffset = offset;
3610 switch (fTagNo(tvb, offset)) {
3611 case 0: /* acknowledgingProcessId */
3612 offset = fUnsignedTag (tvb, tree, offset, "acknowledging Process Id: ");
3614 case 1: /* eventObjectId */
3615 offset = fObjectIdentifier (tvb, tree, offset);
3617 case 2: /* eventStateAcknowledged */
3618 offset = fEnumeratedTagSplit (tvb, tree, offset,
3619 "event State Acknowledged: ", BACnetEventState, 64);
3621 case 3: /* timeStamp */
3622 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
3623 offset = fTimeStamp(tvb, tree, offset);
3624 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
3626 case 4: /* acknowledgementSource */
3627 offset = fCharacterString (tvb, tree, offset, "acknowledgement Source: ");
3629 case 5: /* timeOfAcknowledgement */
3630 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
3631 offset = fTimeStamp(tvb, tree, offset);
3632 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
3643 fGetAlarmSummaryAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3645 guint lastoffset = 0;
3647 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3648 lastoffset = offset;
3649 offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
3650 offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
3651 "alarm State: ", BACnetEventState, 64);
3652 offset = fApplicationTypesEnumerated (tvb, tree, offset,
3653 "acknowledged Transitions: ", BACnetEventTransitionBits);
3659 fGetEnrollmentSummaryRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3661 guint lastoffset = 0;
3662 guint8 tag_no, tag_info;
3665 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3666 lastoffset = offset;
3667 switch (fTagNo(tvb, offset)) {
3668 case 0: /* acknowledgmentFilter */
3669 offset = fEnumeratedTag (tvb, tree, offset,
3670 "acknowledgment Filter: ", BACnetAcknowledgementFilter);
3672 case 1: /* eventObjectId - OPTIONAL */
3673 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3674 offset = fRecipientProcess (tvb, tree, offset);
3675 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3677 case 2: /* eventStateFilter */
3678 offset = fEnumeratedTag (tvb, tree, offset,
3679 "event State Filter: ", BACnetEventStateFilter);
3681 case 3: /* eventTypeFilter - OPTIONAL */
3682 offset = fEnumeratedTag (tvb, tree, offset,
3683 "event Type Filter: ", BACnetEventType);
3685 case 4: /* priorityFilter */
3686 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3687 offset = fUnsignedTag (tvb, tree, offset, "min Priority: ");
3688 offset = fUnsignedTag (tvb, tree, offset, "max Priority: ");
3689 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3691 case 5: /* notificationClassFilter - OPTIONAL */
3692 offset = fUnsignedTag (tvb, tree, offset, "notification Class Filter: ");
3703 fGetEnrollmentSummaryAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3705 guint lastoffset = 0;
3707 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3708 lastoffset = offset;
3709 offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
3710 offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
3711 "event Type: ", BACnetEventType, 64);
3712 offset = fApplicationTypesEnumerated (tvb, tree, offset,
3713 "event State: ", BACnetEventState);
3714 offset = fApplicationTypes (tvb, tree, offset, "Priority: ");
3715 offset = fApplicationTypes (tvb, tree, offset, "Notification Class: ");
3722 fGetEventInformationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3724 if (tvb_length_remaining(tvb, offset) > 0) {
3725 if (fTagNo(tvb, offset) == 0) {
3726 offset = fObjectIdentifier (tvb, tree, offset);
3733 flistOfEventSummaries (tvbuff_t *tvb, proto_tree *tree, guint offset)
3735 guint lastoffset = 0;
3736 guint8 tag_no, tag_info;
3739 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3740 lastoffset = offset;
3741 switch (fTagNo(tvb, offset)) {
3742 case 0: /* ObjectId */
3743 offset = fObjectIdentifier (tvb, tree, offset);
3745 case 1: /* eventState */
3746 offset = fEnumeratedTag (tvb, tree, offset,
3747 "event State: ", BACnetEventStateFilter);
3749 case 2: /* acknowledgedTransitions */
3750 offset = fEnumeratedTag (tvb, tree, offset,
3751 "acknowledged Transitions: ", BACnetEventTransitionBits);
3753 case 3: /* eventTimeStamps */
3754 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3755 offset = fTimeStamp (tvb, tree, offset);
3756 offset = fTimeStamp (tvb, tree, offset);
3757 offset = fTimeStamp (tvb, tree, offset);
3758 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3760 case 4: /* notifyType */
3761 offset = fEnumeratedTag (tvb, tree, offset,
3762 "Notify Type: ", BACnetNotifyType);
3764 case 5: /* eventEnable */
3765 offset = fEnumeratedTag (tvb, tree, offset,
3766 "event Enable: ", BACnetEventTransitionBits);
3768 case 6: /* eventPriorities */
3769 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3770 offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
3771 offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
3772 offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
3773 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3774 lastoffset = offset;
3785 fGetEventInformationACK (tvbuff_t *tvb, proto_tree *tree, guint offset)
3787 guint lastoffset = 0;
3788 guint8 tag_no, tag_info;
3791 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3792 lastoffset = offset;
3793 switch (fTagNo(tvb, offset)) {
3794 case 0: /* listOfEventSummaries */
3795 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3796 offset = flistOfEventSummaries (tvb, tree, offset);
3797 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3799 case 1: /* moreEvents */
3800 offset = fBooleanTag (tvb, tree, offset, "more Events: ");
3811 fAddListElementRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3813 guint lastoffset = 0;
3814 guint8 tag_no, tag_info;
3816 proto_tree *subtree = tree;
3819 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3820 lastoffset = offset;
3821 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
3822 if (tag_is_closing(tag_info)) {
3823 offset += fTagHeaderTree (tvb, subtree, offset,
3824 &tag_no, &tag_info, &lvt);
3830 case 0: /* ObjectId */
3831 offset = fBACnetObjectPropertyReference (tvb, subtree, offset);
3833 case 3: /* listOfElements */
3834 if (tag_is_opening(tag_info)) {
3835 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfElements");
3836 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
3837 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3838 offset = fAbstractSyntaxNType (tvb, subtree, offset);
3852 fDeleteObjectRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3854 return fObjectIdentifier (tvb, tree, offset);
3858 fDeviceCommunicationControlRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3860 guint lastoffset = 0;
3862 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3863 lastoffset = offset;
3865 switch (fTagNo(tvb, offset)) {
3866 case 0: /* timeDuration */
3867 offset = fUnsignedTag (tvb,tree,offset,"time Duration: ");
3869 case 1: /* enable-disable */
3870 offset = fEnumeratedTag (tvb, tree, offset, "enable-disable: ",
3871 BACnetEnableDisable);
3873 case 2: /* password - OPTIONAL */
3874 offset = fCharacterString (tvb, tree, offset, "Password: ");
3885 fReinitializeDeviceRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3887 guint lastoffset = 0;
3889 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3890 lastoffset = offset;
3892 switch (fTagNo(tvb, offset)) {
3893 case 0: /* reinitializedStateOfDevice */
3894 offset = fEnumeratedTag (tvb, tree, offset,
3895 "reinitialized State Of Device: ",
3896 BACnetReinitializedStateOfDevice);
3898 case 1: /* password - OPTIONAL */
3899 offset = fCharacterString (tvb, tree, offset, "Password: ");
3910 fVtOpenRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3912 offset = fApplicationTypesEnumerated (tvb, tree, offset,
3913 "vtClass: ", BACnetVTClass);
3914 return fApplicationTypes (tvb,tree,offset,"local VT Session ID: ");
3918 fVtOpenAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3920 return fApplicationTypes (tvb,tree,offset,"remote VT Session ID: ");
3924 fVtCloseRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3926 guint lastoffset = 0;
3928 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3929 lastoffset = offset;
3930 offset= fApplicationTypes (tvb,tree,offset,"remote VT Session ID: ");
3936 fVtDataRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3938 offset= fApplicationTypes (tvb,tree,offset,"VT Session ID: ");
3939 offset = fApplicationTypes (tvb, tree, offset, "VT New Data: ");
3940 return fApplicationTypes (tvb,tree,offset,"VT Data Flag: ");;
3944 fVtDataAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3946 guint lastoffset = 0;
3948 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3949 lastoffset = offset;
3951 switch (fTagNo(tvb,offset)) {
3952 case 0: /* BOOLEAN */
3953 offset = fBooleanTag (tvb, tree, offset, "all New Data Accepted: ");
3955 case 1: /* Unsigned OPTIONAL */
3956 offset = fUnsignedTag (tvb, tree, offset, "accepted Octet Count: ");
3966 fAuthenticateRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3968 guint lastoffset = 0;
3970 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3971 lastoffset = offset;
3973 switch (fTagNo(tvb,offset)) {
3974 case 0: /* Unsigned32 */
3975 offset = fUnsignedTag (tvb, tree, offset, "pseudo Random Number: ");
3977 case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
3978 proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
3980 case 2: /* Chararacter String OPTIONAL */
3981 offset = fCharacterString (tvb, tree, offset, "operator Name: ");
3983 case 3: /* Chararacter String OPTIONAL */
3984 offset = fCharacterString (tvb, tree, offset, "operator Password: ");
3986 case 4: /* Boolean OPTIONAL */
3987 offset = fBooleanTag (tvb, tree, offset, "start Encyphered Session: ");
3997 fAuthenticateAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3999 return fApplicationTypes (tvb, tree, offset, "modified Random Number: ");
4003 fRequestKeyRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4005 offset = fObjectIdentifier (tvb, tree, offset); /* Requesting Device Identifier */
4006 offset = fAddress (tvb, tree, offset);
4007 offset = fObjectIdentifier (tvb, tree, offset); /* Remote Device Identifier */
4008 return fAddress (tvb, tree, offset);
4012 fRemoveListElementRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4014 /* Same as AddListElement request after service choice */
4015 return fAddListElementRequest(tvb, tree, offset);
4019 fReadPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4021 return fBACnetObjectPropertyReference(tvb, tree, offset);
4025 fReadPropertyAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4027 guint lastoffset = 0;
4028 guint8 tag_no, tag_info;
4030 proto_tree *subtree = tree;
4033 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4034 lastoffset = offset;
4035 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4036 if (tag_is_closing(tag_info)) {
4037 offset += fTagHeaderTree (tvb, subtree, offset,
4038 &tag_no, &tag_info, &lvt);
4043 case 0: /* objectIdentifier */
4044 offset = fObjectIdentifier (tvb, subtree, offset);
4046 case 1: /* propertyIdentifier */
4047 offset = fPropertyIdentifier (tvb, subtree, offset);
4049 case 2: /* propertyArrayIndex */
4050 offset = fSignedTag (tvb, subtree, offset, "property Array Index: ");
4052 case 3: /* propertyValue */
4053 if (tag_is_opening(tag_info)) {
4054 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
4055 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4056 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4057 offset = fAbstractSyntaxNType (tvb, subtree, offset);
4070 fWritePropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4072 guint lastoffset = 0;
4073 guint8 tag_no, tag_info;
4075 proto_tree *subtree = tree;
4078 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4079 lastoffset = offset;
4080 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4081 if (tag_is_closing(tag_info)) {
4082 offset += fTagHeaderTree (tvb, subtree, offset,
4083 &tag_no, &tag_info, &lvt);
4089 case 0: /* objectIdentifier */
4090 offset = fObjectIdentifier (tvb, subtree, offset);
4092 case 1: /* propertyIdentifier */
4093 offset = fPropertyIdentifier (tvb, subtree, offset);
4095 case 2: /* propertyArrayIndex */
4096 offset = fSignedTag (tvb, subtree, offset, "property Array Index: ");
4098 case 3: /* propertyValue */
4099 if (tag_is_opening(tag_info)) {
4100 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
4101 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4102 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4103 offset = fAbstractSyntaxNType (tvb, subtree, offset);
4108 case 4: /* Priority (only used for write) */
4109 offset = fUnsignedTag (tvb, subtree, offset, "Priority: ");
4119 fWriteAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
4121 guint lastoffset = 0;
4122 guint8 tag_no, tag_info;
4125 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4126 lastoffset = offset;
4127 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4128 if (tag_is_closing(tag_info)) {
4129 offset += fTagHeaderTree (tvb, subtree, offset,
4130 &tag_no, &tag_info, &lvt);
4135 case 0: /* objectIdentifier */
4136 offset = fObjectIdentifier (tvb, subtree, offset);
4138 case 1: /* listOfPropertyValues */
4139 if (tag_is_opening(tag_info)) {
4140 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4141 offset = fBACnetPropertyValue (tvb, subtree, offset);
4154 fWritePropertyMultipleRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4156 if (offset >= tvb_reported_length(tvb))
4159 return fWriteAccessSpecification (tvb, tree, offset);
4163 fPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
4165 guint lastoffset = 0;
4166 guint8 tag_no, tag_info;
4169 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4170 lastoffset = offset;
4171 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4172 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
4175 switch (tag_no-tagoffset) {
4176 case 0: /* PropertyIdentifier */
4177 offset = fPropertyIdentifier (tvb, tree, offset);
4179 case 1: /* propertyArrayIndex */
4180 offset = fUnsignedTag (tvb, tree, offset, "property Array Index: ");
4181 if (list != 0) break; /* Continue decoding if this may be a list */
4183 lastoffset = offset; /* Set loop end condition */
4191 fBACnetPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 list)
4193 return fPropertyReference(tvb, tree, offset, 0, list);
4197 fBACnetObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
4199 guint lastoffset = 0;
4201 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4202 lastoffset = offset;
4204 switch (fTagNo(tvb,offset)) {
4205 case 0: /* ObjectIdentifier */
4206 offset = fObjectIdentifier (tvb, tree, offset);
4208 case 1: /* PropertyIdentifier and propertyArrayIndex */
4209 offset = fPropertyReference (tvb, tree, offset, 1, 0);
4211 lastoffset = offset; /* Set loop end condition */
4220 fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
4222 guint lastoffset = 0;
4223 guint8 tag_no, tag_info;
4225 proto_tree* subtree = tree;
4228 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4229 lastoffset = offset;
4230 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4231 if (tag_is_closing(tag_info)) {
4232 offset += fTagHeaderTree (tvb, subtree, offset,
4233 &tag_no, &tag_info, &lvt);
4237 case 0: /* ObjectIdentifier */
4238 offset = fObjectIdentifier (tvb, subtree, offset);
4240 case 1: /* PropertyIdentifier */
4241 offset = fPropertyIdentifier (tvb, subtree, offset);
4243 case 2: /* propertyArrayIndex */
4244 offset = fUnsignedTag (tvb, subtree, offset, "property Array Index: ");
4247 if (tag_is_opening(tag_info)) {
4248 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
4249 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4250 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4251 offset = fAbstractSyntaxNType (tvb, subtree, offset);
4256 case 4: /* Priority */
4257 offset = fUnsignedTag (tvb, subtree, offset, "Priority: ");
4269 fDeviceObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
4271 guint lastoffset = 0;
4273 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4274 lastoffset = offset;
4276 switch (fTagNo(tvb,offset)) {
4277 case 0: /* ObjectIdentifier */
4278 offset = fBACnetObjectPropertyReference (tvb, tree, offset);
4280 case 3: /* deviceIdentifier - OPTIONAL */
4281 offset = fObjectIdentifier (tvb, tree, offset);
4292 fPriorityArray (tvbuff_t *tvb, proto_tree *tree, guint offset)
4296 if (offset >= tvb_reported_length(tvb))
4299 for (i = 1; i <= 16; i++) {
4300 g_snprintf (ar, sizeof(ar), "%s[%d]: ",
4301 val_to_split_str(87 , 512,
4302 BACnetPropertyIdentifier,
4303 ASHRAE_Reserved_Fmt,
4304 Vendor_Proprietary_Fmt),
4306 /* DMR Should be fAbstractNSyntax, but that's where we came from! */
4307 offset = fApplicationTypes(tvb, tree, offset, ar);
4313 fDeviceObjectReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
4315 guint lastoffset = 0;
4317 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4318 lastoffset = offset;
4320 switch (fTagNo(tvb,offset)) {
4321 case 0: /* deviceIdentifier - OPTIONAL */
4322 offset = fObjectIdentifier (tvb, tree, offset);
4324 case 1: /* ObjectIdentifier */
4325 offset = fObjectIdentifier (tvb, tree, offset);
4335 fSpecialEvent (tvbuff_t *tvb, proto_tree *subtree, guint offset)
4337 guint8 tag_no, tag_info;
4339 guint lastoffset = 0;
4341 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4342 lastoffset = offset;
4343 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4344 if (tag_is_closing(tag_info)) {
4349 case 0: /* calendaryEntry */
4350 if (tag_is_opening(tag_info))
4352 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4353 offset = fCalendaryEntry (tvb, subtree, offset);
4354 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4357 case 1: /* calendarReference */
4358 offset = fObjectIdentifier (tvb, subtree, offset);
4360 case 2: /* list of BACnetTimeValue */
4361 if (tag_is_opening(tag_info)) {
4362 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4363 offset = fTimeValue (tvb, subtree, offset);
4364 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4369 case 3: /* eventPriority */
4370 offset = fUnsignedTag (tvb, subtree, offset, "event priority: ");
4380 fSelectionCriteria (tvbuff_t *tvb, proto_tree *tree, guint offset)
4382 guint lastoffset = 0;
4383 guint8 tag_no, tag_info;
4386 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4387 lastoffset = offset;
4388 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4389 if (tag_is_closing(tag_info)) { /* stop when we hit outer closing tag */
4393 switch (fTagNo(tvb,offset)) {
4394 case 0: /* propertyIdentifier */
4395 offset = fPropertyIdentifier (tvb, tree, offset);
4397 case 1: /* propertyArrayIndex */
4398 offset = fUnsignedTag (tvb, tree, offset, "property Array Index: ");
4400 case 2: /* relationSpecifier */
4401 offset = fEnumeratedTag (tvb, tree, offset,
4402 "relation Specifier: ", BACnetRelationSpecifier);
4404 case 3: /* comparisonValue */
4405 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
4406 offset = fAbstractSyntaxNType (tvb, tree, offset);
4407 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
4417 fObjectSelectionCriteria (tvbuff_t *tvb, proto_tree *subtree, guint offset)
4419 guint lastoffset = 0;
4420 guint8 tag_no, tag_info;
4423 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4424 lastoffset = offset;
4425 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4426 if (tag_is_closing(tag_info)) { /* stop when we hit outer closing tag */
4431 case 0: /* selectionLogic */
4432 offset = fEnumeratedTag (tvb, subtree, offset,
4433 "selection Logic: ", BACnetSelectionLogic);
4435 case 1: /* listOfSelectionCriteria */
4436 if (tag_is_opening(tag_info)) {
4437 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4438 offset = fSelectionCriteria (tvb, subtree, offset);
4439 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4453 fReadPropertyConditionalRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
4455 guint lastoffset = 0;
4456 guint8 tag_no, tag_info;
4459 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4460 lastoffset = offset;
4461 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4463 if (tag_is_opening(tag_info) && tag_no < 2) {
4464 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4466 case 0: /* objectSelectionCriteria */
4467 offset = fObjectSelectionCriteria (tvb, subtree, offset);
4469 case 1: /* listOfPropertyReferences */
4470 offset = fBACnetPropertyReference (tvb, subtree, offset, 1);
4475 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4482 fReadAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
4484 guint lastoffset = 0;
4485 guint8 tag_no, tag_info;
4488 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4489 lastoffset = offset;
4490 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4491 if (tag_is_closing(tag_info)) {
4492 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no,
4498 case 0: /* objectIdentifier */
4499 offset = fObjectIdentifier (tvb, subtree, offset);
4501 case 1: /* listOfPropertyReferences */
4502 if (tag_is_opening(tag_info)) {
4503 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4504 offset = fBACnetPropertyReference (tvb, subtree, offset, 1);
4517 fReadAccessResult (tvbuff_t *tvb, proto_tree *tree, guint offset)
4519 guint lastoffset = 0;
4523 proto_tree *subtree = tree;
4526 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4527 lastoffset = offset;
4528 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4529 if (tag_is_closing(tag_info)) {
4530 offset += fTagHeaderTree (tvb, subtree, offset,
4531 &tag_no, &tag_info, &lvt);
4532 if (tag_no == 4 || tag_no == 5) subtree = tree; /* Value and error have extra subtree */
4537 case 0: /* objectSpecifier */
4538 offset = fObjectIdentifier (tvb, subtree, offset);
4540 case 1: /* list of Results */
4541 if (tag_is_opening(tag_info)) {
4542 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfResults");
4543 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4544 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4549 case 2: /* propertyIdentifier */
4550 offset = fPropertyValue(tvb, subtree, offset, 2);
4552 case 5: /* propertyAccessError */
4553 if (tag_is_opening(tag_info)) {
4554 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyAccessError");
4555 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4556 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4557 /* Error Code follows */
4558 offset = fError(tvb, subtree, offset);
4572 fReadPropertyConditionalAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4574 /* listOfReadAccessResults */
4575 return fReadAccessResult (tvb, tree, offset);
4580 fCreateObjectRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
4582 guint lastoffset = 0;
4583 guint8 tag_no, tag_info;
4586 while ((tvb_length_remaining(tvb, offset) > 0) && (offset > lastoffset)) { /* exit loop if nothing happens inside */
4587 lastoffset = offset;
4588 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4592 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4594 case 0: /* objectSpecifier */
4595 switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
4596 case 0: /* objectType */
4597 offset = fEnumeratedTagSplit (tvb, subtree, offset, "Object Type: ", BACnetObjectType, 128);
4599 case 1: /* objectIdentifier */
4600 offset = fObjectIdentifier (tvb, subtree, offset);
4606 case 1: /* propertyValue */
4607 if (tag_is_opening(tag_info)) {
4608 offset = fBACnetPropertyValue (tvb, subtree, offset);
4616 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4623 fCreateObjectAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4625 return fObjectIdentifier (tvb, tree, offset);
4629 fReadRangeRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4631 guint8 tag_no, tag_info;
4633 proto_tree *subtree = tree;
4636 offset = fBACnetObjectPropertyReference(tvb, subtree, offset);
4638 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4639 /* optional range choice */
4640 if (tag_is_opening(tag_info)) {
4641 tt = proto_tree_add_text(subtree, tvb, offset, 1, val_to_str(tag_no, BACnetReadRangeOptions, "unknown range option"));
4642 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4643 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4645 case 3: /* range byPosition */
4646 case 6: /* range bySequenceNumber, 2004 spec */
4647 offset = fApplicationTypes (tvb, subtree, offset, "reference Index: ");
4648 offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
4650 case 4: /* range byTime - deprecated in 2004 */
4651 case 7: /* 2004 spec */
4652 offset = fDateTime(tvb, subtree, offset, "reference Date/Time: ");
4653 offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
4655 case 5: /* range timeRange - deprecated in 2004 */
4656 offset = fDateTime(tvb, subtree, offset, "beginning Time: ");
4657 offset = fDateTime(tvb, subtree, offset, "ending Time: ");
4662 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4668 fReadRangeAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4670 guint8 tag_no, tag_info;
4672 proto_tree *subtree = tree;
4675 offset = fBACnetObjectPropertyReference(tvb, subtree, offset);
4678 offset = fEnumeratedTag (tvb, tree, offset, "result Flags: ", BACnetResultFlags);
4681 offset = fUnsignedTag (tvb, subtree, offset, "item Count: ");
4683 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4685 if (tag_is_opening(tag_info)) {
4686 tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
4687 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4688 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4689 offset = fAbstractSyntaxNType (tvb, subtree, offset);
4690 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4693 if (fTagNo(tvb, offset) == 6) { /* firstSequenceNumber - OPTIONAL */
4694 offset = fUnsignedTag (tvb, subtree, offset, "first Sequence Number: ");
4700 static guint fAccessMethod(tvbuff_t *tvb, proto_tree *tree, guint offset)
4702 guint lastoffset = 0;
4704 guint8 tag_no, tag_info;
4706 proto_tree* subtree = NULL;
4708 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4710 if (tag_is_opening(tag_info))
4712 tt = proto_tree_add_text(tree, tvb, offset, 1, val_to_str(tag_no, BACnetFileAccessOption, "invalid access method"));
4713 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4714 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4715 offset = fApplicationTypes (tvb, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "invalid option"));
4716 offset = fApplicationTypes (tvb, subtree, offset, val_to_str(tag_no, BACnetFileWriteInfo, "unknown option"));
4720 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset))
4721 { /* exit loop if nothing happens inside */
4722 lastoffset = offset;
4723 offset = fApplicationTypes (tvb, subtree, offset, "Record Data: ");
4727 if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0)
4729 /* More Flag is not set, so we can look for closing tag in this segment */
4730 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4731 if (tag_is_closing(tag_info)) {
4732 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4740 fAtomicReadFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4742 guint8 tag_no, tag_info;
4744 proto_tree *subtree = tree;
4747 offset = fObjectIdentifier (tvb, tree, offset);
4749 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4751 if (tag_is_opening(tag_info))
4753 tt = proto_tree_add_text(subtree, tvb, offset, 1, val_to_str(tag_no, BACnetFileAccessOption, "unknown access method"));
4754 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4755 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4756 offset = fSignedTag (tvb, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "unknown option"));
4757 offset = fUnsignedTag (tvb, subtree, offset, val_to_str(tag_no, BACnetFileRequestCount, "unknown option"));
4758 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4764 fAtomicWriteFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4767 offset = fObjectIdentifier (tvb, tree, offset); /* file Identifier */
4768 offset = fAccessMethod(tvb, tree, offset);
4774 fAtomicWriteFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4776 guint tag_no = fTagNo(tvb, offset);
4777 return fSignedTag (tvb, tree, offset, val_to_str(tag_no, BACnetFileStartOption, "unknown option"));
4781 fAtomicReadFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4783 offset = fApplicationTypes (tvb, tree, offset, "End Of File: ");
4784 offset = fAccessMethod(tvb, tree, offset);
4790 fReadPropertyMultipleRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
4792 return fReadAccessSpecification (tvb,subtree,offset);
4796 fReadPropertyMultipleAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4798 return fReadAccessResult (tvb,tree,offset);
4802 fConfirmedServiceRequest (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
4804 if (tvb_length_remaining(tvb,offset) <= 0)
4807 switch (service_choice) {
4808 case 0: /* acknowledgeAlarm */
4809 offset = fAcknowledgeAlarmRequest (tvb, tree, offset);
4811 case 1: /* confirmedCOVNotification */
4812 offset = fConfirmedCOVNotificationRequest (tvb, tree, offset);
4814 case 2: /* confirmedEventNotification */
4815 offset = fConfirmedEventNotificationRequest (tvb, tree, offset);
4817 case 3: /* confirmedGetAlarmSummary conveys no parameters */
4819 case 4: /* getEnrollmentSummaryRequest */
4820 offset = fGetEnrollmentSummaryRequest (tvb, tree, offset);
4822 case 5: /* subscribeCOVRequest */
4823 offset = fSubscribeCOVRequest(tvb, tree, offset);
4825 case 6: /* atomicReadFile-Request */
4826 offset = fAtomicReadFileRequest(tvb, tree, offset);
4828 case 7: /* atomicWriteFile-Request */
4829 offset = fAtomicWriteFileRequest(tvb, tree, offset);
4831 case 8: /* AddListElement-Request */
4832 offset = fAddListElementRequest(tvb, tree, offset);
4834 case 9: /* removeListElement-Request */
4835 offset = fRemoveListElementRequest(tvb, tree, offset);
4837 case 10: /* createObjectRequest */
4838 offset = fCreateObjectRequest(tvb, tree, offset);
4840 case 11: /* deleteObject */
4841 offset = fDeleteObjectRequest(tvb, tree, offset);
4844 offset = fReadPropertyRequest(tvb, tree, offset);
4847 offset = fReadPropertyConditionalRequest(tvb, tree, offset);
4850 offset = fReadPropertyMultipleRequest(tvb, tree, offset);
4853 offset = fWritePropertyRequest(tvb, tree, offset);
4856 offset = fWritePropertyMultipleRequest(tvb, tree, offset);
4859 offset = fDeviceCommunicationControlRequest(tvb, tree, offset);
4862 offset = fConfirmedPrivateTransferRequest(tvb, tree, offset);
4865 offset = fConfirmedTextMessageRequest(tvb, tree, offset);
4868 offset = fReinitializeDeviceRequest(tvb, tree, offset);
4871 offset = fVtOpenRequest(tvb, tree, offset);
4874 offset = fVtCloseRequest (tvb, tree, offset);
4877 offset = fVtDataRequest (tvb, tree, offset);
4880 offset = fAuthenticateRequest (tvb, tree, offset);
4883 offset = fRequestKeyRequest (tvb, tree, offset);
4886 offset = fReadRangeRequest (tvb, tree, offset);
4889 offset = fLifeSafetyOperationRequest(tvb, tree, offset, NULL);
4892 offset = fSubscribeCOVPropertyRequest(tvb, tree, offset);
4895 offset = fGetEventInformationRequest (tvb, tree, offset);
4905 fConfirmedServiceAck (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
4907 if (tvb_length_remaining(tvb,offset) <= 0)
4910 switch (service_choice) {
4911 case 3: /* confirmedEventNotificationAck */
4912 offset = fGetAlarmSummaryAck (tvb, tree, offset);
4914 case 4: /* getEnrollmentSummaryAck */
4915 offset = fGetEnrollmentSummaryAck (tvb, tree, offset);
4917 case 6: /* atomicReadFile */
4918 offset = fAtomicReadFileAck (tvb, tree, offset);
4920 case 7: /* atomicReadFileAck */
4921 offset = fAtomicWriteFileAck (tvb, tree, offset);
4923 case 10: /* createObject */
4924 offset = fCreateObjectAck (tvb, tree, offset);
4927 offset = fReadPropertyAck (tvb, tree, offset);
4930 offset = fReadPropertyConditionalAck (tvb, tree, offset);
4933 offset = fReadPropertyMultipleAck (tvb, tree, offset);
4936 offset = fConfirmedPrivateTransferAck(tvb, tree, offset);
4939 offset = fVtOpenAck (tvb, tree, offset);
4942 offset = fVtDataAck (tvb, tree, offset);
4945 offset = fAuthenticateAck (tvb, tree, offset);
4948 offset = fReadRangeAck (tvb, tree, offset);
4951 offset = fGetEventInformationACK (tvb, tree, offset);
4960 fIAmRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4962 /* BACnetObjectIdentifier */
4963 offset = fApplicationTypes (tvb, tree, offset, "BACnet Object Identifier: ");
4965 /* MaxAPDULengthAccepted */
4966 offset = fApplicationTypes (tvb, tree, offset, "Maximum ADPU Length Accepted: ");
4968 /* segmentationSupported */
4969 offset = fApplicationTypesEnumerated (tvb, tree, offset,
4970 "Segmentation Supported: ", BACnetSegmentation);
4973 return fUnsignedTag (tvb, tree, offset, "Vendor ID: ");
4977 fIHaveRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4979 /* BACnetDeviceIdentifier */
4980 offset = fApplicationTypes (tvb, tree, offset, "Device Identifier: ");
4982 /* BACnetObjectIdentifier */
4983 offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
4986 return fApplicationTypes (tvb, tree, offset, "Object Name: ");
4991 fWhoIsRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4993 guint lastoffset = 0;
4995 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4996 lastoffset = offset;
4997 switch (fTagNo(tvb, offset)) {
4998 case 0: /* DeviceInstanceRangeLowLimit Optional */
4999 offset = fUnsignedTag (tvb, tree, offset, "Device Instance Range Low Limit: ");
5001 case 1: /* DeviceInstanceRangeHighLimit Optional but required if DeviceInstanceRangeLowLimit is there */
5002 offset = fUnsignedTag (tvb, tree, offset, "Device Instance Range High Limit: ");
5013 fUnconfirmedServiceRequest (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
5015 if (tvb_length_remaining(tvb,offset) <= 0)
5018 switch (service_choice) {
5019 case 0: /* I-Am-Request */
5020 offset = fIAmRequest (tvb, tree, offset);
5022 case 1: /* i-Have Request */
5023 offset = fIHaveRequest (tvb, tree, offset);
5025 case 2: /* unconfirmedCOVNotification */
5026 offset = fUnconfirmedCOVNotificationRequest (tvb, tree, offset);
5028 case 3: /* unconfirmedEventNotification */
5029 offset = fUnconfirmedEventNotificationRequest (tvb, tree, offset);
5031 case 4: /* unconfirmedPrivateTransfer */
5032 offset = fUnconfirmedPrivateTransferRequest(tvb, tree, offset);
5034 case 5: /* unconfirmedTextMessage */
5035 offset = fUnconfirmedTextMessageRequest(tvb, tree, offset);
5037 case 6: /* timeSynchronization */
5038 offset = fTimeSynchronizationRequest (tvb, tree, offset);
5040 case 7: /* who-Has */
5041 offset = fWhoHas (tvb, tree, offset);
5043 case 8: /* who-Is */
5044 offset = fWhoIsRequest (tvb, tree, offset);
5046 case 9: /* utcTimeSynchronization */
5047 offset = fUTCTimeSynchronizationRequest (tvb, tree, offset);
5056 fStartConfirmed(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset, guint8 ack,
5057 gint *svc, proto_item **tt)
5060 proto_tree *bacapp_tree_control;
5061 gint tmp, bacapp_type;
5065 tmp = (gint) tvb_get_guint8(tvb, offset);
5066 bacapp_type = (tmp >> 4) & 0x0f;
5067 bacapp_flags = tmp & 0x0f;
5072 *svc = (gint) tvb_get_guint8(tvb, offset+extra);
5073 if (bacapp_flags & 0x08)
5074 *svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
5076 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
5077 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, TRUE);
5078 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
5080 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, TRUE);
5081 proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, TRUE);
5082 if (ack == 0) /* The following are for ConfirmedRequest, not Complex ack */
5084 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, TRUE);
5085 proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
5087 proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
5091 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
5092 if (bacapp_flags & 0x08) {
5093 bacapp_seq = tvb_get_guint8(tvb, offset);
5094 proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
5096 proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
5099 *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
5105 fConfirmedRequestPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5106 { /* BACnet-Confirmed-Request */
5107 /* ASHRAE 135-2001 20.1.2 */
5111 offset = fStartConfirmed(tvb, bacapp_tree, offset, 0, &svc, &tt);
5112 if (bacapp_seq > 0) /* Can't handle continuation segments, so just treat as data */
5114 proto_tree_add_text(bacapp_tree, tvb, offset, 0, "(continuation)");
5119 /* Service Request follows... Variable Encoding 20.2ff */
5120 return fConfirmedServiceRequest (tvb, bacapp_tree, offset, svc);
5125 fUnconfirmedRequestPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5126 { /* BACnet-Unconfirmed-Request-PDU */
5127 /* ASHRAE 135-2001 20.1.3 */
5131 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
5133 tmp = tvb_get_guint8(tvb, offset);
5134 proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
5136 /* Service Request follows... Variable Encoding 20.2ff */
5137 return fUnconfirmedServiceRequest (tvb, bacapp_tree, offset, tmp);
5141 fSimpleAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5142 { /* BACnet-Simple-Ack-PDU */
5143 /* ASHRAE 135-2001 20.1.4 */
5147 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
5149 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5151 proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
5157 fComplexAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5158 { /* BACnet-Complex-Ack-PDU */
5159 /* ASHRAE 135-2001 20.1.5 */
5163 offset = fStartConfirmed(tvb, bacapp_tree, offset, 1, &svc, &tt);
5165 if (bacapp_seq > 0) /* Can't handle continuation segments, so just treat as data */
5167 proto_tree_add_text(bacapp_tree, tvb, offset, 0, "(continuation)");
5172 /* Service ACK follows... */
5173 return fConfirmedServiceAck (tvb, bacapp_tree, offset, svc);
5179 fSegmentAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5180 { /* BACnet-SegmentAck-PDU */
5181 /* ASHRAE 135-2001 20.1.6 */
5184 proto_tree *bacapp_tree_control;
5186 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
5187 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
5189 proto_tree_add_item(bacapp_tree, hf_bacapp_NAK, tvb, offset, 1, TRUE);
5190 proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
5191 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5193 proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
5195 proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
5200 static guint fContextTaggedError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5202 guint8 tag_info = 0;
5203 guint8 parsed_tag = 0;
5205 offset += fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
5206 offset = fError(tvb, tree, offset);
5207 return offset + fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
5211 fConfirmedPrivateTransferError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5213 guint lastoffset = 0;
5214 guint8 tag_no = 0, tag_info = 0;
5217 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
5218 lastoffset = offset;
5219 switch (fTagNo(tvb, offset)) {
5220 case 0: /* errorType */
5221 offset = fContextTaggedError(tvb,tree,offset);
5223 case 1: /* vendorID */
5224 offset = fUnsignedTag (tvb,tree,offset,"vendor ID: ");
5226 case 2: /* serviceNumber */
5227 offset = fUnsignedTag (tvb,tree,offset,"service Number: ");
5229 case 3: /* errorParameters */
5230 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
5231 offset = fAbstractSyntaxNType (tvb, tree, offset);
5232 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
5242 fCreateObjectError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5244 guint lastoffset = 0;
5246 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
5247 lastoffset = offset;
5248 switch (fTagNo(tvb, offset)) {
5249 case 0: /* errorType */
5250 offset = fContextTaggedError(tvb,tree,offset);
5252 case 1: /* firstFailedElementNumber */
5253 offset = fUnsignedTag (tvb,tree,offset,"first failed element number: ");
5263 fChangeListError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5265 /* Identical to CreateObjectError */
5266 return fCreateObjectError(tvb, tree, offset);
5270 fVTCloseError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5272 guint8 tag_no = 0, tag_info = 0;
5275 if (fTagNo(tvb, offset) == 0)
5278 offset = fContextTaggedError(tvb,tree,offset);
5279 if (fTagNo(tvb, offset) == 1)
5281 /* listOfVTSessionIdentifiers [OPTIONAL] */
5282 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
5283 offset = fVtCloseRequest (tvb, tree, offset);
5284 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
5287 /* should report bad packet if initial tag wasn't 0 */
5292 fWritePropertyMultipleError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5294 guint lastoffset = 0;
5295 guint8 tag_no = 0, tag_info = 0;
5298 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
5299 lastoffset = offset;
5300 switch (fTagNo(tvb, offset)) {
5301 case 0: /* errorType */
5302 offset = fContextTaggedError(tvb,tree,offset);
5304 case 1: /* firstFailedWriteAttempt */
5305 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
5306 offset = fBACnetObjectPropertyReference(tvb, tree, offset);
5307 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
5317 fError (tvbuff_t *tvb, proto_tree *tree, guint offset)
5319 offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
5320 "error Class: ", BACnetErrorClass, 64);
5321 return fApplicationTypesEnumeratedSplit (tvb, tree, offset,
5322 "error Code: ", BACnetErrorCode, 256);
5326 fBACnetError (tvbuff_t *tvb, proto_tree *tree, guint offset, guint service)
5329 case 8: /* no break here !!!! */
5331 offset = fChangeListError (tvb, tree, offset);
5334 offset = fCreateObjectError (tvb,tree,offset);
5337 offset = fWritePropertyMultipleError (tvb,tree,offset);
5340 offset = fConfirmedPrivateTransferError (tvb,tree,offset);
5342 offset = fVTCloseError (tvb,tree,offset);
5344 return fError (tvb, tree, offset);
5351 fErrorPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5352 { /* BACnet-Error-PDU */
5353 /* ASHRAE 135-2001 20.1.7 */
5355 proto_item *tc, *tt;
5356 proto_tree *bacapp_tree_control;
5359 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
5360 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
5362 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5364 tmp = tvb_get_guint8(tvb, offset);
5365 tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
5367 /* Error Handling follows... */
5368 return fBACnetError (tvb, bacapp_tree, offset, tmp);
5372 fRejectPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5373 { /* BACnet-Reject-PDU */
5374 /* ASHRAE 135-2001 20.1.8 */
5377 proto_tree *bacapp_tree_control;
5379 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
5380 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
5382 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5384 proto_tree_add_item(bacapp_tree, hf_BACnetRejectReason, tvb,
5390 fAbortPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5391 { /* BACnet-Abort-PDU */
5392 /* ASHRAE 135-2001 20.1.9 */
5395 proto_tree *bacapp_tree_control;
5397 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
5398 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
5400 proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
5401 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5403 proto_tree_add_item(bacapp_tree, hf_BACnetAbortReason, tvb,
5409 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5411 gint8 tmp, bacapp_type;
5414 guint8 bacapp_service, bacapp_reason;
5415 guint8 bacapp_invoke_id;
5417 proto_tree *bacapp_tree;
5419 if (check_col(pinfo->cinfo, COL_PROTOCOL))
5420 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
5421 if (check_col(pinfo->cinfo, COL_INFO))
5422 col_add_str(pinfo->cinfo, COL_INFO, "BACnet APDU ");
5424 tmp = (gint) tvb_get_guint8(tvb, 0);
5425 bacapp_type = (tmp >> 4) & 0x0f;
5427 /* show some descriptive text in the INFO column */
5428 if (check_col(pinfo->cinfo, COL_INFO))
5430 col_clear(pinfo->cinfo, COL_INFO);
5431 col_add_str(pinfo->cinfo, COL_INFO,
5432 val_to_str(bacapp_type, BACnetTypeName, "#### unknown APDU ##### "));
5433 switch (bacapp_type)
5435 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
5436 /* segmented messages have 2 additional bytes */
5437 if (tmp & BACAPP_SEGMENTED_REQUEST)
5439 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 4);
5440 bacapp_service = tvb_get_guint8(tvb, offset + 5);
5444 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
5445 bacapp_service = tvb_get_guint8(tvb, offset + 3);
5447 col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
5449 val_to_str(bacapp_service,
5450 BACnetConfirmedServiceChoice,
5451 bacapp_unknown_service_str));
5453 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
5454 bacapp_service = tvb_get_guint8(tvb, offset + 1);
5455 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
5456 val_to_str(bacapp_service,
5457 BACnetUnconfirmedServiceChoice,
5458 bacapp_unknown_service_str));
5460 case BACAPP_TYPE_SIMPLE_ACK:
5461 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
5462 bacapp_service = tvb_get_guint8(tvb, offset + 2);
5463 col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
5465 val_to_str(bacapp_service,
5466 BACnetConfirmedServiceChoice,
5467 bacapp_unknown_service_str));
5469 case BACAPP_TYPE_COMPLEX_ACK:
5470 /* segmented messages have 2 additional bytes */
5471 if (tmp & BACAPP_SEGMENTED_REQUEST)
5473 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 3);
5474 bacapp_service = tvb_get_guint8(tvb, offset + 4);
5478 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
5479 bacapp_service = tvb_get_guint8(tvb, offset + 2);
5481 col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
5483 val_to_str(bacapp_service,
5484 BACnetConfirmedServiceChoice,
5485 bacapp_unknown_service_str));
5487 case BACAPP_TYPE_SEGMENT_ACK:
5488 /* nothing more to add */
5490 case BACAPP_TYPE_ERROR:
5491 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
5492 bacapp_service = tvb_get_guint8(tvb, offset + 2);
5493 col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
5495 val_to_str(bacapp_service,
5496 BACnetConfirmedServiceChoice,
5497 bacapp_unknown_service_str));
5499 case BACAPP_TYPE_REJECT:
5500 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
5501 bacapp_reason = tvb_get_guint8(tvb, offset + 2);
5502 col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
5504 val_to_split_str(bacapp_reason,
5507 ASHRAE_Reserved_Fmt,
5508 Vendor_Proprietary_Fmt));
5510 case BACAPP_TYPE_ABORT:
5511 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
5512 bacapp_reason = tvb_get_guint8(tvb, offset + 2);
5513 col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
5515 val_to_split_str(bacapp_reason,
5518 ASHRAE_Reserved_Fmt,
5519 Vendor_Proprietary_Fmt));
5523 /* nothing more to add */
5529 ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE);
5530 bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
5532 /* ASHRAE 135-2001 20.1.1 */
5533 switch (bacapp_type) {
5534 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
5535 offset = fConfirmedRequestPDU(tvb, bacapp_tree, offset);
5537 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST: /* BACnet-Unconfirmed-Request-PDU */
5538 offset = fUnconfirmedRequestPDU(tvb, bacapp_tree, offset);
5540 case BACAPP_TYPE_SIMPLE_ACK: /* BACnet-Simple-Ack-PDU */
5541 offset = fSimpleAckPDU(tvb, bacapp_tree, offset);
5543 case BACAPP_TYPE_COMPLEX_ACK: /* BACnet-Complex-Ack-PDU */
5544 offset = fComplexAckPDU(tvb, bacapp_tree, offset);
5546 case BACAPP_TYPE_SEGMENT_ACK: /* BACnet-SegmentAck-PDU */
5547 offset = fSegmentAckPDU(tvb, bacapp_tree, offset);
5549 case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
5550 offset = fErrorPDU(tvb, bacapp_tree, offset);
5552 case BACAPP_TYPE_REJECT: /* BACnet-Reject-PDU */
5553 offset = fRejectPDU(tvb, bacapp_tree, offset);
5555 case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
5556 offset = fAbortPDU(tvb, bacapp_tree, offset);
5561 next_tvb = tvb_new_subset(tvb,offset,-1,tvb_length_remaining(tvb,offset));
5562 call_dissector(data_handle,next_tvb, pinfo, tree);
5566 proto_register_bacapp(void)
5568 static hf_register_info hf[] = {
5570 { "APDU Type", "bacapp.type",
5571 FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, "APDU Type", HFILL }
5573 { &hf_bacapp_pduflags,
5574 { "PDU Flags", "bacapp.pduflags",
5575 FT_UINT8, BASE_HEX, NULL, 0x0f, "PDU Flags", HFILL }
5578 { "Segmented Request", "bacapp.segmented_request",
5579 FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, "Segmented Request", HFILL }
5582 { "More Segments", "bacapp.more_segments",
5583 FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
5586 { "SA", "bacapp.SA",
5587 FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
5589 { &hf_bacapp_max_adpu_size,
5590 { "Size of Maximum ADPU accepted", "bacapp.max_adpu_size",
5591 FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, "Size of Maximum ADPU accepted", HFILL }
5593 { &hf_bacapp_response_segments,
5594 { "Max Response Segments accepted", "bacapp.response_segments",
5595 FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, "Max Response Segments accepted", HFILL }
5597 { &hf_bacapp_objectType,
5598 { "Object Type", "bacapp.objectType",
5599 FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, "Object Type", HFILL }
5601 { &hf_bacapp_instanceNumber,
5602 { "Instance Number", "bacapp.instance_number",
5603 FT_UINT32, BASE_DEC, NULL, 0x003fffff, "Instance Number", HFILL }
5605 { &hf_bacapp_invoke_id,
5606 { "Invoke ID", "bacapp.invoke_id",
5607 FT_UINT8, BASE_DEC, NULL, 0, "Invoke ID", HFILL }
5609 { &hf_bacapp_sequence_number,
5610 { "Sequence Number", "bacapp.sequence_number",
5611 FT_UINT8, BASE_DEC, NULL, 0, "Sequence Number", HFILL }
5613 { &hf_bacapp_window_size,
5614 { "Proposed Window Size", "bacapp.window_size",
5615 FT_UINT8, BASE_DEC, NULL, 0, "Proposed Window Size", HFILL }
5617 { &hf_bacapp_service,
5618 { "Service Choice", "bacapp.confirmed_service",
5619 FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, "Service Choice", HFILL }
5621 { &hf_bacapp_uservice,
5622 { "Unconfirmed Service Choice", "bacapp.unconfirmed_service",
5623 FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, "Unconfirmed Service Choice", HFILL }
5626 { "NAK", "bacapp.NAK",
5627 FT_BOOLEAN, 8, NULL, 0x02, "negativ ACK", HFILL }
5630 { "SRV", "bacapp.SRV",
5631 FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
5633 { &hf_BACnetRejectReason,
5634 { "Reject Reason", "bacapp.reject_reason",
5635 FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, "Reject Reason", HFILL }
5637 { &hf_BACnetAbortReason,
5638 { "Abort Reason", "bacapp.abort_reason",
5639 FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, "Abort Reason", HFILL }
5642 { "BACnet APDU variable part:", "bacapp.variable_part",
5643 FT_NONE, 0, NULL, 0, "BACnet APDU variable part", HFILL }
5648 FT_BYTES, BASE_HEX, NULL, 0,
5649 "BACnet Tag", HFILL }
5651 { &hf_BACnetApplicationTagNumber,
5652 { "Application Tag Number",
5653 "bacapp.application_tag_number",
5654 FT_UINT8, BASE_DEC, VALS(&BACnetApplicationTagNumber), 0xF0,
5655 "Application Tag Number", HFILL }
5657 { &hf_BACnetContextTagNumber,
5658 { "Context Tag Number",
5659 "bacapp.context_tag_number",
5660 FT_UINT8, BASE_DEC, NULL, 0xF0,
5661 "Context Tag Number", HFILL }
5663 { &hf_BACnetExtendedTagNumber,
5664 { "Extended Tag Number",
5665 "bacapp.extended_tag_number",
5666 FT_UINT8, BASE_DEC, NULL, 0,
5667 "Extended Tag Number", HFILL }
5669 { &hf_BACnetNamedTag,
5672 FT_UINT8, BASE_DEC, VALS(&BACnetTagNames), 0x07,
5673 "Named Tag", HFILL }
5675 { &hf_BACnetCharacterSet,
5676 { "String Character Set",
5677 "bacapp.string_character_set",
5678 FT_UINT8, BASE_DEC, VALS(&BACnetCharacterSet),0,
5679 "String Character Set", HFILL }
5681 { &hf_BACnetTagClass,
5682 { "Tag Class", "bacapp.tag_class",
5683 FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, "Tag Class", HFILL }
5685 { &hf_bacapp_tag_lvt,
5686 { "Length Value Type",
5688 FT_UINT8, BASE_DEC, NULL, 0,
5689 "Length Value Type", HFILL }
5691 { &hf_bacapp_tag_value8,
5693 "bacapp.tag_value8",
5694 FT_UINT8, BASE_DEC, NULL, 0,
5695 "Tag Value", HFILL }
5697 { &hf_bacapp_tag_value16,
5698 { "Tag Value 16-bit",
5699 "bacapp.tag_value16",
5700 FT_UINT16, BASE_DEC, NULL, 0,
5701 "Tag Value 16-bit", HFILL }
5703 { &hf_bacapp_tag_value32,
5704 { "Tag Value 32-bit",
5705 "bacapp.tag_value32",
5706 FT_UINT32, BASE_DEC, NULL, 0,
5707 "Tag Value 32-bit", HFILL }
5709 { &hf_bacapp_tag_ProcessId,
5710 { "ProcessIdentifier", "bacapp.processId",
5711 FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
5713 { &hf_bacapp_tag_initiatingObjectType,
5714 { "ObjectType", "bacapp.objectType",
5715 FT_UINT16, BASE_DEC, VALS(BACnetObjectType), 0x00, "Object Type", HFILL }
5718 static gint *ett[] = {
5720 &ett_bacapp_control,
5725 proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
5726 "BACapp", "bacapp");
5728 proto_register_field_array(proto_bacapp, hf, array_length(hf));
5729 proto_register_subtree_array(ett, array_length(ett));
5730 register_dissector("bacapp", dissect_bacapp, proto_bacapp);
5735 proto_reg_handoff_bacapp(void)
5737 data_handle = find_dissector("data");
5741 fConvertXXXtoUTF8 (const guint8 *in, size_t *inbytesleft, guint8 *out, size_t *outbytesleft, const gchar *fromcoding)
5742 { /* I don't want to let in and out be modified */
5743 #ifdef HAVE_CONFIG_H
5747 const char *inp = in;
5749 const char **inpp = &inp;
5750 guint8 **outpp = &outp;
5752 if ((icd = iconv_open ("UTF-8", fromcoding)) != (iconv_t) -1) {
5753 i = iconv (icd, (char**) inpp, inbytesleft, (char**) outpp, outbytesleft);
5762 memcpy (out, in, *inbytesleft);
5763 out[*inbytesleft] = '\0';
5764 *outbytesleft -= *inbytesleft;