summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-rf4ce-profile.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:53 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:53 +0000
commita86c5f7cae7ec9a3398300555a0b644689d946a1 (patch)
tree39fe4b107c71174fd1e8a8ceb9a4d2aa14116248 /epan/dissectors/packet-rf4ce-profile.c
parentReleasing progress-linux version 4.2.6-1~progress7.99u1. (diff)
downloadwireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.tar.xz
wireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.zip
Merging upstream version 4.4.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--epan/dissectors/packet-rf4ce-profile.c2358
1 files changed, 2358 insertions, 0 deletions
diff --git a/epan/dissectors/packet-rf4ce-profile.c b/epan/dissectors/packet-rf4ce-profile.c
new file mode 100644
index 00000000..72cfd1fa
--- /dev/null
+++ b/epan/dissectors/packet-rf4ce-profile.c
@@ -0,0 +1,2358 @@
+/* packet-rf4ce-profile.c
+ * Profile layer related functions and objects for RF4CE dissector
+ * Copyright (C) Atmosic 2023
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include "config.h"
+#include <epan/packet.h>
+#include <epan/expert.h>
+#include <epan/uat.h>
+#include <epan/reassemble.h>
+#include "packet-ieee802154.h"
+#include "packet-rf4ce-secur.h"
+
+/* TLV Node-elements */
+static int proto_rf4ce_profile;
+
+static int ett_rf4ce_profile;
+static int ett_rf4ce_profile_cmd_frame;
+static int ett_rf4ce_profile_attrs;
+static int ett_rf4ce_profile_attrs_sub;
+static int ett_rf4ce_profile_zrc20_ident_cap;
+static int ett_rf4ce_profile_zrc20_mappable_actions_entry;
+static int ett_rf4ce_profile_zrc20_action_control;
+static int ett_rf4ce_profile_zrc20_action_mappings_flags;
+static int ett_rf4ce_profile_zrc20_action_mappings_rf_descr;
+static int ett_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf;
+static int ett_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts;
+static int ett_rf4ce_profile_zrc20_action_mappings_ir_descr;
+static int ett_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf;
+static int ett_rf4ce_profile_gdp_poll_constraints_polling_rec;
+static int ett_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap;
+static int ett_rf4ce_profile_gdp_poll_configuration_polling_trig_conf;
+static int ett_rf4ce_profile_action_records;
+static int ett_rf4ce_profile_action_records_sub;
+static int ett_rf4ce_profile_zrc10_supported_commands;
+static int ett_rf4ce_profile_zrc10_supported_commands_sub;
+
+static dissector_table_t rf4ce_profile_dissector_table;
+
+static dissector_handle_t rf4ce_profile_handle;
+
+/* RF4CE Profile header */
+static int hf_rf4ce_profile_fcf;
+static int hf_rf4ce_profile_fcf_cmd_id;
+static int hf_rf4ce_zrc20_fcf_cmd_id;
+static int hf_rf4ce_profile_fcf_reserved;
+static int hf_rf4ce_profile_fcf_cmd_frame;
+static int hf_rf4ce_profile_fcf_data_pending;
+
+/* RF4CE Profile command - Generic Response */
+static int hf_rf4ce_profile_cmd_generic_resp_status;
+
+/* RF4CE Profile command - Configuration Complete */
+static int hf_rf4ce_profile_cmd_configuration_complete_status;
+
+/* RF4CE Profile command - Heartbeat */
+static int hf_rf4ce_profile_cmd_heartbeat_trigger;
+
+/* RF4CE Profile Attributes - general */
+static int hf_rf4ce_profile_gdp_attr_id;
+static int hf_rf4ce_profile_zrc20_attr_id;
+static int hf_rf4ce_profile_attr_entry_id;
+static int hf_rf4ce_profile_attr_status;
+static int hf_rf4ce_profile_attr_length;
+static int hf_rf4ce_profile_attr_value;
+
+/* RF4CE Profile command - Check Validation */
+static int hf_rf4ce_profile_cmd_check_validation_sub_type;
+static int hf_rf4ce_profile_cmd_check_validation_control;
+static int hf_rf4ce_profile_cmd_check_validation_status;
+
+/* RF4CE Profile command - Client Notification */
+static int hf_rf4ce_profile_cmd_client_notification_sub_type;
+
+static int hf_rf4ce_profile_cmd_client_notification_identify_flags;
+static int hf_rf4ce_profile_cmd_client_notification_identify_flags_stop_on_action;
+static int hf_rf4ce_profile_cmd_client_notification_identify_flags_flash_light;
+static int hf_rf4ce_profile_cmd_client_notification_identify_flags_make_sound;
+static int hf_rf4ce_profile_cmd_client_notification_identify_flags_vibrate;
+static int hf_rf4ce_profile_cmd_client_notification_identify_flags_reserved;
+
+static int hf_rf4ce_profile_cmd_client_notification_identify_time;
+
+/* RF4CE Profile command - Key Exchange */
+static int hf_rf4ce_profile_cmd_key_exchange_sub_type;
+
+static int hf_rf4ce_profile_cmd_key_exchange_flags;
+static int hf_rf4ce_profile_cmd_key_exchange_flags_default_secret;
+static int hf_rf4ce_profile_cmd_key_exchange_flags_initiator_vendor_specific_secret;
+static int hf_rf4ce_profile_cmd_key_exchange_flags_responder_vendor_specific_secret;
+static int hf_rf4ce_profile_cmd_key_exchange_flags_reserved;
+static int hf_rf4ce_profile_cmd_key_exchange_flags_vendor_specific_parameter;
+
+static int hf_rf4ce_profile_cmd_key_exchange_rand_a;
+static int hf_rf4ce_profile_cmd_key_exchange_rand_b;
+static int hf_rf4ce_profile_cmd_key_exchange_tag_b;
+static int hf_rf4ce_profile_cmd_key_exchange_tag_a;
+
+#if 0
+/* RF4CE ZRC 2.0 Profile command - Actions */
+static int hf_rf4ce_zrc20_cmd_actions;
+#endif
+
+static int hf_rf4ce_zrc20_cmd_actions_action_control;
+static int hf_rf4ce_zrc20_cmd_actions_action_control_action_type;
+static int hf_rf4ce_zrc20_cmd_actions_action_control_reserved;
+static int hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_gui;
+static int hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_alt;
+static int hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_shift;
+static int hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_ctrl;
+
+static int hf_rf4ce_zrc20_cmd_actions_action_data_payload_length;
+static int hf_rf4ce_zrc20_cmd_actions_action_data_action_bank;
+static int hf_rf4ce_zrc20_cmd_actions_action_data_action_code;
+static int hf_rf4ce_zrc20_cmd_actions_action_data_action_vendor;
+static int hf_rf4ce_zrc20_cmd_actions_action_data_action_payload;
+
+/* RF4CE ZRC 1.0 profile header */
+static int hf_rf4ce_zrc10_fcf;
+static int hf_rf4ce_zrc10_fcf_cmd_id;
+static int hf_rf4ce_zrc10_fcf_reserved;
+
+#define RF4CE_ZRC10_FCF_CMD_ID_RESERVED 0b00000000
+#define RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_PRESSED 0b00000001
+#define RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_REPEATED 0b00000010
+#define RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_RELEASED 0b00000011
+#define RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_CMD_DISCOVERY_REQ 0b00000100
+#define RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_CMD_DISCOVERY_RSP 0b00000101
+
+#define RF4CE_ZRC10_FCF_CMD_ID_MASK 0b00001111
+#define RF4CE_ZRC10_FCF_RESERVED_MASK 0b11110000
+
+static const value_string rf4ce_zrc10_fcf_cmd_id_vals[] = {
+ { RF4CE_ZRC10_FCF_CMD_ID_RESERVED, "Reserved" },
+ { RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_PRESSED, "User Control Pressed" },
+ { RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_REPEATED, "User Control Repeated" },
+ { RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_RELEASED, "User Control Released" },
+ { RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_CMD_DISCOVERY_REQ, "Command Discovery Request" },
+ { RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_CMD_DISCOVERY_RSP, "Command Discovery Response" },
+ { 0, NULL }
+};
+
+static int hf_rf4ce_zrc10_cmd_common_rc_command_code;
+static int hf_rf4ce_zrc10_cmd_common_rc_command_payload;
+static int hf_rf4ce_zrc10_cmd_disc_reserved;
+static int hf_rf4ce_zrc10_cmd_disc_rsp_supported_commands;
+
+static int hf_rf4ce_profile_unparsed_payload;
+
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_RESERVED 0b00000000
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_START 0b00000001
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_REPEAT 0b00000010
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_ATOMIC 0b00000011
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_RESERVED 0b00001100
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_MODIFIER_BITS_GUI 0b00010000
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_MODIFIER_BITS_ALT 0b00100000
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_MODIFIER_BITS_SHIFT 0b01000000
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_MODIFIER_BITS_CTRL 0b10000000
+
+#define RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_MASK \
+ (RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_RESERVED \
+ | RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_START \
+ | RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_REPEAT \
+ | RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_ATOMIC)
+
+static const value_string rf4ce_zrc20_cmd_actions_action_control_action_type_vals[] = {
+ { RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_RESERVED, "Reserved" },
+ { RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_START, "Start" },
+ { RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_REPEAT, "Repeat" },
+ { RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_ATOMIC, "Atomic" },
+ { 0, NULL }
+};
+
+/* RF4CE Profile frame control field */
+#define RF4CE_PROFILE_FCF_CMD_ID_MASK 0b00001111
+#define RF4CE_PROFILE_FCF_RESERVED_MASK 0b00110000
+#define RF4CE_PROFILE_FCF_CMD_FRAME_MASK 0b01000000
+#define RF4CE_PROFILE_FCF_DATA_PENDING_MASK 0b10000000
+
+/* RF4CE Profile commands */
+#define RF4CE_PROFILE_CMD_GENERIC_RESPONSE 0x00
+#define RF4CE_PROFILE_CMD_CONFIGURATION_COMPLETE 0x01
+#define RF4CE_PROFILE_CMD_HEARTBEAT 0x02
+#define RF4CE_PROFILE_CMD_GET_ATTRIBUTES 0x03
+#define RF4CE_PROFILE_CMD_GET_ATTRIBUTES_RESPONSE 0x04
+#define RF4CE_PROFILE_CMD_PUSH_ATTRIBUTES 0x05
+#define RF4CE_PROFILE_CMD_SET_ATTRIBUTES 0x06
+#define RF4CE_PROFILE_CMD_PULL_ATTRIBUTES 0x07
+#define RF4CE_PROFILE_CMD_PULL_ATTRIBUTES_RESPONSE 0x08
+#define RF4CE_PROFILE_CMD_CHECK_VALIDATION 0x09
+#define RF4CE_PROFILE_CMD_CLIENT_NOTIFICATION 0x0a
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE 0x0b
+
+static const value_string rf4ce_profile_fcf_cmd_id_vals[] = {
+ { RF4CE_PROFILE_CMD_GENERIC_RESPONSE, "Generic Response" },
+ { RF4CE_PROFILE_CMD_CONFIGURATION_COMPLETE, "Configuration Complete" },
+ { RF4CE_PROFILE_CMD_HEARTBEAT, "Heartbeat" },
+ { RF4CE_PROFILE_CMD_GET_ATTRIBUTES, "Get Attributes" },
+ { RF4CE_PROFILE_CMD_GET_ATTRIBUTES_RESPONSE, "Get Attributes Response" },
+ { RF4CE_PROFILE_CMD_PUSH_ATTRIBUTES, "Push Attributes" },
+ { RF4CE_PROFILE_CMD_SET_ATTRIBUTES, "Set Attributes" },
+ { RF4CE_PROFILE_CMD_PULL_ATTRIBUTES, "Pull Attributes" },
+ { RF4CE_PROFILE_CMD_PULL_ATTRIBUTES_RESPONSE, "Pull Attributes Response" },
+ { RF4CE_PROFILE_CMD_CHECK_VALIDATION, "Check Validation" },
+ { RF4CE_PROFILE_CMD_CLIENT_NOTIFICATION, "Client Notification" },
+ { RF4CE_PROFILE_CMD_KEY_EXCHANGE, "Key Exchange" },
+ { 0, NULL }
+};
+
+#define RF4CE_PROFILE_FCF_CMD_PROFILE_SPECIFIC_COMMAND 0
+#define RF4CE_PROFILE_FCF_CMD_GDP_COMMAND 1
+
+static const value_string rf4ce_profile_fcf_cmd_frame_vals[] = {
+ { RF4CE_PROFILE_FCF_CMD_PROFILE_SPECIFIC_COMMAND, "Profile Specific Command" },
+ { RF4CE_PROFILE_FCF_CMD_GDP_COMMAND, "GDP Command" },
+ { 0, NULL }
+};
+
+/* RF4CE ZRC 2.0 Profile commands */
+ /* 0x00 - 0x05 - Reserved */
+#define RF4CE_ZRC20_CMD_ACTIONS 0x06
+ /* 0x07 - 0x0f - Reserved */
+
+static const value_string rf4ce_zrc20_fcf_cmd_id_vals[] = {
+ { RF4CE_ZRC20_CMD_ACTIONS, "Actions" }, { 0, NULL }
+};
+
+/* RF4CE Profile command - Generic Response */
+#define RF4CE_PROFILE_CMD_GENERIC_RESP_STATUS_SUCCESS 0x00
+#define RF4CE_PROFILE_CMD_GENERIC_RESP_STATUS_UNSUPPORTED_REQUEST 0x01
+#define RF4CE_PROFILE_CMD_GENERIC_RESP_STATUS_INVALID_PARAMETER 0x02
+#define RF4CE_PROFILE_CMD_GENERIC_RESP_STATUS_CONFIGURATION_FAILURE 0x03
+ /* 0x04 – 0x3f Reserved error codes */
+ /* 0x40 – 0xff Profile specific error codes */
+
+static const value_string hf_rf4ce_profile_cmd_generic_resp_status_vals[] = {
+ { RF4CE_PROFILE_CMD_GENERIC_RESP_STATUS_SUCCESS, "Success" },
+ { RF4CE_PROFILE_CMD_GENERIC_RESP_STATUS_UNSUPPORTED_REQUEST, "Unsupported Request" },
+ { RF4CE_PROFILE_CMD_GENERIC_RESP_STATUS_INVALID_PARAMETER, "Invalid Parameter" },
+ { RF4CE_PROFILE_CMD_GENERIC_RESP_STATUS_CONFIGURATION_FAILURE, "Configuration Failure" },
+ { 0, NULL }
+};
+
+/* RF4CE Profile command - Configuration Complete */
+#define RF4CE_PROFILE_CMD_CONFIGURATION_COMPLETE_STATUS_SUCCESS 0x00
+ /* 0x01 – 0x02 Reserved error codes */
+#define RF4CE_PROFILE_CMD_CONFIGURATION_COMPLETE_STATUS_CONFIGURATION_FAILURE 0x03
+ /* 0x04 – 0x3f Reserved error codes */
+ /* 0x40 – 0xff Profile specific error codes */
+
+static const value_string hf_rf4ce_profile_cmd_configuration_complete_status_vals[] = {
+ { RF4CE_PROFILE_CMD_CONFIGURATION_COMPLETE_STATUS_SUCCESS, "Success" },
+ { RF4CE_PROFILE_CMD_CONFIGURATION_COMPLETE_STATUS_CONFIGURATION_FAILURE, "Configuration Failure" },
+ { 0, NULL }
+};
+
+/* RF4CE Profile command - Heartbeat */
+#define RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_GENERIC_ACTIVITY 0x00
+#define RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_TIME_BASED_POLLING 0x01
+#define RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_KEY_PRESS 0x02
+#define RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_PICKUP 0x03
+#define RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_RESET 0x04
+#define RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_MICROPHONE_ACTIVITY 0x05
+#define RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_OTHER_USER_ACTIVITY 0x06
+ /* 0x07 – 0xff Reserved */
+
+static const value_string hf_rf4ce_profile_cmd_heartbeat_trigger_vals[] = {
+ { RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_GENERIC_ACTIVITY, "Generic Activity" },
+ { RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_TIME_BASED_POLLING, "Time Based Polling" },
+ { RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_KEY_PRESS, "Polling on Key Press" },
+ { RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_PICKUP, "Polling on Pickup" },
+ { RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_RESET, "Polling on Reset" },
+ { RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_MICROPHONE_ACTIVITY, "Polling on Microphone Activity" },
+ { RF4CE_PROFILE_CMD_HEARTBEAT_TRIGGER_POLLING_ON_OTHER_USER_ACTIVITY, "Polling on other User Activity" },
+ { 0, NULL }
+};
+
+/* RF4CE Profile Attributes common */
+#define RF4CE_PROFILE_ATTR_DISSECT_NOT_SET 0b00000000
+#define RF4CE_PROFILE_ATTR_DISSECT_ATTR_ID_MASK 0b00000001
+#define RF4CE_PROFILE_ATTR_DISSECT_ENTRY_ID_MASK 0b00000010
+#define RF4CE_PROFILE_ATTR_DISSECT_ATTR_STATUS_MASK 0b00000100
+#define RF4CE_PROFILE_ATTR_DISSECT_ATTR_LENGTH_MASK 0b00001000
+#define RF4CE_PROFILE_ATTR_DISSECT_ATTR_VALUE_MASK 0b00010000
+
+#define RF4CE_PROFILE_ATTR_DISSECT_GET_ATTRS_MASK \
+ (RF4CE_PROFILE_ATTR_DISSECT_ATTR_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ENTRY_ID_MASK)
+
+#define RF4CE_PROFILE_ATTR_DISSECT_GET_ATTRS_RESP_MASK \
+ (RF4CE_PROFILE_ATTR_DISSECT_ATTR_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ENTRY_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_STATUS_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_LENGTH_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_VALUE_MASK) \
+
+#define RF4CE_PROFILE_ATTR_DISSECT_PUSH_ATTRS_MASK \
+ (RF4CE_PROFILE_ATTR_DISSECT_ATTR_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ENTRY_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_LENGTH_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_VALUE_MASK)
+
+#define RF4CE_PROFILE_ATTR_DISSECT_SET_ATTRS_MASK \
+ (RF4CE_PROFILE_ATTR_DISSECT_ATTR_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ENTRY_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_LENGTH_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_VALUE_MASK)
+
+#define RF4CE_PROFILE_ATTR_DISSECT_PULL_ATTRS_MASK \
+ (RF4CE_PROFILE_ATTR_DISSECT_ATTR_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ENTRY_ID_MASK)
+
+#define RF4CE_PROFILE_ATTR_DISSECT_PULL_ATTRS_RESP_MASK \
+ (RF4CE_PROFILE_ATTR_DISSECT_ATTR_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ENTRY_ID_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_STATUS_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_LENGTH_MASK \
+ | RF4CE_PROFILE_ATTR_DISSECT_ATTR_VALUE_MASK)
+
+/* RF4CE GDP Attributes */
+
+/* GDP Attribute - Identification Capabilities */
+static int hf_rf4ce_profile_gdp_ident_cap;
+static int hf_rf4ce_profile_gdp_ident_cap_reserved;
+static int hf_rf4ce_profile_gdp_ident_cap_support_flash_light;
+static int hf_rf4ce_profile_gdp_ident_cap_support_make_short_sound;
+static int hf_rf4ce_profile_gdp_ident_cap_support_vibrate;
+static int hf_rf4ce_profile_gdp_ident_cap_reserved2;
+
+#define RF4CE_PROFILE_GDP_IDENT_CAP_RESERVED_MASK 0b00000001
+#define RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_FLASH_LIGHT_MASK 0b00000010
+#define RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_MAKE_SHORT_SOUND_MASK 0b00000100
+#define RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_VIBRATE_MASK 0b00001000
+#define RF4CE_PROFILE_GDP_IDENT_CAP_RESERVED2_MASK 0b11110000
+
+#define RF4CE_PROFILE_GDP_IDENT_CAP_MASK \
+ (RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_FLASH_LIGHT_MASK \
+ | RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_MAKE_SHORT_SOUND_MASK \
+ | RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_VIBRATE_MASK \
+ | RF4CE_PROFILE_GDP_IDENT_CAP_RESERVED2_MASK)
+
+/* GDP Attribute - Poll Constraints */
+static int hf_rf4ce_profile_gdp_poll_constraints_methods_num;
+
+/* Polling constraint record - Polling method ID */
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_method_id;
+
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_METHOD_ID_DIS 0x00
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_METHOD_ID_GDP_HEARTBEAT 0x01
+
+static const value_string rf4ce_profile_gdp_poll_constraints_polling_rec_method_id_vals[] = {
+ { RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_METHOD_ID_DIS, "Disabled" },
+ { RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_METHOD_ID_GDP_HEARTBEAT, "GDP heartbeat based polling" },
+ { 0, NULL}
+};
+
+/* Polling constraint record - Polling trigger capabilities */
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_tbased;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_k_press;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_pick_up;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_reset;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_micro_act;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_user_act;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_reserved;
+
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_TBASED_MASK (0b0000000000000001)
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_K_PRESS_MASK (0b0000000000000010)
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_PICK_UP_MASK (0b0000000000000100)
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_RESET_MASK (0b0000000000001000)
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_MICRO_ACT_MASK (0b0000000000010000)
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_USER_ACT_MASK (0b0000000000100000)
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_RESERVED_MASK (0b1111111111000000)
+
+#define RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_MASK \
+ (RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_TBASED_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_K_PRESS_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_PICK_UP_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_RESET_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_MICRO_ACT_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_USER_ACT_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_RESERVED_MASK)
+
+/* Polling constraint record - other fields */
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_min_polling_key_press_cnt;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_max_polling_key_press_cnt;
+
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_min_polling_time_interval;
+static int hf_rf4ce_profile_gdp_poll_constraints_polling_rec_max_polling_time_interval;
+
+/* GDP Attribute - Poll Configuration */
+static int hf_rf4ce_profile_gdp_poll_configuration_method_id;
+
+/* GDP Attribute - Poll Configuration - Polling Trigger Configuration */
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_tbased;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_k_press;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_pick_up;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_reset;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_micro_act;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_user_act;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_reserved;
+
+#define RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_TBASED_MASK (0b0000000000000001)
+#define RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_K_PRESS_MASK (0b0000000000000010)
+#define RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_PICK_UP_MASK (0b0000000000000100)
+#define RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_RESET_MASK (0b0000000000001000)
+#define RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_MICRO_ACT_MASK (0b0000000000010000)
+#define RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_USER_ACT_MASK (0b0000000000100000)
+#define RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_RESERVED_MASK (0b1111111111000000)
+
+#define RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_MASK \
+ (RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_TBASED_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_K_PRESS_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_PICK_UP_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_RESET_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_MICRO_ACT_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_USER_ACT_MASK \
+ | RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_RESERVED_MASK)
+
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_key_press_cnt;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_time_interval;
+static int hf_rf4ce_profile_gdp_poll_configuration_polling_timeout;
+
+ /* 0x00 - 0x7f - Reserved */
+#define RF4CE_GDP_ATTR_GDP_PROFILE_VERSION 0x80
+#define RF4CE_GDP_ATTR_GDP_PROFILE_CAPABILITIES 0x81
+#define RF4CE_GDP_ATTR_KEY_EXCHANGE_TRANSFER_COUNT 0x82
+#define RF4CE_GDP_ATTR_POWER_STATUS 0x83
+#define RF4CE_GDP_ATTR_POLL_CONSTRAINTS 0x84
+#define RF4CE_GDP_ATTR_POLL_CONFIGURATION 0x85
+#define RF4CE_GDP_ATTR_MAX_BINDING_CANDIDATES 0x86
+#define RF4CE_GDP_ATTR_AUTO_CHECK_VALID_PERIOD 0x87
+#define RF4CE_GDP_ATTR_BINDING_RECIPIENT_VALIDATION_WAIT_TIME 0x88
+#define RF4CE_GDP_ATTR_BINDING_ORIGINATOR_VALIDATION_WAIT_TIME 0x89
+#define RF4CE_GDP_ATTR_LINK_LOST_WAIT_TIME 0x8a
+#define RF4CE_GDP_ATTR_IDENTIFICATION_CAPABILITIES 0x8b
+
+/* Reserved for scalar Profile attributes */
+#define RF4CE_GDP_ATTR_SCALAR1_RESERVED_MIN 0x8c
+#define RF4CE_GDP_ATTR_SCALAR1_RESERVED_MAX 0x8f
+
+/* Reserved for arrayed Profile attributes */
+#define RF4CE_GDP_ATTR_ARRAYED1_RESERVED_MIN 0x90
+#define RF4CE_GDP_ATTR_ARRAYED1_RESERVED_MAX 0x90
+
+/* Reserved for scalar Profile attributes */
+#define RF4CE_GDP_ATTR_SCALAR2_RESERVED_MIN 0xa0
+#define RF4CE_GDP_ATTR_SCALAR2_RESERVED_MAX 0xbf
+
+/* Reserved for arrayed Profile attributes */
+#define RF4CE_GDP_ATTR_ARRAYED2_RESERVED_MIN 0xc0
+#define RF4CE_GDP_ATTR_ARRAYED2_RESERVED_MAX 0xdf
+
+/* Reserved for scalar Profile attributes */
+#define RF4CE_GDP_ATTR_SCALAR3_RESERVED_MIN 0xe0
+#define RF4CE_GDP_ATTR_SCALAR3_RESERVED_MAX 0xff
+
+static const value_string rf4ce_profile_gdp_attr_vals[] = {
+ { RF4CE_GDP_ATTR_GDP_PROFILE_VERSION, "Profile Version" },
+ { RF4CE_GDP_ATTR_GDP_PROFILE_CAPABILITIES, "Profile Capabilities" },
+ { RF4CE_GDP_ATTR_KEY_EXCHANGE_TRANSFER_COUNT, "KEY Exchange Transfer Count" },
+ { RF4CE_GDP_ATTR_POWER_STATUS, "Power Status" },
+ { RF4CE_GDP_ATTR_POLL_CONSTRAINTS, "Poll Constraints" },
+ { RF4CE_GDP_ATTR_POLL_CONFIGURATION, "Poll Configuration" },
+ { RF4CE_GDP_ATTR_MAX_BINDING_CANDIDATES, "Max Binding Candidates" },
+ { RF4CE_GDP_ATTR_AUTO_CHECK_VALID_PERIOD, "Auto Check Valid Period" },
+ { RF4CE_GDP_ATTR_BINDING_RECIPIENT_VALIDATION_WAIT_TIME, "Binding Recipient Validation Wait Time" },
+ { RF4CE_GDP_ATTR_BINDING_ORIGINATOR_VALIDATION_WAIT_TIME, "Binding Originator Validation Wait Time" },
+ { RF4CE_GDP_ATTR_LINK_LOST_WAIT_TIME, "Link Lost Wait Time" },
+ { RF4CE_GDP_ATTR_IDENTIFICATION_CAPABILITIES, "Identification Capabilities" },
+ { 0, NULL }
+};
+
+/* RF4CE ZRC 2.0 Attributes */
+#define RF4CE_ZRC20_ATTR_ZRC_PROFILE_VERSION 0xA0
+#define RF4CE_ZRC20_ATTR_ZRC_PROFILE_CAPABILITIES 0xA1
+#define RF4CE_ZRC20_ATTR_ACTION_REPEAT_TRIGGER_INTERVAL 0xA2
+#define RF4CE_ZRC20_ATTR_ACTION_REPEAT_WAIT_TIME 0xA3
+#define RF4CE_ZRC20_ATTR_ACTION_BANKS_SUPPORTED_RX 0xA4
+#define RF4CE_ZRC20_ATTR_ACTION_BANKS_SUPPORTED_TX 0xA5
+#define RF4CE_ZRC20_ATTR_IRDB_VENDOR_SUPPORT 0xA6
+#define RF4CE_ZRC20_ATTR_ZRC_ACTION_BANKS_VERSION 0xA7
+
+/* Reserved for scalar profile attributes */
+#define RF4CE_ZRC20_ATTR_SCALAR1_MIN 0xA8
+#define RF4CE_ZRC20_ATTR_SCALAR1_MAX 0xBF
+
+#define RF4CE_ZRC20_ATTR_ACTION_CODES_SUPPORTED_RX 0xC0
+#define RF4CE_ZRC20_ATTR_ACTION_CODES_SUPPORTED_TX 0xC1
+#define RF4CE_ZRC20_ATTR_MAPPABLE_ACTIONS 0xC2
+#define RF4CE_ZRC20_ATTR_ACTION_MAPPINGS 0xC3
+#define RF4CE_ZRC20_ATTR_HOME_AUTOMATION 0xC4
+#define RF4CE_ZRC20_ATTR_HOME_AUTOMATION_SUPPORTED 0xC5
+
+/* Reserved for arrayed profile attributes */
+#define RF4CE_ZRC20_ATTR_ARRAYED1_MIN 0xC6
+#define RF4CE_ZRC20_ATTR_ARRAYED2_MAX 0xDF
+
+/* Reserved for scalar profile attributes */
+#define RF4CE_ZRC20_ATTR_SCALAR2_MIN 0xE0
+#define RF4CE_ZRC20_ATTR_SCALAR2_MAX 0xFF
+
+static const value_string rf4ce_profile_zrc20_attr_vals[] = {
+ { RF4CE_ZRC20_ATTR_ZRC_PROFILE_VERSION, "ZRC Profile Version" },
+ { RF4CE_ZRC20_ATTR_ZRC_PROFILE_CAPABILITIES, "ZRC Profile Capabilities" },
+ { RF4CE_ZRC20_ATTR_ACTION_REPEAT_TRIGGER_INTERVAL, "Action Repeat Trigger Interval" },
+ { RF4CE_ZRC20_ATTR_ACTION_REPEAT_WAIT_TIME, "Action Repeat Wait Time" },
+ { RF4CE_ZRC20_ATTR_ACTION_BANKS_SUPPORTED_RX, "Action Banks Supported RX" },
+ { RF4CE_ZRC20_ATTR_ACTION_BANKS_SUPPORTED_TX, "Action Banks Supported TX" },
+ { RF4CE_ZRC20_ATTR_IRDB_VENDOR_SUPPORT, "IRDB Vendor Support" },
+ { RF4CE_ZRC20_ATTR_ZRC_ACTION_BANKS_VERSION, "ZRC Action Banks Version" },
+ { RF4CE_ZRC20_ATTR_ACTION_CODES_SUPPORTED_RX, "Action Codes Supported RX" },
+ { RF4CE_ZRC20_ATTR_ACTION_CODES_SUPPORTED_TX, "Action Codes Supported TX" },
+ { RF4CE_ZRC20_ATTR_MAPPABLE_ACTIONS, "Mappable Actions" },
+ { RF4CE_ZRC20_ATTR_ACTION_MAPPINGS, "Action Mappings" },
+ { RF4CE_ZRC20_ATTR_HOME_AUTOMATION, "Home Automation" },
+ { RF4CE_ZRC20_ATTR_HOME_AUTOMATION_SUPPORTED, "Home Automation Supported" },
+ { 0, NULL }
+};
+
+#define RF4CE_PROFILE_ATTR_STATUS_ATTRIBUTE_SUCCESSFULLY_READ_AND_INCLUDED 0x00
+#define RF4CE_PROFILE_ATTR_STATUS_UNSUPPORTED_ATTRIBUTE 0x01
+#define RF4CE_PROFILE_ATTR_STATUS_ILLEGAL_REQUEST 0x02
+#define RF4CE_PROFILE_ATTR_STATUS_INVALID_ENTRY 0x03
+ /* 0x04 - 0xff Reserved error codes */
+
+static const value_string hf_rf4ce_profile_attr_status_vals[] = {
+ { RF4CE_PROFILE_ATTR_STATUS_ATTRIBUTE_SUCCESSFULLY_READ_AND_INCLUDED, "Attribute Successfully Read and Included" },
+ { RF4CE_PROFILE_ATTR_STATUS_UNSUPPORTED_ATTRIBUTE, "Unsupported Attribute" },
+ { RF4CE_PROFILE_ATTR_STATUS_ILLEGAL_REQUEST, "Illegal Request" },
+ { RF4CE_PROFILE_ATTR_STATUS_INVALID_ENTRY, "Invalid Entry" },
+ { 0, NULL }
+};
+
+/* RF4CE ZRC 2.0 Profile - Mappable Actions attribute */
+static int hf_rf4ce_profile_zrc20_mappable_actions_action_dev_type;
+static int hf_rf4ce_profile_zrc20_mappable_actions_action_bank;
+static int hf_rf4ce_profile_zrc20_mappable_actions_action_code;
+
+#define RF4CE_PROFILE_DEV_TYPE_RESERVED 0x00
+#define RF4CE_PROFILE_DEV_TYPE_REMOTE_CONTROL 0x01
+#define RF4CE_PROFILE_DEV_TYPE_TELEVISION 0x02
+#define RF4CE_PROFILE_DEV_TYPE_PROJECTOR 0x03
+#define RF4CE_PROFILE_DEV_TYPE_PLAYER 0x04
+#define RF4CE_PROFILE_DEV_TYPE_RECORDER 0x05
+#define RF4CE_PROFILE_DEV_TYPE_VIDEO_PLAYER_OR_RECORDER 0x06 /* (VCR, DVR, DVD, Blu-ray, portable) */
+#define RF4CE_PROFILE_DEV_TYPE_AUDIO_PLAYER_OR_RECORDER 0x07 /* (CD, portable) */
+#define RF4CE_PROFILE_DEV_TYPE_AUDIO_VIDEO_RECORDER 0x08
+#define RF4CE_PROFILE_DEV_TYPE_SET_TOP_BOX 0x09
+#define RF4CE_PROFILE_DEV_TYPE_HOME_THEATER_SYSTEM 0x0a
+#define RF4CE_PROFILE_DEV_TYPE_MEDIA_CENTER_OR_PC 0x0b
+#define RF4CE_PROFILE_DEV_TYPE_GAME_CONSOLE 0x0c
+#define RF4CE_PROFILE_DEV_TYPE_SATELLITE_RADIO_RECEIVER 0x0d
+#define RF4CE_PROFILE_DEV_TYPE_IR_EXTENDER 0x0e
+#define RF4CE_PROFILE_DEV_TYPE_MONITOR 0x0f
+ /* 0x10 – 0xcf Reserved */
+ /* 0xd0 – 0xef Vendor-specific device */
+ /* 0xf0 – 0xfb Reserved */
+#define RF4CE_PROFILE_DEV_TYPE_VENDOR_SPECIFIC_WILDCARD_DEV 0xfc
+#define RF4CE_PROFILE_DEV_TYPE_NON_VENDOR_SPECIFIC_WILDCARD_DEV 0xfd
+#define RF4CE_PROFILE_DEV_TYPE_GENERIC 0xfe
+#define RF4CE_PROFILE_DEV_TYPE_RESERVED_FOR_WILDCARDS 0xff
+
+static const value_string rf4ce_profile_device_type_vals[] = {
+ { RF4CE_PROFILE_DEV_TYPE_RESERVED, "Reserved" },
+ { RF4CE_PROFILE_DEV_TYPE_REMOTE_CONTROL, "Remote Control" },
+ { RF4CE_PROFILE_DEV_TYPE_TELEVISION, "Television" },
+ { RF4CE_PROFILE_DEV_TYPE_PROJECTOR, "Projector" },
+ { RF4CE_PROFILE_DEV_TYPE_PLAYER, "Player" },
+ { RF4CE_PROFILE_DEV_TYPE_RECORDER, "Recorder" },
+ { RF4CE_PROFILE_DEV_TYPE_VIDEO_PLAYER_OR_RECORDER, "Video Player\\Recorder" },
+ { RF4CE_PROFILE_DEV_TYPE_AUDIO_PLAYER_OR_RECORDER, "Audio Player\\Recorder" },
+ { RF4CE_PROFILE_DEV_TYPE_AUDIO_VIDEO_RECORDER, "Audio Video Recorder" },
+ { RF4CE_PROFILE_DEV_TYPE_SET_TOP_BOX, "Set Top Box" },
+ { RF4CE_PROFILE_DEV_TYPE_HOME_THEATER_SYSTEM, "Home Theater System" },
+ { RF4CE_PROFILE_DEV_TYPE_MEDIA_CENTER_OR_PC, "Media Center\\PC" },
+ { RF4CE_PROFILE_DEV_TYPE_GAME_CONSOLE, "Game Console" },
+ { RF4CE_PROFILE_DEV_TYPE_SATELLITE_RADIO_RECEIVER, "Satellite Radio Receiver" },
+ { RF4CE_PROFILE_DEV_TYPE_IR_EXTENDER, "IR Extender" },
+ { RF4CE_PROFILE_DEV_TYPE_MONITOR, "Monitor" },
+ { RF4CE_PROFILE_DEV_TYPE_VENDOR_SPECIFIC_WILDCARD_DEV, "Vendor Specific Wildcard Device" },
+ { RF4CE_PROFILE_DEV_TYPE_NON_VENDOR_SPECIFIC_WILDCARD_DEV, "Non-Vendor Specific Wildcard Device" },
+ { RF4CE_PROFILE_DEV_TYPE_GENERIC, "Generic" },
+ { RF4CE_PROFILE_DEV_TYPE_RESERVED_FOR_WILDCARDS, "Reserved for Wildcards" },
+ { 0, NULL }
+};
+
+/* RF4CE ZRC 2.0 Profile - Action Mappings attribute - Mapping Flags */
+static int hf_rf4ce_profile_zrc20_action_mappings_mapping_flags;
+static int hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_rf_specified;
+static int hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_ir_specified;
+static int hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_rf_descr_first;
+static int hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_reserved;
+static int hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_use_default;
+static int hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_permanent;
+
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RF_SPECIFIED_MASK 0b00000001
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_IR_SPECIFIED_MASK 0b00000010
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RF_DESCR_FIRST_MASK 0b00000100
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RESERVED_MASK 0b00111000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_USE_DEFAULT_MASK 0b01000000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_PERMANENT_MASK 0b10000000
+
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_MASK \
+ (RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RF_SPECIFIED_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_IR_SPECIFIED_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RF_DESCR_FIRST_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RESERVED_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_USE_DEFAULT_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_PERMANENT_MASK)
+
+/* RF4CE ZRC 2.0 Profile - Action Mappings attribute - RF Descriptor - RF Config */
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_min_num_of_trans;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_keep_trans_until_key_release;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_short_rf_retry;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_atomic_action;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_reserved;
+
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_MIN_NUM_OF_TRANS_MASK 0b00001111
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_KEEP_TRANS_UNTIL_KEY_RELEASE_MASK 0b00010000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_SHORT_RF_RETRY_MASK 0b00100000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_ATOMIC_ACTION_MASK 0b01000000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_RESERVED_MASK 0b10000000
+
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_MASK \
+ (RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_MIN_NUM_OF_TRANS_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_KEEP_TRANS_UNTIL_KEY_RELEASE_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_SHORT_RF_RETRY_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_ATOMIC_ACTION_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_RESERVED_MASK)
+
+/* RF4CE ZRC 2.0 Profile - Action Mappings attribute - RF Descriptor - RF4CE TX Options */
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_trans_mode;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_dst_addr_mode;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ack_mode;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_sec_mode;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_ag_mode;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_norm_mode;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_payload_mode;
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_reserved;
+
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_TRANS_MODE_MASK 0b00000001
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_DST_ADDR_MODE_MASK 0b00000010
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_ACK_MODE_MASK 0b00000100
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_SEC_MODE_MASK 0b00001000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_CH_AG_MODE_MASK 0b00010000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_CH_NORM_MODE_MASK 0b00100000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_PAYLOAD_MODE_MASK 0b01000000
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_RESERVED_MASK 0b10000000
+
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_MASK \
+ (RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_TRANS_MODE_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_DST_ADDR_MODE_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_ACK_MODE_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_SEC_MODE_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_CH_AG_MODE_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_CH_NORM_MODE_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_PAYLOAD_MODE_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_RESERVED_MASK)
+
+static const true_false_string rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_trans_mode_vals = {
+ "Broadcast Transmission",
+ "Unicast Transmission"
+};
+
+static const true_false_string rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_dst_addr_mode_vals = {
+ "Use Destination IEEE Address",
+ "Use Destination Network Address"
+};
+
+static const true_false_string rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ack_mode_vals = {
+ "Acknowledged Transmission",
+ "Unacknowledged Transmission"
+};
+
+static const true_false_string rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_sec_mode_vals = {
+ "Transmit with Security",
+ "Transmit without Security"
+};
+
+static const true_false_string rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_ag_mode_vals = {
+ "Use Single Channel Operation",
+ "Use Multiple Channel Operation"
+};
+
+static const true_false_string rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_norm_mode_vals = {
+ "Specify Channel Designator",
+ "Do not Specify Channel Designator"
+};
+
+static const true_false_string rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_payload_mode_vals = {
+ "Data is Vendor-specific",
+ "Data is not Vendor-specific"
+};
+
+/* RF4CE ZRC 2.0 Profile - Action Mappings attribute - RF Descriptor - Action Data Length */
+static int hf_rf4ce_profile_zrc20_action_mappings_rf_descr_action_data_len;
+
+/* RF4CE ZRC 2.0 Profile - Action Mappings attribute - IR Descriptor - IR Config */
+static int hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf;
+static int hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf_vendor_specific;
+static int hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf_reserved;
+
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_VENDOR_SPECIFIC_MASK 0b00000001
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_RESERVED_MASK 0b11111110
+
+#define RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_MASK \
+ (RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_VENDOR_SPECIFIC_MASK \
+ | RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_RESERVED_MASK)
+
+/* RF4CE ZRC 2.0 Profile - Action Mappings attribute - IR Descriptor */
+static int hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_vendor_id;
+static int hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_code_len;
+static int hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_code;
+
+/* RF4CE ZRC 2.0 Profile - IRDB Vendor Support attribute - Vendor ID */
+static int hf_rf4ce_profile_zrc20_irdb_vendor_support_vendor_id;
+
+/* RF4CE Profile command - Check Validation */
+#define RF4CE_PROFILE_CMD_CHECK_VALIDATION_SUB_TYPE_REQ 0x00
+#define RF4CE_PROFILE_CMD_CHECK_VALIDATION_SUB_TYPE_RSP 0x01
+ /* 0x02 - 0xff - reserved */
+
+static const value_string rf4ce_profile_cmd_check_validation_sub_type_vals[] = {
+ { RF4CE_PROFILE_CMD_CHECK_VALIDATION_SUB_TYPE_REQ, "Request" },
+ { RF4CE_PROFILE_CMD_CHECK_VALIDATION_SUB_TYPE_RSP, "Response" },
+ { 0, NULL }
+};
+
+#define RF4CE_PROFILE_CMD_CHECK_VALIDATION_STATUS_SUCCESS 0x00
+#define RF4CE_PROFILE_CMD_CHECK_VALIDATION_STATUS_PENDING 0x01
+#define RF4CE_PROFILE_CMD_CHECK_VALIDATION_STATUS_TIMEOUT 0x02
+#define RF4CE_PROFILE_CMD_CHECK_VALIDATION_STATUS_FAILURE 0x03
+
+static const value_string rf4ce_profile_cmd_check_validation_status_vals[] = {
+ { RF4CE_PROFILE_CMD_CHECK_VALIDATION_STATUS_SUCCESS, "Success" },
+ { RF4CE_PROFILE_CMD_CHECK_VALIDATION_STATUS_PENDING, "Pending" },
+ { RF4CE_PROFILE_CMD_CHECK_VALIDATION_STATUS_TIMEOUT, "Timeout" },
+ { RF4CE_PROFILE_CMD_CHECK_VALIDATION_STATUS_FAILURE, "Failure" },
+ { 0, NULL }
+};
+
+/* RF4CE Profile command - Client Notification */
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY 0x00
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_POLL_NEGOTIATION 0x01
+ /* 0x02 - 0x3f
+ Reserved for Profile Client Notification Sub Types. */
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_ACTION_MAPPING_NEGOTIATION 0x40
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_HOME_AUTOMATION_PULL 0x41
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_SELECTIVE_ACTION_MAPPING_UPDATE 0x42
+ /* 0x43 - 0x7f
+ Reserved for profile-specific (non-Profile) Client Notification Sub Types. */
+ /* 0x80 - 0x8f
+ Reserved */
+ /* 0xa0 - 0xff
+ Reserved for vendor specific Client
+ Notification Sub Types. The contents of
+ this field shall be interpreted according to
+ the vendor id of the Recipient. */
+
+static const value_string rf4ce_profile_cmd_client_notification_sub_type_vals[] = {
+ { RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY, "Identify" },
+ { RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_POLL_NEGOTIATION, "Request Poll Negotiation" },
+ { RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_ACTION_MAPPING_NEGOTIATION, "Request Action Mapping Negotiation" },
+ { RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_HOME_AUTOMATION_PULL, "Request Home Automation Pull" },
+ { RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_SELECTIVE_ACTION_MAPPING_UPDATE, "Request Selective Action Mapping Update" },
+ { 0, NULL }
+};
+
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_STOP_ON_ACTION_FLAG 0b00000001
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_FLASH_LIGHT_FLAG 0b00000010
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_MAKE_SOUND_FLAG 0b00000100
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_VIBRATE_FLAG 0b00001000
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_RESERVED_FLAG 0b11110000
+
+#define RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_MASK \
+ (RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_STOP_ON_ACTION_FLAG \
+ | RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_FLASH_LIGHT_FLAG \
+ | RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_MAKE_SOUND_FLAG \
+ | RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_VIBRATE_FLAG \
+ | RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_RESERVED_FLAG)
+
+/* RF4CE Profile command - Key Exchange */
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CHALLENGE 0x00
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CHALLENGE_RSP 0x01
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_RSP 0x02
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CONFIRM 0x03
+ /* 0x04 - 0xff - Reserved */
+
+static const value_string rf4ce_profile_cmd_key_exchange_sub_type_vals[] = {
+ { RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CHALLENGE, "Challenge" },
+ { RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CHALLENGE_RSP, "Challenge Response" },
+ { RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_RSP, "Response" },
+ { RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CONFIRM, "Confirm" },
+ { 0, NULL }
+};
+
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_DEFAULT_SECRET_FLAG (0b0000000000000001)
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_INITIATOR_VENDOR_SPECIFIC_SECRET_FLAG (0b0000000000000010)
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_RESPONDER_VENDOR_SPECIFIC_SECRET_FLAG (0b0000000000000100)
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_RESERVED_FLAG (0b0000000011111000)
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_VENDOR_SPECIFIC_PARAMETER_FLAG (0b1111111100000000)
+
+#define RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_MASK \
+ (RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_DEFAULT_SECRET_FLAG \
+ | RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_INITIATOR_VENDOR_SPECIFIC_SECRET_FLAG \
+ | RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_RESPONDER_VENDOR_SPECIFIC_SECRET_FLAG \
+ | RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_RESERVED_FLAG \
+ | RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_VENDOR_SPECIFIC_PARAMETER_FLAG)
+
+/* RF4CE - Vendor ID list */
+#define RF4CE_VENDOR_ID_RESERVED 0x0000
+#define RF4CE_VENDOR_ID_PANASONIC 0x0001
+#define RF4CE_VENDOR_ID_SONY 0x0002
+#define RF4CE_VENDOR_ID_SAMSUNG 0x0003
+#define RF4CE_VENDOR_ID_PHILIPS 0x0004
+#define RF4CE_VENDOR_ID_FREESCALE 0x0005
+#define RF4CE_VENDOR_ID_OKI_SEMICONDUCTOR 0x0006
+#define RF4CE_VENDOR_ID_TEXAS_INSTRUMENTS 0x0007
+ /* 0x0008 - 0xfff0 Reserved */
+#define RF4CE_VENDOR_ID_TEST_VENDOR_1 0xfff1
+#define RF4CE_VENDOR_ID_TEST_VENDOR_2 0xfff2
+#define RF4CE_VENDOR_ID_TEST_VENDOR_3 0xfff3
+ /* 0xfff4 - 0xffff Reserved */
+
+#define RF4CE_VENDOR_ID_MASK 0x0007
+
+static const value_string rf4ce_vendor_id_vals[] = {
+ { RF4CE_VENDOR_ID_RESERVED, "Reserved" },
+ { RF4CE_VENDOR_ID_PANASONIC, "Panasonic" },
+ { RF4CE_VENDOR_ID_SONY, "Sony" },
+ { RF4CE_VENDOR_ID_SAMSUNG, "Samsung" },
+ { RF4CE_VENDOR_ID_PHILIPS, "Philips" },
+ { RF4CE_VENDOR_ID_FREESCALE, "Freescale" },
+ { RF4CE_VENDOR_ID_OKI_SEMICONDUCTOR, "Oki Semiconductor" },
+ { RF4CE_VENDOR_ID_TEXAS_INSTRUMENTS, "Texas Instruments" },
+ { 0, NULL }
+};
+
+static int dissect_rf4ce_profile_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
+
+/* RF4CE Profile common commands dissectors */
+static void dissect_rf4ce_profile_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned *offset, uint8_t cmd_id, char *profile_str, bool is_cmd_frame);
+
+static void dissect_rf4ce_profile_common_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned *offset, uint8_t cmd_id, bool is_zrc20);
+
+static void dissect_rf4ce_profile_cmd_generic_resp(tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
+static void dissect_rf4ce_profile_cmd_configuration_complete(tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
+static void dissect_rf4ce_profile_cmd_heartbeat(tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
+
+static bool dissect_rf4ce_profile_zrc20_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t attr_id, uint8_t attr_length);
+static bool dissect_rf4ce_profile_gdp_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t attr_id);
+static void dissect_rf4ce_profile_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t dissection_mask, bool is_zrc20);
+static void dissect_rf4ce_profile_cmd_get_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20);
+static void dissect_rf4ce_profile_cmd_get_attrs_resp(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20);
+static void dissect_rf4ce_profile_cmd_push_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20);
+static void dissect_rf4ce_profile_cmd_set_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20);
+static void dissect_rf4ce_profile_cmd_pull_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20);
+static void dissect_rf4ce_profile_cmd_pull_attrs_resp(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20);
+static bool rf4ce_profile_is_gdp_attr_arrayed(uint8_t attr_id);
+static bool rf4ce_profile_is_zrc20_attr_arrayed(uint8_t attr_id);
+
+static void dissect_rf4ce_profile_cmd_check_validation(tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
+static void dissect_rf4ce_profile_cmd_client_notification(tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
+static void dissect_rf4ce_profile_cmd_key_exchange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned *offset);
+
+/* RF4CE ZRC 1.0 profile commands dissectors */
+static void dissect_rf4ce_profile_zrc10_cmd(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t cmd_id);
+
+static void dissect_rf4ce_profile_zrc10_cmd_user_control_common(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool parse_payload);
+
+static void dissect_rf4ce_profile_zrc10_cmd_discovery_req(tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
+static void dissect_rf4ce_profile_zrc10_cmd_discovery_rsp(tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
+
+/* RF4CE ZRC 2.0 profile commands dissectors */
+static void dissect_rf4ce_profile_zrc20_cmd(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t cmd_id);
+static void dissect_rf4ce_profile_zrc20_action_data(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool dissect_action_control);
+
+void proto_register_rf4ce_profile(void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rf4ce_profile_fcf,
+ {"Frame Control Field", "rf4ce-profile.fcf",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_fcf_cmd_id,
+ {"Command ID", "rf4ce-profile.fcf.cmd_id",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_fcf_cmd_id_vals), RF4CE_PROFILE_FCF_CMD_ID_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_fcf_cmd_id,
+ {"Command ID", "rf4ce-profile.fcf.cmd_id",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_zrc20_fcf_cmd_id_vals), RF4CE_PROFILE_FCF_CMD_ID_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_fcf_reserved,
+ {"Reserved", "rf4ce-profile.fcf.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_FCF_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_fcf_cmd_frame,
+ {"Command Frame", "rf4ce-profile.fcf.cmd_frame",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_fcf_cmd_frame_vals), RF4CE_PROFILE_FCF_CMD_FRAME_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_fcf_data_pending,
+ {"Data Pending", "rf4ce-profile.fcf.data_pending",
+ FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), RF4CE_PROFILE_FCF_DATA_PENDING_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_generic_resp_status,
+ {"Status", "rf4ce-profile.cmd.generic_resp.status",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_rf4ce_profile_cmd_generic_resp_status_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_configuration_complete_status,
+ {"Status", "rf4ce-profile.cmd.configuration_complete.status",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_rf4ce_profile_cmd_configuration_complete_status_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_heartbeat_trigger,
+ {"Trigger", "rf4ce-profile.cmd.heartbeat.trigger",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_rf4ce_profile_cmd_heartbeat_trigger_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_attr_id,
+ {"Attribute ID", "rf4ce-profile.gdp.attr.id",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_gdp_attr_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_attr_id,
+ {"Attribute ID", "rf4ce-profile.zrc20.attr.id",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_zrc20_attr_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_attr_entry_id,
+ {"Entry Identifier", "rf4ce-profile.zrc20.attr.entry_identifier",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_attr_status,
+ {"Status", "rf4ce-profile.attr.status",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_rf4ce_profile_attr_status_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_attr_length,
+ {"Length", "rf4ce-profile.attr.length",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_attr_value,
+ {"Value", "rf4ce-profile.attr.value",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_ident_cap,
+ {"Identification Capabilities", "rf4ce-profile.attr.ident_cap",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_ident_cap_reserved,
+ {"Reserved", "rf4ce-profile.attr.ident_cap.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_GDP_IDENT_CAP_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_ident_cap_support_flash_light,
+ {"Support Flash Light", "rf4ce-profile.attr.ident_cap.support_flash_light",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_FLASH_LIGHT_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_ident_cap_support_make_short_sound,
+ {"Support Make Short Sound", "rf4ce-profile.attr.ident_cap.support_make_short_sound",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_MAKE_SHORT_SOUND_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_ident_cap_support_vibrate,
+ {"Support Vibrate", "rf4ce-profile.attr.ident_cap.support_vibrate",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_GDP_IDENT_CAP_SUPPORT_VIBRATE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_ident_cap_reserved2,
+ {"Reserved", "rf4ce-profile.attr.ident_cap.reserved2",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_GDP_IDENT_CAP_RESERVED2_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_methods_num,
+ {"Polling Methods Number", "rf4ce-profile.attr.poll_constraints.methods_num",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_method_id,
+ {"Polling Method ID", "rf4ce-profile.attr.poll_constraints.polling_record.method_id",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_gdp_poll_constraints_polling_rec_method_id_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap,
+ {"Polling Trigger Capabilities", "rf4ce-profile.attr.poll_constraints.polling_record.polling_trig_cap",
+ FT_UINT16, BASE_HEX,
+ NULL, RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_tbased,
+ {"Time based polling capable", "rf4ce-profile.attr.poll_constraints.polling_record.polling_trig_cap.tbased",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_TBASED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_k_press,
+ {"Polling On Key Press Capable", "rf4ce-profile.attr.poll_constraints.polling_record.polling_trig_cap.on_k_press",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_K_PRESS_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_pick_up,
+ {"Polling On Pick Up Capable", "rf4ce-profile.attr.poll_constraints.polling_record.polling_trig_cap.on_pick_up",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_PICK_UP_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_reset,
+ {"Polling On Reset Capable", "rf4ce-profile.attr.poll_constraints.polling_record.polling_trig_cap.on_reset",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_RESET_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_micro_act,
+ {"Polling On Microphone Activity Capable", "rf4ce-profile.attr.poll_constraints.polling_record.polling_trig_cap.on_micro_act",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_MICRO_ACT_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_user_act,
+ {"Polling On Other User Activity Capable", "rf4ce-profile.attr.poll_constraints.polling_record.polling_trig_cap.on_user_act",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_ON_USER_ACT_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_reserved,
+ {"Reserved", "rf4ce-profile.attr.poll_constraints.polling_record.polling_trig_cap.reserved",
+ FT_UINT16, BASE_HEX,
+ NULL, RF4CE_PROFILE_GDP_POLL_CONSTRAINTS_POLLING_REC_POLLING_TRIG_CAP_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_min_polling_key_press_cnt,
+ {"Minimum Polling Key Press Counter", "rf4ce-profile.attr.poll_constraints.polling_record.min_polling_key_press_cnt",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_max_polling_key_press_cnt,
+ {"Maximum Polling Key Press Counter", "rf4ce-profile.attr.poll_constraints.polling_record.max_polling_key_press_cnt",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_min_polling_time_interval,
+ {"Minimum Polling Time Interval", "rf4ce-profile.attr.poll_constraints.polling_record.min_polling_time_interval",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_constraints_polling_rec_max_polling_time_interval,
+ {"Maximum Polling Time Interval", "rf4ce-profile.attr.poll_constraints.polling_record.max_polling_time_interval",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_method_id,
+ {"Polling Method ID", "rf4ce-profile.attr.poll_configuration.method_id",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_gdp_poll_constraints_polling_rec_method_id_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf,
+ {"Polling Trigger Configuration", "rf4ce-profile.attr.poll_configuration.polling_trig_conf",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_tbased,
+ {"Time Based Polling", "rf4ce-profile.attr.poll_configuration.polling_trig_conf.tbased",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_TBASED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_k_press,
+ {"Polling on Key Press", "rf4ce-profile.attr.poll_configuration.polling_trig_conf.on_k_press",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_K_PRESS_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_pick_up,
+ {"Polling on Pick up", "rf4ce-profile.attr.poll_configuration.polling_trig_conf.on_pick_up",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_PICK_UP_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_reset,
+ {"Polling on Reset", "rf4ce-profile.attr.poll_configuration.polling_trig_conf.on_reset",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_RESET_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_micro_act,
+ {"Polling on Microphone Activity", "rf4ce-profile.attr.poll_configuration.polling_trig_conf.on_micro_act",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_MICRO_ACT_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_user_act,
+ {"Polling on User Activity", "rf4ce-profile.attr.poll_configuration.polling_trig_conf.on_user_act",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_enabled_disabled), RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_ON_USER_ACT_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_reserved,
+ {"Reserved", "rf4ce-profile.attr.poll_configuration.polling_trig_conf.reserved",
+ FT_UINT16, BASE_HEX,
+ NULL, RF4CE_PROFILE_GDP_POLL_CONFIGURATION_POLLING_TRIG_CONF_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_key_press_cnt,
+ {"Polling Key Press Counter", "rf4ce-profile.attr.poll_configuration.polling_key_press_cnt",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_time_interval,
+ {"Polling Time Interval", "rf4ce-profile.attr.poll_configuration.polling_time_interval",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_gdp_poll_configuration_polling_timeout,
+ {"Polling Timeout", "rf4ce-profile.attr.poll_configuration.polling_timeout",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_mappable_actions_action_dev_type,
+ {"Action Device Type", "rf4ce-profile.attr.mappable_actions.action_dev_type",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_device_type_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_mappable_actions_action_bank,
+ {"Action Bank", "rf4ce-profile.attr.mappable_actions.action_bank",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_mappable_actions_action_code,
+ {"Action Code", "rf4ce-profile.attr.mappable_actions.action_code",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_mapping_flags,
+ {"Mapping Flags", "rf4ce-profile.attr.action_mappings.mapping_flags",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_rf_specified,
+ {"RF Specified", "rf4ce-profile.attr.action_mappings.mapping_flags.rf_specified",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RF_SPECIFIED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_ir_specified,
+ {"IR Specified", "rf4ce-profile.attr.action_mappings.mapping_flags.ir_specified",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_IR_SPECIFIED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_rf_descr_first,
+ {"RF Descriptor First", "rf4ce-profile.attr.action_mappings.mapping_flags.rf_descr_first",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RF_DESCR_FIRST_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_reserved,
+ {"Reserved", "rf4ce-profile.attr.action_mappings.mapping_flags.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_use_default,
+ {"Use Default", "rf4ce-profile.attr.action_mappings.mapping_flags.use_default",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_USE_DEFAULT_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_permanent,
+ {"Permanent", "rf4ce-profile.attr.action_mappings.mapping_flags.permanent",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_PERMANENT_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf,
+ {"RF Config", "rf4ce-profile.attr.action_mappings.rf_descr.rf_conf",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_min_num_of_trans,
+ {"Minimum Number of Transmissions", "rf4ce-profile.attr.action_mappings.rf_descr.rf_conf.min_num_of_trans",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_MIN_NUM_OF_TRANS_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_keep_trans_until_key_release,
+ {"Keep Transmitting Until Key Release", "rf4ce-profile.attr.action_mappings.rf_descr.rf_conf.keep_trans_until_key_release",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_KEEP_TRANS_UNTIL_KEY_RELEASE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_short_rf_retry,
+ {"Short RF Retry", "rf4ce-profile.attr.action_mappings.rf_descr.rf_conf.short_rf_retry",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_SHORT_RF_RETRY_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_atomic_action,
+ {"Atomic Action", "rf4ce-profile.attr.action_mappings.rf_descr.rf_conf.atomic_action",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_ATOMIC_ACTION_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_reserved,
+ {"Reserved", "rf4ce-profile.attr.action_mappings.rf_descr.rf_conf.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_RF_CONF_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts,
+ {"TX Options", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_trans_mode,
+ {"Transmission Mode", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts.trans_mode",
+ FT_BOOLEAN, SEP_DOT,
+ TFS(&rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_trans_mode_vals), RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_TRANS_MODE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_dst_addr_mode,
+ {"Destination Addressing Mode", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts.dst_addr_mode",
+ FT_BOOLEAN, SEP_DOT,
+ TFS(&rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_dst_addr_mode_vals), RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_DST_ADDR_MODE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ack_mode,
+ {"Acknowledgement Mode", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts.ack_mode",
+ FT_BOOLEAN, SEP_DOT,
+ TFS(&rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ack_mode_vals), RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_ACK_MODE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_sec_mode,
+ {"Security Mode", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts.sec_mode",
+ FT_BOOLEAN, SEP_DOT,
+ TFS(&rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_sec_mode_vals), RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_SEC_MODE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_ag_mode,
+ {"Channel Agility Mode", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts.ch_ag_mode",
+ FT_BOOLEAN, SEP_DOT,
+ TFS(&rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_ag_mode_vals), RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_CH_AG_MODE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_norm_mode,
+ {"Channel Normalization Mode", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts.ch_norm_mode",
+ FT_BOOLEAN, SEP_DOT,
+ TFS(&rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_norm_mode_vals), RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_CH_NORM_MODE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_payload_mode,
+ {"Payload Mode", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts.payload_mode",
+ FT_BOOLEAN, SEP_DOT,
+ TFS(&rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_payload_mode_vals), RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_PAYLOAD_MODE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_reserved,
+ {"Reserved", "rf4ce-profile.attr.action_mappings.rf_descr.tx_opts.reserved",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_RF_DESCR_TX_OPTS_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_rf_descr_action_data_len,
+ {"Action Data Length", "rf4ce-profile.attr.action_mappings.rf_descr.action_data_len",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf,
+ {"IR Config", "rf4ce-profile.attr.action_mappings.ir_descr.ir_conf",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf_vendor_specific,
+ {"Vendor Specific", "rf4ce-profile.attr.action_mappings.ir_descr.ir_conf.vendor_specific",
+ FT_BOOLEAN, SEP_DOT,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_VENDOR_SPECIFIC_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf_reserved,
+ {"Reserved", "rf4ce-profile.attr.action_mappings.ir_descr.ir_conf.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_vendor_id,
+ {"IR Vendor ID", "rf4ce-profile.attr.action_mappings.ir_descr.ir_vendor_id",
+ FT_UINT16, BASE_HEX,
+ VALS(rf4ce_vendor_id_vals), RF4CE_VENDOR_ID_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_code_len,
+ {"IR Code Length", "rf4ce-profile.attr.action_mappings.ir_descr.ir_code_len",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_code,
+ {"IR Code", "rf4ce-profile.attr.action_mappings.ir_descr.ir_code",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_zrc20_irdb_vendor_support_vendor_id,
+ {"Vendor ID", "rf4ce-profile.attr.irdb_vendor_support.vendor_id",
+ FT_UINT16, BASE_HEX,
+ VALS(rf4ce_vendor_id_vals), RF4CE_VENDOR_ID_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_check_validation_sub_type,
+ {"Sub-type", "rf4ce-profile.cmd.check_validation.sub_type",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_cmd_check_validation_sub_type_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_check_validation_control,
+ {"Validation Control", "rf4ce-profile.cmd.check_validation.validation_control",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_check_validation_status,
+ {"Validation Status", "rf4ce-profile.cmd.check_validation.validation_status",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_cmd_check_validation_status_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_client_notification_sub_type,
+ {"Sub-ype", "rf4ce-profile.cmd.client_notification.sub_type",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_cmd_client_notification_sub_type_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_client_notification_identify_flags,
+ {"Identify Flags", "rf4ce-profile.cmd.client_notification.identify_flags",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_client_notification_identify_flags_stop_on_action,
+ {"Stop on Action", "rf4ce-profile.cmd.client_notification.identify_flags.stop_on_action",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_STOP_ON_ACTION_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_client_notification_identify_flags_flash_light,
+ {"Flash Light", "rf4ce-profile.cmd.client_notification.identify_flags.flash_light",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_FLASH_LIGHT_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_client_notification_identify_flags_make_sound,
+ {"Make Sound", "rf4ce-profile.cmd.client_notification.identify_flags.make_sound",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_MAKE_SOUND_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_client_notification_identify_flags_vibrate,
+ {"Vibrate", "rf4ce-profile.cmd.client_notification.identify_flags.vibrate",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_VIBRATE_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_client_notification_identify_flags_reserved,
+ {"Reserved", "rf4ce-profile.cmd.client_notification.identify_flags.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY_RESERVED_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_client_notification_identify_time,
+ {"Identify Time", "rf4ce-profile.cmd.client_notification.identify_time",
+ FT_UINT16, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_sub_type,
+ {"Sub-type", "rf4ce-profile.cmd.key_exchange.sub_type",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_profile_cmd_key_exchange_sub_type_vals), 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_flags,
+ {"Key Exchange Flags", "rf4ce-profile.cmd.key_exchange.flags",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_flags_default_secret,
+ {"Default Secret", "rf4ce-profile.cmd.key_exchange.flags.default_secret",
+ FT_UINT16, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_DEFAULT_SECRET_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_flags_initiator_vendor_specific_secret,
+ {"Initiator Vendor Specific Secret", "rf4ce-profile.cmd.key_exchange.flags.initiator_vendor_specific_secret",
+ FT_UINT16, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_INITIATOR_VENDOR_SPECIFIC_SECRET_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_flags_responder_vendor_specific_secret,
+ {"Responder Vendor Specific Secret", "rf4ce-profile.cmd.key_exchange.flags.responder_vendor_specific_secret",
+ FT_UINT16, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_RESPONDER_VENDOR_SPECIFIC_SECRET_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_flags_reserved,
+ {"Reserved", "rf4ce-profile.cmd.key_exchange.flags.reserved",
+ FT_UINT16, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_RESERVED_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_flags_vendor_specific_parameter,
+ {"Vendor Specific Parameter", "rf4ce-profile.cmd.key_exchange.flags.vendor_specific_parameter",
+ FT_UINT16, BASE_HEX,
+ NULL, RF4CE_PROFILE_CMD_KEY_EXCHANGE_FLAGS_VENDOR_SPECIFIC_PARAMETER_FLAG,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_rand_a,
+ {"Rand-A", "rf4ce-profile.cmd.key_exchange.rand_a",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x00,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_rand_b,
+ {"Rand-B", "rf4ce-profile.cmd.key_exchange.rand_b",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x00,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_tag_b,
+ {"TAG-B", "rf4ce-profile.cmd.key_exchange.tag_b",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x00,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_cmd_key_exchange_tag_a,
+ {"TAG-A", "rf4ce-profile.cmd.key_exchange.tag_a",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x00,
+ NULL, HFILL}},
+#if 0
+ {&hf_rf4ce_zrc20_cmd_actions,
+ {"Actions", "rf4ce-profile.zrc20.cmd.actions",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x00,
+ NULL, HFILL}},
+#endif
+ {&hf_rf4ce_zrc20_cmd_actions_action_control,
+ {"Action Control", "rf4ce-profile.zrc20.cmd.actions.action_control",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x00,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_control_action_type,
+ {"Action Type", "rf4ce-profile.zrc20.cmd.actions.action_control.action_type",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_zrc20_cmd_actions_action_control_action_type_vals), RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_ACTION_TYPE_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_control_reserved,
+ {"Reserved", "rf4ce-profile.zrc20.cmd.actions.action_control.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_RESERVED,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_gui,
+ {"GUI Modifier", "rf4ce-profile.zrc20.cmd.actions.action_control.modifier_bits.gui",
+ FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_MODIFIER_BITS_GUI,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_alt,
+ {"ALT Modifier", "rf4ce-profile.zrc20.cmd.actions.action_control.modifier_bits.alt",
+ FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_MODIFIER_BITS_ALT,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_shift,
+ {"SHIFT Modifier", "rf4ce-profile.zrc20.cmd.actions.action_control.modifier_bits.shift",
+ FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_MODIFIER_BITS_SHIFT,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_ctrl,
+ {"CTRL Modifier", "rf4ce-profile.zrc20.cmd.actions.action_control.modifier_bits.ctrl",
+ FT_BOOLEAN, 8,
+ TFS(&tfs_yes_no), RF4CE_ZRC20_CMD_ACTIONS_ACTION_CONTROL_MODIFIER_BITS_CTRL,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_data_payload_length,
+ {"Payload Length", "rf4ce-profile.zrc20.cmd.actions.action_data.payload_length",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_data_action_bank,
+ {"Action Bank", "rf4ce-profile.zrc20.cmd.actions.action_data.action_bank",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_data_action_code,
+ {"Action Code", "rf4ce-profile.zrc20.cmd.actions.action_data.action_code",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_data_action_vendor,
+ {"Action Vendor", "rf4ce-profile.zrc20.cmd.actions.action_data.action_vendor",
+ FT_UINT16, BASE_HEX,
+ VALS(rf4ce_vendor_id_vals), RF4CE_VENDOR_ID_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc20_cmd_actions_action_data_action_payload,
+ {"Action Payload", "rf4ce-profile.zrc20.cmd.actions.action_data.action_payload",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc10_fcf,
+ {"Frame Control Field", "rf4ce-profile.zrc10.fcf",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc10_fcf_cmd_id,
+ {"Command ID", "rf4ce-profile.zrc10.fcf.cmd_id",
+ FT_UINT8, BASE_HEX,
+ VALS(rf4ce_zrc10_fcf_cmd_id_vals), RF4CE_ZRC10_FCF_CMD_ID_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc10_fcf_reserved,
+ {"Reserved", "rf4ce-profile.zrc10.fcf.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, RF4CE_ZRC10_FCF_RESERVED_MASK,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc10_cmd_common_rc_command_code,
+ {"RC Command Code", "rf4ce-profile.zrc10.cmd_common.rc_command_code",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc10_cmd_common_rc_command_payload,
+ {"RC Command Payload", "rf4ce-profile.zrc10.cmd_common.rc_command_payload",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc10_cmd_disc_reserved,
+ {"Reserved", "rf4ce-profile.zrc10.cmd.discovery.reserved",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_zrc10_cmd_disc_rsp_supported_commands,
+ {"Supported Commands", "rf4ce-profile.zrc10.cmd_disc_rsp.supported_commands",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x0,
+ NULL, HFILL}},
+ {&hf_rf4ce_profile_unparsed_payload,
+ {"Unparsed Profile Payload", "rf4ce-profile.unparsed_payload",
+ FT_BYTES, SEP_COLON,
+ NULL, 0x0,
+ NULL, HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static int *ett[] = {
+ &ett_rf4ce_profile,
+ &ett_rf4ce_profile_cmd_frame,
+ &ett_rf4ce_profile_attrs,
+ &ett_rf4ce_profile_attrs_sub,
+ &ett_rf4ce_profile_zrc20_ident_cap,
+ &ett_rf4ce_profile_zrc20_mappable_actions_entry,
+ &ett_rf4ce_profile_zrc20_action_control,
+ &ett_rf4ce_profile_zrc20_action_mappings_flags,
+ &ett_rf4ce_profile_zrc20_action_mappings_rf_descr,
+ &ett_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf,
+ &ett_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts,
+ &ett_rf4ce_profile_zrc20_action_mappings_ir_descr,
+ &ett_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf,
+ &ett_rf4ce_profile_gdp_poll_constraints_polling_rec,
+ &ett_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap,
+ &ett_rf4ce_profile_gdp_poll_configuration_polling_trig_conf,
+ &ett_rf4ce_profile_action_records,
+ &ett_rf4ce_profile_action_records_sub,
+ &ett_rf4ce_profile_zrc10_supported_commands,
+ &ett_rf4ce_profile_zrc10_supported_commands_sub};
+
+ proto_rf4ce_profile = proto_register_protocol("RF4CE Profile", "RF4CE Profile", "rf4ce_profile");
+ proto_register_field_array(proto_rf4ce_profile, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ rf4ce_profile_dissector_table = register_dissector_table("rf4ce.profile", "RF4CE Profile", proto_rf4ce_profile, FT_NONE, BASE_NONE);
+ rf4ce_profile_handle = register_dissector("rf4ce_profile", dissect_rf4ce_profile_common, proto_rf4ce_profile);
+}
+
+void proto_reg_handoff_rf4ce_profile(void)
+{
+}
+
+/* RF4CE Profile common dissector */
+static int dissect_rf4ce_profile_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ unsigned offset = 0;
+ proto_item *ti = proto_tree_add_item(tree, proto_rf4ce_profile, tvb, 0, -1, ENC_LITTLE_ENDIAN);
+ proto_tree *rf4ce_profile_tree = proto_item_add_subtree(ti, ett_rf4ce_profile);
+
+ uint8_t fcf = tvb_get_uint8(tvb, offset);
+ uint8_t cmd_id = fcf & RF4CE_PROFILE_FCF_CMD_ID_MASK;
+ bool is_cmd_frame = fcf & RF4CE_PROFILE_FCF_CMD_FRAME_MASK;
+ bool is_gdp = !strncmp("GDP", (char *)data, 3);
+ bool is_zrc20 = !strncmp("ZRC 2.0", (char *)data, 7);
+ bool is_zrc10 = !strncmp("ZRC 1.0", (char *)data, 7);
+
+ char protocol_str[14] = {0};
+
+ /* Clear the info column */
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (is_gdp || (is_zrc20 && is_cmd_frame))
+ {
+ static int *const gdp_fcf_bits[] = {
+ &hf_rf4ce_profile_fcf_cmd_id,
+ &hf_rf4ce_profile_fcf_reserved,
+ &hf_rf4ce_profile_fcf_cmd_frame,
+ &hf_rf4ce_profile_fcf_data_pending,
+ NULL};
+
+ proto_tree_add_bitmask(rf4ce_profile_tree, tvb, offset, hf_rf4ce_profile_fcf, ett_rf4ce_profile, gdp_fcf_bits, ENC_LITTLE_ENDIAN);
+ offset += 1;
+ }
+ else if (is_zrc20)
+ {
+ static int *const zrc20_fcf_bits[] = {
+ &hf_rf4ce_zrc20_fcf_cmd_id,
+ &hf_rf4ce_profile_fcf_reserved,
+ &hf_rf4ce_profile_fcf_cmd_frame,
+ &hf_rf4ce_profile_fcf_data_pending,
+ NULL};
+
+ proto_tree_add_bitmask(rf4ce_profile_tree, tvb, offset, hf_rf4ce_profile_fcf, ett_rf4ce_profile, zrc20_fcf_bits, ENC_LITTLE_ENDIAN);
+ offset += 1;
+ }
+ else if (is_zrc10)
+ {
+ static int *const zrc10_fcf_bits[] = {
+ &hf_rf4ce_zrc10_fcf_cmd_id,
+ &hf_rf4ce_zrc10_fcf_reserved,
+ NULL};
+
+ proto_tree_add_bitmask(rf4ce_profile_tree, tvb, offset, hf_rf4ce_zrc10_fcf, ett_rf4ce_profile, zrc10_fcf_bits, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ cmd_id = fcf & RF4CE_ZRC10_FCF_CMD_ID_MASK;
+ }
+
+ snprintf(protocol_str, sizeof(protocol_str), "%s %s", "RF4CE", (char *)data);
+ col_add_str(pinfo->cinfo, COL_PROTOCOL, protocol_str);
+
+ if (is_gdp || is_zrc20 || is_zrc10)
+ {
+ dissect_rf4ce_profile_cmd(tvb, pinfo, rf4ce_profile_tree, &offset, cmd_id, (char *)data, is_cmd_frame);
+ }
+
+ if (offset < tvb_captured_length(tvb))
+ {
+ unsigned unparsed_length = tvb_captured_length(tvb) - offset;
+ proto_tree_add_item(rf4ce_profile_tree, hf_rf4ce_profile_unparsed_payload, tvb, offset, unparsed_length, ENC_NA);
+ offset += unparsed_length;
+ }
+
+ return offset;
+}
+
+static void dissect_rf4ce_profile_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned *offset, uint8_t cmd_id, char *profile_str, bool is_cmd_frame)
+{
+ proto_tree *profile_cmd_tree;
+ bool is_zrc10 = !strncmp("ZRC 1.0", profile_str, 7);
+ bool is_zrc20 = !strncmp("ZRC 2.0", profile_str, 7);
+
+ profile_cmd_tree = proto_tree_add_subtree(tree, tvb, *offset, tvb_captured_length(tvb) - *offset, ett_rf4ce_profile_cmd_frame, NULL, "Profile Command Frame");
+
+ if (is_cmd_frame)
+ {
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd_id, rf4ce_profile_fcf_cmd_id_vals, "Unknown Command"));
+ dissect_rf4ce_profile_common_cmd(tvb, pinfo, profile_cmd_tree, offset, cmd_id, is_zrc20);
+ }
+ else if (is_zrc10)
+ {
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd_id, rf4ce_zrc10_fcf_cmd_id_vals, "Unknown Command"));
+ dissect_rf4ce_profile_zrc10_cmd(tvb, profile_cmd_tree, offset, cmd_id);
+ }
+ /* cmd_frame bit MUST be zero for ZRC 2.0 profile */
+ else if (is_zrc20 || !is_cmd_frame)
+ {
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd_id, rf4ce_zrc20_fcf_cmd_id_vals, "Unknown Command"));
+ dissect_rf4ce_profile_zrc20_cmd(tvb, profile_cmd_tree, offset, cmd_id);
+ }
+}
+
+static void dissect_rf4ce_profile_common_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned *offset, uint8_t cmd_id, bool is_zrc20)
+{
+ switch (cmd_id)
+ {
+ case RF4CE_PROFILE_CMD_GENERIC_RESPONSE:
+ dissect_rf4ce_profile_cmd_generic_resp(tvb, tree, offset);
+ break;
+
+ case RF4CE_PROFILE_CMD_CONFIGURATION_COMPLETE:
+ dissect_rf4ce_profile_cmd_configuration_complete(tvb, tree, offset);
+ break;
+
+ case RF4CE_PROFILE_CMD_HEARTBEAT:
+ dissect_rf4ce_profile_cmd_heartbeat(tvb, tree, offset);
+ break;
+
+ case RF4CE_PROFILE_CMD_GET_ATTRIBUTES:
+ dissect_rf4ce_profile_cmd_get_attrs(tvb, tree, offset, is_zrc20);
+ break;
+
+ case RF4CE_PROFILE_CMD_GET_ATTRIBUTES_RESPONSE:
+ dissect_rf4ce_profile_cmd_get_attrs_resp(tvb, tree, offset, is_zrc20);
+ break;
+
+ case RF4CE_PROFILE_CMD_PUSH_ATTRIBUTES:
+ dissect_rf4ce_profile_cmd_push_attrs(tvb, tree, offset, is_zrc20);
+ break;
+
+ case RF4CE_PROFILE_CMD_SET_ATTRIBUTES:
+ dissect_rf4ce_profile_cmd_set_attrs(tvb, tree, offset, is_zrc20);
+ break;
+
+ case RF4CE_PROFILE_CMD_PULL_ATTRIBUTES:
+ dissect_rf4ce_profile_cmd_pull_attrs(tvb, tree, offset, is_zrc20);
+ break;
+
+ case RF4CE_PROFILE_CMD_PULL_ATTRIBUTES_RESPONSE:
+ dissect_rf4ce_profile_cmd_pull_attrs_resp(tvb, tree, offset, is_zrc20);
+ break;
+
+ case RF4CE_PROFILE_CMD_CHECK_VALIDATION:
+ dissect_rf4ce_profile_cmd_check_validation(tvb, tree, offset);
+ break;
+
+ case RF4CE_PROFILE_CMD_CLIENT_NOTIFICATION:
+ dissect_rf4ce_profile_cmd_client_notification(tvb, tree, offset);
+ break;
+
+ case RF4CE_PROFILE_CMD_KEY_EXCHANGE:
+ dissect_rf4ce_profile_cmd_key_exchange(tvb, pinfo, tree, offset);
+ break;
+ }
+}
+
+static void dissect_rf4ce_profile_cmd_generic_resp(tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
+{
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_generic_resp_status, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+}
+
+static void dissect_rf4ce_profile_cmd_configuration_complete(tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
+{
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_configuration_complete_status, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+}
+
+static void dissect_rf4ce_profile_cmd_heartbeat(tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
+{
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_heartbeat_trigger, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+}
+
+static bool dissect_rf4ce_profile_gdp_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t attr_id)
+{
+ bool is_parsed = true;
+
+ if (attr_id == RF4CE_GDP_ATTR_IDENTIFICATION_CAPABILITIES)
+ {
+ static int *const ident_cap_bits[] = {
+ &hf_rf4ce_profile_gdp_ident_cap_reserved,
+ &hf_rf4ce_profile_gdp_ident_cap_support_flash_light,
+ &hf_rf4ce_profile_gdp_ident_cap_support_make_short_sound,
+ &hf_rf4ce_profile_gdp_ident_cap_support_vibrate,
+ &hf_rf4ce_profile_gdp_ident_cap_reserved2,
+ NULL};
+
+ proto_tree_add_bitmask(tree, tvb, *offset, hf_rf4ce_profile_gdp_ident_cap, ett_rf4ce_profile_zrc20_ident_cap, ident_cap_bits, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+ }
+ else if (attr_id == RF4CE_GDP_ATTR_POLL_CONSTRAINTS)
+ {
+ int methods_index;
+ uint8_t methods_num;
+
+ static int *const polling_trig_cap_bits[] = {
+ &hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_tbased,
+ &hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_k_press,
+ &hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_pick_up,
+ &hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_reset,
+ &hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_micro_act,
+ &hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_on_user_act,
+ &hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap_reserved,
+ NULL};
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_gdp_poll_constraints_methods_num, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ methods_num = tvb_get_uint8(tvb, *offset);
+ *offset += 1;
+
+ for (methods_index = 1; methods_index <= methods_num; methods_index++)
+ {
+ char subtree_name[40];
+ proto_tree *record_subtree;
+
+ snprintf(subtree_name, sizeof(subtree_name), "Polling Constraint Record %d:", methods_index);
+ record_subtree = proto_tree_add_subtree(tree, tvb, *offset, tvb_captured_length(tvb) - *offset, ett_rf4ce_profile_gdp_poll_constraints_polling_rec, NULL, subtree_name);
+
+ proto_tree_add_item(record_subtree, hf_rf4ce_profile_gdp_poll_constraints_polling_rec_method_id, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_bitmask(record_subtree, tvb, *offset, hf_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap, ett_rf4ce_profile_gdp_poll_constraints_polling_rec_polling_trig_cap, polling_trig_cap_bits, ENC_LITTLE_ENDIAN);
+ *offset += 2;
+
+ proto_tree_add_item(record_subtree, hf_rf4ce_profile_gdp_poll_constraints_polling_rec_min_polling_key_press_cnt, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_item(record_subtree, hf_rf4ce_profile_gdp_poll_constraints_polling_rec_max_polling_key_press_cnt, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_item(record_subtree, hf_rf4ce_profile_gdp_poll_constraints_polling_rec_min_polling_time_interval, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
+ *offset += 4;
+
+ proto_tree_add_item(record_subtree, hf_rf4ce_profile_gdp_poll_constraints_polling_rec_max_polling_time_interval, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
+ *offset += 4;
+ }
+ }
+ else if (attr_id == RF4CE_GDP_ATTR_POLL_CONFIGURATION)
+ {
+ proto_tree_add_item(tree, hf_rf4ce_profile_gdp_poll_configuration_method_id, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ static int *const polling_trig_conf_bits[] = {
+ &hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_tbased,
+ &hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_k_press,
+ &hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_pick_up,
+ &hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_reset,
+ &hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_micro_act,
+ &hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_on_user_act,
+ &hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf_reserved,
+ NULL};
+
+ proto_tree_add_bitmask_len(tree, tvb, *offset, 2, hf_rf4ce_profile_gdp_poll_configuration_polling_trig_conf, ett_rf4ce_profile_gdp_poll_configuration_polling_trig_conf, polling_trig_conf_bits, NULL, ENC_LITTLE_ENDIAN);
+ *offset += 2;
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_gdp_poll_configuration_polling_key_press_cnt, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_gdp_poll_configuration_polling_time_interval, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
+ *offset += 4;
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_gdp_poll_configuration_polling_timeout, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+ }
+#if 0
+ else if (attr_id == RF4CE_GDP_ATTR_GDP_PROFILE_CAPABILITIES)
+ {
+ /* TODO: Implement RF4CE_GDP_ATTR_GDP_CAPABILITIES parsing */
+ }
+ else if (attr_id == RF4CE_GDP_ATTR_POWER_STATUS)
+ {
+ /* TODO: Implement RF4CE_GDP_ATTR_POWER_STATUS parsing */
+ }
+#endif
+ else
+ {
+ is_parsed = false;
+ }
+
+ return is_parsed;
+}
+
+static bool dissect_rf4ce_profile_zrc20_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t attr_id, uint8_t attr_length)
+{
+ bool is_parsed = true;
+
+ if (attr_id == RF4CE_ZRC20_ATTR_MAPPABLE_ACTIONS)
+ {
+ proto_tree *entry_subtree;
+ char entry_subtree_name[11];
+ unsigned entries_num = attr_length / 3;
+
+ for (unsigned i = 1; i <= entries_num; i++)
+ {
+ snprintf(entry_subtree_name, sizeof(entry_subtree_name), "Entry %d:", i);
+ entry_subtree = proto_tree_add_subtree(tree, tvb, *offset, tvb_captured_length(tvb) - *offset, ett_rf4ce_profile_zrc20_mappable_actions_entry, NULL, entry_subtree_name);
+
+ proto_tree_add_item(entry_subtree, hf_rf4ce_profile_zrc20_mappable_actions_action_dev_type, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_item(entry_subtree, hf_rf4ce_profile_zrc20_mappable_actions_action_bank, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_item(entry_subtree, hf_rf4ce_profile_zrc20_mappable_actions_action_code, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+ }
+ }
+ else if (attr_id == RF4CE_ZRC20_ATTR_ACTION_MAPPINGS)
+ {
+ uint8_t action_mapping_flags = tvb_get_uint8(tvb, *offset);
+ bool rf_specified = (action_mapping_flags & RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_RF_SPECIFIED_MASK) != 0;
+ bool ir_specified = (action_mapping_flags & RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_IR_SPECIFIED_MASK) != 0;
+ bool use_default = (action_mapping_flags & RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_MAPPING_FLAGS_USE_DEFAULT_MASK) != 0;
+
+ static int *const action_mapping_flags_bits[] = {
+ &hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_rf_specified,
+ &hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_ir_specified,
+ &hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_rf_descr_first,
+ &hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_reserved,
+ &hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_use_default,
+ &hf_rf4ce_profile_zrc20_action_mappings_mapping_flags_permanent,
+ NULL};
+
+ proto_tree_add_bitmask(tree, tvb, *offset, hf_rf4ce_profile_zrc20_action_mappings_mapping_flags, ett_rf4ce_profile_zrc20_action_mappings_flags, action_mapping_flags_bits, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ if (rf_specified && !use_default)
+ {
+ proto_tree *rf_desc_subtree = proto_tree_add_subtree(tree, tvb, *offset, tvb_captured_length(tvb) - *offset, ett_rf4ce_profile_zrc20_action_mappings_rf_descr, NULL, "RF Descriptor");
+ uint8_t action_data_len;
+
+ static int *const rf_conf_bits[] = {
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_min_num_of_trans,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_keep_trans_until_key_release,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_short_rf_retry,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_atomic_action,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf_reserved,
+ NULL};
+
+ proto_tree_add_bitmask(rf_desc_subtree, tvb, *offset, hf_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf, ett_rf4ce_profile_zrc20_action_mappings_rf_descr_rf_conf, rf_conf_bits, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ static int *const tx_opts_bits[] = {
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_trans_mode,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_dst_addr_mode,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ack_mode,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_sec_mode,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_ag_mode,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_ch_norm_mode,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_payload_mode,
+ &hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts_reserved,
+ NULL};
+
+ proto_tree_add_bitmask(rf_desc_subtree, tvb, *offset, hf_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts, ett_rf4ce_profile_zrc20_action_mappings_rf_descr_tx_opts, tx_opts_bits, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_item(rf_desc_subtree, hf_rf4ce_profile_zrc20_action_mappings_rf_descr_action_data_len, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ action_data_len = tvb_get_uint8(tvb, *offset);
+ *offset += 1;
+
+ if (action_data_len > 0)
+ {
+ dissect_rf4ce_profile_zrc20_action_data(tvb, rf_desc_subtree, offset, false /* do not dissect the Action Control field */);
+ }
+ }
+
+ if (ir_specified && !use_default)
+ {
+ proto_tree *ir_desc_subtree = proto_tree_add_subtree(tree, tvb, *offset, tvb_captured_length(tvb) - *offset, ett_rf4ce_profile_zrc20_action_mappings_ir_descr, NULL, "IR Descriptor");
+ uint8_t ir_config;
+ bool vendor_specific;
+ uint8_t ir_code_len;
+
+ static int *const ir_conf_bits[] = {
+ &hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf_vendor_specific,
+ &hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf_reserved,
+ NULL};
+
+ proto_tree_add_bitmask(ir_desc_subtree, tvb, *offset, hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf, ett_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_conf, ir_conf_bits, ENC_LITTLE_ENDIAN);
+ ir_config = tvb_get_uint8(tvb, *offset);
+ *offset += 1;
+
+ vendor_specific = (ir_config & RF4CE_PROFILE_ZRC20_ACTION_MAPPINGS_IR_DESCR_IR_CONF_VENDOR_SPECIFIC_MASK) != 0;
+ if (vendor_specific)
+ {
+ proto_tree_add_item(ir_desc_subtree, hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_vendor_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ *offset += 2;
+ }
+
+ proto_tree_add_item(ir_desc_subtree, hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_code_len, tvb, *offset, 1, ENC_NA);
+ ir_code_len = tvb_get_uint8(tvb, *offset);
+ *offset += 1;
+
+ if (ir_code_len > 0)
+ {
+ proto_tree_add_item(ir_desc_subtree, hf_rf4ce_profile_zrc20_action_mappings_ir_descr_ir_code, tvb, *offset, ir_code_len, ENC_NA);
+ *offset += ir_code_len;
+ }
+ }
+ }
+ else if (attr_id == RF4CE_ZRC20_ATTR_IRDB_VENDOR_SUPPORT)
+ {
+ int remaining_length = tvb_reported_length_remaining(tvb, *offset);
+ while (remaining_length > 0)
+ {
+ proto_tree_add_item(tree, hf_rf4ce_profile_zrc20_irdb_vendor_support_vendor_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ *offset += 2;
+ remaining_length -= 2;
+ }
+ }
+ else
+ {
+ is_parsed = false;
+ }
+
+ return is_parsed;
+}
+
+static void dissect_rf4ce_profile_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t dissection_mask, bool is_zrc20)
+{
+ int attr_counter = 1;
+ uint8_t attr_id = 0xff;
+ uint8_t attr_status = RF4CE_PROFILE_ATTR_STATUS_ATTRIBUTE_SUCCESSFULLY_READ_AND_INCLUDED;
+ uint8_t attr_length = 0xff;
+ proto_tree *attrs_tree = proto_tree_add_subtree(tree, tvb, *offset, tvb_captured_length(tvb) - *offset, ett_rf4ce_profile_attrs, NULL, "Attributes List");
+ unsigned prev_offset = *offset;
+
+ while (tvb_captured_length(tvb) - *offset)
+ {
+ char attr_subtree_name[14];
+ proto_tree *attrs_subtree;
+
+ snprintf(attr_subtree_name, sizeof(attr_subtree_name), "Attribute %d:", attr_counter);
+ attr_counter++;
+
+ attrs_subtree = proto_tree_add_subtree(attrs_tree, tvb, *offset, tvb_captured_length(tvb) - *offset, ett_rf4ce_profile_attrs_sub, NULL, attr_subtree_name);
+
+ if (dissection_mask & RF4CE_PROFILE_ATTR_DISSECT_ATTR_ID_MASK)
+ {
+ int hf_temp = is_zrc20 ? hf_rf4ce_profile_zrc20_attr_id : hf_rf4ce_profile_gdp_attr_id;
+
+ proto_tree_add_item(attrs_subtree, hf_temp, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ attr_id = tvb_get_uint8(tvb, *offset);
+ *offset += 1;
+ }
+
+ if (dissection_mask & RF4CE_PROFILE_ATTR_DISSECT_ENTRY_ID_MASK)
+ {
+ bool is_attr_arrayed =
+ is_zrc20 ? rf4ce_profile_is_zrc20_attr_arrayed(attr_id) : rf4ce_profile_is_gdp_attr_arrayed(attr_id);
+ if (is_attr_arrayed)
+ {
+ proto_tree_add_item(attrs_subtree, hf_rf4ce_profile_attr_entry_id, tvb, *offset, 2, ENC_NA);
+ *offset += 2;
+ }
+ }
+
+ if (dissection_mask & RF4CE_PROFILE_ATTR_DISSECT_ATTR_STATUS_MASK)
+ {
+ proto_tree_add_item(attrs_subtree, hf_rf4ce_profile_attr_status, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ attr_status = tvb_get_uint8(tvb, *offset);
+ *offset += 1;
+ }
+
+ if (attr_status == RF4CE_PROFILE_ATTR_STATUS_ATTRIBUTE_SUCCESSFULLY_READ_AND_INCLUDED && dissection_mask & RF4CE_PROFILE_ATTR_DISSECT_ATTR_LENGTH_MASK)
+ {
+ proto_tree_add_item(attrs_subtree, hf_rf4ce_profile_attr_length, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ attr_length = tvb_get_uint8(tvb, *offset);
+ *offset += 1;
+ }
+
+ if (attr_status == RF4CE_PROFILE_ATTR_STATUS_ATTRIBUTE_SUCCESSFULLY_READ_AND_INCLUDED && dissection_mask & RF4CE_PROFILE_ATTR_DISSECT_ATTR_VALUE_MASK && attr_length != 0xff && attr_length != 0x00)
+ {
+ bool is_parsed;
+
+ if (is_zrc20)
+ {
+ is_parsed = dissect_rf4ce_profile_zrc20_attrs(tvb, attrs_subtree, offset, attr_id, attr_length);
+ }
+ else
+ {
+ is_parsed = dissect_rf4ce_profile_gdp_attrs(tvb, attrs_subtree, offset, attr_id);
+ }
+
+ if (!is_parsed)
+ {
+ proto_tree_add_item(attrs_subtree, hf_rf4ce_profile_attr_value, tvb, *offset, attr_length, ENC_NA);
+ *offset += attr_length;
+ }
+ }
+
+ if (dissection_mask == RF4CE_PROFILE_ATTR_DISSECT_NOT_SET || prev_offset == *offset)
+ {
+ attr_length = tvb_captured_length(tvb) - *offset;
+ proto_tree_add_item(attrs_subtree, hf_rf4ce_profile_attr_value, tvb, *offset, attr_length, ENC_NA);
+ *offset += attr_length;
+ }
+
+ prev_offset = *offset;
+ }
+}
+
+static void dissect_rf4ce_profile_cmd_get_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20)
+{
+ dissect_rf4ce_profile_attrs(tvb, tree, offset, RF4CE_PROFILE_ATTR_DISSECT_GET_ATTRS_MASK, is_zrc20);
+}
+
+static void dissect_rf4ce_profile_cmd_get_attrs_resp(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20)
+{
+ dissect_rf4ce_profile_attrs(tvb, tree, offset, RF4CE_PROFILE_ATTR_DISSECT_GET_ATTRS_RESP_MASK, is_zrc20);
+}
+
+static void dissect_rf4ce_profile_cmd_push_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20)
+{
+ dissect_rf4ce_profile_attrs(tvb, tree, offset, RF4CE_PROFILE_ATTR_DISSECT_PUSH_ATTRS_MASK, is_zrc20);
+}
+
+static void dissect_rf4ce_profile_cmd_set_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20)
+{
+ dissect_rf4ce_profile_attrs(tvb, tree, offset, RF4CE_PROFILE_ATTR_DISSECT_SET_ATTRS_MASK, is_zrc20);
+}
+
+static void dissect_rf4ce_profile_cmd_pull_attrs(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20)
+{
+ dissect_rf4ce_profile_attrs(tvb, tree, offset, RF4CE_PROFILE_ATTR_DISSECT_PULL_ATTRS_MASK, is_zrc20);
+}
+
+static void dissect_rf4ce_profile_cmd_pull_attrs_resp(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool is_zrc20)
+{
+ dissect_rf4ce_profile_attrs(tvb, tree, offset, RF4CE_PROFILE_ATTR_DISSECT_PULL_ATTRS_RESP_MASK, is_zrc20);
+}
+
+static bool rf4ce_profile_is_gdp_attr_arrayed(uint8_t attr_id)
+{
+ /* other values are scalar */
+ return ((attr_id >= RF4CE_GDP_ATTR_ARRAYED1_RESERVED_MIN && attr_id <= RF4CE_GDP_ATTR_ARRAYED1_RESERVED_MAX) || (attr_id >= RF4CE_GDP_ATTR_ARRAYED2_RESERVED_MIN && attr_id <= RF4CE_GDP_ATTR_ARRAYED2_RESERVED_MAX));
+}
+
+static bool rf4ce_profile_is_zrc20_attr_arrayed(uint8_t attr_id)
+{
+ /* other values are scalar */
+ return (attr_id == RF4CE_ZRC20_ATTR_ACTION_CODES_SUPPORTED_RX || attr_id == RF4CE_ZRC20_ATTR_ACTION_CODES_SUPPORTED_TX || attr_id == RF4CE_ZRC20_ATTR_MAPPABLE_ACTIONS || attr_id == RF4CE_ZRC20_ATTR_ACTION_MAPPINGS || attr_id == RF4CE_ZRC20_ATTR_HOME_AUTOMATION || attr_id == RF4CE_ZRC20_ATTR_HOME_AUTOMATION_SUPPORTED || (attr_id >= RF4CE_ZRC20_ATTR_ARRAYED1_MIN && attr_id <= RF4CE_ZRC20_ATTR_ARRAYED2_MAX));
+}
+
+static void dissect_rf4ce_profile_cmd_check_validation(tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
+{
+ uint8_t sub_type = tvb_get_uint8(tvb, *offset);
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_check_validation_sub_type, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ if (sub_type == RF4CE_PROFILE_CMD_CHECK_VALIDATION_SUB_TYPE_REQ)
+ {
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_check_validation_control, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+ }
+ else if (sub_type == RF4CE_PROFILE_CMD_CHECK_VALIDATION_SUB_TYPE_RSP)
+ {
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_check_validation_status, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+ }
+}
+
+static void dissect_rf4ce_profile_cmd_client_notification(tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
+{
+ uint8_t sub_type = tvb_get_uint8(tvb, *offset);
+ ;
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_client_notification_sub_type, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ if (sub_type == RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_IDENTIFY)
+ {
+ static int *const identify_bits[] = {
+ &hf_rf4ce_profile_cmd_client_notification_identify_flags_stop_on_action,
+ &hf_rf4ce_profile_cmd_client_notification_identify_flags_flash_light,
+ &hf_rf4ce_profile_cmd_client_notification_identify_flags_make_sound,
+ &hf_rf4ce_profile_cmd_client_notification_identify_flags_vibrate,
+ &hf_rf4ce_profile_cmd_client_notification_identify_flags_reserved,
+ NULL};
+
+ proto_tree_add_bitmask(tree, tvb, *offset, hf_rf4ce_profile_cmd_client_notification_identify_flags, ett_rf4ce_profile_cmd_frame, identify_bits, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_client_notification_identify_time, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ *offset += 2;
+ }
+ else if (sub_type == RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_HOME_AUTOMATION_PULL)
+ {
+ /* TODO: implement payload parsing */
+ }
+ else if (sub_type == RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_SELECTIVE_ACTION_MAPPING_UPDATE)
+ {
+ /* TODO: implement payload parsing */
+ }
+ else if (sub_type == RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_POLL_NEGOTIATION || sub_type == RF4CE_PROFILE_CMD_CL_NOTIF_SUB_TYPE_REQ_ACTION_MAPPING_NEGOTIATION)
+ {
+ /* No payload */
+ }
+}
+
+static void dissect_rf4ce_profile_cmd_key_exchange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned *offset)
+{
+ uint8_t sub_type = tvb_get_uint8(tvb, *offset);
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_key_exchange_sub_type, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ if (sub_type == RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CHALLENGE || sub_type == RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CHALLENGE_RSP)
+ {
+ static int *const key_exchange_bits[] = {
+ &hf_rf4ce_profile_cmd_key_exchange_flags_default_secret,
+ &hf_rf4ce_profile_cmd_key_exchange_flags_initiator_vendor_specific_secret,
+ &hf_rf4ce_profile_cmd_key_exchange_flags_responder_vendor_specific_secret,
+ &hf_rf4ce_profile_cmd_key_exchange_flags_reserved,
+ &hf_rf4ce_profile_cmd_key_exchange_flags_vendor_specific_parameter,
+ NULL};
+
+ proto_tree_add_bitmask(tree, tvb, *offset, hf_rf4ce_profile_cmd_key_exchange_flags, ett_rf4ce_profile_cmd_frame, key_exchange_bits, ENC_LITTLE_ENDIAN);
+ *offset += 2;
+ }
+
+ if (sub_type == RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CHALLENGE)
+ {
+ uint8_t rand_a[RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH];
+ uint8_t target_addr[RF4CE_IEEE_ADDR_LEN];
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_key_exchange_rand_a, tvb, *offset, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH, ENC_NA);
+ tvb_memcpy(tvb, (void *)rand_a, *offset, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH);
+ *offset += RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH;
+
+ if (!key_exchange_context_is_procedure_started())
+ {
+ if (rf4ce_addr_table_get_ieee_addr(target_addr, pinfo, true))
+ {
+ key_exchange_context_init();
+
+ key_exchange_context_set_rand_a(rand_a);
+ key_exchange_context_set_mac_a(target_addr);
+
+ key_exchange_context_start_procedure();
+ }
+ }
+ }
+
+ if (sub_type == RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_CHALLENGE_RSP)
+ {
+ uint8_t rand_b[RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH];
+ uint32_t tag_b_pack;
+
+ uint8_t controller_addr[RF4CE_IEEE_ADDR_LEN];
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_key_exchange_rand_b, tvb, *offset, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH, ENC_NA);
+ tvb_memcpy(tvb, (void *)rand_b, *offset, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH);
+ *offset += RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH;
+
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_key_exchange_tag_b, tvb, *offset, RF4CE_PROFILE_CMD_KEY_EXCHANGE_TAG_B_LENGTH, ENC_NA);
+ tag_b_pack = tvb_get_uint32(tvb, *offset, ENC_LITTLE_ENDIAN);
+ *offset += RF4CE_PROFILE_CMD_KEY_EXCHANGE_TAG_B_LENGTH;
+
+ if (key_exchange_context_is_procedure_started())
+ {
+ if (rf4ce_addr_table_get_ieee_addr(controller_addr, pinfo, true))
+ {
+ key_exchange_context_set_rand_b(rand_b);
+ key_exchange_context_set_mac_b(controller_addr);
+
+ key_exchange_calc_key(tag_b_pack);
+ }
+
+ key_exchange_context_stop_procedure();
+ }
+ }
+
+ if (sub_type == RF4CE_PROFILE_CMD_KEY_EXCHANGE_SUB_TYPE_RSP)
+ {
+ proto_tree_add_item(tree, hf_rf4ce_profile_cmd_key_exchange_tag_a, tvb, *offset, RF4CE_PROFILE_CMD_KEY_EXCHANGE_TAG_A_LENGTH, ENC_NA);
+ *offset += RF4CE_PROFILE_CMD_KEY_EXCHANGE_TAG_A_LENGTH;
+ }
+}
+
+static void dissect_rf4ce_profile_zrc10_cmd(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t cmd_id)
+{
+ switch (cmd_id)
+ {
+ case RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_PRESSED:
+ dissect_rf4ce_profile_zrc10_cmd_user_control_common(tvb, tree, offset, true);
+ break;
+
+ case RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_REPEATED:
+ dissect_rf4ce_profile_zrc10_cmd_user_control_common(tvb, tree, offset, true);
+ break;
+
+ case RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_RELEASED:
+ dissect_rf4ce_profile_zrc10_cmd_user_control_common(tvb, tree, offset, false);
+ break;
+
+ case RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_CMD_DISCOVERY_REQ:
+ dissect_rf4ce_profile_zrc10_cmd_discovery_req(tvb, tree, offset);
+ break;
+
+ case RF4CE_ZRC10_FCF_CMD_ID_USER_CONTROL_CMD_DISCOVERY_RSP:
+ dissect_rf4ce_profile_zrc10_cmd_discovery_rsp(tvb, tree, offset);
+ break;
+ }
+}
+
+static void dissect_rf4ce_profile_zrc10_cmd_user_control_common(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool parse_payload)
+{
+ proto_tree_add_item(tree, hf_rf4ce_zrc10_cmd_common_rc_command_code, tvb, *offset, 1, ENC_NA);
+ *offset += 1;
+
+ if (parse_payload)
+ {
+ int remaining_length = tvb_reported_length_remaining(tvb, *offset);
+ if (remaining_length > 0)
+ {
+ proto_tree_add_item(tree, hf_rf4ce_zrc10_cmd_common_rc_command_payload, tvb, *offset, remaining_length, ENC_NA);
+ *offset += remaining_length;
+ }
+ }
+}
+
+static void dissect_rf4ce_profile_zrc10_cmd_discovery_req(tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
+{
+ proto_tree_add_item(tree, hf_rf4ce_zrc10_cmd_disc_reserved, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+}
+
+static void dissect_rf4ce_profile_zrc10_cmd_discovery_rsp(tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
+{
+ int remaining_length = tvb_reported_length_remaining(tvb, *offset);
+
+ if (remaining_length > 0)
+ {
+ proto_tree_add_item(tree, hf_rf4ce_zrc10_cmd_disc_rsp_supported_commands, tvb, *offset, remaining_length, ENC_NA);
+ *offset += remaining_length;
+ }
+}
+
+static void dissect_rf4ce_profile_zrc20_cmd(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, uint8_t cmd_id)
+{
+ if (cmd_id == RF4CE_ZRC20_CMD_ACTIONS)
+ {
+ int remaining_length = tvb_reported_length_remaining(tvb, *offset);
+ proto_tree *action_records_tree;
+
+ if (remaining_length > 0)
+ {
+ action_records_tree = proto_tree_add_subtree(tree, tvb, *offset, remaining_length, ett_rf4ce_profile_action_records, NULL, "Action Records List");
+
+ while (remaining_length > 0)
+ {
+ dissect_rf4ce_profile_zrc20_action_data(tvb, action_records_tree, offset, true /* dissect the Action Control field */);
+ remaining_length = tvb_reported_length_remaining(tvb, *offset);
+ }
+ }
+ else
+ {
+ proto_tree_add_subtree(tree, tvb, *offset, remaining_length, ett_rf4ce_profile_action_records, NULL, "Action Records List - empty");
+ }
+ }
+}
+
+static void dissect_rf4ce_profile_zrc20_action_data(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, bool dissect_action_control)
+{
+ char record_tree_name[10];
+ proto_tree *record_tree;
+ uint8_t payload_length;
+ int remaining_length;
+ int attr_counter = 1;
+
+ snprintf(record_tree_name, sizeof(record_tree_name), "Record %d:", attr_counter);
+ attr_counter++;
+
+ record_tree = proto_tree_add_subtree(tree, tvb, *offset, tvb_reported_length_remaining(tvb, *offset), ett_rf4ce_profile_action_records_sub, NULL, record_tree_name);
+
+ if (dissect_action_control)
+ {
+ static int *const action_control_bits[] = {
+ &hf_rf4ce_zrc20_cmd_actions_action_control_action_type,
+ &hf_rf4ce_zrc20_cmd_actions_action_control_reserved,
+ &hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_gui,
+ &hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_alt,
+ &hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_shift,
+ &hf_rf4ce_zrc20_cmd_actions_action_control_modifier_bits_ctrl,
+ NULL};
+
+ proto_tree_add_bitmask(record_tree, tvb, *offset, hf_rf4ce_zrc20_cmd_actions_action_control, ett_rf4ce_profile_zrc20_action_control, action_control_bits, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+ }
+
+ proto_tree_add_item(record_tree, hf_rf4ce_zrc20_cmd_actions_action_data_payload_length, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ payload_length = tvb_get_uint8(tvb, *offset);
+ *offset += 1;
+
+ proto_tree_add_item(record_tree, hf_rf4ce_zrc20_cmd_actions_action_data_action_bank, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ proto_tree_add_item(record_tree, hf_rf4ce_zrc20_cmd_actions_action_data_action_code, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
+ *offset += 1;
+
+ /* TODO: fix action_vendor parsing according to spec */
+ remaining_length = tvb_reported_length_remaining(tvb, *offset);
+ if (((payload_length > 0) && (remaining_length - payload_length == 3)) || ((payload_length == 0) && (remaining_length - payload_length == 2)))
+ {
+ proto_tree_add_item(record_tree, hf_rf4ce_zrc20_cmd_actions_action_data_action_vendor, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+ *offset += 2;
+ }
+
+ if (payload_length > 0)
+ {
+ proto_tree_add_item(record_tree, hf_rf4ce_zrc20_cmd_actions_action_data_action_payload, tvb, *offset, payload_length, ENC_NA);
+ *offset += payload_length;
+ }
+}