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 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@ethereal.com>
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 static const value_string
160 BACnetAbortReason [] = {
162 {1,"buffer-overflow"},
163 {2,"invalid-apdu-in-this-state"},
164 {3,"preempted-by-higher-priority-task"},
165 {4,"segmentation-not-supported"},
169 static const value_string
170 BACnetLifeSafetyMode [] = {
184 {13,"atomic-release-disabled"},
187 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
188 Enumerated values 256-65535 may be used by others subject to
189 procedures and constraints described in Clause 23. */
192 static const value_string
193 BACnetLifeSafetyOperation [] = {
196 {2,"silence-audible"},
197 {3,"silence-visual"},
202 {8,"unsilence-audible"},
203 {9,"unsilence-visual"},
205 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
206 Enumerated values 64-65535 may be used by others subject to
207 procedures and constraints described in Clause 23. */
210 static const value_string
211 BACnetLimitEnable [] = {
212 {0,"lowLimitEnable"},
213 {1,"highLimitEnable"},
217 static const value_string
218 BACnetLifeSafetyState [] = {
223 {4,"fault-pre-alarm"},
231 {12,"test-fault-alarm"},
236 {17,"emergency-power"},
240 {21,"general-alarm"},
242 {23,"test-supervisory"},
244 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
245 Enumerated values 256-65535 may be used by others subject to
246 procedures and constraints described in Clause 23. */
249 static const value_string
250 BACnetConfirmedServiceChoice [] = {
251 {0,"acknowledgeAlarm"},
252 {1,"confirmedCOVNotification"},
253 {2,"confirmedEventNotification"},
254 {3,"getAlarmSummary"},
255 {4,"getEnrollmentSummary"},
257 {6,"atomicReadFile"},
258 {7,"atomicWriteFile"},
259 {8,"addListElement"},
260 {9,"removeListElement"},
264 {13,"readPropertyConditional"},
265 {14,"readPropertyMultiple"},
266 {15,"writeProperty"},
267 {16,"writePropertyMultiple"},
268 {17,"deviceCommunicationControl"},
269 {18,"confirmedPrivateTransfer"},
270 {19,"confirmedTextMessage"},
271 {20,"reinitializeDevice"},
278 {27,"lifeSafetyOperation"},
279 {28,"subscribeCOVProperty"},
280 {29,"getEventInformation"},
281 {30,"reserved by ASHRAE"},
285 static const value_string
286 BACnetReliability [] = {
287 {0,"no-fault-detected"},
294 {7,"unreliable-other"},
296 {9,"multi-state-fault"},
300 static const value_string
301 BACnetUnconfirmedServiceChoice [] = {
304 {2,"unconfirmedCOVNotification"},
305 {3,"unconfirmedEventNotification"},
306 {4,"unconfirmedPrivateTransfer"},
307 {5,"unconfirmedTextMessage"},
308 {6,"timeSynchronization"},
311 {9,"utcTimeSynchonization"},
315 static const value_string
316 BACnetUnconfirmedServiceRequest [] = {
318 {1,"i-Have-Request"},
319 {2,"unconfirmedCOVNotification-Request"},
320 {3,"unconfirmedEventNotification-Request"},
321 {4,"unconfirmedPrivateTransfer-Request"},
322 {5,"unconfirmedTextMessage-Request"},
323 {6,"timeSynchronization-Request"},
324 {7,"who-Has-Request"},
325 {8,"who-Is-Request"},
326 {9,"utcTimeSynchonization-Request"},
330 static const value_string
331 BACnetObjectType [] = {
332 {0,"analog-input object"},
333 {1,"analog-output object"},
334 {2,"analog-value object"},
335 {3,"binary-input object"},
336 {4,"binary-output object"},
337 {5,"binary-value object"},
338 {6,"calendar object"},
339 {7,"command object"},
341 {9,"event-enrollment object"},
345 {13,"multi-state-input object"},
346 {14,"multi-state-output object"},
347 {15,"notification-class object"},
348 {16,"program object"},
349 {17,"schedule object"},
350 {18,"averaging object"},
351 {19,"multi-state-value object"},
352 {20,"trend-log object"},
353 {21,"life-safety-point object"},
354 {22,"life-safety-zone object"},
355 {23,"accumulator object"},
356 {24,"pulse-converter object"},
358 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
359 Enumerated values 128-1023 may be used by others subject to
360 the procedures and constraints described in Clause 23. */
363 static const value_string
364 BACnetEngineeringUnits [] = {
374 {9,"Kilovolt Amperes"},
375 {10,"Megavolt Amperes"},
376 {11,"Volt Amperes Reactive"},
377 {12,"Kilovolt Amperes Reactive"},
378 {13,"Megavolt Amperes Ractive"},
379 {14,"Degrees Phase"},
384 {19,"Kilowatt Hours"},
388 {23,"Joules Per Kg Dry Air"},
389 {24,"BTUs Per Pound Dry Air"},
390 {25,"Cycles Per Hour"},
391 {26,"Cycles Per Minute"},
393 {28,"Gramms Of Water Per Kilogram Dry Air"},
394 {29,"Relative Humidity"},
399 {34,"Watts Per Sq Foot"},
400 {35,"Watts Per Sq meter"},
407 {42,"Kgs per Second"},
408 {43,"Kgs Per Minute"},
410 {45,"Pounds Mass Per Minute"},
411 {46,"Pounds Mass Per Hour"},
415 {50,"BTUs Per Hour"},
417 {52,"Tons Refrigeration"},
421 {56,"Pounds Force Per Square Inch"},
422 {57,"Centimeters Of Water"},
423 {58,"Inches Of Water"},
424 {59,"Millimeters Of Mercury"},
425 {60,"Centimeters Of Mercury"},
426 {61,"Inches Of Mercury"},
427 {62,"Degrees Celsius"},
428 {63,"Degress Kelvin"},
429 {64,"Degrees Fahrenheit"},
430 {65,"Degree Days Celsius"},
431 {66,"Degree Days Fahrenheit"},
439 {74,"Meters Per Second"},
440 {75,"Kilometers Per Hour"},
441 {76,"Feed Per Second"},
442 {77,"Feet Per Minute"},
443 {78,"Miles Per Hour"},
446 {81,"Imperial Gallons"},
449 {84,"Cubic Feet Per Minute"},
450 {85,"Cubic Meters Per Second"},
451 {86,"Imperial Gallons Per Minute"},
452 {87,"Liters Per Second"},
453 {88,"Liters Per Minute"},
454 {89,"US Gallons Per Minute"},
455 {90,"Degrees Angular"},
456 {91,"Degrees Celsius Per Hour"},
457 {92,"Degrees Celsius Per Minute"},
458 {93,"Degrees Fahrenheit Per Hour"},
459 {94,"Degrees Fahrenheit Per Minute"},
461 {96,"Parts Per Million"},
462 {97,"Parts Per Billion"},
464 {99,"Pecent Per Second"},
467 {102,"Psi Per Degree Fahrenheit"},
469 {104,"Revolutions Per Min"},
481 {116,"Sq Centimeters"},
482 {117,"BTUs Per Pound"},
484 {119,"Pounds Mass Per Second"},
485 {120,"Delta Degrees Fahrenheit"},
486 {121,"Delta Degrees Kelvin"},
490 {125,"Kilojoules Per Kg"},
492 {127,"Joules Per Degree Kelvin"},
493 {128,"Joules Per Kg Degree Kelvin"},
498 {133,"Hectopascals"},
500 {135,"Cubic Meters Per Hour"},
501 {136,"Liters Per Hour"},
502 {137,"KWatt Hours Per Square Meter"},
503 {138,"KWatt Hours Per Square Foot"},
504 {139,"Megajoules Per Square Meter"},
505 {140,"Megajoules Per Square Foot"},
506 {141,"Watts Per Sq Meter Degree Kelvin"},
507 {142,"Cubic Feet Per Second"},
508 {143,"Percent Obstruction Per Foot"},
509 {144,"Percent Obstruction Per Meter"},
511 {146,"megawatt-hours"},
514 {149,"kilojoules-per-kilogram-dry-air"},
515 {150,"megajoules-per-kilogram-dry-air"},
516 {151,"kilojoules-per-degree-Kelvin"},
517 {152,"megajoules-per-degree-Kelvin"},
519 {154,"grams-per-second"},
520 {155,"grams-per-minute"},
521 {156,"tons-per-hour"},
522 {157,"kilo-btus-per-hour"},
523 {158,"hundredths-seconds"},
524 {159,"milliseconds"},
525 {160,"newton-meters"},
526 {161,"millimeters-per-second"},
527 {162,"millimeters-per-minute"},
528 {163,"meters-per-minute"},
529 {164,"meters-per-hour"},
530 {165,"cubic-meters-per-minute"},
531 {166,"meters-per-second-per-second"},
532 {167,"amperes-per-meter"},
533 {168,"amperes-per-square-meter"},
534 {169,"ampere-square-meters"},
539 {174,"siemens-per-meter"},
541 {176,"volts-per-degree-Kelvin"},
542 {177,"volts-per-meter"},
545 {180,"candelas-per-square-meter"},
546 {181,"degrees-Kelvin-per-hour"},
547 {182,"degrees-Kelvin-per-minute"},
548 {183,"joule-seconds"},
549 {184,"radians-per-second"},
550 {185,"square-meters-per-Newton"},
551 {186,"kilograms-per-cubic-meter"},
552 {187,"newton-seconds"},
553 {188,"newtons-per-meter"},
554 {189,"watts-per-meter-per-degree-Kelvin"},
556 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
557 Enumerated values 256-65535 may be used by others subject to
558 the procedures and constraints described in Clause 23. */
561 static const value_string
562 BACnetErrorCode [] = {
564 {1,"authentication-failed"},
565 {2,"character-set-not-supported"},
566 {3,"configuration-in-progress"},
568 {5,"file-access-denied"},
569 {6,"incompatible-security-levels"},
570 {7,"inconsistent-parameters"},
571 {8,"inconsistent-selection-criterion"},
572 {9,"invalid-data-type"},
573 {10,"invalid-file-access-method"},
574 {11,"invalid-file-start-position"},
575 {12,"invalid-operator-name"},
576 {13,"invalid-parameter-data-type"},
577 {14,"invalid-time-stamp"},
578 {15,"key-generation-error"},
579 {16,"missing-required-parameter"},
580 {17,"no-objects-of-specified-type"},
581 {18,"no-space-for-object"},
582 {19,"no-space-to-add-list-element"},
583 {20,"no-space-to-write-property"},
584 {21,"no-vt-sessions-available"},
585 {22,"property-is-not-a-list"},
586 {23,"object-deletion-not-permitted"},
587 {24,"object-identifier-already-exists"},
588 {25,"operational-problem"},
589 {26,"password-failure"},
590 {27,"read-access-denied"},
591 {28,"security-not-supported"},
592 {29,"service-request-denied"},
594 {31,"unknown-object"},
595 {32,"unknown-property"},
596 {33,"removed enumeration"},
597 {34,"unknown-vt-class"},
598 {35,"unknown-vt-session"},
599 {36,"unsupported-object-type"},
600 {37,"value-out-of-range"},
601 {38,"vt-session-already-closed"},
602 {39,"vt-session-termination-failure"},
603 {40,"write-access-denied"},
604 {41,"character-set-not-supported"},
605 {42,"invalid-array-index"},
606 {43,"cov-subscription-failed"},
607 {44,"not-cov-property"},
608 {45,"optional-functionaltity-not-supported"},
609 {46,"invalid-configuration-data"},
610 {47,"datatype-not-supported"},
611 {48,"duplicate-name"},
612 {49,"duplicate-object-id"},
613 {50,"property-is-not-an-array"},
615 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
616 Enumerated values 256-65535 may be used by others subject to the
617 procedures and constraints described in Clause 23. */
620 static const value_string
621 BACnetPropertyIdentifier [] = {
622 {0,"acked-transition"},
627 {5,"active-vt-session"},
631 {9,"all-write-successful"},
632 {10,"apdu-segment-timeout"},
634 {12,"application-software-version"},
637 {15,"change-of-state-count"},
638 {16,"change-of-state-time"},
639 {17,"notification-class"},
640 {18,"the property in this place was deleted"},
641 {19,"controlled-variable-reference"},
642 {20,"controlled-variable-units"},
643 {21,"controlled-variable-value"},
644 {22,"cov-increment"},
646 {24,"daylights-savings-status"},
648 {26,"derivative-constant"},
649 {27,"derivative-constant-units"},
651 {29,"description-of-halt"},
652 {30,"device-address-binding"},
654 {32,"effective-period"},
655 {33,"elapsed-active-time"},
660 {38,"exception-schedule"},
662 {40,"feedback-value"},
663 {41,"file-access-method"},
666 {44,"firmware-revision"},
668 {46,"inactive-text"},
671 {49,"integral-constant"},
672 {50,"integral-constant-units"},
673 {51,"issue-confirmed-notifications"},
675 {53,"list-of-group-members"},
676 {54,"list-of-object-property-references"},
677 {55,"list-of-session-keys"},
682 {60,"manipulated-variable-reference"},
683 {61,"maximum-output"},
684 {62,"max-apdu-length-accepted"},
685 {63,"max-info-frames"},
687 {65,"max-pres-value"},
688 {66,"minimum-off-time"},
689 {67,"minimum-on-time"},
690 {68,"minimum-output"},
691 {69,"min-pres-value"},
693 {71,"modification-date"},
695 {73,"number-of-APDU-retries"},
696 {74,"number-of-states"},
697 {75,"object-identifier"},
700 {78,"object-property-reference"},
703 {81,"out-of-service"},
705 {83,"event-parameters"},
707 {85,"present-value"},
709 {87,"priority-array"},
710 {88,"priority-for-writing"},
711 {89,"process-identifier"},
712 {90,"program-change"},
713 {91,"program-location"},
714 {92,"program-state"},
715 {93,"proportional-constant"},
716 {94,"proportional-constant-units"},
717 {95,"protocol-conformance-class"},
718 {96,"protocol-object-types-supported"},
719 {97,"protocol-services-supported"},
720 {98,"protocol-version"},
722 {100,"reason-for-halt"},
724 {102,"recipient-list"},
726 {104,"relinquish-default"},
729 {107,"segmentation-supported"},
731 {109,"setpoint-reference"},
733 {111,"status-flags"},
734 {112,"system-status"},
736 {114,"time-of-active-time-reset"},
737 {115,"time-of-state-count-reset"},
738 {116,"time-synchronization-recipients"},
740 {118,"update-interval"},
742 {120,"vendor-identifier"},
744 {122,"vt-class-supported"},
745 {123,"weekly-schedule"},
746 {124,"attempted-samples"},
747 {125,"average-value"},
749 {127,"client-cov-increment"},
750 {128,"cov-resubscription-interval"},
751 {129,"current-notify-time"},
752 {130,"event-time-stamp"},
754 {132,"log-device-object-property"},
756 {134,"log-interval"},
757 {135,"maximum-value"},
758 {136,"minimum-value"},
759 {137,"notification-threshold"},
760 {138,"previous-notify-time"},
761 {139,"protocol-revision"},
762 {140,"records-since-notification"},
763 {141,"record-count"},
766 {144,"stop-when-full"},
767 {145,"total-record-count"},
768 {146,"valid-samples"},
769 {147,"window-interval"},
770 {148,"window-samples"},
771 {149,"maximum-value-time-stamp"},
772 {150,"minimum-value-time-stamp"},
773 {151,"variance-value"},
774 {152,"active-cov-subscriptions"},
775 {153,"backup-failure-timeout"},
776 {154,"configuration-files"},
777 {155,"database-revision"},
778 {156,"direct-reading"},
779 {157,"last-restore-time"},
780 {158,"maintenance-required"},
783 {161,"operation-expected"},
786 {164,"tracking-value"},
787 {165,"zone-members"},
788 {166,"life-safety-alarm-values"},
789 {167,"max-segments-accepted"},
790 {168,"profile-name"},
791 {169,"auto-slave-discovery"},
792 {170,"manual-slave-address-binding"},
793 {171,"slave-address-binding"},
794 {172,"slave-proxy-enable"},
795 {173,"last-notify-time"},
796 {174,"schedule-default"},
797 {175,"accepted-modes"},
798 {176,"adjust-value"},
800 {178,"count-before-change"},
801 {179,"count-change-time"},
803 {181,"input-reference"},
804 {182,"limit-monitoring-interval"},
805 {183,"logging-device"},
806 {184,"logging-record"},
810 {188,"scale-factor"},
812 {190,"value-before-change"},
814 {192,"value-change-time"},
816 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
817 Enumerated values 512-4194303 may be used by others subject to
818 the procedures and constraints described in Clause 23. */
821 static const value_string
822 BACnetBinaryPV [] = {
829 static const value_string
830 BACnetCharacterSet [] = {
832 {1,"IBM/Microsoft DBCS"},
834 {3,"ISO 10646(UCS-4)"},
835 {4,"ISO 10646(UCS-2)"},
840 static const value_string
841 BACnetStatusFlags [] = {
845 {3,"out-of-service"},
849 static const value_string
850 BACnetMessagePriority [] = {
856 static const value_string
857 BACnetAcknowledgementFilter [] = {
864 static const value_string
865 BACnetResultFlags [] = {
872 static const value_string
873 BACnetRelationSpecifier [] = {
878 {4,"less-than-or-equal"},
879 {5,"greater-than-or-equal"},
883 static const value_string
884 BACnetSelectionLogic [] = {
891 static const value_string
892 BACnetEventStateFilter [] = {
901 static const value_string
902 BACnetEventTransitionBits [] = {
909 static const value_string
910 BACnetSegmentation [] = {
911 {0,"segmented-both"},
912 {1,"segmented-transmit"},
913 {2,"segmented-receive"},
914 {3,"no-segmentation"},
918 static const value_string
919 BACnetSilencedState [] = {
921 {1,"audible-silenced"},
922 {2,"visible-silenced"},
927 static const value_string
928 BACnetDeviceStatus [] = {
930 {1,"operational-read-only"},
931 {2,"download-required"},
932 {3,"download-in-progress"},
933 {4,"non-operational"},
934 {5,"backup-in-progress"},
938 static const value_string
939 BACnetEnableDisable [] = {
942 {2,"disable-initiation"},
946 static const value_string
964 static const value_string
966 {1,"days numbered 1-7" },
967 {2,"days numbered 8-14" },
968 {3,"days numbered 15-21" },
969 {4,"days numbered 22-28" },
970 {5,"days numbered 29-31" },
971 {6,"last 7 days of this month" },
972 {255,"any week of this month" },
976 static const value_string
985 {255,"any day of week" },
989 static const value_string
990 BACnetErrorClass [] = {
999 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
1000 Enumerated values64-65535 may be used by others subject to
1001 the procedures and constraints described in Clause 23. */
1004 static const value_string
1005 BACnetVTClass [] = {
1006 {0,"default-terminal" },
1016 static const value_string
1017 BACnetEventType [] = {
1018 {0,"change-of-bitstring" },
1019 {1,"change-of-state" },
1020 {2,"change-of-value" },
1021 {3,"command-failure" },
1022 {4,"floating-limit" },
1023 {5,"out-of-range" },
1024 {6,"complex-event-type" },
1025 {7,"buffer-ready" },
1026 {8,"change-of-life-safety" },
1028 {10,"buffer-ready" },
1029 {11,"unsigned-range" },
1031 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
1032 Enumerated values 64-65535 may be used by others subject to
1033 the procedures and constraints described in Clause 23.
1034 It is expected that these enumerated values will correspond
1035 to the use of the complex-event-type CHOICE [6] of the
1036 BACnetNotificationParameters production. */
1039 static const value_string
1040 BACnetEventState [] = {
1046 {5,"life-safety-alarm" },
1048 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
1049 Enumerated values 64-65535 may be used by others subject to
1050 the procedures and constraints described in Clause 23. */
1053 static const value_string
1054 BACnetLogStatus [] = {
1055 {0,"log-disabled" },
1056 {1,"buffer-purged" },
1060 static const value_string
1061 BACnetMaintenance [] = {
1063 {1,"periodic-test" },
1064 {2,"need-service-operational" },
1065 {3,"need-service-inoperative" },
1069 static const value_string
1070 BACnetNotifyType [] = {
1073 {2,"ack-notification" },
1077 static const value_string
1078 BACnetServicesSupported [] = {
1079 {0,"acknowledgeAlarm"},
1080 {1,"confirmedCOVNotification"},
1081 {2,"confirmedEventNotification"},
1082 {3,"getAlarmSummary"},
1083 {4,"getEnrollmentSummary"},
1085 {6,"atomicReadFile"},
1086 {7,"atomicWriteFile"},
1087 {8,"addListElement"},
1088 {9,"removeListElement"},
1089 {10,"createObject"},
1090 {11,"deleteObject"},
1091 {12,"readProperty"},
1092 {13,"readPropertyConditional"},
1093 {14,"readPropertyMultiple"},
1094 {15,"writeProperty"},
1095 {16,"writePropertyMultiple"},
1096 {17,"deviceCommunicationControl"},
1097 {18,"confirmedPrivateTransfer"},
1098 {19,"confirmedTextMessage"},
1099 {20,"reinitializeDevice"},
1103 {24,"authenticate"},
1107 {28,"unconfirmedCOVNotification"},
1108 {29,"unconfirmedEventNotification"},
1109 {30,"unconfirmedPrivateTransfer"},
1110 {31,"unconfirmedTextMessage"},
1111 {32,"timeSynchronization"},
1115 {36,"utcTimeSynchronization"},
1116 {37,"lifeSafetyOperation"},
1117 {38,"subscribeCOVProperty"},
1118 {39,"getEventInformation"},
1122 static const value_string
1123 BACnetPropertyStates [] = {
1124 {0,"boolean-value"},
1128 {4,"program-change"},
1129 {5,"program-state"},
1130 {6,"reason-for-halt"},
1133 {9,"system-status"},
1135 {11,"unsigned-value"},
1136 {12,"life-safety-mode"},
1137 {13,"life-safety-state"},
1139 /* Tag values 0-63 are reserved for definition by ASHRAE.
1140 Tag values of 64-254 may be used by others to accommodate
1141 vendor specific properties that have discrete or enumerated values,
1142 subject to the constraints described in Clause 23. */
1145 static const value_string
1146 BACnetProgramError [] = {
1153 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
1154 Enumerated values 64-65535 may be used by others subject to
1155 the procedures and constraints described in Clause 23. */
1158 static const value_string
1159 BACnetProgramRequest [] = {
1169 static const value_string
1170 BACnetProgramState [] = {
1180 static const value_string
1181 BACnetReinitializedStateOfDevice [] = {
1192 static const value_string
1193 BACnetPolarity [] = {
1199 static const value_string
1200 BACnetTagNames[] = {
1201 { 5, "Extended Value" },
1202 { 6, "Opening Tag" },
1203 { 7, "Closing Tag" },
1207 static int proto_bacapp = -1;
1208 static int hf_bacapp_type = -1;
1209 static int hf_bacapp_pduflags = -1;
1210 static int hf_bacapp_SEG = -1;
1211 static int hf_bacapp_MOR = -1;
1212 static int hf_bacapp_SA = -1;
1213 static int hf_bacapp_response_segments = -1;
1214 static int hf_bacapp_max_adpu_size = -1;
1215 static int hf_bacapp_invoke_id = -1;
1216 static int hf_bacapp_objectType = -1;
1217 static int hf_bacapp_instanceNumber = -1;
1218 static int hf_bacapp_sequence_number = -1;
1219 static int hf_bacapp_window_size = -1;
1220 static int hf_bacapp_service = -1;
1221 static int hf_bacapp_NAK = -1;
1222 static int hf_bacapp_SRV = -1;
1223 static int hf_BACnetRejectReason = -1;
1224 static int hf_BACnetAbortReason = -1;
1225 static int hf_BACnetApplicationTagNumber = -1;
1226 static int hf_BACnetContextTagNumber = -1;
1227 static int hf_BACnetExtendedTagNumber = -1;
1228 static int hf_BACnetNamedTag = -1;
1229 static int hf_BACnetTagClass = -1;
1230 static int hf_BACnetCharacterSet = -1;
1231 static int hf_bacapp_tag = -1;
1232 static int hf_bacapp_tag_lvt = -1;
1233 static int hf_bacapp_tag_value8 = -1;
1234 static int hf_bacapp_tag_value16 = -1;
1235 static int hf_bacapp_tag_value32 = -1;
1236 static int hf_bacapp_tag_ProcessId = -1;
1237 static int hf_bacapp_tag_initiatingObjectType = -1;
1238 static int hf_bacapp_vpart = -1;
1240 static int hf_bacapp_uservice = -1;
1243 static gint ett_bacapp = -1;
1244 static gint ett_bacapp_control = -1;
1245 static gint ett_bacapp_tag = -1;
1246 static gint ett_bacapp_list = -1;
1247 static gint ett_bacapp_value = -1;
1249 static dissector_handle_t data_handle;
1250 static gint32 propertyIdentifier = -1;
1251 static guint32 object_type = 4096;
1253 static guint8 bacapp_flags = 0;
1254 static guint8 bacapp_seq = 0;
1256 /* Used when there are ranges of reserved and proprietary enumerations */
1258 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
1259 const char *fmt, const char *split_fmt)
1261 if (val < split_val)
1262 return val_to_str(val, vs, fmt);
1264 return val_to_str(val, vs, split_fmt);
1267 /* from clause 20.2.1.3.2 Constructed Data */
1268 /* returns true if the extended value is used */
1269 static gboolean tag_is_extended_value(guint8 tag)
1271 return (tag & 0x07) == 5;
1274 static gboolean tag_is_opening(guint8 tag)
1276 return (tag & 0x07) == 6;
1279 static gboolean tag_is_closing(guint8 tag)
1281 return (tag & 0x07) == 7;
1284 /* from clause 20.2.1.1 Class
1285 class bit shall be one for context specific tags */
1286 /* returns true if the tag is context specific */
1287 static gboolean tag_is_context_specific(guint8 tag)
1289 return (tag & 0x08) != 0;
1292 static gboolean tag_is_extended_tag_number(guint8 tag)
1294 return ((tag & 0xF0) == 0xF0);
1297 static guint32 object_id_type(guint32 object_identifier)
1299 return ((object_identifier >> 22) & 0x3FF);
1302 static guint32 object_id_instance(guint32 object_identifier)
1304 return (object_identifier & 0x3FFFFF);
1308 fTagNo (tvbuff_t *tvb, guint offset)
1310 return (guint)(tvb_get_guint8(tvb, offset) >> 4);
1314 fUnsigned32 (tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
1316 gboolean valid = TRUE;
1320 *val = tvb_get_guint8(tvb, offset);
1323 *val = tvb_get_ntohs(tvb, offset);
1326 *val = tvb_get_ntoh24(tvb, offset);
1329 *val = tvb_get_ntohl(tvb, offset);
1340 fUnsigned64 (tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
1342 gboolean valid = TRUE;
1346 *val = tvb_get_guint8(tvb, offset);
1349 *val = tvb_get_ntohs(tvb, offset);
1352 *val = tvb_get_ntoh24(tvb, offset);
1355 *val = tvb_get_ntohl(tvb, offset);
1358 *val = tvb_get_ntoh64(tvb, offset);
1369 fTagHeaderTree (tvbuff_t *tvb, proto_tree *tree, guint offset,
1370 guint8 *tag_no, guint8* tag_info, guint32 *lvt)
1375 guint lvt_len = 1; /* used for tree display of lvt */
1376 guint lvt_offset; /* used for tree display of lvt */
1378 proto_tree *subtree;
1380 lvt_offset = offset;
1381 tag = tvb_get_guint8(tvb, offset);
1384 /* To solve the problem of lvt values of 6/7 being indeterminate - it */
1385 /* can mean open/close tag or length of 6/7 after the length is */
1386 /* computed below - store whole tag info, not just context bit. */
1387 if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
1389 if (tag_is_extended_tag_number(tag)) {
1390 *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
1392 if (tag_is_extended_value(tag)) { /* length is more than 4 Bytes */
1393 lvt_offset += tag_len;
1394 value = tvb_get_guint8(tvb, lvt_offset);
1396 if (value == 254) { /* length is encoded with 16 Bits */
1397 *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
1400 } else if (value == 255) { /* length is encoded with 32 Bits */
1401 *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
1409 if (tag_is_closing(tag) || tag_is_opening(tag))
1410 ti = proto_tree_add_text(tree, tvb, offset, tag_len,
1411 "%s: %u", match_strval(
1412 tag & 0x07, BACnetTagNames),
1414 else if (tag_is_context_specific(tag)) {
1415 ti = proto_tree_add_text(tree, tvb, offset, tag_len,
1416 "Context Tag: %u, Length/Value/Type: %u",
1419 ti = proto_tree_add_text(tree, tvb, offset, tag_len,
1420 "Application Tag: %s, Length/Value/Type: %u",
1422 BACnetApplicationTagNumber,
1423 ASHRAE_Reserved_Fmt),
1425 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1426 /* details if needed */
1427 proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, FALSE);
1428 if (tag_is_extended_tag_number(tag)) {
1429 proto_tree_add_uint_format(subtree,
1430 hf_BACnetContextTagNumber,
1431 tvb, offset, 1, tag,
1432 "Extended Tag Number");
1433 proto_tree_add_item(subtree,
1434 hf_BACnetExtendedTagNumber,
1435 tvb, offset + 1, 1, FALSE);
1437 if (tag_is_context_specific(tag))
1438 proto_tree_add_item(subtree,
1439 hf_BACnetContextTagNumber,
1440 tvb, offset, 1, FALSE);
1442 proto_tree_add_item(subtree,
1443 hf_BACnetApplicationTagNumber,
1444 tvb, offset, 1, FALSE);
1446 if (tag_is_closing(tag) || tag_is_opening(tag))
1447 proto_tree_add_item(subtree,
1449 tvb, offset, 1, FALSE);
1450 else if (tag_is_extended_value(tag)) {
1451 proto_tree_add_item(subtree,
1453 tvb, offset, 1, FALSE);
1454 proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
1455 tvb, lvt_offset, lvt_len, *lvt);
1457 proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
1458 tvb, lvt_offset, lvt_len, *lvt);
1465 fTagHeader (tvbuff_t *tvb, guint offset, guint8 *tag_no, guint8* tag_info,
1468 return fTagHeaderTree (tvb, NULL, offset, tag_no, tag_info, lvt);
1472 fNullTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1474 guint8 tag_no, tag_info;
1477 proto_tree *subtree;
1479 ti = proto_tree_add_text(tree, tvb, offset, 1, "%sNULL", label);
1480 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1481 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1487 fBooleanTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1489 guint8 tag_no, tag_info;
1493 proto_tree *subtree;
1496 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1497 if (tag_info && lvt == 1)
1499 lvt = tvb_get_guint8(tvb, offset+1);
1503 ti = proto_tree_add_text(tree, tvb, offset, bool_len,
1504 "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
1505 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1506 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1508 return offset + bool_len;
1512 fUnsignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1515 guint8 tag_no, tag_info;
1519 proto_tree *subtree;
1521 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1522 /* only support up to an 8 byte (64-bit) integer */
1523 if (fUnsigned64 (tvb, offset + tag_len, lvt, &val))
1524 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1525 "%s(Unsigned) %" PRIu64, label, val);
1527 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1528 "%s - %u octets (Unsigned)", label, lvt);
1529 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1530 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1532 return offset+tag_len+lvt;
1535 /* set split_val to zero when not needed */
1537 fEnumeratedTagSplit (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
1538 const value_string *vs, guint32 split_val)
1541 guint8 tag_no, tag_info;
1545 proto_tree *subtree;
1547 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1548 /* only support up to a 4 byte (32-bit) enumeration */
1549 if (fUnsigned32 (tvb, offset+tag_len, lvt, &val)) {
1551 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1552 "%s %s", label, val_to_split_str(val, split_val, vs,
1553 ASHRAE_Reserved_Fmt,Vendor_Proprietary_Fmt));
1555 ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1556 "%s %u", label, val);
1558 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1559 "%s - %u octets (enumeration)", label, lvt);
1561 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1562 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1564 return offset+tag_len+lvt;
1568 fEnumeratedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
1569 const value_string *vs)
1571 return fEnumeratedTagSplit (tvb, tree, offset, label, vs, 0);
1575 fSignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1578 guint8 tag_no, tag_info;
1582 proto_tree *subtree;
1584 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1585 if (fUnsigned64 (tvb, offset + tag_len, lvt, &val))
1586 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1587 "%s(Signed) %" PRId64, label, (gint64) val);
1589 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1590 "%s - %u octets (Signed)", label, lvt);
1591 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1592 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1594 return offset+tag_len+lvt;
1598 fRealTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1600 guint8 tag_no, tag_info;
1605 proto_tree *subtree;
1607 tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
1608 f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
1609 ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
1610 "%s%f (Real)", label, f_val);
1611 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1612 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1614 return offset+tag_len+4;
1618 fDoubleTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1620 guint8 tag_no, tag_info;
1623 gdouble d_val = 0.0;
1625 proto_tree *subtree;
1627 tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
1628 d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
1629 ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
1630 "%s%lf (Double)", label, d_val);
1631 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1632 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1634 return offset+tag_len+8;
1638 fProcessId (tvbuff_t *tvb, proto_tree *tree, guint offset)
1640 guint32 val = 0, lvt;
1641 guint8 tag_no, tag_info;
1643 proto_tree *subtree;
1646 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1647 if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
1648 ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
1649 tvb, offset, lvt+tag_len, val);
1651 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1652 "Process Identifier - %u octets (Signed)", lvt);
1653 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1654 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1656 return offset+tag_len+lvt;
1660 fTimeSpan (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1662 guint32 val = 0, lvt;
1663 guint8 tag_no, tag_info;
1665 proto_tree *subtree;
1668 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1669 if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
1670 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1671 "%s (hh.mm.ss): %d.%02d.%02d%s",
1673 (val / 3600), ((val % 3600) / 60), (val % 60),
1674 val == 0 ? " (indefinite)" : "");
1676 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1677 "%s - %u octets (Signed)", label, lvt);
1678 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1679 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1681 return offset+tag_len+lvt;
1685 fWeekNDay (tvbuff_t *tvb, proto_tree *tree, guint offset)
1687 guint32 month, weekOfMonth, dayOfWeek;
1688 guint8 tag_no, tag_info;
1692 proto_tree *subtree;
1694 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1695 month = tvb_get_guint8(tvb, offset+tag_len);
1696 weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
1697 dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
1698 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
1699 val_to_str(month, months, "month (%d) not found"),
1700 val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
1701 val_to_str(dayOfWeek, days, "day of week (%d) not found"));
1702 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1703 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1705 return offset+tag_len+lvt;
1709 fDate (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1711 guint32 year, month, day, weekday;
1712 guint8 tag_no, tag_info;
1716 proto_tree *subtree;
1718 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1719 year = tvb_get_guint8(tvb, offset+tag_len) + 1900;
1720 month = tvb_get_guint8(tvb, offset+tag_len+1);
1721 day = tvb_get_guint8(tvb, offset+tag_len+2);
1722 weekday = tvb_get_guint8(tvb, offset+tag_len+3);
1723 if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255))
1724 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1727 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1728 "%s%s %d, %d, (Day of Week = %s)",
1729 label, val_to_str(month,
1731 "month (%d) not found"),
1732 day, year, val_to_str(weekday,
1735 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1736 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1738 return offset+tag_len+lvt;
1742 fTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1744 guint32 year, month, day, weekday, lvt;
1745 guint8 tag_no, tag_info;
1748 proto_tree *subtree;
1750 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1751 year = tvb_get_guint8(tvb, offset+tag_len);
1752 month = tvb_get_guint8(tvb, offset+tag_len+1);
1753 day = tvb_get_guint8(tvb, offset+tag_len+2);
1754 weekday = tvb_get_guint8(tvb, offset+tag_len+3);
1755 if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255))
1756 ti = proto_tree_add_text(tree, tvb, offset,
1757 lvt+tag_len, "%sany", label);
1759 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
1760 "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
1762 year > 12 ? year -12 : year,
1763 month, day, weekday,
1764 year > 12 ? "P.M." : "A.M.",
1765 year, month, day, weekday);
1766 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1767 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1769 return offset+tag_len+lvt;
1773 fDateTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
1775 proto_tree *subtree = tree;
1778 if (label != NULL) {
1779 tt = proto_tree_add_text (subtree, tvb, offset, 1, "%s", label);
1780 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
1782 offset = fDate (tvb,subtree,offset,"Date: ");
1783 return fTime (tvb,subtree,offset,"Time: ");
1787 fTimeValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
1789 guint lastoffset = 0;
1790 guint8 tag_no, tag_info;
1793 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
1794 lastoffset = offset;
1795 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1796 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
1799 offset = fTime (tvb,tree,offset,"Time: ");
1800 offset = fApplicationTypes(tvb, tree, offset, "Value: ");
1806 fCalendaryEntry (tvbuff_t *tvb, proto_tree *tree, guint offset)
1808 guint lastoffset = 0;
1810 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
1811 lastoffset = offset;
1813 switch (fTagNo(tvb, offset)) {
1815 offset = fDate (tvb, tree, offset, "Date: ");
1817 case 1: /* dateRange */
1818 offset = fDateRange (tvb, tree, offset);
1820 case 2: /* BACnetWeekNDay */
1821 offset = fWeekNDay (tvb, tree, offset);
1832 fTimeStamp (tvbuff_t *tvb, proto_tree *tree, guint offset)
1834 guint8 tag_no = 0, tag_info = 0;
1837 if (tvb_length_remaining(tvb, offset) > 0) { /* don't loop, it's a CHOICE */
1838 switch (fTagNo(tvb, offset)) {
1840 offset = fTime (tvb, tree, offset, "timestamp: ");
1842 case 1: /* sequenceNumber */
1843 offset = fUnsignedTag (tvb, tree, offset, "sequence Number: ");
1845 case 2: /* dateTime */
1846 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
1847 offset = fDateTime (tvb, tree, offset, "timestamp: ");
1848 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
1860 fSetpointReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
1862 guint lastoffset = 0;
1864 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
1865 lastoffset = offset;
1867 switch (fTagNo(tvb, offset)) {
1868 case 0: /* setpointReference */
1869 offset = fBACnetObjectPropertyReference (tvb,tree,offset);
1882 fClientCOV (tvbuff_t *tvb, proto_tree *tree, guint offset)
1884 if (tvb_length_remaining(tvb, offset) > 0) {
1885 offset = fApplicationTypes(tvb,tree,offset, "increment: ");
1891 fDestination (tvbuff_t *tvb, proto_tree *tree, guint offset)
1893 if (tvb_length_remaining(tvb, offset) > 0) {
1894 offset = fApplicationTypesEnumerated(tvb,tree,offset,
1895 "valid Days: ", days);
1896 offset = fTime (tvb,tree,offset,"from time: ");
1897 offset = fTime (tvb,tree,offset,"to time: ");
1898 offset = fRecipient (tvb,tree,offset);
1899 offset = fProcessId (tvb,tree,offset);
1900 offset = fApplicationTypes (tvb,tree,offset,
1901 "issue confirmed notifications: ");
1902 offset = fApplicationTypesEnumerated (tvb,tree,offset,
1903 "transitions: ", BACnetEventTransitionBits);
1911 fOctetString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
1914 guint start = offset;
1915 guint8 tag_no, tag_info;
1916 proto_tree* subtree = tree;
1919 offset += fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1923 tmp = tvb_bytes_to_str(tvb, offset, lvt);
1924 ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
1929 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1931 fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
1937 fAddress (tvbuff_t *tvb, proto_tree *tree, guint offset)
1939 guint8 tag_no, tag_info;
1943 offset = fUnsignedTag (tvb, tree, offset, "network-number");
1944 offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
1946 proto_tree_add_text(tree, tvb, offset, offs, "mac-address: broadcast");
1949 offset = fOctetString (tvb, tree, offset, "mac-address: ", lvt);
1955 fSessionKey (tvbuff_t *tvb, proto_tree *tree, guint offset)
1957 offset = fOctetString (tvb,tree,offset,"session key: ", 8);
1958 return fAddress (tvb,tree,offset);
1963 fObjectIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
1965 guint8 tag_no, tag_info;
1969 proto_tree *subtree;
1972 tag_length = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
1973 object_id = tvb_get_ntohl(tvb,offset+tag_length);
1974 object_type = object_id_type(object_id);
1975 ti = proto_tree_add_text(tree, tvb, offset, tag_length + 4,
1976 "ObjectIdentifier: %s, %u",
1977 val_to_split_str(object_type,
1980 ASHRAE_Reserved_Fmt,
1981 Vendor_Proprietary_Fmt),
1982 object_id_instance(object_id));
1983 /* here are the details of how we arrived at the above text */
1984 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
1985 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
1986 offset += tag_length;
1987 proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, FALSE);
1988 proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, FALSE);
1995 fRecipient (tvbuff_t *tvb, proto_tree *tree, guint offset)
1997 guint lastoffset = 0;
1999 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2000 lastoffset = offset;
2002 switch (fTagNo(tvb, offset)) {
2003 case 0: /* device */
2004 offset = fObjectIdentifier (tvb, tree, offset);
2006 case 1: /* address */
2007 offset = fAddress (tvb, tree, offset);
2018 fRecipientProcess (tvbuff_t *tvb, proto_tree *tree, guint offset)
2020 guint lastoffset = 0;
2022 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2023 lastoffset = offset;
2025 switch (fTagNo(tvb, offset)) {
2026 case 0: /* recipient */
2027 offset = fRecipient (tvb, tree, offset);
2029 case 1: /* processId */
2030 offset = fProcessId (tvb, tree, offset);
2041 fAddressBinding (tvbuff_t *tvb, proto_tree *tree, guint offset)
2043 offset = fObjectIdentifier (tvb, tree, offset);
2044 return fAddress (tvb, tree, offset);
2048 fActionCommand (tvbuff_t *tvb, proto_tree *tree, guint offset)
2050 guint lastoffset = 0;
2051 guint8 tag_no, tag_info;
2053 proto_tree *subtree = tree;
2056 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2057 lastoffset = offset;
2058 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2059 if (tag_is_closing(tag_info)) {
2060 offset += fTagHeaderTree (tvb, subtree, offset,
2061 &tag_no, &tag_info, &lvt);
2067 case 0: /* deviceIdentifier */
2068 offset = fObjectIdentifier (tvb, subtree, offset);
2070 case 1: /* objectIdentifier */
2071 offset = fObjectIdentifier (tvb, subtree, offset);
2073 case 2: /* propertyIdentifier */
2074 offset = fPropertyIdentifier (tvb, subtree, offset);
2076 case 3: /* propertyArrayIndex */
2077 offset = fUnsignedTag (tvb,subtree,offset,"Property Array Index: ");
2079 case 4: /* propertyValue */
2080 if (tag_is_opening(tag_info)) {
2081 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
2082 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2083 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2084 offset = fAbstractSyntaxNType (tvb, subtree, offset);
2089 case 5: /* priority */
2090 offset = fUnsignedTag (tvb,subtree,offset,"Priority: ");
2092 case 6: /* postDelay */
2093 offset = fUnsignedTag (tvb,subtree,offset,"Post Delay: ");
2095 case 7: /* quitOnFailure */
2096 offset = fBooleanTag(tvb, subtree, offset,
2097 "Quit On Failure: ");
2099 case 8: /* writeSuccessful */
2100 offset = fBooleanTag(tvb, subtree, offset,
2101 "Write Successful: ");
2111 fActionList (tvbuff_t *tvb, proto_tree *tree, guint offset)
2113 return fActionCommand (tvb,tree,offset);
2117 fPropertyIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
2119 guint8 tag_no, tag_info;
2123 proto_tree *subtree;
2125 propertyIdentifier = 0; /* global Variable */
2126 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2127 if (fUnsigned32 (tvb, offset+tag_len, lvt, &propertyIdentifier))
2128 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
2129 "property Identifier: %s",
2130 val_to_split_str(propertyIdentifier, 512,
2131 BACnetPropertyIdentifier,
2132 ASHRAE_Reserved_Fmt,
2133 Vendor_Proprietary_Fmt));
2135 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
2136 "Property Identifier - %u octets", lvt);
2137 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
2138 fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2140 return offset+tag_len+lvt;
2144 fCharacterString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
2146 guint8 tag_no, tag_info, character_set;
2148 size_t inbytesleft, outbytesleft = 512;
2149 guint offs, extra = 1;
2151 guint8 bf_arr[512], *out = &bf_arr[0];
2153 proto_tree *subtree;
2154 guint start = offset;
2156 if (tvb_length_remaining(tvb, offset) > 0) {
2158 offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2160 character_set = tvb_get_guint8(tvb, offset+offs);
2161 /* Account for code page if DBCS */
2162 if (character_set == 1)
2166 offset += (offs+extra);
2170 l = inbytesleft = min(lvt, 255);
2172 * XXX - are we guaranteed that these encoding
2173 * names correspond, on *all* platforms with
2174 * iconv(), to the encodings we want?
2175 * If not (and perhaps even if so), we should
2176 * perhaps have our own iconv() implementation,
2177 * with a different name, so that we control the
2178 * encodings it supports and the names of those
2181 * We should also handle that in the general
2182 * string handling code, rather than making it
2183 * specific to the BACAPP dissector, as many
2184 * other dissectors need to handle various
2185 * character encodings.
2187 str_val = tvb_get_ephemeral_string(tvb, offset, l);
2188 /** this decoding may be not correct for multi-byte characters, Lka */
2189 switch (character_set) {
2190 case 0x00: /* ANSI_X3.4 */
2191 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ANSI_X3.4");
2193 case 1: /* IBM/MICROSOFT DBCS */
2196 case 2: /* JIS C 6226 */
2200 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-4BE");
2203 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-2BE");
2205 case 5: /* ISO8859-1 */
2206 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ISO8859-1");
2212 ti = proto_tree_add_text(tree, tvb, offset, l, "%s'%s'", label, out);
2217 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
2219 fTagHeaderTree (tvb, subtree, start, &tag_no, &tag_info, &lvt);
2220 proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, FALSE);
2221 if (character_set == 1)
2223 proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
2230 fBitStringTagVS (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
2231 const value_string *src)
2233 guint8 tag_no, tag_info, tmp;
2234 gint j, unused, skip;
2236 guint32 lvt, i, numberOfBytes;
2239 offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2240 numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
2242 unused = tvb_get_guint8(tvb, offset); /* get the unused Bits */
2244 for (i = 0; i < numberOfBytes; i++) {
2245 tmp = tvb_get_guint8(tvb, (offset)+i+1);
2246 if (i == numberOfBytes-1) { skip = unused; }
2247 for (j = 0; j < 8-skip; j++) {
2249 if (tmp & (1 << (7 - j)))
2250 proto_tree_add_text(tree, tvb,
2254 val_to_str((guint) (i*8 +j),
2256 ASHRAE_Reserved_Fmt));
2258 proto_tree_add_text(tree, tvb,
2262 val_to_str((guint) (i*8 +j),
2264 ASHRAE_Reserved_Fmt));
2267 bf_arr[min(255,(i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
2274 bf_arr[min(255,numberOfBytes*8-unused)] = 0;
2275 proto_tree_add_text(tree, tvb, offset, lvt, "%sB'%s'", label, bf_arr);
2284 fBitStringTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
2286 return fBitStringTagVS (tvb, tree, offset, label, NULL);
2289 /* handles generic application types, as well as enumerated and enumerations
2290 with reserved and proprietarty ranges (split) */
2292 fApplicationTypesEnumeratedSplit (tvbuff_t *tvb, proto_tree *tree, guint offset,
2293 const gchar *label, const value_string *src, guint32 split_val)
2295 guint8 tag_no, tag_info;
2299 if (tvb_length_remaining(tvb, offset) > 0) {
2301 tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2304 case 0: /** NULL 20.2.2 */
2305 offset = fNullTag(tvb, tree, offset, label);
2307 case 1: /** BOOLEAN 20.2.3 */
2308 offset = fBooleanTag(tvb, tree, offset, label);
2310 case 2: /** Unsigned Integer 20.2.4 */
2311 offset = fUnsignedTag(tvb, tree, offset, label);
2313 case 3: /** Signed Integer 20.2.5 */
2314 offset = fSignedTag(tvb, tree, offset, label);
2316 case 4: /** Real 20.2.6 */
2317 offset = fRealTag(tvb, tree, offset, label);
2319 case 5: /** Double 20.2.7 */
2320 offset = fDoubleTag(tvb, tree, offset, label);
2322 case 6: /** Octet String 20.2.8 */
2323 offset = fOctetString (tvb, tree, offset, label, lvt);
2325 case 7: /** Character String 20.2.9 */
2326 offset = fCharacterString (tvb,tree,offset,label);
2328 case 8: /** Bit String 20.2.10 */
2329 offset = fBitStringTagVS (tvb, tree, offset, label, src);
2331 case 9: /** Enumerated 20.2.11 */
2332 offset = fEnumeratedTagSplit (tvb, tree, offset, label, src, split_val);
2334 case 10: /** Date 20.2.12 */
2335 offset = fDate (tvb, tree, offset, label);
2337 case 11: /** Time 20.2.13 */
2338 offset = fTime (tvb, tree, offset, label);
2340 case 12: /** BACnetObjectIdentifier 20.2.14 */
2341 offset = fObjectIdentifier (tvb, tree, offset);
2343 case 13: /* reserved for ASHRAE */
2346 proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
2347 offset+=lvt+tag_len;
2357 fApplicationTypesEnumerated (tvbuff_t *tvb, proto_tree *tree, guint offset,
2358 const gchar *label, const value_string *vs)
2360 return fApplicationTypesEnumeratedSplit(tvb, tree, offset, label, vs, 0);
2364 fApplicationTypes (tvbuff_t *tvb, proto_tree *tree, guint offset,
2367 return fApplicationTypesEnumeratedSplit(tvb, tree, offset, label, NULL, 0);
2371 fContextTaggedValue(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
2373 guint8 tag_no, tag_info;
2377 proto_tree *subtree;
2381 tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
2382 /* cap the the suggested length in case of bad data */
2383 tvb_len = tvb_length_remaining(tvb, offset+tag_len);
2384 if ((tvb_len >= 0) && ((guint32)tvb_len < lvt))
2388 ti = proto_tree_add_text(tree, tvb, offset+tag_len, lvt,
2389 "Context Value (as %u DATA octets)", lvt);
2391 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
2392 fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2394 return offset + tag_len + lvt;
2398 fAbstractSyntaxNType (tvbuff_t *tvb, proto_tree *tree, guint offset)
2400 guint8 tag_no, tag_info;
2402 guint lastoffset = 0, depth = 0;
2405 if (propertyIdentifier >= 0)
2407 g_snprintf (ar, sizeof(ar), "%s: ",
2408 val_to_split_str(propertyIdentifier, 512,
2409 BACnetPropertyIdentifier,
2410 ASHRAE_Reserved_Fmt,
2411 Vendor_Proprietary_Fmt));
2415 g_snprintf (ar, sizeof(ar), "Abstract Type: ");
2417 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2418 lastoffset = offset;
2419 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2420 if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
2421 if (depth <= 0) return offset;
2424 /* Application Tags */
2425 switch (propertyIdentifier) {
2426 case 2: /* BACnetActionList */
2427 offset = fActionList (tvb,tree,offset);
2429 case 30: /* BACnetAddressBinding */
2430 offset = fAddressBinding (tvb,tree,offset);
2432 case 79: /* object-type */
2433 case 96: /* protocol-object-types-supported */
2434 offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, ar,
2435 BACnetObjectType, 128);
2437 case 97: /* Protocol-Services-Supported */
2438 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2439 BACnetServicesSupported);
2441 case 107: /* segmentation-supported */
2442 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2443 BACnetSegmentation);
2445 case 111: /* Status-Flags */
2446 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2449 case 112: /* System-Status */
2450 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2451 BACnetDeviceStatus);
2453 case 117: /* units */
2454 offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
2455 BACnetEngineeringUnits);
2457 case 87: /* priority-array */
2458 offset = fPriorityArray (tvb, tree, offset);
2460 case 38: /* exception-schedule */
2461 if (object_type < 128)
2463 offset = fSpecialEvent (tvb,tree,offset);
2466 case 123: /* weekly-schedule */
2467 if (object_type < 128)
2469 offset = fWeeklySchedule (tvb,tree,offset);
2475 if (tag_is_opening(tag_info))
2478 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
2480 else if (tag_is_closing(tag_info))
2483 offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
2487 offset = fContextTaggedValue(tvb, tree, offset, ar);
2492 offset = fApplicationTypes (tvb, tree, offset, ar);
2502 fPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 tagoffset)
2504 guint lastoffset = offset;
2506 proto_tree *subtree;
2507 guint8 tag_no, tag_info;
2510 offset = fPropertyReference(tvb, tree, offset, tagoffset, 0);
2511 if (offset > lastoffset)
2513 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2514 if (tag_no == tagoffset+2) { /* Value - might not be present in ReadAccessResult */
2515 if (tag_is_opening(tag_info)) {
2516 tt = proto_tree_add_text(tree, tvb, offset, 1, "propertyValue");
2517 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2518 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2519 offset = fAbstractSyntaxNType (tvb, subtree, offset);
2520 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2528 fBACnetPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
2530 guint lastoffset = 0;
2531 guint8 tag_no, tag_info;
2534 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2535 lastoffset = offset;
2536 offset = fPropertyValue(tvb, tree, offset, 0);
2537 if (offset > lastoffset)
2539 /* detect optional priority
2540 by looking to see if the next tag is context tag number 3 */
2541 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2542 if (tag_is_context_specific(tag_info) && (tag_no == 3))
2543 offset = fUnsignedTag (tvb,tree,offset,"Priority: ");
2550 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2552 guint lastoffset = 0;
2554 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2555 lastoffset = offset;
2557 switch (fTagNo(tvb,offset)) {
2558 case 0: /* ProcessId */
2559 offset = fUnsignedTag (tvb, tree, offset, "subscriber Process Id: ");
2561 case 1: /* monitored ObjectId */
2562 offset = fObjectIdentifier (tvb, tree, offset);
2564 case 2: /* issueConfirmedNotifications */
2565 offset = fBooleanTag (tvb, tree, offset, "issue Confirmed Notifications: ");
2567 case 3: /* life time */
2568 offset = fTimeSpan (tvb,tree,offset,"life time");
2570 case 4: /* monitoredPropertyIdentifier */
2571 offset = fBACnetPropertyReference (tvb, tree, offset, 0);
2573 case 5: /* covIncrement */
2574 offset = fRealTag (tvb, tree, offset, "COV Increment: ");
2585 fSubscribeCOVRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2587 return fSubscribeCOVPropertyRequest(tvb, tree, offset);
2591 fWhoHas (tvbuff_t *tvb, proto_tree *tree, guint offset)
2593 guint lastoffset = 0;
2595 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2596 lastoffset = offset;
2598 switch (fTagNo(tvb, offset)) {
2599 case 0: /* deviceInstanceLowLimit */
2600 offset = fUnsignedTag (tvb, tree, offset, "device Instance Low Limit: ");
2602 case 1: /* deviceInstanceHighLimit */
2603 offset = fUnsignedTag (tvb, tree, offset, "device Instance High Limit: ");
2605 case 2: /* BACnetObjectId */
2606 offset = fObjectIdentifier (tvb, tree, offset);
2608 case 3: /* messageText */
2609 offset = fCharacterString (tvb,tree,offset, "Object Name: ");
2620 fDailySchedule (tvbuff_t *tvb, proto_tree *subtree, guint offset)
2622 guint lastoffset = 0;
2623 guint8 tag_no, tag_info;
2626 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2627 lastoffset = offset;
2628 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2629 if (tag_is_closing(tag_info)) {
2630 offset += fTagHeaderTree (tvb, subtree, offset,
2631 &tag_no, &tag_info, &lvt);
2636 case 0: /* day-schedule */
2637 if (tag_is_opening(tag_info)) {
2638 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2639 offset = fTimeValue (tvb, subtree, offset);
2652 fWeeklySchedule (tvbuff_t *tvb, proto_tree *tree, guint offset)
2654 guint lastoffset = 0;
2655 guint8 tag_no, tag_info;
2658 proto_tree *subtree = tree;
2661 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2662 lastoffset = offset;
2663 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2664 if (tag_is_closing(tag_info)) {
2665 offset += fTagHeaderTree (tvb, tree, offset,
2666 &tag_no, &tag_info, &lvt);
2669 tt = proto_tree_add_text(tree, tvb, offset, 0, val_to_str(i++, days, "day of week (%d) not found"));
2670 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2671 offset = fDailySchedule (tvb,subtree,offset);
2678 fUTCTimeSynchronizationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
2680 if (tvb_length_remaining(tvb, offset) <= 0)
2683 return fDateTime (tvb, tree, offset, "UTC-Time: ");
2687 fTimeSynchronizationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
2689 if (tvb_length_remaining(tvb, offset) <= 0)
2692 return fDateTime (tvb, tree, offset, NULL);
2696 fDateRange (tvbuff_t *tvb, proto_tree *tree, guint offset)
2698 if (tvb_length_remaining(tvb, offset) <= 0)
2700 offset = fDate (tvb,tree,offset,"Start Date: ");
2701 return fDate (tvb, tree, offset, "End Date: ");
2705 fConfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2707 guint lastoffset = 0;
2709 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2710 lastoffset = offset;
2711 switch (fTagNo(tvb, offset)) {
2713 case 0: /* textMessageSourceDevice */
2714 offset = fObjectIdentifier (tvb, tree, offset);
2716 case 1: /* messageClass */
2717 switch (fTagNo(tvb, offset)) {
2718 case 0: /* numeric */
2719 offset = fUnsignedTag (tvb, tree, offset, "message Class: ");
2721 case 1: /* character */
2722 offset = fCharacterString (tvb, tree, offset, "message Class: ");
2726 case 2: /* messagePriority */
2727 offset = fEnumeratedTag (tvb, tree, offset, "message Priority: ",
2728 BACnetMessagePriority);
2730 case 3: /* message */
2731 offset = fCharacterString (tvb, tree, offset, "message: ");
2742 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2744 return fConfirmedTextMessageRequest(tvb, tree, offset);
2748 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2750 guint lastoffset = 0;
2751 guint8 tag_no, tag_info;
2753 proto_tree *subtree = tree;
2756 /* exit loop if nothing happens inside */
2757 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
2758 lastoffset = offset;
2759 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2760 if (tag_is_closing(tag_info)) {
2761 if (tag_no == 2) /* Make sure it's the expected tag */
2763 offset += fTagHeaderTree (tvb, subtree, offset,
2764 &tag_no, &tag_info, &lvt);
2770 break; /* End loop if incorrect closing tag */
2775 case 0: /* vendorID */
2776 offset = fUnsignedTag (tvb, subtree, offset, "vendor ID: ");
2778 case 1: /* serviceNumber */
2779 offset = fUnsignedTag (tvb, subtree, offset, "service Number: ");
2781 case 2: /*serviceParameters */
2782 if (tag_is_opening(tag_info)) {
2783 tt = proto_tree_add_text(subtree, tvb, offset, 1, "service Parameters");
2784 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2785 propertyIdentifier = -1;
2786 offset = fAbstractSyntaxNType (tvb, subtree, offset);
2799 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
2801 return fConfirmedPrivateTransferRequest(tvb, tree, offset);
2805 fConfirmedPrivateTransferAck(tvbuff_t *tvb, proto_tree *tree, guint offset)
2807 return fConfirmedPrivateTransferRequest(tvb, tree, offset);
2811 fLifeSafetyOperationRequest(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
2813 guint lastoffset = 0;
2814 guint8 tag_no, tag_info;
2816 proto_tree *subtree = tree;
2819 if (label != NULL) {
2820 tt = proto_tree_add_text (subtree, tvb, offset, 1, "%s", label);
2821 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2824 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2825 lastoffset = offset;
2826 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
2829 case 0: /* subscriberProcessId */
2830 offset = fUnsignedTag (tvb, subtree, offset, "requesting Process Id: ");
2832 case 1: /* requestingSource */
2833 offset = fCharacterString (tvb, tree, offset, "requesting Source: ");
2835 case 2: /* request */
2836 offset = fEnumeratedTagSplit (tvb, tree, offset,
2837 "request: ", BACnetLifeSafetyOperation, 64);
2839 case 3: /* objectId */
2840 offset = fObjectIdentifier (tvb, subtree, offset);
2850 static guint fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset)
2852 switch (fTagNo(tvb, offset))
2855 offset = fBooleanTag (tvb, tree, offset, "boolean-value: ");
2858 offset = fEnumeratedTagSplit (tvb, tree, offset,
2859 "binary-value: ", BACnetBinaryPV, 2);
2862 offset = fEnumeratedTagSplit (tvb, tree, offset,
2863 "event-type: ", BACnetEventType, 12);
2866 offset = fEnumeratedTagSplit (tvb, tree, offset,
2867 "polarity: ", BACnetPolarity, 2);
2870 offset = fEnumeratedTagSplit (tvb, tree, offset,
2871 "program-change: ", BACnetProgramRequest, 5);
2874 offset = fEnumeratedTagSplit (tvb, tree, offset,
2875 "program-state: ", BACnetProgramState, 5);
2878 offset = fEnumeratedTagSplit (tvb, tree, offset,
2879 "reason-for-halt: ", BACnetProgramError, 5);
2882 offset = fEnumeratedTagSplit (tvb, tree, offset,
2883 "reliability: ", BACnetReliability, 10);
2886 offset = fEnumeratedTagSplit (tvb, tree, offset,
2887 "state: ", BACnetEventState, 64);
2890 offset = fEnumeratedTagSplit (tvb, tree, offset,
2891 "system-status: ", BACnetDeviceStatus, 64);
2894 offset = fEnumeratedTagSplit (tvb, tree, offset,
2895 "units: ", BACnetEngineeringUnits, 2);
2898 offset = fUnsignedTag(tvb, tree, offset, "unsigned-value: ");
2901 offset = fEnumeratedTagSplit (tvb, tree, offset,
2902 "life-safety-mode: ", BACnetLifeSafetyMode, 64);
2905 offset = fEnumeratedTagSplit (tvb, tree, offset,
2906 "life-safety-state: ", BACnetLifeSafetyState, 64);
2915 fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
2917 guint lastoffset = offset;
2918 guint8 tag_no, tag_info;
2920 proto_tree *subtree = tree;
2923 tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters");
2924 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
2925 /* Opeing tag for parameter choice */
2926 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2929 case 0: /* change-of-bitstring */
2930 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2931 lastoffset = offset;
2932 switch (fTagNo(tvb, offset)) {
2934 offset = fBitStringTag (tvb, subtree, offset,
2935 "referenced-bitstring: ");
2938 offset = fEnumeratedTag (tvb, subtree, offset,
2939 "status-flags: ", BACnetStatusFlags);
2947 case 1: /* change-of-state */
2948 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2949 lastoffset = offset;
2950 switch (fTagNo(tvb, offset)) {
2952 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2953 offset = fBACnetPropertyStates(tvb, subtree, offset);
2954 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2956 offset = fEnumeratedTag (tvb, subtree, offset,
2957 "status-flags: ", BACnetStatusFlags);
2958 lastoffset = offset;
2965 case 2: /* change-of-value */
2966 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2967 lastoffset = offset;
2968 switch (fTagNo(tvb, offset)) {
2970 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2971 switch (fTagNo(tvb, offset)) {
2973 offset = fBitStringTag (tvb, subtree, offset,
2977 offset = fRealTag (tvb, subtree, offset,
2983 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
2986 offset = fEnumeratedTag (tvb, subtree, offset,
2987 "status-flags: ", BACnetStatusFlags);
2994 case 3: /* command-failure */
2995 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
2996 lastoffset = offset;
2997 switch (fTagNo(tvb, offset)) {
2998 case 0: /* "command-value: " */
2999 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3000 offset = fAbstractSyntaxNType (tvb, subtree, offset);
3001 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3004 offset = fEnumeratedTag (tvb, subtree, offset,
3005 "status-flags: ", BACnetStatusFlags);
3006 case 2: /* "feedback-value: " */
3007 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3008 offset = fAbstractSyntaxNType (tvb, subtree, offset);
3009 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3015 case 4: /* floating-limit */
3016 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3017 lastoffset = offset;
3018 switch (fTagNo(tvb, offset)) {
3020 offset = fRealTag (tvb, subtree, offset, "reference-value: ");
3023 offset = fEnumeratedTag (tvb, subtree, offset,
3024 "status-flags: ", BACnetStatusFlags);
3027 offset = fRealTag (tvb, subtree, offset, "setpoint-value: ");
3030 offset = fRealTag (tvb, subtree, offset, "error-limit: ");
3036 case 5: /* out-of-range */
3037 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3038 lastoffset = offset;
3039 switch (fTagNo(tvb, offset)) {
3041 offset = fRealTag (tvb, subtree, offset, "exceeding-value: ");
3044 offset = fEnumeratedTag (tvb, subtree, offset,
3045 "status-flags: ", BACnetStatusFlags);
3048 offset = fRealTag (tvb, subtree, offset, "deadband: ");
3051 offset = fRealTag (tvb, subtree, offset, "exceeded-limit: ");
3058 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3059 lastoffset = offset;
3060 offset =fBACnetPropertyValue (tvb,subtree,offset);
3063 case 7: /* buffer-ready */
3064 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3065 lastoffset = offset;
3066 switch (fTagNo(tvb, offset)) {
3068 offset = fObjectIdentifier (tvb, subtree, offset); /* buffer-device */
3071 offset = fObjectIdentifier (tvb, subtree, offset); /* buffer-object */
3074 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3075 offset = fDateTime (tvb, subtree, offset, "previous-notification: ");
3076 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3079 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3080 offset = fDateTime (tvb, subtree, offset, "current-notification: ");
3081 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3087 case 8: /* change-of-life-safety */
3088 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3089 lastoffset = offset;
3090 switch (fTagNo(tvb, offset)) {
3092 offset = fEnumeratedTagSplit (tvb, subtree, offset,
3093 "new-state: ", BACnetLifeSafetyState, 256);
3096 offset = fEnumeratedTagSplit (tvb, subtree, offset,
3097 "new-mode: ", BACnetLifeSafetyState, 256);
3100 offset = fEnumeratedTag (tvb, subtree, offset,
3101 "status-flags: ", BACnetStatusFlags);
3103 offset = fEnumeratedTagSplit (tvb, subtree, offset,
3104 "operation-expected: ", BACnetLifeSafetyOperation, 64);
3114 /* Closing tag for parameter choice */
3115 offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3122 fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset)
3124 guint lastoffset = 0;
3126 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3127 lastoffset = offset;
3128 switch (fTagNo(tvb, offset)) {
3129 case 0: /* change-of-bitstring */
3130 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3131 lastoffset = offset;
3132 switch (fTagNo(tvb, offset)) {
3134 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3137 offset = fBitStringTag (tvb, tree, offset, "bitmask: ");
3139 case 2: /* SEQUENCE OF BIT STRING */
3140 offset = fBitStringTagVS (tvb, tree, offset,
3141 "bitstring value: ", BACnetEventTransitionBits);
3148 case 1: /* change-of-state */
3149 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3150 lastoffset = offset;
3151 switch (fTagNo(tvb, offset)) {
3153 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3155 case 1: /* SEQUENCE OF BACnetPropertyStates */
3156 offset = fEnumeratedTagSplit (tvb, tree, offset,
3157 "value: ", BACnetPropertyStates, 64);
3164 case 2: /* change-of-value */
3165 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3166 lastoffset = offset;
3167 switch (fTagNo(tvb, offset)) {
3169 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3171 case 1: /* don't loop it, it's a CHOICE */
3172 switch (fTagNo(tvb, offset)) {
3174 offset = fBitStringTag (tvb, tree, offset, "bitmask: ");
3177 offset = fRealTag (tvb, tree, offset,
3178 "referenced Property Increment: ");
3188 case 3: /* command-failure */
3189 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3190 lastoffset = offset;
3191 switch (fTagNo(tvb, offset)) {
3193 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3196 offset = fDeviceObjectPropertyReference (tvb,tree,offset);
3202 case 4: /* floating-limit */
3203 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3204 lastoffset = offset;
3205 switch (fTagNo(tvb, offset)) {
3207 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3210 offset = fDeviceObjectPropertyReference (tvb,tree,offset);
3213 offset = fRealTag (tvb, tree, offset, "low diff limit: ");
3216 offset = fRealTag (tvb, tree, offset, "high diff limit: ");
3219 offset = fRealTag (tvb, tree, offset, "deadband: ");
3226 case 5: /* out-of-range */
3227 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3228 lastoffset = offset;
3229 switch (fTagNo(tvb, offset)) {
3231 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3234 offset = fRealTag (tvb, tree, offset, "low limit: ");
3237 offset = fRealTag (tvb, tree, offset, "high limit: ");
3240 offset = fRealTag (tvb, tree, offset, "deadband: ");
3248 offset = fBACnetPropertyValue (tvb,tree,offset);
3250 case 7: /* buffer-ready */
3251 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3252 lastoffset = offset;
3253 switch (fTagNo(tvb, offset)) {
3255 offset = fUnsignedTag (tvb,tree,offset,"notification threshold");
3258 offset = fUnsignedTag (tvb,tree,offset,
3259 "previous notification count: ");
3266 case 8: /* change-of-life-safety */
3267 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3268 lastoffset = offset;
3269 switch (fTagNo(tvb, offset)) {
3271 offset = fTimeSpan (tvb, tree, offset, "Time Delay");
3274 offset = fEnumeratedTagSplit (tvb, tree, offset,
3275 "life safety alarm value: ", BACnetLifeSafetyState, 256);
3278 offset = fEnumeratedTagSplit (tvb, tree, offset,
3279 "alarm value: ", BACnetLifeSafetyState, 256);
3282 offset = fDeviceObjectPropertyReference (tvb, tree, offset);
3297 fLogRecord (tvbuff_t *tvb, proto_tree *tree, guint offset)
3299 guint lastoffset = 0;
3301 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3302 lastoffset = offset;
3303 switch (fTagNo(tvb, offset)) {
3304 case 0: /* timestamp */
3305 offset = fDateTime (tvb,tree,offset,NULL);
3307 case 1: /* logDatum: don't loop, it's a CHOICE */
3308 switch (fTagNo(tvb, offset)) {
3309 case 0: /* logStatus */
3310 offset = fEnumeratedTag (tvb, tree, offset,
3311 "log status: ", BACnetLogStatus);
3314 offset = fBooleanTag (tvb, tree, offset, "boolean-value: ");
3317 offset = fRealTag (tvb, tree, offset, "real value: ");
3320 offset = fUnsignedTag (tvb, tree, offset, "enum value: ");
3323 offset = fUnsignedTag (tvb, tree, offset, "unsigned value: ");
3326 offset = fSignedTag (tvb, tree, offset, "signed value: ");
3329 offset = fBitStringTag (tvb, tree, offset, "bitstring value: ");
3332 offset = fNullTag(tvb, tree, offset, "null value: ");
3335 offset = fError (tvb,tree,offset);
3338 offset = fRealTag (tvb, tree, offset, "time change: ");
3340 case 10: /* any Value */
3341 offset = fAbstractSyntaxNType (tvb, tree, offset);
3348 offset = fEnumeratedTag (tvb, tree, offset,
3349 "status Flags: ", BACnetStatusFlags);
3360 fConfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3362 guint lastoffset = 0;
3363 guint8 tag_no, tag_info;
3366 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3367 lastoffset = offset;
3369 switch (fTagNo(tvb,offset)) {
3370 case 0: /* ProcessId */
3371 offset = fProcessId (tvb,tree,offset);
3373 case 1: /* initiating ObjectId */
3374 offset = fObjectIdentifier (tvb, tree, offset);
3376 case 2: /* event ObjectId */
3377 offset = fObjectIdentifier (tvb, tree, offset);
3379 case 3: /* time stamp */
3380 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3381 offset = fTimeStamp (tvb, tree, offset);
3382 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3384 case 4: /* notificationClass */
3385 offset = fUnsignedTag (tvb, tree, offset, "Notification Class: ");
3387 case 5: /* Priority */
3388 offset = fUnsignedTag (tvb, tree, offset, "Priority: ");
3390 case 6: /* EventType */
3391 offset = fEnumeratedTagSplit (tvb, tree, offset,
3392 "Event Type: ", BACnetEventType, 64);
3394 case 7: /* messageText */
3395 offset = fCharacterString (tvb, tree, offset, "message Text: ");
3397 case 8: /* NotifyType */
3398 offset = fEnumeratedTag (tvb, tree, offset,
3399 "Notify Type: ", BACnetNotifyType);
3401 case 9: /* ackRequired */
3402 offset = fBooleanTag (tvb, tree, offset, "ack Required: ");
3404 case 10: /* fromState */
3405 offset = fEnumeratedTagSplit (tvb, tree, offset,
3406 "from State: ", BACnetEventState, 64);
3408 case 11: /* toState */
3409 offset = fEnumeratedTagSplit (tvb, tree, offset,
3410 "to State: ", BACnetEventState, 64);
3412 case 12: /* NotificationParameters */
3413 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3414 offset = fNotificationParameters (tvb, tree, offset);
3415 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3425 fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3427 return fConfirmedEventNotificationRequest (tvb, tree, offset);
3431 fConfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3433 guint lastoffset = 0;
3434 guint8 tag_no, tag_info;
3436 proto_tree *subtree = tree;
3439 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3440 lastoffset = offset;
3441 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
3442 if (tag_is_closing(tag_info)) {
3443 offset += fTagHeaderTree (tvb, subtree, offset,
3444 &tag_no, &tag_info, &lvt);
3450 case 0: /* ProcessId */
3451 offset = fProcessId (tvb,tree,offset);
3453 case 1: /* initiating ObjectId */
3454 offset = fObjectIdentifier (tvb, subtree, offset);
3456 case 2: /* monitored ObjectId */
3457 offset = fObjectIdentifier (tvb, subtree, offset);
3459 case 3: /* time remaining */
3460 offset = fTimeSpan (tvb, tree, offset, "Time remaining");
3462 case 4: /* List of Values */
3463 if (tag_is_opening(tag_info)) {
3464 tt = proto_tree_add_text(subtree, tvb, offset, 1, "list of Values");
3465 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
3466 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3467 offset = fBACnetPropertyValue (tvb, subtree, offset);
3481 fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3483 return fConfirmedCOVNotificationRequest (tvb, tree, offset);
3487 fAcknowlegdeAlarmRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3489 guint lastoffset = 0;
3491 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3492 lastoffset = offset;
3493 switch (fTagNo(tvb, offset)) {
3494 case 0: /* acknowledgingProcessId */
3495 offset = fUnsignedTag (tvb, tree, offset, "acknowledging Process Id: ");
3497 case 1: /* eventObjectId */
3498 offset = fObjectIdentifier (tvb, tree, offset);
3500 case 2: /* eventStateAcknowledged */
3501 offset = fEnumeratedTagSplit (tvb, tree, offset,
3502 "event State Acknowledged: ", BACnetEventState, 64);
3504 case 3: /* timeStamp */
3505 offset = fTime (tvb, tree, offset, "time Stamp: ");
3507 case 4: /* acknowledgementSource */
3508 offset = fCharacterString (tvb, tree, offset, "acknowledgement Source: ");
3510 case 5: /* timeOfAcknowledgement */
3511 offset = fTime (tvb, tree, offset, "time Of Acknowledgement: ");
3522 fGetAlarmSummaryAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3524 guint lastoffset = 0;
3526 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3527 lastoffset = offset;
3528 offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
3529 offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
3530 "alarm State: ", BACnetEventState, 64);
3531 offset = fApplicationTypesEnumerated (tvb, tree, offset,
3532 "acknowledged Transitions: ", BACnetEventTransitionBits);
3538 fGetEnrollmentSummaryRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3540 guint lastoffset = 0;
3541 guint8 tag_no, tag_info;
3544 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3545 lastoffset = offset;
3546 switch (fTagNo(tvb, offset)) {
3547 case 0: /* acknowledgmentFilter */
3548 offset = fEnumeratedTag (tvb, tree, offset,
3549 "acknowledgment Filter: ", BACnetAcknowledgementFilter);
3551 case 1: /* eventObjectId */
3552 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3553 offset = fRecipientProcess (tvb, tree, offset);
3555 case 2: /* eventStateFilter */
3556 offset = fEnumeratedTag (tvb, tree, offset,
3557 "event State Filter: ", BACnetEventStateFilter);
3559 case 3: /* eventTypeFilter */
3560 offset = fEnumeratedTag (tvb, tree, offset,
3561 "event Type Filter: ", BACnetEventType);
3563 case 4: /* priorityFilter */
3564 offset = fUnsignedTag (tvb, tree, offset, "min Priority: ");
3565 offset = fUnsignedTag (tvb, tree, offset, "max Priority: ");
3567 case 5: /* notificationClassFilter */
3568 offset = fUnsignedTag (tvb, tree, offset, "notification Class Filter: ");
3579 fGetEnrollmentSummaryAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3581 guint lastoffset = 0;
3583 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3584 lastoffset = offset;
3585 offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
3586 offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
3587 "event Type: ", BACnetEventType, 64);
3588 offset = fApplicationTypesEnumerated (tvb, tree, offset,
3589 "event State: ", BACnetEventStateFilter);
3590 offset = fApplicationTypes (tvb, tree, offset, "Priority: ");
3591 offset = fApplicationTypes (tvb, tree, offset, "Notification Class: ");
3598 fGetEventInformationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3600 guint lastoffset = 0;
3602 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3603 lastoffset = offset;
3604 switch (fTagNo(tvb, offset)) {
3605 case 0: /* lastReceivedObjectId */
3606 offset = fObjectIdentifier (tvb, tree, offset);
3617 flistOfEventSummaries (tvbuff_t *tvb, proto_tree *tree, guint offset)
3619 guint lastoffset = 0;
3621 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3622 lastoffset = offset;
3623 switch (fTagNo(tvb, offset)) {
3624 case 0: /* ObjectId */
3625 offset = fObjectIdentifier (tvb, tree, offset);
3627 case 1: /* eventState */
3628 offset = fEnumeratedTag (tvb, tree, offset,
3629 "event State: ", BACnetEventStateFilter);
3631 case 2: /* acknowledgedTransitions */
3632 offset = fEnumeratedTag (tvb, tree, offset,
3633 "acknowledged Transitions: ", BACnetEventTransitionBits);
3635 case 3: /* eventTimeStamps */
3636 offset = fTime (tvb, tree, offset, "time Stamp: ");
3637 offset = fTime (tvb, tree, offset, "time Stamp: ");
3638 offset = fTime (tvb, tree, offset, "time Stamp: ");
3640 case 4: /* notifyType */
3641 offset = fEnumeratedTag (tvb, tree, offset,
3642 "Notify Type: ", BACnetNotifyType);
3644 case 5: /* eventEnable */
3645 offset = fEnumeratedTag (tvb, tree, offset,
3646 "event Enable: ", BACnetEventTransitionBits);
3648 case 6: /* eventPriorities */
3649 offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
3650 offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
3651 offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
3662 fGetEventInformationACK (tvbuff_t *tvb, proto_tree *tree, guint offset)
3664 guint lastoffset = 0;
3665 guint8 tag_no, tag_info;
3668 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3669 lastoffset = offset;
3670 switch (fTagNo(tvb, offset)) {
3671 case 0: /* listOfEventSummaries */
3672 offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
3673 offset = flistOfEventSummaries (tvb, tree, offset);
3675 case 1: /* moreEvents */
3676 offset = fBooleanTag (tvb, tree, offset, "more Events: ");
3687 fAddListElementRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3689 guint lastoffset = 0;
3690 guint8 tag_no, tag_info;
3692 proto_tree *subtree = tree;
3695 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3696 lastoffset = offset;
3697 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
3698 if (tag_is_closing(tag_info)) {
3699 offset += fTagHeaderTree (tvb, subtree, offset,
3700 &tag_no, &tag_info, &lvt);
3706 case 0: /* ObjectId */
3707 offset = fBACnetObjectPropertyReference (tvb, subtree, offset);
3709 case 3: /* listOfElements */
3710 if (tag_is_opening(tag_info)) {
3711 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfElements");
3712 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
3713 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3714 offset = fAbstractSyntaxNType (tvb, subtree, offset);
3728 fDeleteObjectRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3730 return fObjectIdentifier (tvb, tree, offset);
3734 fDeviceCommunicationControlRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3736 guint lastoffset = 0;
3738 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3739 lastoffset = offset;
3741 switch (fTagNo(tvb, offset)) {
3742 case 0: /* timeDuration */
3743 offset = fUnsignedTag (tvb,tree,offset,"time Duration: ");
3745 case 1: /* enable-disable */
3746 offset = fEnumeratedTag (tvb, tree, offset, "enable-disable: ",
3747 BACnetEnableDisable);
3749 case 2: /* password */
3750 offset = fCharacterString (tvb, tree, offset, "Password: ");
3761 fReinitializeDeviceRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3763 guint lastoffset = 0;
3765 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3766 lastoffset = offset;
3768 switch (fTagNo(tvb, offset)) {
3769 case 0: /* reinitializedStateOfDevice */
3770 offset = fEnumeratedTag (tvb, tree, offset,
3771 "reinitialized State Of Device: ",
3772 BACnetReinitializedStateOfDevice);
3774 case 1: /* password */
3775 offset = fCharacterString (tvb, tree, offset, "Password: ");
3786 fVtOpenRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3788 offset = fApplicationTypesEnumerated (tvb, tree, offset,
3789 "vtClass: ", BACnetVTClass);
3790 return fApplicationTypes (tvb,tree,offset,"local VT Session ID: ");
3794 fVtOpenAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3796 return fApplicationTypes (tvb,tree,offset,"remote VT Session ID: ");
3800 fVtCloseRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3802 guint lastoffset = 0;
3804 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3805 lastoffset = offset;
3806 offset= fApplicationTypes (tvb,tree,offset,"remote VT Session ID: ");
3812 fVtDataRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3814 offset= fApplicationTypes (tvb,tree,offset,"VT Session ID: ");
3815 offset = fApplicationTypes (tvb, tree, offset, "VT New Data: ");
3816 return fApplicationTypes (tvb,tree,offset,"VT Data Flag: ");;
3820 fVtDataAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3822 guint lastoffset = 0;
3824 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3825 lastoffset = offset;
3827 switch (fTagNo(tvb,offset)) {
3828 case 0: /* BOOLEAN */
3829 offset = fBooleanTag (tvb, tree, offset, "all New Data Accepted: ");
3831 case 1: /* Unsigned OPTIONAL */
3832 offset = fUnsignedTag (tvb, tree, offset, "accepted Octet Count: ");
3842 fAuthenticateRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3844 guint lastoffset = 0;
3846 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3847 lastoffset = offset;
3849 switch (fTagNo(tvb,offset)) {
3850 case 0: /* Unsigned32 */
3851 offset = fUnsignedTag (tvb, tree, offset, "pseudo Random Number: ");
3853 case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
3854 proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
3856 case 2: /* Chararacter String OPTIONAL */
3857 offset = fCharacterString (tvb, tree, offset, "operator Name: ");
3859 case 3: /* Chararacter String OPTIONAL */
3860 offset = fCharacterString (tvb, tree, offset, "operator Password: ");
3862 case 4: /* Boolean OPTIONAL */
3863 offset = fBooleanTag (tvb, tree, offset, "start Encyphered Session: ");
3873 fAuthenticateAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3875 return fApplicationTypes (tvb, tree, offset, "modified Random Number: ");
3879 fRequestKeyRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
3881 offset = fObjectIdentifier (tvb, tree, offset); /* Requesting Device Identifier */
3882 offset = fAddress (tvb, tree, offset);
3883 offset = fObjectIdentifier (tvb, tree, offset); /* Remote Device Identifier */
3884 return fAddress (tvb, tree, offset);
3888 fRemoveListElementRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3890 /* Same as AddListElement request after service choice */
3891 return fAddListElementRequest(tvb, tree, offset);
3895 fReadPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3897 return fBACnetObjectPropertyReference(tvb, tree, offset);
3901 fReadPropertyAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
3903 guint lastoffset = 0;
3904 guint8 tag_no, tag_info;
3906 proto_tree *subtree = tree;
3909 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3910 lastoffset = offset;
3911 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
3912 if (tag_is_closing(tag_info)) {
3913 offset += fTagHeaderTree (tvb, subtree, offset,
3914 &tag_no, &tag_info, &lvt);
3919 case 0: /* objectIdentifier */
3920 offset = fObjectIdentifier (tvb, subtree, offset);
3922 case 1: /* propertyIdentifier */
3923 offset = fPropertyIdentifier (tvb, subtree, offset);
3925 case 2: /* propertyArrayIndex */
3926 offset = fSignedTag (tvb, subtree, offset, "property Array Index: ");
3928 case 3: /* propertyValue */
3929 if (tag_is_opening(tag_info)) {
3930 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
3931 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
3932 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3933 offset = fAbstractSyntaxNType (tvb, subtree, offset);
3946 fWritePropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
3948 guint lastoffset = 0;
3949 guint8 tag_no, tag_info;
3951 proto_tree *subtree = tree;
3954 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
3955 lastoffset = offset;
3956 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
3957 if (tag_is_closing(tag_info)) {
3958 offset += fTagHeaderTree (tvb, subtree, offset,
3959 &tag_no, &tag_info, &lvt);
3965 case 0: /* objectIdentifier */
3966 offset = fObjectIdentifier (tvb, subtree, offset);
3968 case 1: /* propertyIdentifier */
3969 offset = fPropertyIdentifier (tvb, subtree, offset);
3971 case 2: /* propertyArrayIndex */
3972 offset = fSignedTag (tvb, subtree, offset, "property Array Index: ");
3974 case 3: /* propertyValue */
3975 if (tag_is_opening(tag_info)) {
3976 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
3977 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
3978 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
3979 offset = fAbstractSyntaxNType (tvb, subtree, offset);
3984 case 4: /* Priority (only used for write) */
3985 offset = fSignedTag (tvb, subtree, offset, "Priority: ");
3995 fWriteAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
3997 guint lastoffset = 0;
3998 guint8 tag_no, tag_info;
4001 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4002 lastoffset = offset;
4003 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4004 if (tag_is_closing(tag_info)) {
4005 offset += fTagHeaderTree (tvb, subtree, offset,
4006 &tag_no, &tag_info, &lvt);
4011 case 0: /* objectIdentifier */
4012 offset = fObjectIdentifier (tvb, subtree, offset);
4014 case 1: /* listOfPropertyValues */
4015 if (tag_is_opening(tag_info)) {
4016 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4017 offset = fBACnetPropertyValue (tvb, subtree, offset);
4030 fWritePropertyMultipleRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4032 if (offset >= tvb_reported_length(tvb))
4035 return fWriteAccessSpecification (tvb, tree, offset);
4039 fPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
4041 guint lastoffset = 0;
4042 guint8 tag_no, tag_info;
4045 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4046 lastoffset = offset;
4047 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4048 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
4051 switch (tag_no-tagoffset) {
4052 case 0: /* PropertyIdentifier */
4053 offset = fPropertyIdentifier (tvb, tree, offset);
4055 case 1: /* propertyArrayIndex */
4056 offset = fUnsignedTag (tvb, tree, offset, "property Array Index: ");
4057 if (list != 0) break; /* Continue decoding if this may be a list */
4059 lastoffset = offset; /* Set loop end condition */
4067 fBACnetPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 list)
4069 return fPropertyReference(tvb, tree, offset, 0, list);
4073 fBACnetObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
4075 guint lastoffset = 0;
4077 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4078 lastoffset = offset;
4080 switch (fTagNo(tvb,offset)) {
4081 case 0: /* ObjectIdentifier */
4082 offset = fObjectIdentifier (tvb, tree, offset);
4084 case 1: /* PropertyIdentifier and propertyArrayIndex */
4085 offset = fPropertyReference (tvb, tree, offset, 1, 0);
4087 lastoffset = offset; /* Set loop end condition */
4096 fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
4098 guint lastoffset = 0;
4099 guint8 tag_no, tag_info;
4101 proto_tree* subtree = tree;
4104 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4105 lastoffset = offset;
4106 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4107 if (tag_is_closing(tag_info)) {
4108 offset += fTagHeaderTree (tvb, subtree, offset,
4109 &tag_no, &tag_info, &lvt);
4113 case 0: /* ObjectIdentifier */
4114 offset = fObjectIdentifier (tvb, subtree, offset);
4116 case 1: /* PropertyIdentifier */
4117 offset = fPropertyIdentifier (tvb, subtree, offset);
4119 case 2: /* propertyArrayIndex */
4120 offset = fUnsignedTag (tvb, subtree, offset, "property Array Index: ");
4123 if (tag_is_opening(tag_info)) {
4124 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
4125 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4126 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4127 offset = fAbstractSyntaxNType (tvb, subtree, offset);
4132 case 4: /* Priority */
4133 offset = fSignedTag (tvb, subtree, offset, "Priority: ");
4145 fDeviceObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
4147 guint lastoffset = 0;
4149 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4150 lastoffset = offset;
4152 switch (fTagNo(tvb,offset)) {
4153 case 0: /* ObjectIdentifier */
4154 offset = fBACnetObjectPropertyReference (tvb, tree, offset);
4156 case 3: /* deviceIdentifier */
4157 offset = fObjectIdentifier (tvb, tree, offset);
4168 fPriorityArray (tvbuff_t *tvb, proto_tree *tree, guint offset)
4172 if (offset >= tvb_reported_length(tvb))
4175 for (i = 1; i <= 16; i++) {
4176 g_snprintf (ar, sizeof(ar), "%s[%d]: ",
4177 val_to_split_str(87 , 512,
4178 BACnetPropertyIdentifier,
4179 ASHRAE_Reserved_Fmt,
4180 Vendor_Proprietary_Fmt),
4182 /* DMR Replace with fAbstractNSyntax */
4183 offset = fApplicationTypes(tvb, tree, offset, ar);
4190 fDeviceObjectReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
4192 guint lastoffset = 0;
4194 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4195 lastoffset = offset;
4197 switch (fTagNo(tvb,offset)) {
4198 case 0: /* deviceIdentifier */
4199 offset = fObjectIdentifier (tvb, tree, offset);
4201 case 1: /* ObjectIdentifier */
4202 offset = fObjectIdentifier (tvb, tree, offset);
4213 fSpecialEvent (tvbuff_t *tvb, proto_tree *subtree, guint offset)
4215 guint8 tag_no, tag_info;
4217 guint lastoffset = 0;
4219 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4220 lastoffset = offset;
4221 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4222 if (tag_is_closing(tag_info)) {
4223 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4227 switch (fTagNo(tvb,offset)) {
4228 case 0: /* calendaryEntry */
4229 offset = fCalendaryEntry (tvb, subtree, offset);
4231 case 1: /* calendarReference */
4232 offset = fObjectIdentifier (tvb, subtree, offset);
4234 case 2: /* calendarReference */
4235 if (tag_is_opening(tag_info)) {
4236 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4237 offset = fTimeValue (tvb, subtree, offset);
4242 case 3: /* eventPriority */
4243 offset = fUnsignedTag (tvb, subtree, offset, "event priority: ");
4253 fSelectionCriteria (tvbuff_t *tvb, proto_tree *tree, guint offset)
4255 guint lastoffset = 0;
4257 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4258 lastoffset = offset;
4260 switch (fTagNo(tvb,offset)) {
4261 case 0: /* propertyIdentifier */
4262 offset = fPropertyIdentifier (tvb, tree, offset);
4264 case 1: /* propertyArrayIndex */
4265 offset = fUnsignedTag (tvb, tree, offset, "property Array Index: ");
4267 case 2: /* relationSpecifier */
4268 offset = fEnumeratedTag (tvb, tree, offset,
4269 "relation Specifier: ", BACnetRelationSpecifier);
4271 case 3: /* comparisonValue */
4272 offset = fAbstractSyntaxNType (tvb, tree, offset);
4282 fObjectSelectionCriteria (tvbuff_t *tvb, proto_tree *subtree, guint offset)
4284 guint lastoffset = 0;
4285 guint8 tag_no, tag_info;
4288 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4289 lastoffset = offset;
4290 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4291 if (tag_is_closing(tag_info)) {
4292 offset += fTagHeaderTree (tvb, subtree, offset,
4293 &tag_no, &tag_info, &lvt);
4298 case 0: /* selectionLogic */
4299 offset = fEnumeratedTag (tvb, subtree, offset,
4300 "selection Logic: ", BACnetSelectionLogic);
4302 case 1: /* listOfSelectionCriteria */
4303 if (tag_is_opening(tag_info)) {
4304 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4305 offset = fSelectionCriteria (tvb, subtree, offset);
4319 fReadPropertyConditionalRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
4321 guint lastoffset = 0;
4322 guint8 tag_no, tag_info;
4325 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4326 lastoffset = offset;
4327 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4328 if (tag_is_closing(tag_info)) {
4329 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4334 case 0: /* objectSelectionCriteria */
4335 offset = fObjectSelectionCriteria (tvb, subtree, offset);
4337 case 1: /* listOfPropertyReferences */
4338 if (tag_is_opening(tag_info)) {
4339 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4340 offset = fBACnetPropertyReference (tvb, subtree, offset, 1);
4353 fReadAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
4355 guint lastoffset = 0;
4356 guint8 tag_no, tag_info;
4359 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4360 lastoffset = offset;
4361 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4362 if (tag_is_closing(tag_info)) {
4363 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no,
4369 case 0: /* objectIdentifier */
4370 offset = fObjectIdentifier (tvb, subtree, offset);
4372 case 1: /* listOfPropertyReferences */
4373 if (tag_is_opening(tag_info)) {
4374 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4375 offset = fBACnetPropertyReference (tvb, subtree, offset, 1);
4388 fReadAccessResult (tvbuff_t *tvb, proto_tree *tree, guint offset)
4390 guint lastoffset = 0;
4394 proto_tree *subtree = tree;
4397 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4398 lastoffset = offset;
4399 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4400 if (tag_is_closing(tag_info)) {
4401 offset += fTagHeaderTree (tvb, subtree, offset,
4402 &tag_no, &tag_info, &lvt);
4403 if (tag_no == 4 || tag_no == 5) subtree = tree; /* Value and error have extra subtree */
4408 case 0: /* objectSpecifier */
4409 offset = fObjectIdentifier (tvb, subtree, offset);
4411 case 1: /* list of Results */
4412 if (tag_is_opening(tag_info)) {
4413 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfResults");
4414 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4415 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4420 case 2: /* propertyIdentifier */
4421 offset = fPropertyValue(tvb, subtree, offset, 2);
4423 case 5: /* propertyAccessError */
4424 if (tag_is_opening(tag_info)) {
4425 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyAccessError");
4426 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4427 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4428 /* Error Code follows */
4429 offset = fError(tvb, subtree, offset);
4443 fReadPropertyConditionalAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4445 /* listOfReadAccessResults */
4446 return fReadAccessResult (tvb, tree, offset);
4451 fObjectSpecifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
4453 guint lastoffset = 0;
4455 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4456 lastoffset = offset;
4457 switch (fTagNo(tvb, offset)) {
4458 case 0: /* objectType */
4459 proto_tree_add_item(tree, hf_bacapp_tag_initiatingObjectType, tvb, offset++, 1, TRUE);
4461 case 1: /* objectIdentifier */
4462 offset = fObjectIdentifier (tvb, tree, offset);
4472 fCreateObjectRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
4474 guint lastoffset = 0;
4475 guint8 tag_no, tag_info;
4478 while ((tvb_length_remaining(tvb, offset) > 0) && (offset > lastoffset)) { /* exit loop if nothing happens inside */
4479 lastoffset = offset;
4480 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4481 if (tag_is_closing(tag_info)) {
4482 offset += fTagHeaderTree (tvb, subtree, offset,
4483 &tag_no, &tag_info, &lvt);
4488 case 0: /* objectSpecifier */
4489 offset = fObjectSpecifier (tvb, subtree, offset);
4491 case 1: /* propertyValue */
4492 if (tag_is_opening(tag_info)) {
4493 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4494 offset = fBACnetPropertyValue (tvb, subtree, offset);
4507 fCreateObjectAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4509 return fObjectIdentifier (tvb, tree, offset);
4513 fReadRangeRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4515 guint lastoffset = 0;
4516 guint8 tag_no, tag_info;
4518 proto_tree *subtree = tree;
4521 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4522 lastoffset = offset;
4523 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4524 if (tag_is_closing(tag_info)) {
4525 offset += fTagHeaderTree (tvb, subtree, offset,
4526 &tag_no, &tag_info, &lvt);
4532 case 0: /* objectSpecifier */
4533 offset = fObjectIdentifier (tvb, subtree, offset);
4535 case 1: /* propertyIdentifier */
4536 offset = fPropertyIdentifier (tvb, subtree, offset);
4538 case 2: /* propertyArrayIndex Optional */
4539 offset = fUnsignedTag (tvb, subtree, offset, "Property Array Index: ");
4541 case 3: /* range byPosition */
4542 if (tag_is_opening(tag_info)) {
4543 tt = proto_tree_add_text(subtree, tvb, offset, 1, "range byPosition");
4544 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4545 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4546 offset = fApplicationTypes (tvb, subtree, offset, "reference Index: ");
4547 offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
4552 case 4: /* range byTime */
4553 if (tag_is_opening(tag_info)) {
4554 tt = proto_tree_add_text(subtree, tvb, offset, 1, "range byTime");
4555 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4556 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4557 offset = fApplicationTypes (tvb, subtree, offset, "reference Time: ");
4558 offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
4563 case 5: /* range timeRange */
4564 if (tag_is_opening(tag_info)) {
4565 tt = proto_tree_add_text(subtree, tvb, offset, 1, "range timeRange");
4566 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4567 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4568 offset = fApplicationTypes (tvb, subtree, offset, "beginning Time: ");
4569 offset = fApplicationTypes (tvb, subtree, offset, "ending Time: ");
4582 fReadRangeAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4584 guint lastoffset = 0;
4585 guint8 tag_no, tag_info;
4587 proto_tree *subtree = tree;
4590 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4591 lastoffset = offset;
4592 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4593 if (tag_is_closing(tag_info)) {
4594 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4600 case 0: /* objectSpecifier */
4601 offset = fObjectIdentifier (tvb, subtree, offset);
4603 case 1: /* propertyIdentifier */
4604 offset = fPropertyIdentifier (tvb, subtree, offset);
4606 case 2: /* propertyArrayIndex Optional */
4607 offset = fUnsignedTag (tvb, subtree, offset, "Property Array Index: ");
4609 case 3: /* resultFlags */
4610 offset = fEnumeratedTag (tvb, tree, offset,
4611 "result Flags: ", BACnetResultFlags);
4613 case 4: /* itemCount */
4614 offset = fUnsignedTag (tvb, subtree, offset, "item Count: ");
4616 case 5: /* itemData */
4617 if (tag_is_opening(tag_info)) {
4618 tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
4619 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4620 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4621 offset = fAbstractSyntaxNType (tvb, subtree, offset);
4626 case 6: /* firstSequenceNumber */
4627 offset = fUnsignedTag (tvb, subtree, offset, "first Sequence Number: ");
4636 static guint fAccessMethod(tvbuff_t *tvb, proto_tree *tree, guint offset)
4639 guint8 tag_no, tag_info;
4641 proto_tree* subtree = NULL;
4643 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4646 case 0: /* streamAccess */
4647 if (tag_is_opening(tag_info)) {
4648 tt = proto_tree_add_text(tree, tvb, offset, 1, "stream Access");
4649 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4650 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4651 offset = fApplicationTypes (tvb, subtree, offset, "File Start Position: ");
4652 offset = fApplicationTypes (tvb, subtree, offset, "file Data: ");
4654 if (bacapp_flags & 0x04) { /* More Flag is set */
4657 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4658 if (tag_is_closing(tag_info)) {
4659 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4662 case 1: /* recordAccess */
4663 if (tag_is_opening(tag_info)) {
4664 tt = proto_tree_add_text(tree, tvb, offset, 1, "record Access");
4665 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4666 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4667 offset = fApplicationTypes (tvb, subtree, offset, "File Start Record: ");
4668 offset = fApplicationTypes (tvb, subtree, offset, "Record Count: ");
4669 offset = fApplicationTypes (tvb, subtree, offset, "Data: ");
4671 if (bacapp_flags & 0x04) { /* More Flag is set */
4674 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4675 if (tag_is_closing(tag_info)) {
4676 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4687 fAtomicReadFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4689 guint lastoffset = 0;
4690 guint8 tag_no, tag_info;
4692 proto_tree *subtree = tree;
4695 offset = fObjectIdentifier (tvb, tree, offset);
4697 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4698 lastoffset = offset;
4699 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4700 if (tag_is_closing(tag_info)) {
4701 offset += fTagHeaderTree (tvb, subtree, offset,
4702 &tag_no, &tag_info, &lvt);
4708 case 0: /* streamAccess */
4709 if (tag_is_opening(tag_info)) {
4710 tt = proto_tree_add_text(subtree, tvb, offset, 1, "stream Access");
4711 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4712 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4713 offset = fSignedTag (tvb, subtree, offset, "File Start Position: ");
4714 offset = fUnsignedTag (tvb, subtree, offset, "requested Octet Count: ");
4719 case 1: /* recordAccess */
4720 if (tag_is_opening(tag_info)) {
4721 tt = proto_tree_add_text(subtree, tvb, offset, 1, "record Access");
4722 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
4723 offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
4724 offset = fSignedTag (tvb, subtree, offset, "File Start Record: ");
4725 offset = fUnsignedTag (tvb, subtree, offset, "requested Record Count: ");
4738 fAtomicWriteFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
4741 offset = fObjectIdentifier (tvb, tree, offset); /* file Identifier */
4742 offset = fAccessMethod(tvb, tree, offset);
4748 fAtomicWriteFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4750 switch (fTagNo(tvb, offset)) {
4751 case 0: /* streamAccess */
4752 offset = fSignedTag (tvb, tree, offset, "File Start Position: ");
4754 case 1: /* recordAccess */
4755 offset = fSignedTag (tvb, tree, offset, "File Start Record: ");
4764 fAtomicReadFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4766 guint8 tag_no, tag_info;
4768 proto_tree *subtree = tree;
4770 fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
4771 offset = fApplicationTypes (tvb, subtree, offset, "End Of File: ");
4772 offset = fAccessMethod(tvb, tree, offset);
4778 fReadPropertyMultipleRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
4780 return fReadAccessSpecification (tvb,subtree,offset);
4784 fReadPropertyMultipleAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
4786 return fReadAccessResult (tvb,tree,offset);
4790 fConfirmedServiceRequest (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
4792 if (tvb_length_remaining(tvb,offset) <= 0)
4795 switch (service_choice) {
4796 case 0: /* acknowledgeAlarm */
4797 offset = fAcknowlegdeAlarmRequest (tvb, tree, offset);
4799 case 1: /* confirmedCOVNotification */
4800 offset = fConfirmedCOVNotificationRequest (tvb, tree, offset);
4802 case 2: /* confirmedEventNotification */
4803 offset = fConfirmedEventNotificationRequest (tvb, tree, offset);
4805 case 3: /* confirmedGetAlarmSummary conveys no parameters */
4807 case 4: /* getEnrollmentSummaryRequest */
4808 offset = fGetEnrollmentSummaryRequest (tvb, tree, offset);
4810 case 5: /* subscribeCOVRequest */
4811 offset = fSubscribeCOVRequest(tvb, tree, offset);
4813 case 6: /* atomicReadFile-Request */
4814 offset = fAtomicReadFileRequest(tvb, tree, offset);
4816 case 7: /* atomicWriteFile-Request */
4817 offset = fAtomicWriteFileRequest(tvb, tree, offset);
4819 case 8: /* AddListElement-Request */
4820 offset = fAddListElementRequest(tvb, tree, offset);
4822 case 9: /* removeListElement-Request */
4823 offset = fRemoveListElementRequest(tvb, tree, offset);
4825 case 10: /* createObjectRequest */
4826 offset = fCreateObjectRequest(tvb, tree, offset);
4828 case 11: /* deleteObject */
4829 offset = fDeleteObjectRequest(tvb, tree, offset);
4832 offset = fReadPropertyRequest(tvb, tree, offset);
4835 offset = fReadPropertyConditionalRequest(tvb, tree, offset);
4838 offset = fReadPropertyMultipleRequest(tvb, tree, offset);
4841 offset = fWritePropertyRequest(tvb, tree, offset);
4844 offset = fWritePropertyMultipleRequest(tvb, tree, offset);
4847 offset = fDeviceCommunicationControlRequest(tvb, tree, offset);
4850 offset = fConfirmedPrivateTransferRequest(tvb, tree, offset);
4853 offset = fConfirmedTextMessageRequest(tvb, tree, offset);
4856 offset = fReinitializeDeviceRequest(tvb, tree, offset);
4859 offset = fVtOpenRequest(tvb, tree, offset);
4862 offset = fVtCloseRequest (tvb, tree, offset);
4865 offset = fVtDataRequest (tvb, tree, offset);
4868 offset = fAuthenticateRequest (tvb, tree, offset);
4871 offset = fRequestKeyRequest (tvb, tree, offset);
4874 offset = fReadRangeRequest (tvb, tree, offset);
4877 offset = fLifeSafetyOperationRequest(tvb, tree, offset, NULL);
4880 offset = fSubscribeCOVPropertyRequest(tvb, tree, offset);
4883 offset = fGetEventInformationRequest (tvb, tree, offset);
4893 fConfirmedServiceAck (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
4895 if (tvb_length_remaining(tvb,offset) <= 0)
4898 switch (service_choice) {
4899 case 3: /* confirmedEventNotificationAck */
4900 offset = fGetAlarmSummaryAck (tvb, tree, offset);
4902 case 4: /* getEnrollmentSummaryAck */
4903 offset = fGetEnrollmentSummaryAck (tvb, tree, offset);
4905 case 6: /* atomicReadFile */
4906 offset = fAtomicReadFileAck (tvb, tree, offset);
4908 case 7: /* atomicReadFileAck */
4909 offset = fAtomicWriteFileAck (tvb, tree, offset);
4911 case 10: /* createObject */
4912 offset = fCreateObjectAck (tvb, tree, offset);
4915 offset = fReadPropertyAck (tvb, tree, offset);
4918 offset = fReadPropertyConditionalAck (tvb, tree, offset);
4921 offset = fReadPropertyMultipleAck (tvb, tree, offset);
4924 offset = fConfirmedPrivateTransferAck(tvb, tree, offset);
4927 offset = fVtOpenAck (tvb, tree, offset);
4930 offset = fVtDataAck (tvb, tree, offset);
4933 offset = fAuthenticateAck (tvb, tree, offset);
4936 offset = fReadRangeAck (tvb, tree, offset);
4939 offset = fGetEventInformationACK (tvb, tree, offset);
4948 fIAmRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4950 /* BACnetObjectIdentifier */
4951 offset = fApplicationTypes (tvb, tree, offset, "BACnet Object Identifier: ");
4953 /* MaxAPDULengthAccepted */
4954 offset = fApplicationTypes (tvb, tree, offset, "Maximum ADPU Length Accepted: ");
4956 /* segmentationSupported */
4957 offset = fApplicationTypesEnumerated (tvb, tree, offset,
4958 "Segmentation Supported: ", BACnetSegmentation);
4961 return fUnsignedTag (tvb, tree, offset, "Vendor ID: ");
4965 fIHaveRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4967 /* BACnetDeviceIdentifier */
4968 offset = fApplicationTypes (tvb, tree, offset, "Device Identifier: ");
4970 /* BACnetObjectIdentifier */
4971 offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
4974 return fApplicationTypes (tvb, tree, offset, "Object Name: ");
4979 fWhoIsRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
4981 guint lastoffset = 0;
4983 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
4984 lastoffset = offset;
4985 switch (fTagNo(tvb, offset)) {
4986 case 0: /* DeviceInstanceRangeLowLimit Optional */
4987 offset = fUnsignedTag (tvb, tree, offset, "Device Instance Range Low Limit: ");
4989 case 1: /* DeviceInstanceRangeHighLimit Optional but required if DeviceInstanceRangeLowLimit is there */
4990 offset = fUnsignedTag (tvb, tree, offset, "Device Instance Range High Limit: ");
5001 fUnconfirmedServiceRequest (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
5003 if (tvb_length_remaining(tvb,offset) <= 0)
5006 switch (service_choice) {
5007 case 0: /* I-Am-Request */
5008 offset = fIAmRequest (tvb, tree, offset);
5010 case 1: /* i-Have Request */
5011 offset = fIHaveRequest (tvb, tree, offset);
5013 case 2: /* unconfirmedCOVNotification */
5014 offset = fUnconfirmedCOVNotificationRequest (tvb, tree, offset);
5016 case 3: /* unconfirmedEventNotification */
5017 offset = fUnconfirmedEventNotificationRequest (tvb, tree, offset);
5019 case 4: /* unconfirmedPrivateTransfer */
5020 offset = fUnconfirmedPrivateTransferRequest(tvb, tree, offset);
5022 case 5: /* unconfirmedTextMessage */
5023 offset = fUnconfirmedTextMessageRequest(tvb, tree, offset);
5025 case 6: /* timeSynchronization */
5026 offset = fTimeSynchronizationRequest (tvb, tree, offset);
5028 case 7: /* who-Has */
5029 offset = fWhoHas (tvb, tree, offset);
5031 case 8: /* who-Is */
5032 offset = fWhoIsRequest (tvb, tree, offset);
5034 case 9: /* utcTimeSynchronization */
5035 offset = fUTCTimeSynchronizationRequest (tvb, tree, offset);
5044 fStartConfirmed(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset, guint8 ack,
5045 gint *svc, proto_item **tt)
5048 proto_tree *bacapp_tree_control;
5049 gint tmp, bacapp_type;
5053 tmp = (gint) tvb_get_guint8(tvb, offset);
5054 bacapp_type = (tmp >> 4) & 0x0f;
5055 bacapp_flags = tmp & 0x0f;
5060 *svc = (gint) tvb_get_guint8(tvb, offset+extra);
5061 if (bacapp_flags & 0x08)
5062 *svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
5064 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
5065 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, TRUE);
5066 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
5068 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, TRUE);
5069 proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, TRUE);
5070 if (ack == 0) /* The following are for ConfirmedRequest, not Complex ack */
5072 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, TRUE);
5073 proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
5075 proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
5079 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
5080 if (bacapp_flags & 0x08) {
5081 bacapp_seq = tvb_get_guint8(tvb, offset);
5082 proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
5084 proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
5087 *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
5093 fConfirmedRequestPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5094 { /* BACnet-Confirmed-Request */
5095 /* ASHRAE 135-2001 20.1.2 */
5099 offset = fStartConfirmed(tvb, bacapp_tree, offset, 0, &svc, &tt);
5100 if (bacapp_seq > 0) /* Can't handle continuation segments, so just treat as data */
5102 proto_tree_add_text(bacapp_tree, tvb, offset, 0, "(continuation)");
5107 /* Service Request follows... Variable Encoding 20.2ff */
5108 return fConfirmedServiceRequest (tvb, bacapp_tree, offset, svc);
5113 fUnconfirmedRequestPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5114 { /* BACnet-Unconfirmed-Request-PDU */
5115 /* ASHRAE 135-2001 20.1.3 */
5119 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
5121 tmp = tvb_get_guint8(tvb, offset);
5122 proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
5124 /* Service Request follows... Variable Encoding 20.2ff */
5125 return fUnconfirmedServiceRequest (tvb, bacapp_tree, offset, tmp);
5129 fSimpleAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5130 { /* BACnet-Simple-Ack-PDU */
5131 /* ASHRAE 135-2001 20.1.4 */
5135 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
5137 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5139 proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
5145 fComplexAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5146 { /* BACnet-Complex-Ack-PDU */
5147 /* ASHRAE 135-2001 20.1.5 */
5151 offset = fStartConfirmed(tvb, bacapp_tree, offset, 1, &svc, &tt);
5153 if (bacapp_seq > 0) /* Can't handle continuation segments, so just treat as data */
5155 proto_tree_add_text(bacapp_tree, tvb, offset, 0, "(continuation)");
5160 /* Service ACK follows... */
5161 return fConfirmedServiceAck (tvb, bacapp_tree, offset, svc);
5167 fSegmentAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5168 { /* BACnet-SegmentAck-PDU */
5169 /* ASHRAE 135-2001 20.1.6 */
5172 proto_tree *bacapp_tree_control;
5174 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
5175 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
5177 proto_tree_add_item(bacapp_tree, hf_bacapp_NAK, tvb, offset, 1, TRUE);
5178 proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
5179 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5181 proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
5183 proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
5188 static guint fContextTaggedError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5190 guint8 tag_info = 0;
5191 guint8 parsed_tag = 0;
5193 offset += fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
5194 offset = fError(tvb, tree, offset);
5195 return offset + fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
5199 fConfirmedPrivateTransferError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5201 guint lastoffset = 0;
5203 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
5204 lastoffset = offset;
5205 switch (fTagNo(tvb, offset)) {
5206 case 0: /* errorType */
5207 offset = fContextTaggedError(tvb,tree,offset);
5209 case 1: /* vendorID */
5210 offset = fUnsignedTag (tvb,tree,offset,"vendor ID: ");
5212 case 2: /* serviceNumber */
5213 offset = fUnsignedTag (tvb,tree,offset,"service Number: ");
5215 case 3: /* errorParameters */
5216 offset = fAbstractSyntaxNType (tvb, tree, offset);
5226 fCreateObjectError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5228 guint lastoffset = 0;
5230 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
5231 lastoffset = offset;
5232 switch (fTagNo(tvb, offset)) {
5233 case 0: /* errorType */
5234 offset = fContextTaggedError(tvb,tree,offset);
5236 case 1: /* firstFailedElementNumber */
5237 offset = fUnsignedTag (tvb,tree,offset,"first failed element number: ");
5247 fChangeListError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5249 guint lastoffset = 0;
5251 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
5252 lastoffset = offset;
5253 switch (fTagNo(tvb, offset)) {
5254 case 0: /* errorType */
5255 offset = fContextTaggedError(tvb,tree,offset);
5257 case 1: /* firstFailedElementNumber */
5258 offset = fUnsignedTag (tvb,tree,offset,"first failed element number: ");
5269 fVTSession(tvbuff_t *tvb, proto_tree *tree, guint offset)
5271 if (tvb_length_remaining(tvb, offset) > 0) { /* don't loop */
5272 offset = fUnsignedTag (tvb,tree,offset, "local-VTSessionID: ");
5273 offset = fUnsignedTag (tvb,tree,offset, "remote-VTSessionID: ");
5274 offset = fAddress (tvb,tree,offset);
5281 fVTCloseError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5283 guint lastoffset = 0;
5285 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
5286 lastoffset = offset;
5287 switch (fTagNo(tvb, offset)) {
5288 case 0: /* errorType */
5289 offset = fContextTaggedError(tvb,tree,offset);
5291 case 1: /* listOfVTSessionIdentifiers */
5292 offset = fUnsignedTag (tvb,tree,offset,"VT SessionID: ");
5302 fWritePropertyMultipleError(tvbuff_t *tvb, proto_tree *tree, guint offset)
5304 guint lastoffset = 0;
5306 while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
5307 lastoffset = offset;
5308 switch (fTagNo(tvb, offset)) {
5309 case 0: /* errorType */
5310 offset = fContextTaggedError(tvb,tree,offset);
5312 case 1: /* firstFailedWriteAttempt */
5313 offset = fUnsignedTag (tvb,tree,offset,"first failed write attempt: ");
5323 fError (tvbuff_t *tvb, proto_tree *tree, guint offset)
5325 offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
5326 "error Class: ", BACnetErrorClass, 64);
5327 return fApplicationTypesEnumeratedSplit (tvb, tree, offset,
5328 "error Code: ", BACnetErrorCode, 256);
5332 fBACnetError (tvbuff_t *tvb, proto_tree *tree, guint offset, guint service)
5335 case 8: /* no break here !!!! */
5337 offset = fChangeListError (tvb, tree, offset);
5340 offset = fCreateObjectError (tvb,tree,offset);
5343 offset = fWritePropertyMultipleError (tvb,tree,offset);
5346 offset = fConfirmedPrivateTransferError (tvb,tree,offset);
5348 offset = fVTCloseError (tvb,tree,offset);
5350 return fError (tvb, tree, offset);
5357 fErrorPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5358 { /* BACnet-Error-PDU */
5359 /* ASHRAE 135-2001 20.1.7 */
5361 proto_item *tc, *tt;
5362 proto_tree *bacapp_tree_control;
5365 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
5366 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
5368 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5370 tmp = tvb_get_guint8(tvb, offset);
5371 tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
5373 /* Error Handling follows... */
5374 return fBACnetError (tvb, bacapp_tree, offset, tmp);
5378 fRejectPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5379 { /* BACnet-Reject-PDU */
5380 /* ASHRAE 135-2001 20.1.8 */
5383 proto_tree *bacapp_tree_control;
5385 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
5386 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
5388 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5390 proto_tree_add_item(bacapp_tree, hf_BACnetRejectReason, tvb,
5396 fAbortPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
5397 { /* BACnet-Abort-PDU */
5398 /* ASHRAE 135-2001 20.1.9 */
5401 proto_tree *bacapp_tree_control;
5403 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
5404 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
5406 proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
5407 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
5409 proto_tree_add_item(bacapp_tree, hf_BACnetAbortReason, tvb,
5415 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5417 gint8 tmp, bacapp_type;
5420 guint8 bacapp_service, bacapp_reason;
5422 proto_tree *bacapp_tree;
5424 if (check_col(pinfo->cinfo, COL_PROTOCOL))
5425 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
5426 if (check_col(pinfo->cinfo, COL_INFO))
5427 col_add_str(pinfo->cinfo, COL_INFO, "BACnet APDU ");
5429 tmp = (gint) tvb_get_guint8(tvb, 0);
5430 bacapp_type = (tmp >> 4) & 0x0f;
5432 /* show some descriptive text in the INFO column */
5433 if (check_col(pinfo->cinfo, COL_INFO))
5435 col_clear(pinfo->cinfo, COL_INFO);
5436 col_add_str(pinfo->cinfo, COL_INFO,
5437 val_to_str(bacapp_type, BACnetTypeName, "#### unknown APDU ##### "));
5438 switch (bacapp_type)
5440 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
5441 /* segmented messages have 2 additional bytes */
5442 if (tmp & BACAPP_SEGMENTED_REQUEST)
5443 bacapp_service = tvb_get_guint8(tvb, offset + 5);
5445 bacapp_service = tvb_get_guint8(tvb, offset + 3);
5446 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
5447 val_to_str(bacapp_service,
5448 BACnetConfirmedServiceChoice,
5449 bacapp_unknown_service_str));
5451 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
5452 bacapp_service = tvb_get_guint8(tvb, offset + 1);
5453 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
5454 val_to_str(bacapp_service,
5455 BACnetUnconfirmedServiceChoice,
5456 bacapp_unknown_service_str));
5458 case BACAPP_TYPE_SIMPLE_ACK:
5459 bacapp_service = tvb_get_guint8(tvb, offset + 2);
5460 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
5461 val_to_str(bacapp_service,
5462 BACnetConfirmedServiceChoice,
5463 bacapp_unknown_service_str));
5465 case BACAPP_TYPE_COMPLEX_ACK:
5466 /* segmented messages have 2 additional bytes */
5467 if (tmp & BACAPP_SEGMENTED_REQUEST)
5468 bacapp_service = tvb_get_guint8(tvb, offset + 4);
5470 bacapp_service = tvb_get_guint8(tvb, offset + 2);
5471 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
5472 val_to_str(bacapp_service,
5473 BACnetConfirmedServiceChoice,
5474 bacapp_unknown_service_str));
5476 case BACAPP_TYPE_SEGMENT_ACK:
5477 /* nothing more to add */
5479 case BACAPP_TYPE_ERROR:
5480 bacapp_service = tvb_get_guint8(tvb, offset + 2);
5481 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
5482 val_to_str(bacapp_service,
5483 BACnetConfirmedServiceChoice,
5484 bacapp_unknown_service_str));
5486 case BACAPP_TYPE_REJECT:
5487 bacapp_reason = tvb_get_guint8(tvb, offset + 2);
5488 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
5489 val_to_split_str(bacapp_reason,
5492 ASHRAE_Reserved_Fmt,
5493 Vendor_Proprietary_Fmt));
5495 case BACAPP_TYPE_ABORT:
5496 bacapp_reason = tvb_get_guint8(tvb, offset + 2);
5497 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
5498 val_to_split_str(bacapp_reason,
5501 ASHRAE_Reserved_Fmt,
5502 Vendor_Proprietary_Fmt));
5506 /* nothing more to add */
5512 ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE);
5513 bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
5515 /* ASHRAE 135-2001 20.1.1 */
5516 switch (bacapp_type) {
5517 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
5518 offset = fConfirmedRequestPDU(tvb, bacapp_tree, offset);
5520 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST: /* BACnet-Unconfirmed-Request-PDU */
5521 offset = fUnconfirmedRequestPDU(tvb, bacapp_tree, offset);
5523 case BACAPP_TYPE_SIMPLE_ACK: /* BACnet-Simple-Ack-PDU */
5524 offset = fSimpleAckPDU(tvb, bacapp_tree, offset);
5526 case BACAPP_TYPE_COMPLEX_ACK: /* BACnet-Complex-Ack-PDU */
5527 offset = fComplexAckPDU(tvb, bacapp_tree, offset);
5529 case BACAPP_TYPE_SEGMENT_ACK: /* BACnet-SegmentAck-PDU */
5530 offset = fSegmentAckPDU(tvb, bacapp_tree, offset);
5532 case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
5533 offset = fErrorPDU(tvb, bacapp_tree, offset);
5535 case BACAPP_TYPE_REJECT: /* BACnet-Reject-PDU */
5536 offset = fRejectPDU(tvb, bacapp_tree, offset);
5538 case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
5539 offset = fAbortPDU(tvb, bacapp_tree, offset);
5544 next_tvb = tvb_new_subset(tvb,offset,-1,tvb_length_remaining(tvb,offset));
5545 call_dissector(data_handle,next_tvb, pinfo, tree);
5549 proto_register_bacapp(void)
5551 static hf_register_info hf[] = {
5553 { "APDU Type", "bacapp.type",
5554 FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, "APDU Type", HFILL }
5556 { &hf_bacapp_pduflags,
5557 { "PDU Flags", "bacapp.pduflags",
5558 FT_UINT8, BASE_HEX, NULL, 0x0f, "PDU Flags", HFILL }
5561 { "Segmented Request", "bacapp.segmented_request",
5562 FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, "Segmented Request", HFILL }
5565 { "More Segments", "bacapp.more_segments",
5566 FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
5569 { "SA", "bacapp.SA",
5570 FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
5572 { &hf_bacapp_max_adpu_size,
5573 { "Size of Maximum ADPU accepted", "bacapp.max_adpu_size",
5574 FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, "Size of Maximum ADPU accepted", HFILL }
5576 { &hf_bacapp_response_segments,
5577 { "Max Response Segments accepted", "bacapp.response_segments",
5578 FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, "Max Response Segments accepted", HFILL }
5580 { &hf_bacapp_objectType,
5581 { "Object Type", "bacapp.objectType",
5582 FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, "Object Type", HFILL }
5584 { &hf_bacapp_instanceNumber,
5585 { "Instance Number", "bacapp.instance_number",
5586 FT_UINT32, BASE_DEC, NULL, 0x003fffff, "Instance Number", HFILL }
5588 { &hf_bacapp_invoke_id,
5589 { "Invoke ID", "bacapp.invoke_id",
5590 FT_UINT8, BASE_DEC, NULL, 0, "Invoke ID", HFILL }
5592 { &hf_bacapp_sequence_number,
5593 { "Sequence Number", "bacapp.sequence_number",
5594 FT_UINT8, BASE_DEC, NULL, 0, "Sequence Number", HFILL }
5596 { &hf_bacapp_window_size,
5597 { "Proposed Window Size", "bacapp.window_size",
5598 FT_UINT8, BASE_DEC, NULL, 0, "Proposed Window Size", HFILL }
5600 { &hf_bacapp_service,
5601 { "Service Choice", "bacapp.confirmed_service",
5602 FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, "Service Choice", HFILL }
5604 { &hf_bacapp_uservice,
5605 { "Unconfirmed Service Choice", "bacapp.unconfirmed_service",
5606 FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, "Unconfirmed Service Choice", HFILL }
5609 { "NAK", "bacapp.NAK",
5610 FT_BOOLEAN, 8, NULL, 0x02, "negativ ACK", HFILL }
5613 { "SRV", "bacapp.SRV",
5614 FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
5616 { &hf_BACnetRejectReason,
5617 { "Reject Reason", "bacapp.reject_reason",
5618 FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, "Reject Reason", HFILL }
5620 { &hf_BACnetAbortReason,
5621 { "Abort Reason", "bacapp.abort_reason",
5622 FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, "Abort Reason", HFILL }
5625 { "BACnet APDU variable part:", "bacapp.variable_part",
5626 FT_NONE, 0, NULL, 0, "BACnet APDU variable part", HFILL }
5631 FT_BYTES, BASE_HEX, NULL, 0,
5632 "BACnet Tag", HFILL }
5634 { &hf_BACnetApplicationTagNumber,
5635 { "Application Tag Number",
5636 "bacapp.application_tag_number",
5637 FT_UINT8, BASE_DEC, VALS(&BACnetApplicationTagNumber), 0xF0,
5638 "Application Tag Number", HFILL }
5640 { &hf_BACnetContextTagNumber,
5641 { "Context Tag Number",
5642 "bacapp.context_tag_number",
5643 FT_UINT8, BASE_DEC, NULL, 0xF0,
5644 "Context Tag Number", HFILL }
5646 { &hf_BACnetExtendedTagNumber,
5647 { "Extended Tag Number",
5648 "bacapp.extended_tag_number",
5649 FT_UINT8, BASE_DEC, NULL, 0,
5650 "Extended Tag Number", HFILL }
5652 { &hf_BACnetNamedTag,
5655 FT_UINT8, BASE_DEC, VALS(&BACnetTagNames), 0x07,
5656 "Named Tag", HFILL }
5658 { &hf_BACnetCharacterSet,
5659 { "String Character Set",
5660 "bacapp.string_character_set",
5661 FT_UINT8, BASE_DEC, VALS(&BACnetCharacterSet),0,
5662 "String Character Set", HFILL }
5664 { &hf_BACnetTagClass,
5665 { "Tag Class", "bacapp.tag_class",
5666 FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, "Tag Class", HFILL }
5668 { &hf_bacapp_tag_lvt,
5669 { "Length Value Type",
5671 FT_UINT8, BASE_DEC, NULL, 0,
5672 "Length Value Type", HFILL }
5674 { &hf_bacapp_tag_value8,
5676 "bacapp.tag_value8",
5677 FT_UINT8, BASE_DEC, NULL, 0,
5678 "Tag Value", HFILL }
5680 { &hf_bacapp_tag_value16,
5681 { "Tag Value 16-bit",
5682 "bacapp.tag_value16",
5683 FT_UINT16, BASE_DEC, NULL, 0,
5684 "Tag Value 16-bit", HFILL }
5686 { &hf_bacapp_tag_value32,
5687 { "Tag Value 32-bit",
5688 "bacapp.tag_value32",
5689 FT_UINT32, BASE_DEC, NULL, 0,
5690 "Tag Value 32-bit", HFILL }
5692 { &hf_bacapp_tag_ProcessId,
5693 { "ProcessIdentifier", "bacapp.processId",
5694 FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
5696 { &hf_bacapp_tag_initiatingObjectType,
5697 { "ObjectType", "bacapp.objectType",
5698 FT_UINT16, BASE_DEC, VALS(BACnetObjectType), 0x00, "Object Type", HFILL }
5701 static gint *ett[] = {
5703 &ett_bacapp_control,
5708 proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
5709 "BACapp", "bacapp");
5711 proto_register_field_array(proto_bacapp, hf, array_length(hf));
5712 proto_register_subtree_array(ett, array_length(ett));
5713 register_dissector("bacapp", dissect_bacapp, proto_bacapp);
5718 proto_reg_handoff_bacapp(void)
5720 data_handle = find_dissector("data");
5724 fConvertXXXtoUTF8 (const guint8 *in, size_t *inbytesleft, guint8 *out, size_t *outbytesleft, const gchar *fromcoding)
5725 { /* I don't want to let in and out be modified */
5726 #ifdef HAVE_CONFIG_H
5730 const guint8 *inp = in;
5732 const guint8 **inpp = &inp;
5733 guint8 **outpp = &outp;
5735 if ((icd = iconv_open ("UTF-8", fromcoding)) != (iconv_t) -1) {
5736 i = iconv (icd, (char**) inpp, inbytesleft, (char**) outpp, outbytesleft);
5745 memcpy (out, in, *inbytesleft);
5746 out[*inbytesleft] = '\0';
5747 *outbytesleft -= *inbytesleft;