/* packet-btsdp.c
 * Routines for Bluetooth SDP dissection
 * Copyright 2002, Wolfgang Hansmann <hansmann@cs.uni-bonn.de>
 * Copyright 2006, Ronnie Sahlberg
 *     - refactored for Wireshark checkin
 * Copyright 2013, Michal Labedzki  for Tieto Corporation
 *     - support SDP fragmentation (Continuation State)
 *     - implement DI 1.3
 *     - dissect profile specific attributes
 *     - fix service recognize
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "config.h"

#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/prefs.h>
#include <epan/etypes.h>
#include <epan/to_str.h>
#include <epan/iana_charsets.h>
#include <epan/exceptions.h>

#include "data-usb.h"
#include "packet-btsdp.h"
#include "packet-btl2cap.h"
#include "packet-usb.h"

static int proto_btsdp;

static int hf_pdu_id;
static int hf_tid;
static int hf_parameter_length;
static int hf_ssr_total_count;
static int hf_ssr_current_count;
static int hf_error_code;
static int hf_attribute_id_list;
static int hf_attribute_id_range;
static int hf_attribute_id_range_from;
static int hf_attribute_id_range_to;
static int hf_attribute_list_byte_count;
static int hf_maximum_service_record_count;
static int hf_maximum_attribute_byte_count;
static int hf_continuation_state;
static int hf_continuation_state_length;
static int hf_continuation_state_value;
static int hf_fragment;
static int hf_partial_record_handle_list;
static int hf_reassembled_record_handle_list;
static int hf_partial_attribute_list;
static int hf_reassembled_attribute_list;
static int hf_data_element;
static int hf_data_element_size;
static int hf_data_element_type;
static int hf_data_element_var_size;
static int hf_data_element_value;
static int hf_data_element_value_nil;
static int hf_data_element_value_boolean;
static int hf_data_element_value_signed_int;
static int hf_data_element_value_unsigned_int;
static int hf_data_element_value_uuid_16;
static int hf_data_element_value_uuid_32;
static int hf_data_element_value_uuid_128;
static int hf_data_element_value_uuid;
static int hf_data_element_value_string;
static int hf_data_element_value_url;
static int hf_data_element_value_alternative;
static int hf_data_element_value_sequence;
static int hf_profile_descriptor_list;
static int hf_attribute_list;
static int hf_attribute_lists;
static int hf_service_search_pattern;
static int hf_service_record_handle_list;
static int hf_service_attribute;
static int hf_service_attribute_id;
static int hf_service_attribute_value;
static int hf_service_attribute_id_generic;
static int hf_service_attribute_id_a2dp;
static int hf_service_attribute_id_avrcp;
static int hf_service_attribute_id_ctp;
static int hf_service_attribute_id_bip_imaging_responder;
static int hf_service_attribute_id_bip_imaging_other;
static int hf_service_attribute_id_bpp;
static int hf_service_attribute_id_bpp_rui;
static int hf_service_attribute_id_did;
static int hf_service_attribute_id_dun;
static int hf_service_attribute_id_fax;
static int hf_service_attribute_id_ftp;
static int hf_service_attribute_id_gnss;
static int hf_service_attribute_id_hfp_hf;
static int hf_service_attribute_id_hfp_ag;
static int hf_service_attribute_id_hcrp;
static int hf_service_attribute_id_hsp;
static int hf_service_attribute_id_hdp;
static int hf_service_attribute_id_hid;
static int hf_service_attribute_id_wap;
static int hf_service_attribute_id_map_mas;
static int hf_service_attribute_id_map_mns;
static int hf_service_attribute_id_opp;
static int hf_service_attribute_id_pan_nap;
static int hf_service_attribute_id_pan_gn;
static int hf_service_attribute_id_pan_panu;
static int hf_service_attribute_id_pbap;
static int hf_service_attribute_id_synch;
static int hf_service_attribute_id_ctn_as;
static int hf_service_attribute_id_ctn_ns;
static int hf_service_attribute_id_mps;
static int hf_did_specification_id;
static int hf_did_vendor_id;
static int hf_did_vendor_id_bluetooth_sig;
static int hf_did_vendor_id_usb_forum;
static int hf_did_product_id;
static int hf_did_primary_record;
static int hf_did_version;
static int hf_did_vendor_id_source;
static int hf_a2dp_sink_supported_features_reserved;
static int hf_a2dp_sink_supported_features_amplifier;
static int hf_a2dp_sink_supported_features_recorder;
static int hf_a2dp_sink_supported_features_speaker;
static int hf_a2dp_sink_supported_features_headphone;
static int hf_a2dp_source_supported_features_reserved;
static int hf_a2dp_source_supported_features_mixer;
static int hf_a2dp_source_supported_features_tuner;
static int hf_a2dp_source_supported_features_microphone;
static int hf_a2dp_source_supported_features_player;
static int hf_synch_supported_data_store;
static int hf_ctp_external_network;
static int hf_avrcp_ct_supported_features_reserved_10_15;
static int hf_avrcp_ct_supported_features_cover_art_get_linked_thumbnail;
static int hf_avrcp_ct_supported_features_cover_art_get_image;
static int hf_avrcp_ct_supported_features_cover_art_get_image_properties;
static int hf_avrcp_ct_supported_features_browsing;
static int hf_avrcp_ct_supported_features_reserved_4_5;
static int hf_avrcp_ct_supported_features_category_4;
static int hf_avrcp_ct_supported_features_category_3;
static int hf_avrcp_ct_supported_features_category_2;
static int hf_avrcp_ct_supported_features_category_1;
static int hf_avrcp_tg_supported_features_reserved_9_15;
static int hf_avrcp_tg_supported_features_cover_art;
static int hf_avrcp_tg_supported_features_multiple_player;
static int hf_avrcp_tg_supported_features_browsing;
static int hf_avrcp_tg_supported_features_group_navigation;
static int hf_avrcp_tg_supported_features_settings;
static int hf_avrcp_tg_supported_features_category_4;
static int hf_avrcp_tg_supported_features_category_3;
static int hf_avrcp_tg_supported_features_category_2;
static int hf_avrcp_tg_supported_features_category_1;
static int hf_hsp_remote_audio_volume_control;
static int hf_gnss_supported_features;
static int hf_pbap_pse_supported_repositories;
static int hf_pbap_pse_supported_repositories_reserved;
static int hf_pbap_pse_supported_repositories_favourites;
static int hf_pbap_pse_supported_repositories_speed_dial;
static int hf_pbap_pse_supported_repositories_sim_card;
static int hf_pbap_pse_supported_repositories_local_phonebook;
static int hf_fax_support_class_1;
static int hf_fax_support_class_2;
static int hf_fax_support_class_2_vendor;
static int hf_fax_support_audio_feedback;
static int hf_ftp_goep_l2cap_psm;
static int hf_map_mas_instance_id;
static int hf_map_mas_supported_message_types_reserved;
static int hf_map_mas_supported_message_types_mms;
static int hf_map_mas_supported_message_types_sms_cdma;
static int hf_map_mas_supported_message_types_sms_gsm;
static int hf_map_mas_supported_message_types_email;
static int hf_hcrp_1284_id;
static int hf_hcrp_device_location;
static int hf_hcrp_device_name;
static int hf_hcrp_friendly_name;
static int hf_wap_network_address;
static int hf_wap_gateway;
static int hf_wap_homepage_url;
static int hf_wap_stack_type;
static int hf_hdp_data_exchange;
static int hf_hdp_support_procedure_reserved_5_7;
static int hf_hdp_support_procedure_sync_master_role;
static int hf_hdp_support_procedure_clock_synchronization_protocol;
static int hf_hdp_support_procedure_reconnect_acceptance;
static int hf_hdp_support_procedure_reconnect_initiation;
static int hf_hdp_support_procedure_reserved;
static int hf_hdp_supported_features_data;
static int hf_hdp_supported_features_data_mdep_id;
static int hf_hdp_supported_features_data_mdep_data_type;
static int hf_hdp_supported_features_data_mdep_role;
static int hf_hdp_supported_features_data_mdep_description;
static int hf_hdp_supported_features_mdep_id;
static int hf_hdp_supported_features_mdep_data_type;
static int hf_hdp_supported_features_mdep_data_type_01;
static int hf_hdp_supported_features_mdep_role;
static int hf_hdp_supported_features_mdep_description;
static int hf_pan_sercurity_description;
static int hf_pan_ipv4_subnet;
static int hf_pan_ipv6_subnet;
static int hf_pan_max_net_access_rate;
static int hf_pan_net_access_type;
static int hf_opp_goep_l2cap_psm;
static int hf_opp_supported_format;
static int hf_dun_escape_sequence;
static int hf_dun_support_audio_feedback;
static int hf_hfp_hf_supported_features_reserved;
static int hf_hfp_hf_supported_features_wide_band_speech;
static int hf_hfp_hf_supported_features_remote_volume_control;
static int hf_hfp_hf_supported_features_voice_recognition_activation;
static int hf_hfp_hf_supported_features_cli_presentation_capability;
static int hf_hfp_hf_supported_features_call_waiting_or_three_way_calling;
static int hf_hfp_hf_supported_features_ec_and_or_nr_function;
static int hf_hfp_gw_network;
static int hf_hfp_gw_supported_features_reserved;
static int hf_hfp_gw_supported_features_wide_band_speech;
static int hf_hfp_gw_supported_features_attach_phone_number_to_voice_tag;
static int hf_hfp_gw_supported_features_inband_ring_tone_capability;
static int hf_hfp_gw_supported_features_voice_recognition_function;
static int hf_hfp_gw_supported_features_ec_and_or_nr_function;
static int hf_hfp_gw_supported_features_three_way_calling;
static int hf_sdp_protocol_item;
static int hf_sdp_protocol;
static int hf_sdp_protocol_psm;
static int hf_sdp_protocol_channel;
static int hf_sdp_protocol_gatt_handle_start;
static int hf_sdp_protocol_gatt_handle_end;
static int hf_sdp_protocol_version;
static int hf_sdp_protocol_bnep_type;
static int hf_sdp_service_record_handle;
static int hf_sdp_service_record_state;
static int hf_sdp_service_info_time_to_live;
static int hf_sdp_service_availability;
static int hf_sdp_service_documentation_url;
static int hf_sdp_service_client_executable_url;
static int hf_sdp_service_icon_url;
static int hf_sdp_service_name;
static int hf_sdp_service_description;
static int hf_sdp_service_provider_name;
static int hf_sdp_lang;
static int hf_sdp_lang_id;
static int hf_sdp_lang_code;
static int hf_sdp_lang_encoding;
static int hf_sdp_lang_attribute_base;
static int hf_hid_descriptor_list_descriptor_data;
static int hf_hid_lang;
static int hf_hid_device_release_number;
static int hf_hid_parser_version;
static int hf_hid_device_subclass_type;
static int hf_hid_device_subclass_subtype;
static int hf_hid_device_subclass_reserved;
static int hf_hid_country_code;
static int hf_hid_virtual_cable;
static int hf_hid_reconnect_initiate;
static int hf_hid_sdp_disable;
static int hf_hid_battery_power;
static int hf_hid_remote_wake;
static int hf_hid_profile_version;
static int hf_hid_supervision_timeout;
static int hf_hid_normally_connectable;
static int hf_hid_boot_device;
static int hf_hid_ssr_host_max_latency;
static int hf_hid_ssr_host_min_timeout;
static int hf_hid_descriptor_list_type;
static int hf_hid_descriptor_list_descriptor;
static int hf_bip_goep_l2cap_psm;
static int hf_bip_supported_capabilities_reserved_4_7;
static int hf_bip_supported_capabilities_displaying;
static int hf_bip_supported_capabilities_printing;
static int hf_bip_supported_capabilities_capturing;
static int hf_bip_supported_capabilities_genering_imaging;
static int hf_bip_supported_features_reserved_9_15;
static int hf_bip_supported_features_remote_display;
static int hf_bip_supported_features_remote_camera;
static int hf_bip_supported_features_automatic_archive;
static int hf_bip_supported_features_advanced_image_printing;
static int hf_bip_supported_features_image_pull;
static int hf_bip_supported_features_image_push_display;
static int hf_bip_supported_features_image_push_print;
static int hf_bip_supported_features_image_push_store;
static int hf_bip_supported_features_image_push;
static int hf_bip_supported_functions_reserved_17_31;
static int hf_bip_supported_functions_get_status;
static int hf_bip_supported_functions_reserved_15;
static int hf_bip_supported_functions_get_monitoring_image;
static int hf_bip_supported_functions_start_archive;
static int hf_bip_supported_functions_reserved_12;
static int hf_bip_supported_functions_start_print;
static int hf_bip_supported_functions_delete_image;
static int hf_bip_supported_functions_get_linked_attachment;
static int hf_bip_supported_functions_get_linked_thumbnail;
static int hf_bip_supported_functions_get_image;
static int hf_bip_supported_functions_get_image_property;
static int hf_bip_supported_functions_get_images_list;
static int hf_bip_supported_functions_remote_display;
static int hf_bip_supported_functions_put_linked_thumbnail;
static int hf_bip_supported_functions_put_linked_attachment;
static int hf_bip_supported_functions_put_image;
static int hf_bip_supported_functions_get_capabilities;
static int hf_bip_supported_functions_reserved_13_31;
static int hf_bip_supported_functions_get_partial_image;
static int hf_bip_supported_functions_reserved_1_11;
static int hf_bip_supported_functions_reserved_1_4;
static int hf_bip_supported_functions_reserved_11_31;
static int hf_bip_total_imaging_data_capacity;
static int hf_bpp_document_formats_supported;
static int hf_bpp_character_repertoires_support;
static int hf_bpp_xhtml_print_image_formats_supported;
static int hf_bpp_color_supported;
static int hf_bpp_1284_id;
static int hf_bpp_printer_name;
static int hf_bpp_printer_location;
static int hf_bpp_duplex_supported;
static int hf_bpp_media_types_supported;
static int hf_bpp_max_media_width;
static int hf_bpp_max_media_length;
static int hf_bpp_enhanced_layout_supported;
static int hf_bpp_rui_formats_supported;
static int hf_bpp_reference_printing_rui_supported;
static int hf_bpp_direct_printing_rui_supported;
static int hf_bpp_reference_printing_top_url;
static int hf_bpp_direct_printing_top_url;
static int hf_bpp_device_name;
static int hf_bpp_printer_admin_rui_top_url;
static int hf_ctn_instance_id;
static int hf_ctn_supported_features;
static int hf_ctn_supported_features_reserved;
static int hf_ctn_supported_features_forward;
static int hf_ctn_supported_features_delete;
static int hf_ctn_supported_features_uploading;
static int hf_ctn_supported_features_downloading;
static int hf_ctn_supported_features_browsing;
static int hf_ctn_supported_features_notification;
static int hf_ctn_supported_features_account_management;
static int hf_mps_mpsd_scenarios;
static int hf_mps_mpsd_scenarios_reserved;
static int hf_mps_mpsd_scenarios_37;
static int hf_mps_mpsd_scenarios_36;
static int hf_mps_mpsd_scenarios_35;
static int hf_mps_mpsd_scenarios_34;
static int hf_mps_mpsd_scenarios_33;
static int hf_mps_mpsd_scenarios_32;
static int hf_mps_mpsd_scenarios_31;
static int hf_mps_mpsd_scenarios_30;
static int hf_mps_mpsd_scenarios_29;
static int hf_mps_mpsd_scenarios_28;
static int hf_mps_mpsd_scenarios_27;
static int hf_mps_mpsd_scenarios_26;
static int hf_mps_mpsd_scenarios_25;
static int hf_mps_mpsd_scenarios_24;
static int hf_mps_mpsd_scenarios_23;
static int hf_mps_mpsd_scenarios_22;
static int hf_mps_mpsd_scenarios_21;
static int hf_mps_mpsd_scenarios_20;
static int hf_mps_mpsd_scenarios_19;
static int hf_mps_mpsd_scenarios_18;
static int hf_mps_mpsd_scenarios_17;
static int hf_mps_mpsd_scenarios_16;
static int hf_mps_mpsd_scenarios_15;
static int hf_mps_mpsd_scenarios_14;
static int hf_mps_mpsd_scenarios_13;
static int hf_mps_mpsd_scenarios_12;
static int hf_mps_mpsd_scenarios_11;
static int hf_mps_mpsd_scenarios_10;
static int hf_mps_mpsd_scenarios_9;
static int hf_mps_mpsd_scenarios_8;
static int hf_mps_mpsd_scenarios_7;
static int hf_mps_mpsd_scenarios_6;
static int hf_mps_mpsd_scenarios_5;
static int hf_mps_mpsd_scenarios_4;
static int hf_mps_mpsd_scenarios_3;
static int hf_mps_mpsd_scenarios_2;
static int hf_mps_mpsd_scenarios_1;
static int hf_mps_mpsd_scenarios_0;
static int hf_mps_mpmd_scenarios;
static int hf_mps_mpmd_scenarios_reserved;
static int hf_mps_mpmd_scenarios_18;
static int hf_mps_mpmd_scenarios_17;
static int hf_mps_mpmd_scenarios_16;
static int hf_mps_mpmd_scenarios_15;
static int hf_mps_mpmd_scenarios_14;
static int hf_mps_mpmd_scenarios_13;
static int hf_mps_mpmd_scenarios_12;
static int hf_mps_mpmd_scenarios_11;
static int hf_mps_mpmd_scenarios_10;
static int hf_mps_mpmd_scenarios_9;
static int hf_mps_mpmd_scenarios_8;
static int hf_mps_mpmd_scenarios_7;
static int hf_mps_mpmd_scenarios_6;
static int hf_mps_mpmd_scenarios_5;
static int hf_mps_mpmd_scenarios_4;
static int hf_mps_mpmd_scenarios_3;
static int hf_mps_mpmd_scenarios_2;
static int hf_mps_mpmd_scenarios_1;
static int hf_mps_mpmd_scenarios_0;
static int hf_mps_supported_profile_and_protocol_dependency;
static int hf_mps_supported_profile_and_protocol_dependency_reserved;
static int hf_mps_supported_profile_and_protocol_dependency_dis_connection_order_behaviour;
static int hf_mps_supported_profile_and_protocol_dependency_gavdp_requirements;
static int hf_mps_supported_profile_and_protocol_dependency_sniff_mode_during_streaming;
static int hf_map_mas_goep_l2cap_psm;
static int hf_map_mns_goep_l2cap_psm;
static int hf_map_supported_features;
static int hf_map_supported_features_reserved;
static int hf_map_supported_features_extended_event_report_1_1;
static int hf_map_supported_features_instance_information_feature;
static int hf_map_supported_features_delete_feature;
static int hf_map_supported_features_uploading_feature;
static int hf_map_supported_features_browsing_feature;
static int hf_map_supported_features_notification_feature;
static int hf_map_supported_features_notification_registration_feature;
static int hf_pbap_pse_supported_features;
static int hf_pbap_pse_supported_features_reserved;
static int hf_pbap_pse_supported_features_download;
static int hf_pbap_pse_supported_features_browsing;
static int hf_pbap_pse_supported_features_database_identifier;
static int hf_pbap_pse_supported_features_folder_version_counters;
static int hf_pbap_pse_supported_features_vcard_selecting;
static int hf_pbap_pse_supported_features_enhanced_missed_calls;
static int hf_pbap_pse_supported_features_x_bt_uci_vcard_property;
static int hf_pbap_pse_supported_features_x_bt_uid_vcard_property;
static int hf_pbap_pse_supported_features_contact_referencing;
static int hf_pbap_pse_supported_features_default_contact_image_format;
static int hf_pbap_goep_l2cap_psm;

static int ett_btsdp;
static int ett_btsdp_ssr;
static int ett_btsdp_des;
static int ett_btsdp_attribute;
static int ett_btsdp_attribute_id;
static int ett_btsdp_attribute_value;
static int ett_btsdp_attribute_idlist;
static int ett_btsdp_service_search_pattern;
static int ett_btsdp_continuation_state;
static int ett_btsdp_data_element;
static int ett_btsdp_data_element_value;
static int ett_btsdp_reassembled;
static int ett_btsdp_supported_features;
static int ett_btsdp_supported_features_mdep_id;
static int ett_btsdp_supported_features_mdep_data_type;
static int ett_btsdp_supported_features_mdep_role;
static int ett_btsdp_supported_features_mdep_description;
static int ett_btsdp_protocol;

static int * const hfx_ctn_supported_features[] = {
    &hf_ctn_supported_features_reserved,
    &hf_ctn_supported_features_forward,
    &hf_ctn_supported_features_delete,
    &hf_ctn_supported_features_uploading,
    &hf_ctn_supported_features_downloading,
    &hf_ctn_supported_features_browsing,
    &hf_ctn_supported_features_notification,
    &hf_ctn_supported_features_account_management,
    NULL
};

static int * const hfx_mps_mpsd_scenarios[] = {
    &hf_mps_mpsd_scenarios_reserved,
    &hf_mps_mpsd_scenarios_37,
    &hf_mps_mpsd_scenarios_36,
    &hf_mps_mpsd_scenarios_35,
    &hf_mps_mpsd_scenarios_34,
    &hf_mps_mpsd_scenarios_33,
    &hf_mps_mpsd_scenarios_32,
    &hf_mps_mpsd_scenarios_31,
    &hf_mps_mpsd_scenarios_30,
    &hf_mps_mpsd_scenarios_29,
    &hf_mps_mpsd_scenarios_28,
    &hf_mps_mpsd_scenarios_27,
    &hf_mps_mpsd_scenarios_26,
    &hf_mps_mpsd_scenarios_25,
    &hf_mps_mpsd_scenarios_24,
    &hf_mps_mpsd_scenarios_23,
    &hf_mps_mpsd_scenarios_22,
    &hf_mps_mpsd_scenarios_21,
    &hf_mps_mpsd_scenarios_20,
    &hf_mps_mpsd_scenarios_19,
    &hf_mps_mpsd_scenarios_18,
    &hf_mps_mpsd_scenarios_17,
    &hf_mps_mpsd_scenarios_16,
    &hf_mps_mpsd_scenarios_15,
    &hf_mps_mpsd_scenarios_14,
    &hf_mps_mpsd_scenarios_13,
    &hf_mps_mpsd_scenarios_12,
    &hf_mps_mpsd_scenarios_11,
    &hf_mps_mpsd_scenarios_10,
    &hf_mps_mpsd_scenarios_9,
    &hf_mps_mpsd_scenarios_8,
    &hf_mps_mpsd_scenarios_7,
    &hf_mps_mpsd_scenarios_6,
    &hf_mps_mpsd_scenarios_5,
    &hf_mps_mpsd_scenarios_4,
    &hf_mps_mpsd_scenarios_3,
    &hf_mps_mpsd_scenarios_2,
    &hf_mps_mpsd_scenarios_1,
    &hf_mps_mpsd_scenarios_0,
    NULL
};

static int * const hfx_mps_mpmd_scenarios[] = {
    &hf_mps_mpmd_scenarios_reserved,
    &hf_mps_mpmd_scenarios_18,
    &hf_mps_mpmd_scenarios_17,
    &hf_mps_mpmd_scenarios_16,
    &hf_mps_mpmd_scenarios_15,
    &hf_mps_mpmd_scenarios_14,
    &hf_mps_mpmd_scenarios_13,
    &hf_mps_mpmd_scenarios_12,
    &hf_mps_mpmd_scenarios_11,
    &hf_mps_mpmd_scenarios_10,
    &hf_mps_mpmd_scenarios_9,
    &hf_mps_mpmd_scenarios_8,
    &hf_mps_mpmd_scenarios_7,
    &hf_mps_mpmd_scenarios_6,
    &hf_mps_mpmd_scenarios_5,
    &hf_mps_mpmd_scenarios_4,
    &hf_mps_mpmd_scenarios_3,
    &hf_mps_mpmd_scenarios_2,
    &hf_mps_mpmd_scenarios_1,
    &hf_mps_mpmd_scenarios_0,
    NULL
};

static int * const hfx_mps_supported_profile_and_protocol_dependency[] = {
    &hf_mps_supported_profile_and_protocol_dependency_reserved,
    &hf_mps_supported_profile_and_protocol_dependency_dis_connection_order_behaviour,
    &hf_mps_supported_profile_and_protocol_dependency_gavdp_requirements,
    &hf_mps_supported_profile_and_protocol_dependency_sniff_mode_during_streaming,
    NULL
};

static int * const hfx_map_supported_features[] = {
    &hf_map_supported_features_reserved,
    &hf_map_supported_features_extended_event_report_1_1,
    &hf_map_supported_features_instance_information_feature,
    &hf_map_supported_features_delete_feature,
    &hf_map_supported_features_uploading_feature,
    &hf_map_supported_features_browsing_feature,
    &hf_map_supported_features_notification_feature,
    &hf_map_supported_features_notification_registration_feature,
    NULL
};

static int * const hfx_pbap_pse_supported_repositories[] = {
    &hf_pbap_pse_supported_repositories_reserved,
    &hf_pbap_pse_supported_repositories_favourites,
    &hf_pbap_pse_supported_repositories_speed_dial,
    &hf_pbap_pse_supported_repositories_sim_card,
    &hf_pbap_pse_supported_repositories_local_phonebook,
    NULL
};

static int * const hfx_pbap_pse_supported_features[] = {
    &hf_pbap_pse_supported_features_reserved,
    &hf_pbap_pse_supported_features_default_contact_image_format,
    &hf_pbap_pse_supported_features_contact_referencing,
    &hf_pbap_pse_supported_features_x_bt_uid_vcard_property,
    &hf_pbap_pse_supported_features_x_bt_uci_vcard_property,
    &hf_pbap_pse_supported_features_enhanced_missed_calls,
    &hf_pbap_pse_supported_features_vcard_selecting,
    &hf_pbap_pse_supported_features_folder_version_counters,
    &hf_pbap_pse_supported_features_database_identifier,
    &hf_pbap_pse_supported_features_browsing,
    &hf_pbap_pse_supported_features_download,
    NULL
};

static expert_field ei_btsdp_continuation_state_none;
static expert_field ei_btsdp_continuation_state_large;
static expert_field ei_data_element_value_large;
static expert_field ei_length_bad;

static dissector_handle_t btsdp_handle;

static wmem_tree_t *tid_requests;
static wmem_tree_t *continuation_states;
static wmem_tree_t *record_handle_services;
static wmem_tree_t *service_infos;

typedef struct _tid_request_t {
    uint32_t       interface_id;
    uint32_t       adapter_id;
    uint32_t       chandle;
    uint32_t       psm;
    uint32_t       tid;
    uint32_t       pdu_type;

    wmem_array_t  *uuid_array;
    uint32_t       record_handle;

    char          *continuation_state;
    uint8_t        continuation_state_length;

    uint32_t       data_length;
    uint8_t       *data;
} tid_request_t;

typedef struct _continuation_state_data_t {
    uint32_t interface_id;
    uint32_t adapter_id;
    uint32_t chandle;
    uint32_t psm;
    uint32_t pdu_type;
    uint32_t continuation_state[5];

    uint32_t data_length;
    uint8_t *data;
} continuation_state_data_t;

typedef struct _record_handle_service_t {
    uint32_t      interface_id;
    uint32_t      adapter_id;
    uint32_t      chandle;
    uint32_t      psm;
    uint32_t      record_handle;

    wmem_array_t *uuid_array;
} record_handle_service_t;

#define PDU_TYPE_SERVICE_SEARCH            0x00
#define PDU_TYPE_SERVICE_ATTRIBUTE         0x01
#define PDU_TYPE_SERVICE_SEARCH_ATTRIBUTE  0x02

#define MAX_SDP_LEN 1024

static const value_string vs_pduid[] = {
    { 0x01,   "Error Response" },
    { 0x02,   "Service Search Request" },
    { 0x03,   "Service Search Response" },
    { 0x04,   "Service Attribute Request" },
    { 0x05,   "Service Attribute Response" },
    { 0x06,   "Service Search Attribute Request" },
    { 0x07,   "Service Search Attribute Response" },
    { 0, NULL }
};

static const value_string vs_general_attribute_id[] = {
    { 0x0000,   "Service Record Handle" },
    { 0x0001,   "Service Class ID List" },
    { 0x0002,   "Service Record State" },
    { 0x0003,   "Service ID" },
    { 0x0004,   "Protocol Descriptor List" },
    { 0x0005,   "Browse Group List" },
    { 0x0006,   "Language Base Attribute ID List" },
    { 0x0007,   "Service Info Time To Live" },
    { 0x0008,   "Service Availability" },
    { 0x0009,   "Bluetooth Profile Descriptor List" },
    { 0x000A,   "Documentation URL" },
    { 0x000B,   "Client Executable URL" },
    { 0x000C,   "Icon URL" },
    { 0x000D,   "Additional Protocol Descriptor Lists" },
    /* Localized string default offset is 0x100,
       the rest based on Language Base Attribute ID List */
    { 0x0100,   "Service Name" },
    { 0x0101,   "Service Description" },
    { 0x0102,   "Provider Name" },
    { 0, NULL }
};

static const value_string vs_a2dp_attribute_id[] = {
    { 0x0311,   "Supported Features" },
    { 0, NULL }
};

static const value_string vs_avrcp_attribute_id[] = {
    { 0x0311,   "Supported Features" },
    { 0, NULL }
};

static const value_string vs_bip_imaging_responder_attribute_id[] = {
    { 0x0200,   "GOEP L2CAP PSM" },
    { 0x0310,   "Supported Capabilities" },
    { 0x0311,   "Supported Features" },
    { 0x0312,   "Supported Functions" },
    { 0x0313,   "Total Imaging Data Capacity" },
    { 0, NULL }
};

static const value_string vs_bip_imaging_other_attribute_id[] = {
    { 0x0200,   "GOEP L2CAP PSM" },
    { 0x0312,   "Supported Functions" },
    { 0, NULL }
};

static const value_string vs_bpp_attribute_id[] = {
    { 0x0350,   "Document Formats Supported" },
    { 0x0352,   "Character Repertoires Supported" },
    { 0x0354,   "XHTML-Print Image Formats Supported" },
    { 0x0356,   "Color Supported" },
    { 0x0358,   "1284ID" },
    { 0x035A,   "Printer Name" },
    { 0x035C,   "Printer Location" },
    { 0x035E,   "Duplex Supported" },
    { 0x0360,   "Media Types Supported" },
    { 0x0362,   "Max Media Width" },
    { 0x0364,   "Max Media Length" },
    { 0x0366,   "Enhanced Layout Supported" },
    { 0x0368,   "RUI Formats Supported" },
    { 0x0370,   "Reference Printing RUI Supported" },
    { 0x0372,   "Direct Printing RUI Supported" },
    { 0x0374,   "Reference Printing Top URL" },
    { 0x0376,   "Direct Printing Top URL" },
    { 0x037A,   "Device Name" },
    { 0, NULL }
};

static const value_string vs_bpp_reflected_ui_attribute_id[] = {
    { 0x0368,   "RUI Formats Supported" },
    { 0x0378,   "Printer Admin RUI Top URL" },
    { 0, NULL }
};

static const value_string vs_ctp_attribute_id[] = {
    { 0x0301,   "External Network" },
    { 0, NULL }
};

static const value_string vs_did_attribute_id[] = {
    { 0x0200,   "Specification ID" },
    { 0x0201,   "Vendor ID" },
    { 0x0202,   "Product ID" },
    { 0x0203,   "Version" },
    { 0x0204,   "Primary Record" },
    { 0x0205,   "Vendor ID Source" },
    { 0, NULL }
};

static const value_string vs_dun_attribute_id[] = {
    { 0x0305,   "Audio Feedback Support" },
    { 0x0306,   "Escape Sequence" },
    { 0, NULL }
};


static const value_string vs_fax_attribute_id[] = {
    { 0x0302,   "Fax Class 1 Support" },
    { 0x0303,   "Fax Class 2.0 Support" },
    { 0x0304,   "Fax Class 2 Support (vendor-specific class)" },
    { 0x0305,   "Audio Feedback Support" },
    { 0, NULL }
};

static const value_string vs_ftp_attribute_id[] = {
    { 0x0200,   "GOEP L2CAP PSM" },
    { 0, NULL }
};

static const value_string vs_gnss_attribute_id[] = {
    { 0x0200,   "Supported Features" },
    { 0, NULL }
};

static const value_string vs_hfp_gw_attribute_id[] = {
    { 0x0311,   "Supported Features" },
    { 0, NULL }
};

static const value_string vs_hfp_ag_attribute_id[] = {
    { 0x0301,   "Network" },
    { 0x0311,   "Supported Features" },
    { 0, NULL }
};

static const value_string vs_hcrp_attribute_id[] = {
    { 0x0300,   "1284ID" },
    { 0x0302,   "Device Name" },
    { 0x0304,   "Friendly Name" },
    { 0x0306,   "Device Location" },
    { 0, NULL }
};

static const value_string vs_hsp_attribute_id[] = {
    { 0x0302,   "Remote Audio Volume Control" },
    { 0, NULL }
};

static const value_string vs_hdp_attribute_id[] = {
    { 0x0200,   "Support Features List" },
    { 0x0301,   "Data Exchange Specification" },
    { 0x0302,   "MCAP Supported Procedures" },
    { 0, NULL }
};

static const value_string vs_hid_attribute_id[] = {
    { 0x0200,   "Device Release Number" },
    { 0x0201,   "Parser Version" },
    { 0x0202,   "Device Subclass" },
    { 0x0203,   "Country Code" },
    { 0x0204,   "Virtual Cable" },
    { 0x0205,   "Reconnect Initiate" },
    { 0x0206,   "Descriptor List" },
    { 0x0207,   "LANG ID Base List" },
    { 0x0208,   "SDP Disable" },
    { 0x0209,   "Battery Power" },
    { 0x020A,   "Remote Wake" },
    { 0x020B,   "Profile Version" },
    { 0x020C,   "Supervision Timeout" },
    { 0x020D,   "Normally Connectable" },
    { 0x020E,   "BootDevice" },
    { 0x020F,   "SSR Host Max Latency" },
    { 0x0210,   "SSR Host Min Timeout" },
    { 0, NULL }
};

static const value_string vs_wap_attribute_id[] = {
    { 0x0306,   "Network Address" },
    { 0x0307,   "WAP Gateway" },
    { 0x0308,   "Home Page URL" },
    { 0x0309,   "WAP Stack Type" },
    { 0, NULL }
};

static const value_string vs_map_mas_attribute_id[] = {
    { 0x200,    "GOEP L2CAP PSM" }, /* MAP v1.2 and later */
    { 0x0315,   "MAS Instance ID" },
    { 0x0316,   "Supported Message Types" },
    { 0x0317,   "Supported Features" }, /* MAP v1.2 and later */
    { 0, NULL }
};

static const value_string vs_map_mns_attribute_id[] = {
    { 0x200,    "GOEP L2CAP PSM" }, /* MAP v1.2 and later */
    { 0x0317,   "Supported Features" }, /* MAP v1.2 and later */
    { 0, NULL }
};

static const value_string vs_opp_attribute_id[] = {
    { 0x0200,   "GOEP L2CAP PSM" },
    { 0x0300,   "Service Version" },
    { 0x0303,   "Supported Formats List" },
    { 0, NULL }
};

static const value_string vs_pan_nap_attribute_id[] = {
    { 0x0200,   "IP Subnet" }, /* Deprecated */
    { 0x030A,   "Security Description" },
    { 0x030B,   "Net Access Type" },
    { 0x030C,   "Max Net Access Rate" },
    { 0x030D,   "IPv4Subnet" },
    { 0x030E,   "IPv6Subnet" },
    { 0, NULL }
};

static const value_string vs_pan_gn_attribute_id[] = {
    { 0x0200,   "IP Subnet" }, /* Deprecated */
    { 0x030A,   "Security Description" },
    { 0x030D,   "IPv4Subnet" },
    { 0x030E,   "IPv6Subnet" },
    { 0, NULL }
};

static const value_string vs_pan_panu_attribute_id[] = {
    { 0x030A,   "Security Description" },
    { 0, NULL }
};

static const value_string vs_pbap_attribute_id[] = {
    { 0x0200,   "GOEP L2CAP PSM" },
    { 0x0314,   "Supported Repositories" },
    { 0x0317,   "Supported Features" },
    { 0, NULL }
};

static const value_string vs_synch_attribute_id[] = {
    { 0x0301,   "Supported Data Stores List" },
    { 0, NULL }
};

static const value_string vs_mps_attribute_id[] = {
    { 0x0200,  "Multiple Profiles - Single Device Supported Scenarios" },
    { 0x0201,  "Multiple Profiles - Multiple Device Supported Scenarios" },
    { 0x0202,  "Supported Profile and Protocol Dependency" },
    { 0, NULL }
};

static const value_string vs_ctn_as_attribute_id[] = {
    { 0x0315,  "Instance ID" },
    { 0x0317,  "Supported Features" },
    { 0, NULL }
};

static const value_string vs_ctn_ns_attribute_id[] = {
    { 0x0317,  "Supported Features" },
    { 0, NULL }
};

static const value_string did_vendor_id_source_vals[] = {
    { 0x0001,   "Bluetooth SIG" },
    { 0x0002,   "USB Implementer's Forum" },
    { 0, NULL }
};
value_string_ext did_vendor_id_source_vals_ext = VALUE_STRING_EXT_INIT(did_vendor_id_source_vals);

static const value_string synch_supported_data_store_vals[] = {
    { 0x01,   "Phonebook" },
    { 0x03,   "Calendar" },
    { 0x05,   "Notes" },
    { 0x06,   "Messages" },
    { 0, NULL }
};

static const value_string ctp_external_network_vals[] = {
    { 0x01,   "Phonebook" },
    { 0x02,   "ISDN" },
    { 0x03,   "GSM" },
    { 0x04,   "CDMA" },
    { 0x05,   "Analogue Cellular" },
    { 0x06,   "Packet-switched" },
    { 0x07,   "Other" },
    { 0, NULL }
};

static const value_string wap_stack_type_vals[] = {
    { 0x01,   "Connectionless" },
    { 0x02,   "Connection Oriented" },
    { 0x03,   "All (Connectionless + Connection Oriented)" },
    { 0, NULL }
};

static const value_string wap_gateway_vals[] = {
    { 0x01,   "Origin Server" },
    { 0x02,   "Proxy" },
    { 0, NULL }
};

static const value_string hdp_data_exchange_specification_vals[] = {
    { 0x01,   "ISO/IEEE 11073-20601 (Health informatics)" },
    { 0, NULL }
};

static const range_string hdp_mdep_id_rvals[] = {
    { 0x00, 0x00,  "Reserved For Echo Test Function" },
    { 0x01, 0x7F,  "Available for use" },
    { 0x80, 0xFF,  "Reserved by MCAP" },
    { 0, 0, NULL }
};

static const value_string hdp_mdep_role_vals[] = {
    { 0x00,   "Source" },
    { 0x01,   "Sink" },
    { 0, NULL }
};

static const value_string hdp_mdep_data_type_01_vals[] = {
    { 0x1004,   "Pulse Oximeter" },
    { 0x1006,   "Basic ECG" },
    { 0x1007,   "Blood Pressure Monitor" },
    { 0x1008,   "Body Thermometer" },
    { 0x100F,   "Body Weight Scale" },
    { 0x1011,   "Glucose Meter" },
    { 0x1012,   "International Normalized Ratio Monitor" },
    { 0x1014,   "Body Composition Analyzer" },
    { 0x1015,   "Peak Flow Monitor" },
    { 0x1029,   "Cardiovascular Fitness and Activity Monitor" },
    { 0x102A,   "Strength Fitness Equipment" },
    { 0x1047,   "Independent Living Activity Hub" },
    { 0x1048,   "Medication monitor" },
    { 0x1068,   "Step Counter based on 10441" },
    { 0x1075,   "Fall Sensor" },
    { 0x1076,   "Personal Emergency Response Sensor" },
    { 0x1077,   "Smoke Sensor" },
    { 0x1078,   "Carbon Monoxide Sensor" },
    { 0x1079,   "Water Sensor" },
    { 0x107A,   "Gas Sensor" },
    { 0x107B,   "Motion Sensor" },
    { 0x107C,   "Property Exit Sensor" },
    { 0x107D,   "Enuresis Sensor" },
    { 0x107E,   "Contact Closure Sensor" },
    { 0x107F,   "Usage Sensor" },
    { 0x1080,   "Switch Sensor" },
    { 0x1081,   "Medication Dosing Sensor" },
    { 0x1082,   "Temperature Sensor" },
    { 0, NULL }
};

static const value_string pan_security_description_vals[] = {
    { 0x0000,   "None" },
    { 0x0001,   "Service-level Enforced Security" },
    { 0x0002,   "802.1x Security" },
    { 0, NULL }
};

static const value_string opp_supported_format_vals[] = {
    { 0x01,   "vCard 2.1" },
    { 0x02,   "vCard 3.0" },
    { 0x03,   "vCal 1.0" },
    { 0x04,   "iCal 2.0" },
    { 0x05,   "vNote" },
    { 0x06,   "vMessage" },
    { 0xFF,   "AllFormats" },
    { 0, NULL }
};

static const value_string pan_net_access_type_vals[] = {
    { 0x0000,   "PSTN" },
    { 0x0001,   "ISDN" },
    { 0x0002,   "DSL" },
    { 0x0003,   "Cable Modem" },
    { 0x0004,   "10Mb Ethernet" },
    { 0x0005,   "100Mb Ethernet" },
    { 0x0006,   "4Mb Token Ring" },
    { 0x0007,   "16Mb Token Ring" },
    { 0x0008,   "100Mb Token Ring" },
    { 0x0009,   "FDDI" },
    { 0x000A,   "GSM" },
    { 0x000B,   "CDMA" },
    { 0x000c,   "GPRS" },
    { 0x000D,   "3G" },
    { 0xFFFE,   "Other" },
    { 0, NULL }
};

static const value_string hfp_gw_network_vals[] = {
    { 0x00,   "No ability to reject a call" },
    { 0x01,   "Ability to reject a call" },
    { 0, NULL }
};

static const value_string hid_device_subclass_type_vals[] = {
    { 0x00,   "Not Keyboard / Not Pointing Device" },
    { 0x01,   "Keyboard" },
    { 0x02,   "Pointing Device" },
    { 0x03,   "Combo keyboard/pointing device" },
    { 0, NULL }
};

static const value_string hid_device_subclass_subtype_vals[] = {
    { 0x00,   "Uncategorized device" },
    { 0x01,   "Joystick" },
    { 0x02,   "Gamepad" },
    { 0x03,   "Remote control" },
    { 0x04,   "Sensing device" },
    { 0x05,   "Digitizer tablet" },
    { 0x06,   "Card Reader" },
    { 0, NULL }
};

/* USB HID 1.11 bCountryCode */
const value_string hid_country_code_vals[] = {
    {  0,   "Not Supported" },
    {  1,   "Arabic" },
    {  2,   "Belgian" },
    {  3,   "Canadian-Bilingual" },
    {  4,   "Canadian-French" },
    {  5,   "Czech Republic" },
    {  6,   "Danish" },
    {  7,   "Finnish" },
    {  8,   "French" },
    {  9,   "German" },
    { 10,   "Greek" },
    { 11,   "Hebrew" },
    { 12,   "Hungary" },
    { 13,   "International (ISO)" },
    { 14,   "Italian" },
    { 15,   "Japan (Katakana)" },
    { 16,   "Korean" },
    { 17,   "Latin American" },
    { 18,   "Netherlands/Dutch" },
    { 19,   "Norwegian" },
    { 20,   "Persian (Farsi)" },
    { 21,   "Poland" },
    { 22,   "Portuguese" },
    { 23,   "Russia" },
    { 24,   "Slovakia" },
    { 25,   "Spanish" },
    { 26,   "Swedish" },
    { 27,   "Swiss/French" },
    { 28,   "Swiss/German" },
    { 29,   "Switzerland" },
    { 30,   "Taiwan" },
    { 31,   "Turkish-Q" },
    { 32,   "UK" },
    { 33,   "US" },
    { 34,   "Yugoslavia" },
    { 35,   "Turkish-F" },
    { 0, NULL }
};

static const value_string descriptor_list_type_vals[] = {
    { 0x22,  "Report" },
    { 0x23,  "Physical"},
    { 0, NULL }
};

static const value_string vs_error_code[] = {
    { 0x0001,   "Invalid/Unsupported SDP Version" },
    { 0x0002,   "Invalid Service Record Handle" },
    { 0x0003,   "Invalid Request Syntax" },
    { 0x0004,   "Invalid PDU Size" },
    { 0x0005,   "Invalid Continuation State" },
    { 0x0006,   "Insufficient Resources to Satisfy Request" },
    { 0, NULL }
};

static const value_string vs_data_element_size[] = {
    { 0x00,   "1 byte (0 bytes if Nil)" },
    { 0x01,   "2 bytes" },
    { 0x02,   "4 bytes" },
    { 0x03,   "8 bytes" },
    { 0x04,   "16 bytes" },
    { 0x05,   "uint8" },
    { 0x06,   "uint16" },
    { 0x07,   "uint32" },
    { 0, NULL }
};

static const value_string vs_data_element_type[] = {
    { 0x00,   "Nil" },
    { 0x01,   "Unsigned Integer" },
    { 0x02,   "Signed Twos-Complement Integer" },
    { 0x03,   "UUID" },
    { 0x04,   "Text string" },
    { 0x05,   "Boolean" },
    { 0x06,   "Sequence" },
    { 0x07,   "Alternative" },
    { 0x08,   "URL" },
    { 0, NULL }
};

void proto_register_btsdp(void);
void proto_reg_handoff_btsdp(void);

service_info_t* btsdp_get_service_info(wmem_tree_key_t* key)
{
    if (service_infos == NULL)
        return NULL;

    return (service_info_t *)wmem_tree_lookup32_array_le(service_infos, key);
}

static bluetooth_uuid_t
get_specified_uuid(wmem_allocator_t *pool, wmem_array_t  *uuid_array)
{
    bluetooth_uuid_t uuid;

/* Try to find UUID that is already use in RFCOMM or L2CAP, otherwise try to
   return last one (most generic).
   NOTE: UUIDs in array are from (most specified) to (most generic) */
    if (uuid_array) {
        uint32_t i_uuid;
        uint32_t size;
        bluetooth_uuid_t *p_uuid = NULL;

        size = wmem_array_get_count(uuid_array);

        for (i_uuid = 0; i_uuid < size; i_uuid += 1) {
            p_uuid = (bluetooth_uuid_t *) wmem_array_index(uuid_array, i_uuid);
            if (p_uuid->size == 16) /* CustomUUID (UUID128) is always ok */
                break;
            if (p_uuid->size == 0)
                continue;
            if (dissector_get_string_handle(bluetooth_uuid_table, print_numeric_bluetooth_uuid(pool, p_uuid)))
                break;
        }

        if (p_uuid) return *p_uuid;
    }

    memset(&uuid, 0, sizeof(bluetooth_uuid_t));
    return uuid;
}


static wmem_array_t *
get_uuids(packet_info *pinfo, uint32_t record_handle, btl2cap_data_t *l2cap_data)
{
    record_handle_service_t  *record_handle_service;
    wmem_tree_key_t           key[7];
    uint32_t                  k_interface_id;
    uint32_t                  k_adapter_id;
    uint32_t                  k_chandle;
    uint32_t                  k_psm;
    uint32_t                  k_record_handle;
    uint32_t                  k_frame_number;
    uint32_t                  interface_id;
    uint32_t                  adapter_id;
    uint32_t                  chandle;
    uint32_t                  psm;
    uint32_t                  frame_number;

    interface_id = l2cap_data->interface_id;
    adapter_id   = l2cap_data->adapter_id;
    chandle  = l2cap_data->chandle;
    psm  = l2cap_data->psm;
    frame_number = pinfo->num;

    k_interface_id  = interface_id;
    k_adapter_id    = adapter_id;
    k_chandle   = chandle;
    k_psm   = psm;
    k_record_handle = record_handle;
    k_frame_number  = frame_number;


    key[0].length = 1;
    key[0].key    = &k_interface_id;
    key[1].length = 1;
    key[1].key    = &k_adapter_id;
    key[2].length = 1;
    key[2].key    = &k_chandle;
    key[3].length = 1;
    key[3].key    = &k_psm;
    key[4].length = 1;
    key[4].key    = &k_record_handle;
    key[5].length = 1;
    key[5].key    = &k_frame_number;
    key[6].length = 0;
    key[6].key    = NULL;

    record_handle_service = (record_handle_service_t *) wmem_tree_lookup32_array_le(record_handle_services, key);
    if (record_handle_service && record_handle_service->interface_id == interface_id &&
            record_handle_service->adapter_id == adapter_id &&
            record_handle_service->chandle == chandle &&
            record_handle_service->psm == psm &&
            record_handle_service->record_handle == record_handle) {
        return record_handle_service->uuid_array;
    }

    return NULL;
}


static service_info_t *
save_channel(packet_info *pinfo, uint32_t type_protocol, uint32_t channel,
        int protocol_order, service_info_t *parent_service_info)
{
    wmem_tree_key_t  key[10];
    uint32_t         k_interface_id;
    uint32_t         k_adapter_id;
    uint32_t         k_sdp_psm;
    uint32_t         k_direction;
    uint32_t         k_bd_addr_oui;
    uint32_t         k_bd_addr_id;
    uint32_t         k_service_type;
    uint32_t         k_service_channel;
    uint32_t         k_frame_number;
    service_info_t  *service_info;

    service_info = (service_info_t *) wmem_new(wmem_file_scope(), service_info_t);
    service_info->interface_id   = parent_service_info->interface_id;
    service_info->adapter_id     = parent_service_info->adapter_id;
    service_info->sdp_psm        = parent_service_info->sdp_psm;
    service_info->direction      = parent_service_info->direction;
    service_info->bd_addr_oui    = parent_service_info->bd_addr_oui;
    service_info->bd_addr_id     = parent_service_info->bd_addr_id;

    service_info->type           = type_protocol;
    service_info->channel        = channel;

    service_info->uuid           = parent_service_info->uuid;

    service_info->protocol       = -1;
    service_info->protocol_order = protocol_order;
    service_info->parent_info    = parent_service_info;
    service_info->data           = parent_service_info->data;


    k_interface_id    = service_info->interface_id;
    k_adapter_id      = service_info->adapter_id;
    k_sdp_psm         = service_info->sdp_psm;
    k_direction       = service_info->direction;
    k_bd_addr_oui     = service_info->bd_addr_oui;
    k_bd_addr_id      = service_info->bd_addr_id;
    k_service_type    = service_info->type;
    k_service_channel = service_info->channel;
    k_frame_number    = pinfo->num;

    key[0].length = 1;
    key[0].key = &k_interface_id;
    key[1].length = 1;
    key[1].key = &k_adapter_id;
    key[2].length = 1;
    key[2].key = &k_sdp_psm;
    key[3].length = 1;
    key[3].key = &k_direction;
    key[4].length = 1;
    key[4].key = &k_bd_addr_oui;
    key[5].length = 1;
    key[5].key = &k_bd_addr_id;
    key[6].length = 1;
    key[6].key = &k_service_type;
    key[7].length = 1;
    key[7].key = &k_service_channel;
    key[8].length = 1;
    key[8].key = &k_frame_number;
    key[9].length = 0;
    key[9].key = NULL;

    wmem_tree_insert32_array(service_infos, key, service_info);

    return service_info;
}


static unsigned
get_type_length(tvbuff_t *tvb, unsigned offset, unsigned*length)
{
    unsigned size  = 0;
    uint8_t  byte;

    byte = tvb_get_uint8(tvb, offset);
    offset += 1;

    switch (byte & 0x07) {
    case 0:
        size = (byte >> 3) == 0 ? 0 : 1;
        break;
    case 1:
        size = 2;
        break;
    case 2:
        size = 4;
        break;
    case 3:
        size = 8;
        break;
    case 4:
        size = 16;
        break;
    case 5:
        size = tvb_get_uint8(tvb, offset);
        offset += 1;
        break;
    case 6:
        size = tvb_get_ntohs(tvb, offset);
        offset += 2;
        break;
    case 7:
        size = tvb_get_ntohl(tvb, offset);
        offset += 4;
        break;
    }

    *length = size;

    return offset;
}


static uint32_t
get_uint_by_size(tvbuff_t *tvb, unsigned off, unsigned size)
{
    switch (size) {
    case 0:
        return tvb_get_uint8(tvb, off);
    case 1:
        return tvb_get_ntohs(tvb, off);
    case 2:
        return tvb_get_ntohl(tvb, off);
    default:
        return 0xffffffff;
    }
}


static int32_t
get_int_by_size(tvbuff_t *tvb, unsigned off, unsigned size)
{
    switch (size) {
    case 0:
        return tvb_get_uint8(tvb, off);
    case 1:
        return tvb_get_ntohs(tvb, off);
    case 2:
        return tvb_get_ntohl(tvb, off);
    default:
        return -1;
    }
}

static unsigned
dissect_uuid(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, unsigned offset, unsigned size, bluetooth_uuid_t *uuid)
{
    proto_item  *item;

    DISSECTOR_ASSERT(uuid);

    *uuid = get_bluetooth_uuid_be(tvb, offset, size);

    if (size == 2) {
        proto_tree_add_item(tree, hf_data_element_value_uuid_16, tvb, offset, size, ENC_BIG_ENDIAN);
    } else if (size == 4 && uuid->size == 2) {
        proto_tree_add_item(tree, hf_data_element_value_uuid_32, tvb, offset, size, ENC_BIG_ENDIAN);
    } else if (size == 16 && uuid->size == 2) {
        item = proto_tree_add_item(tree, hf_data_element_value_uuid_128, tvb, offset, size, ENC_NA);
        proto_item_append_text(item, " (%s)", val_to_str_ext_const(uuid->bt_uuid, &bluetooth_uuid_vals_ext, "Unknown"));
    } else {
        item = proto_tree_add_item(tree, hf_data_element_value_uuid, tvb, offset, size, ENC_NA);
        proto_item_append_text(item, " (%s)", print_bluetooth_uuid(uuid));
    }

    return offset + size;
}


static unsigned
dissect_continuation_state(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
        unsigned offset)
{
    proto_item  *cont_item;
    unsigned length;

    length = (unsigned)tvb_reported_length_remaining(tvb, offset);
    if (length == 0)  {
        proto_tree_add_expert_remaining(tree, pinfo, &ei_btsdp_continuation_state_none, tvb, offset);
    } else if (length > 17) {
        proto_tree_add_expert_remaining(tree, pinfo, &ei_btsdp_continuation_state_large, tvb, offset);
    } else if (length == 1 && tvb_get_uint8(tvb, offset) == 0x00) {
        proto_tree_add_none_format(tree, hf_continuation_state, tvb,
                offset, -1, "Continuation State: no (00)");
    } else {
        proto_item  *cont_tree;
        unsigned     data;
        uint8_t      i_data;
        uint8_t      continuation_state_length;

        continuation_state_length = tvb_get_uint8(tvb, offset);
        cont_item = proto_tree_add_none_format(tree, hf_continuation_state, tvb, offset,
                1 + continuation_state_length, "Continuation State: yes (");
        cont_tree = proto_item_add_subtree(cont_item, ett_btsdp_continuation_state);

        proto_tree_add_item(cont_tree, hf_continuation_state_length, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;
        proto_tree_add_item(cont_tree, hf_continuation_state_value, tvb, offset,
                continuation_state_length, ENC_NA);

        for (i_data = 0; i_data < continuation_state_length - 1; ++i_data) {
            data = tvb_get_uint8(tvb, offset);
            proto_item_append_text(cont_item, "%02X ", data);
            offset += 1;
        }

        data = tvb_get_uint8(tvb, offset);
        proto_item_append_text(cont_item, "%02X)", data);
        offset += 1;
    }

    return offset;
}

// The only specification I could find says the max length is 16:
// https://lost-contact.mit.edu/afs/nada.kth.se/misc/cas/documentation/bluetooth/bluetooth_e.pdf
#define MAX_CONTINUATION_STATE_LEN 16
static int
reassemble_continuation_state(tvbuff_t *tvb, packet_info *pinfo,
        unsigned offset, unsigned tid, bool is_request,
        int attribute_list_byte_offset, int attribute_list_byte_count,
        uint32_t pdu_type, tvbuff_t **new_tvb, bool *is_first,
        bool *is_continued, wmem_array_t **uuid_array,
        uint32_t *record_handle, btl2cap_data_t *l2cap_data)
{
    unsigned           length;
    tid_request_t     *tid_request;
    continuation_state_data_t *continuation_state_data;
    wmem_tree_key_t    key[12];
    wmem_tree_t       *subtree;
    uint32_t           k_interface_id;
    uint32_t           k_adapter_id;
    uint32_t           k_chandle;
    uint32_t           k_psm;
    uint32_t           k_tid;
    uint32_t           k_pdu_type;
    uint32_t           k_frame_number;
    uint32_t          *k_continuation_state_array;
    uint8_t           *continuation_state;
    uint32_t           interface_id;
    uint32_t           adapter_id;
    uint32_t           chandle;
    uint32_t           psm;
    uint32_t           frame_number;

    if (new_tvb) *new_tvb = NULL;

    interface_id = l2cap_data->interface_id;
    adapter_id   = l2cap_data->adapter_id;
    chandle      = l2cap_data->chandle;
    psm          = l2cap_data->psm;
    frame_number = pinfo->num;

    k_interface_id = interface_id;
    k_adapter_id   = adapter_id;
    k_chandle      = chandle;
    k_psm          = psm;
    k_tid          = tid;
    k_frame_number = frame_number;

    key[0].length = 1;
    key[0].key    = &k_interface_id;
    key[1].length = 1;
    key[1].key    = &k_adapter_id;
    key[2].length = 1;
    key[2].key    = &k_chandle;
    key[3].length = 1;
    key[3].key    = &k_psm;
    key[4].length = 1;
    key[4].key    = &k_tid;
    key[5].length = 1;
    key[5].key    = &k_frame_number;
    key[6].length = 0;
    key[6].key    = NULL;

    if (is_first) *is_first = true;
    if (is_continued) *is_continued = true;

    length = (unsigned)tvb_reported_length_remaining(tvb, offset);
    if (length == 0)  {
        return offset;
    } else if (length > 17) {
        return offset;
    } else if (length == 1 && tvb_get_uint8(tvb, offset) == 0x00) {
        if (is_continued) *is_continued = false;

        if (!pinfo->fd->visited) {
            if (is_request) {
                tid_request = (tid_request_t *) wmem_new(wmem_file_scope(), tid_request_t);
                tid_request->interface_id = interface_id;
                tid_request->adapter_id   = adapter_id;
                tid_request->chandle      = chandle;
                tid_request->psm          = psm;
                tid_request->tid          = tid;

                if (uuid_array)
                    tid_request->uuid_array = *uuid_array;
                else
                    tid_request->uuid_array = NULL;
                if (record_handle)
                    tid_request->record_handle   = *record_handle;
                else
                    tid_request->record_handle = 0;

                tid_request->data         = NULL;
                tid_request->data_length  = 0;

                tid_request->pdu_type = pdu_type;

                tid_request->continuation_state        = NULL;
                tid_request->continuation_state_length = 0;

                wmem_tree_insert32_array(tid_requests, key, tid_request);
            } else {
                tid_request = (tid_request_t *) wmem_tree_lookup32_array_le(tid_requests, key);
                if (tid_request && tid_request->interface_id == interface_id &&
                        tid_request->adapter_id == adapter_id &&
                        tid_request->chandle == chandle &&
                        tid_request->psm == psm &&
                        tid_request->tid == tid) {
                    if (tid_request->continuation_state_length > 0) {
                        /* fetch tid_request->continuation_state */

                        k_continuation_state_array =  (uint32_t *) wmem_alloc0(pinfo->pool, 20);
                        continuation_state = (uint8_t *) k_continuation_state_array;
                        continuation_state[0] = tid_request->continuation_state_length;
                        memcpy(&continuation_state[1], tid_request->continuation_state, tid_request->continuation_state_length);

                        k_interface_id       = interface_id;
                        k_adapter_id         = adapter_id;
                        k_chandle            = chandle;
                        k_psm                = psm;
                        k_pdu_type           = tid_request->pdu_type;
                        k_frame_number       = frame_number;

                        key[0].length = 1;
                        key[0].key    = &k_interface_id;
                        key[1].length = 1;
                        key[1].key    = &k_adapter_id;
                        key[2].length = 1;
                        key[2].key    = &k_chandle;
                        key[3].length = 1;
                        key[3].key    = &k_psm;
                        key[4].length = 1;
                        key[4].key    = &k_pdu_type;
                        key[5].length = 1;
                        key[5].key    = &k_continuation_state_array[0];
                        key[6].length = 1;
                        key[6].key    = &k_continuation_state_array[1];
                        key[7].length = 1;
                        key[7].key    = &k_continuation_state_array[2];
                        key[8].length = 1;
                        key[8].key    = &k_continuation_state_array[3];
                        key[9].length = 1;
                        key[9].key    = &k_continuation_state_array[4];
                        key[10].length = 1;
                        key[10].key    = &k_frame_number;
                        key[11].length = 0;
                        key[11].key    = NULL;

                        continuation_state_data = (continuation_state_data_t *) wmem_tree_lookup32_array_le(continuation_states, key);
                        if (continuation_state_data && continuation_state_data->interface_id == interface_id &&
                                continuation_state_data->adapter_id == adapter_id &&
                                continuation_state_data->chandle == chandle &&
                                continuation_state_data->psm == psm &&
                                continuation_state_data->pdu_type == tid_request->pdu_type &&
                                continuation_state_data->continuation_state[0] == k_continuation_state_array[0] &&
                                continuation_state_data->continuation_state[1] == k_continuation_state_array[1] &&
                                continuation_state_data->continuation_state[2] == k_continuation_state_array[2] &&
                                continuation_state_data->continuation_state[3] == k_continuation_state_array[3] &&
                                continuation_state_data->continuation_state[4] == k_continuation_state_array[4]) {
                            tid_request->data = (uint8_t *) wmem_alloc(wmem_file_scope(), continuation_state_data->data_length + attribute_list_byte_count);
                            tid_request->data_length = continuation_state_data->data_length + attribute_list_byte_count;
                            memcpy(tid_request->data, continuation_state_data->data, continuation_state_data->data_length);
                            tvb_memcpy(tvb, tid_request->data + continuation_state_data->data_length, attribute_list_byte_offset, attribute_list_byte_count);
                        }
                    } else {
                        tid_request->data        = (uint8_t *) wmem_alloc(wmem_file_scope(), attribute_list_byte_count);
                        tid_request->data_length = attribute_list_byte_count;

                        tvb_memcpy(tvb, tid_request->data, attribute_list_byte_offset, attribute_list_byte_count);
                    }

                    if (uuid_array) *uuid_array = tid_request->uuid_array;
                    if (record_handle) *record_handle = tid_request->record_handle;
                }
            }

            k_interface_id = interface_id;
            k_adapter_id   = adapter_id;
            k_chandle      = chandle;
            k_psm          = psm;
            k_tid          = tid;
            k_frame_number = frame_number;

            key[0].length = 1;
            key[0].key    = &k_interface_id;
            key[1].length = 1;
            key[1].key    = &k_adapter_id;
            key[2].length = 1;
            key[2].key    = &k_chandle;
            key[3].length = 1;
            key[3].key    = &k_psm;
            key[4].length = 1;
            key[4].key    = &k_tid;
            key[5].length = 1;
            key[5].key    = &k_frame_number;
            key[6].length = 0;
            key[6].key    = NULL;
        }

        /* full reassemble */
        if (!is_request) {
            tid_request = (tid_request_t *) wmem_tree_lookup32_array_le(tid_requests, key);
            if (tid_request && tid_request->interface_id == interface_id &&
                    tid_request->adapter_id == adapter_id &&
                    tid_request->chandle == chandle &&
                    tid_request->psm == psm &&
                    tid_request->tid == tid) {
                tvbuff_t *next_tvb;

                next_tvb = tvb_new_child_real_data(tvb, tid_request->data,
                        tid_request->data_length, tid_request->data_length);

                if (new_tvb) *new_tvb = next_tvb;
                if (tid_request->continuation_state_length && is_first) *is_first = false;

                if (uuid_array) *uuid_array = tid_request->uuid_array;
                if (record_handle) *record_handle = tid_request->record_handle;
            }
        }
    } else {
        char        *continuation_state_buffer;
        unsigned     continuation_state_length;

        continuation_state_length = tvb_get_uint8(tvb, offset);
        offset++;

        continuation_state_buffer = tvb_bytes_to_str(wmem_file_scope(), tvb, offset, continuation_state_length);

        if (continuation_state_length > MAX_CONTINUATION_STATE_LEN) {
            // Try to make do with what we can.
            expert_add_info(pinfo, NULL, &ei_length_bad);
            continuation_state_length = MAX_CONTINUATION_STATE_LEN;
        }

        if (!pinfo->fd->visited) {
            if (is_request) {
                tid_request = (tid_request_t *) wmem_new(wmem_file_scope(), tid_request_t);
                tid_request->interface_id              = interface_id;
                tid_request->adapter_id                = adapter_id;
                tid_request->chandle                   = chandle;
                tid_request->psm                       = psm;
                tid_request->tid                       = tid;

                if (uuid_array)
                    tid_request->uuid_array = *uuid_array;
                else
                    tid_request->uuid_array = NULL;

                if (record_handle)
                    tid_request->record_handle = *record_handle;
                else
                    tid_request->record_handle = 0;

                /* fetch data saved in continuation_state */
                tid_request->data        = NULL;
                tid_request->data_length = 0;

                tid_request->pdu_type = pdu_type;

                tid_request->continuation_state        = continuation_state_buffer;
                tid_request->continuation_state_length = continuation_state_length;

                wmem_tree_insert32_array(tid_requests, key, tid_request);
            } else {
                tid_request = (tid_request_t *) wmem_tree_lookup32_array_le(tid_requests, key);
                if (tid_request && tid_request->interface_id == interface_id &&
                        tid_request->adapter_id == adapter_id &&
                        tid_request->chandle == chandle &&
                        tid_request->psm == psm &&
                        tid_request->tid == tid) {
                    /* data comes from here and saved in previous continuation_state */

                    if (tid_request->continuation_state_length > 0) {
                        /* fetch tid_request->continuation_state */
                        k_continuation_state_array =  (uint32_t *) wmem_alloc0(pinfo->pool, 20);
                        continuation_state = (uint8_t *) k_continuation_state_array;
                        continuation_state[0] = tid_request->continuation_state_length;
                        memcpy(&continuation_state[1], tid_request->continuation_state, tid_request->continuation_state_length);

                        k_interface_id       = interface_id;
                        k_adapter_id         = adapter_id;
                        k_chandle            = chandle;
                        k_psm                = psm;
                        k_pdu_type           = tid_request->pdu_type;

                        key[0].length = 1;
                        key[0].key    = &k_interface_id;
                        key[1].length = 1;
                        key[1].key    = &k_adapter_id;
                        key[2].length = 1;
                        key[2].key    = &k_chandle;
                        key[3].length = 1;
                        key[3].key    = &k_psm;
                        key[4].length = 1;
                        key[4].key    = &k_pdu_type;
                        key[5].length = 1;
                        key[5].key    = &k_continuation_state_array[0];
                        key[6].length = 1;
                        key[6].key    = &k_continuation_state_array[1];
                        key[7].length = 1;
                        key[7].key    = &k_continuation_state_array[2];
                        key[8].length = 1;
                        key[8].key    = &k_continuation_state_array[3];
                        key[9].length = 1;
                        key[9].key     = &k_continuation_state_array[4];
                        key[10].length = 0;
                        key[10].key    = NULL;

                        subtree = (wmem_tree_t *) wmem_tree_lookup32_array(continuation_states, key);
                        continuation_state_data = (subtree) ? (continuation_state_data_t *) wmem_tree_lookup32_le(subtree, frame_number) : NULL;
                        if (continuation_state_data) {
                            tid_request->data = (uint8_t *) wmem_alloc(wmem_file_scope(), continuation_state_data->data_length + attribute_list_byte_count);
                            tid_request->data_length = continuation_state_data->data_length + attribute_list_byte_count;
                            memcpy(tid_request->data, continuation_state_data->data, continuation_state_data->data_length);
                            tvb_memcpy(tvb, tid_request->data + continuation_state_data->data_length, attribute_list_byte_offset, attribute_list_byte_count);
                        }
                    } else {
                        tid_request->data        = (uint8_t *) wmem_alloc(wmem_file_scope(), attribute_list_byte_count);
                        tid_request->data_length = attribute_list_byte_count;

                        tvb_memcpy(tvb, tid_request->data, attribute_list_byte_offset, attribute_list_byte_count);
                    }

                    if (uuid_array) *uuid_array = tid_request->uuid_array;
                    if (record_handle) *record_handle = tid_request->record_handle;

                    /* save tid_request in continuation_state data */
                    k_continuation_state_array =  (uint32_t *) wmem_alloc0(pinfo->pool, 20);
                    continuation_state = (uint8_t *) k_continuation_state_array;
                    continuation_state[0] = continuation_state_length;
                    memcpy(&continuation_state[1], continuation_state_buffer, continuation_state_length);

                    k_interface_id       = interface_id;
                    k_adapter_id         = adapter_id;
                    k_chandle            = chandle;
                    k_psm                = psm;
                    k_pdu_type           = pdu_type;
                    k_frame_number       = frame_number;

                    key[0].length = 1;
                    key[0].key    = &k_interface_id;
                    key[1].length = 1;
                    key[1].key    = &k_adapter_id;
                    key[2].length = 1;
                    key[2].key    = &k_chandle;
                    key[3].length = 1;
                    key[3].key    = &k_psm;
                    key[4].length = 1;
                    key[4].key    = &k_pdu_type;
                    key[5].length = 1;
                    key[5].key    = &k_continuation_state_array[0];
                    key[6].length = 1;
                    key[6].key    = &k_continuation_state_array[1];
                    key[7].length = 1;
                    key[7].key    = &k_continuation_state_array[2];
                    key[8].length = 1;
                    key[8].key    = &k_continuation_state_array[3];
                    key[9].length = 1;
                    key[9].key    = &k_continuation_state_array[4];
                    key[10].length = 1;
                    key[10].key    = &k_frame_number;
                    key[11].length = 0;
                    key[11].key    = NULL;

                    continuation_state_data = (continuation_state_data_t *) wmem_new(wmem_file_scope(), continuation_state_data_t);
                    continuation_state_data->interface_id = interface_id;
                    continuation_state_data->adapter_id = adapter_id;
                    continuation_state_data->chandle = chandle;
                    continuation_state_data->psm = psm;
                    continuation_state_data->pdu_type = pdu_type;
                    continuation_state_data->continuation_state[0] = k_continuation_state_array[0];
                    continuation_state_data->continuation_state[1] = k_continuation_state_array[1];
                    continuation_state_data->continuation_state[2] = k_continuation_state_array[2];
                    continuation_state_data->continuation_state[3] = k_continuation_state_array[3];
                    continuation_state_data->continuation_state[4] = k_continuation_state_array[4];
                    continuation_state_data->data = tid_request->data;
                    continuation_state_data->data_length = tid_request->data_length;

                    wmem_tree_insert32_array(continuation_states, key, continuation_state_data);
                }
            }

            k_interface_id = interface_id;
            k_adapter_id   = adapter_id;
            k_chandle      = chandle;
            k_psm          = psm;
            k_tid          = tid;
            k_frame_number = frame_number;

            key[0].length = 1;
            key[0].key    = &k_interface_id;
            key[1].length = 1;
            key[1].key    = &k_adapter_id;
            key[2].length = 1;
            key[2].key    = &k_chandle;
            key[3].length = 1;
            key[3].key    = &k_psm;
            key[4].length = 1;
            key[4].key    = &k_tid;
            key[5].length = 1;
            key[5].key    = &k_frame_number;
            key[6].length = 0;
            key[6].key    = NULL;
        }

        /* partial reassemble */
        if (!is_request) {
            tid_request = (tid_request_t *) wmem_tree_lookup32_array_le(tid_requests, key);
            if (tid_request && tid_request->interface_id == interface_id &&
                    tid_request->adapter_id == adapter_id &&
                    tid_request->chandle == chandle &&
                    tid_request->psm == psm &&
                    tid_request->tid == tid) {
                tvbuff_t *next_tvb;

                next_tvb = tvb_new_child_real_data(tvb, tid_request->data,
                        tid_request->data_length, tid_request->data_length);

                if (new_tvb) *new_tvb = next_tvb;
                if (tid_request->continuation_state_length && is_first) *is_first = false;

                if (uuid_array) *uuid_array = tid_request->uuid_array;
                if (record_handle) *record_handle = tid_request->record_handle;
            }

        }
    }

    return offset;
}

static unsigned
dissect_data_element(proto_tree *tree, proto_tree **next_tree,
        packet_info *pinfo, tvbuff_t *tvb, unsigned offset)
{
    proto_item  *pitem;
    proto_tree  *ptree;
    unsigned    new_offset;
    unsigned    length;
    unsigned    len;
    uint8_t     type;
    uint8_t     size;

    type = tvb_get_uint8(tvb, offset);
    size = type & 0x07;
    type = type >> 3;

    pitem = proto_tree_add_none_format(tree, hf_data_element, tvb, offset, 1, "Data Element: %s %s",
            val_to_str_const(type, vs_data_element_type, "Unknown Type"),
            val_to_str_const(size, vs_data_element_size, "Unknown Size"));
    ptree = proto_item_add_subtree(pitem, ett_btsdp_data_element);

    proto_tree_add_item(ptree, hf_data_element_type, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(ptree, hf_data_element_size, tvb, offset, 1, ENC_BIG_ENDIAN);

    new_offset = get_type_length(tvb, offset, &length);

    if ((unsigned)tvb_reported_length_remaining(tvb, new_offset) < length) {
        len = (unsigned)tvb_reported_length_remaining(tvb, offset);
    } else {
        len = new_offset - offset + length;
    }
    proto_item_set_len(pitem, len);

    offset += 1;

    if (new_offset > offset) {
        proto_tree_add_uint(ptree, hf_data_element_var_size, tvb,
                offset, new_offset - offset, length);
        proto_item_append_text(pitem, (length != 1) ? " %u bytes" : " %u byte", length);
        offset = new_offset;
    }

    pitem = proto_tree_add_item(ptree, hf_data_element_value, tvb, offset, length, ENC_NA);
    if (length > (unsigned)tvb_reported_length_remaining(tvb, offset)) {
        expert_add_info(pinfo, pitem, &ei_data_element_value_large);
        proto_item_append_text(pitem, ": MISSING");
    } else if (length == 0)
        proto_item_append_text(pitem, ": MISSING");

    if (next_tree) *next_tree = proto_item_add_subtree(pitem, ett_btsdp_data_element_value);

    /* XXX - proto_tree_add_item above does not throw an exception because
     * hf_data_element_value is a FT_NONE. Normally that works because
     * dissectors do not advance the offset until after dissecting the
     * contained items. However, some callers do not check the length,
     * assuming the expected type, so we have to check for overflow here.
     */
    if (ckd_add(&offset, offset, length)) {
        THROW(ReportedBoundsError);
    }

    return offset;
}

static unsigned
findUintAttribute(tvbuff_t *tvb, unsigned service_offset,
        unsigned number_of_attributes, int attribute_id)
{
    unsigned result = 0;
    unsigned search_length;
    unsigned search_offset;
    unsigned i_number_of_attributes;
    uint16_t attribute;

    search_offset = service_offset;
    i_number_of_attributes = 0;

    while (i_number_of_attributes < number_of_attributes) {
        search_offset = get_type_length(tvb, search_offset, &search_length);
        attribute = tvb_get_ntohs(tvb, search_offset);

        search_offset += search_length;
        search_offset = get_type_length(tvb, search_offset, &search_length);

        if (attribute == attribute_id) {
            result = get_uint_by_size(tvb, search_offset, 1);
        }

        search_offset += search_length;
        i_number_of_attributes += 1;
    }

    return result;
}


static void
dissect_protocol_descriptor_list(proto_tree *next_tree, tvbuff_t *tvb,
        packet_info *pinfo, unsigned offset, unsigned size, wmem_strbuf_t *info_buf,
        service_info_t  *service_info, unsigned *protocol_order)
{
    proto_tree      *feature_tree;
    proto_item      *feature_item;
    proto_tree      *entry_tree;
    proto_item      *entry_item;
    proto_tree      *sub_tree;
    proto_tree      *last_tree;
    unsigned         new_offset;
    unsigned         list_offset;
    unsigned         entry_start;
    unsigned         entry_offset;
    unsigned         entry_length;
    uint32_t         value;
    unsigned         length;
    uint32_t         i_protocol;
    bluetooth_uuid_t uuid;
    service_info_t  *record = NULL;

    list_offset = offset;
    i_protocol = 1;
    while (list_offset - offset < size) {
        const char      *uuid_str;

        feature_item = proto_tree_add_none_format(next_tree, hf_sdp_protocol_item, tvb, list_offset, 0, "Protocol #%u", i_protocol);
        feature_tree = proto_item_add_subtree(feature_item, ett_btsdp_protocol);
        entry_start = get_type_length(tvb, list_offset, &entry_length);
        entry_offset = entry_start;
        proto_item_set_len(feature_item, entry_length + (entry_offset - list_offset));

        dissect_data_element(feature_tree, &sub_tree, pinfo, tvb, list_offset);

        entry_item = proto_tree_add_item(sub_tree, hf_sdp_protocol, tvb, entry_offset, entry_length, ENC_NA);
        entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_id);
        dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
        new_offset = get_type_length(tvb, entry_offset, &length);
        entry_offset = new_offset;

        dissect_uuid(sub_tree, pinfo, tvb, entry_offset, length, &uuid);

        uuid_str = print_bluetooth_uuid(&uuid);
        wmem_strbuf_append(info_buf, uuid_str);
        proto_item_append_text(feature_item, ": %s", uuid_str);
        proto_item_append_text(entry_item, ": %s", uuid_str);

        entry_offset += length;

        if (entry_offset - entry_start < entry_length) {
            dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
            new_offset = get_type_length(tvb, entry_offset, &length);
            entry_offset = new_offset;
            value = get_int_by_size(tvb, entry_offset, length / 2);

            if (uuid.bt_uuid == BTSDP_L2CAP_PROTOCOL_UUID) {
                wmem_strbuf_append_printf(info_buf, ":%u", value);
                proto_item_append_text(feature_item, ", PSM: %u", value);
                proto_item_append_text(entry_item, ", PSM: %u", value);
                proto_tree_add_item(sub_tree, hf_sdp_protocol_psm, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
                if (!pinfo->fd->visited && service_info)
                    record = save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, value, *protocol_order, service_info);
                *protocol_order += 1;
            } else if (uuid.bt_uuid == BTSDP_RFCOMM_PROTOCOL_UUID) {
                wmem_strbuf_append_printf(info_buf, ":%u", value);
                proto_item_append_text(feature_item, ", RFCOMM Channel: %u", value);
                proto_item_append_text(entry_item, ", RFCOMM Channel: %u", value);
                proto_tree_add_item(sub_tree, hf_sdp_protocol_channel, tvb, entry_offset, 1, ENC_BIG_ENDIAN);
                if (!pinfo->fd->visited && service_info)
                    record = save_channel(pinfo, BTSDP_RFCOMM_PROTOCOL_UUID, value, *protocol_order, service_info);
                *protocol_order += 1;
            } else if (uuid.bt_uuid == BTSDP_ATT_PROTOCOL_UUID) {
                proto_item_append_text(feature_item, ", GATT Handle Start: 0x%04x", value);
                proto_item_append_text(entry_item, ", GATT Handle Start: 0x%04x", value);
                wmem_strbuf_append_printf(info_buf, ":0x%04x.", value);
                proto_tree_add_item(sub_tree, hf_sdp_protocol_gatt_handle_start, tvb, entry_offset, 2, ENC_BIG_ENDIAN);

                if ((entry_offset - list_offset) + length <= entry_length) {
                    entry_offset += length;
                    dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
                    new_offset = get_type_length(tvb, entry_offset, &length);
                    entry_offset = new_offset;
                    value = get_int_by_size(tvb, entry_offset, length / 2);

                    wmem_strbuf_append_printf(info_buf, ".0x%04x", value);
                    proto_item_append_text(feature_item, ", GATT Handle End: 0x%04x", value);
                    proto_item_append_text(entry_item, ", GATT Handle End: 0x%04x", value);
                    proto_tree_add_item(sub_tree, hf_sdp_protocol_gatt_handle_end, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
                }
            } else {
                wmem_strbuf_append_printf(info_buf, " (%x.%x)", value >> 8, value & 0xFF);
                proto_item_append_text(feature_item, ", Version %x.%x", value >> 8, value & 0xFF);
                proto_item_append_text(entry_item, ", Version 0x%03x", value);
                proto_tree_add_item(sub_tree, hf_sdp_protocol_version, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
            }

            entry_offset += length;
        }

        while (entry_offset - entry_start < entry_length) {
            unsigned value_offset;
            unsigned len;

            dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
            new_offset = get_type_length(tvb, entry_offset, &length);

            if (uuid.bt_uuid == BTSDP_BNEP_PROTOCOL_UUID) {
                wmem_strbuf_append(info_buf, " (");
                value_offset = new_offset;
                while (value_offset - new_offset < length) {
                    unsigned next_offset;
                    dissect_data_element(sub_tree, &last_tree, pinfo, tvb, value_offset);
                    next_offset = get_type_length(tvb, value_offset, &len);
                    value = get_int_by_size(tvb, next_offset, len / 2);

                    proto_tree_add_item(last_tree, hf_sdp_protocol_bnep_type, tvb, next_offset, 2, ENC_BIG_ENDIAN);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, etype_vals, "Unknown"));
                    value_offset = next_offset + len;

                    if (value_offset - new_offset < length)
                        wmem_strbuf_append(info_buf, " ");
                }
                wmem_strbuf_append(info_buf, ")");
            }

            entry_offset = new_offset + length;
        }

        i_protocol += 1;
        list_offset = entry_offset;

        if (list_offset - offset < size)
            wmem_strbuf_append(info_buf, " -> ");

        if (record)
            record->protocol = uuid.bt_uuid;
    }

}


static unsigned
// NOLINTNEXTLINE(misc-no-recursion)
dissect_sdp_type(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
        unsigned offset, int attribute, bluetooth_uuid_t service_uuid,
        int service_did_vendor_id, int service_did_vendor_id_source,
        int service_hdp_data_exchange_specification,
        service_info_t  *service_info, wmem_strbuf_t **pinfo_buf)
{
    proto_tree    *feature_tree;
    proto_item    *feature_item;
    proto_tree    *entry_tree;
    proto_item    *entry_item;
    proto_tree    *next_tree;
    proto_tree    *sub_tree;
    proto_tree    *last_tree;
    unsigned       size;
    uint8_t        byte;
    uint8_t        type;
    uint8_t        size_index;
    unsigned       start_offset;
    unsigned       new_offset;
    unsigned       list_offset;
    unsigned       list_length;
    unsigned       entry_offset;
    unsigned       entry_length;
    bool           found;
    uint16_t       specification_id;
    uint16_t       vendor_id;
    uint16_t       product_id;
    uint16_t       version;
    uint8_t        primary_record;
    uint8_t        mdep_id;
    uint16_t       vendor_id_source;
    const char    *str_val;
    uint32_t       supported_features;
    unsigned       i_feature;
    unsigned       i_protocol;
    uint16_t       psm;
    const uint8_t *new_str;
    uint32_t       value;
    uint64_t       value_64;
    bluetooth_uuid_t uuid;
    const char    *uuid_str;
    unsigned       length;
    unsigned       protocol_order;
    wmem_strbuf_t *info_buf;

    info_buf = wmem_strbuf_create(pinfo->pool);
    *pinfo_buf = info_buf;


    byte         = tvb_get_uint8(tvb, offset);
    type         = (byte >> 3) & 0x1f;
    size_index   = byte & 0x07;

    start_offset = offset;
    new_offset = dissect_data_element(tree, &next_tree, pinfo, tvb, offset);

    offset = get_type_length(tvb, offset, &size);

    found = true;
    switch(service_uuid.bt_uuid) {
        case BTSDP_DID_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_did_specification_id, tvb, offset, 2, ENC_BIG_ENDIAN, &specification_id);
                    wmem_strbuf_append_printf(info_buf, "%x.%02x (0x%04x)", specification_id >> 8, specification_id & 0xFF, specification_id);
                    break;
                case 0x201:
                    vendor_id = tvb_get_ntohs(tvb, offset);
                    if (service_did_vendor_id_source == DID_VENDOR_ID_SOURCE_BLUETOOTH_SIG) {
                        proto_tree_add_item(next_tree, hf_did_vendor_id_bluetooth_sig, tvb, offset, 2, ENC_BIG_ENDIAN);
                        str_val = val_to_str_ext_const(vendor_id, &bluetooth_company_id_vals_ext, "Unknown");
                    } else if (service_did_vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
                        proto_tree_add_item(next_tree, hf_did_vendor_id_usb_forum, tvb, offset, 2, ENC_BIG_ENDIAN);
                        str_val = val_to_str_ext_const(vendor_id, &ext_usb_vendors_vals, "Unknown");
                    } else {
                        proto_tree_add_item(next_tree, hf_did_vendor_id, tvb, offset, 2, ENC_BIG_ENDIAN);
                        str_val = "Unknown";
                    }
                    wmem_strbuf_append_printf(info_buf, "%s (0x%04x)", str_val, vendor_id);
                    break;
                case 0x202:
                    entry_item = proto_tree_add_item_ret_uint16(next_tree, hf_did_product_id, tvb, offset, 2, ENC_BIG_ENDIAN, &product_id);

                    if (service_did_vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
                        str_val = val_to_str_ext_const(service_did_vendor_id << 16 | product_id, &ext_usb_products_vals, "Unknown");
                        wmem_strbuf_append_printf(info_buf, "%s (0x%04x)", str_val, product_id);
                        proto_item_append_text(entry_item, " (%s)", str_val);
                    } else {
                        wmem_strbuf_append_printf(info_buf, "0x%04x", product_id);
                    }
                    break;
                case 0x203:
                    proto_tree_add_item_ret_uint16(next_tree, hf_did_version, tvb, offset, 2, ENC_BIG_ENDIAN, &version);
                    wmem_strbuf_append_printf(info_buf, "%x.%x.%x (0x%04x)", version >> 8, (version >> 4) & 0xF, version & 0xF, version);
                    break;
                case 0x204:
                    proto_tree_add_item(next_tree, hf_did_primary_record, tvb, offset, 1, ENC_BIG_ENDIAN);
                    primary_record = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, primary_record ? "true" : "false");
                    break;
                case 0x205:
                    proto_tree_add_item_ret_uint16(next_tree, hf_did_vendor_id_source, tvb, offset, 2, ENC_BIG_ENDIAN, &vendor_id_source);
                    wmem_strbuf_append_printf(info_buf, "%s (0x%04x)",
                            val_to_str_const(vendor_id_source, did_vendor_id_source_vals, "Unknown"),
                            vendor_id_source);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_A2DP_SINK_SERVICE_UUID:
            switch (attribute) {
                case 0x311:
                    proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_amplifier, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_recorder, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_speaker, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_headphone, tvb, offset, 2, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_ntohs(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
                            (supported_features & 0x01) ? "Headphone " : "",
                            (supported_features & 0x02) ? "Speaker " : "",
                            (supported_features & 0x04) ? "Recorder " : "",
                            (supported_features & 0x08) ? "Amplifier " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_A2DP_SOURCE_SERVICE_UUID:
            switch (attribute) {
                case 0x311:
                    proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_mixer, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_tuner, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_microphone, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_player, tvb, offset, 2, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_ntohs(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
                            (supported_features & 0x01) ? "Player " : "",
                            (supported_features & 0x02) ? "Microphone " : "",
                            (supported_features & 0x04) ? "Tuner " : "",
                            (supported_features & 0x08) ? "Mixer " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_SYNC_SERVICE_UUID:
            switch (attribute) {
                case 0x301:
                    list_offset = offset;
                    while (list_offset - offset < size) {
                        dissect_data_element(next_tree, &entry_tree, pinfo, tvb, list_offset);
                        list_offset = get_type_length(tvb, list_offset, &list_length);
                        proto_tree_add_item(entry_tree, hf_synch_supported_data_store, tvb, list_offset, 1, ENC_BIG_ENDIAN);
                        value = tvb_get_uint8(tvb, list_offset);

                        wmem_strbuf_append_printf(info_buf, "%s ", val_to_str_const(value, synch_supported_data_store_vals, "Unknown"));
                        list_offset += list_length;
                    }
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_CTP_SERVICE_UUID:
            switch (attribute) {
                case 0x311:
                    proto_tree_add_item(next_tree, hf_ctp_external_network, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);

                    wmem_strbuf_append(info_buf, val_to_str_const(value, ctp_external_network_vals, "Unknown"));
                break;
                default:
                    found = false;
            }
            break;
        case BTSDP_AVRCP_SERVICE_UUID:
        case BTSDP_AVRCP_CT_SERVICE_UUID:
            switch (attribute) {
                case 0x311:
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_reserved_10_15, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_cover_art_get_linked_thumbnail, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_cover_art_get_image, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_cover_art_get_image_properties, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_browsing, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_reserved_4_5, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_category_4, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_category_3, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_category_2, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_category_1, tvb, offset, 2, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_ntohs(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s%s",
                            (supported_features & 0x01) ? "Category1(Player/Recorder) " : "",
                            (supported_features & 0x02) ? "Category2(Monitor/Amplifier) " : "",
                            (supported_features & 0x04) ? "Category3(Tuner) " : "",
                            (supported_features & 0x08) ? "Category4(Menu) " : "",
                            (supported_features & 0x40) ? "Browsing " : "",
                            (supported_features & 0x80) ? "CoverArt/GetImageProperties) " : "",
                            (supported_features & 0x100) ? "CoverArt/GetImage) " : "",
                            (supported_features & 0x200) ? "CoverArt/GetLinkedThumbnail) " : "");
                break;
                default:
                    found = false;
            }
            break;
        case BTSDP_AVRCP_TG_SERVICE_UUID:
            switch (attribute) {
                case 0x311:
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_reserved_9_15, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_cover_art, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_multiple_player, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_browsing, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_group_navigation, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_settings, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_category_4, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_category_3, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_category_2, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_category_1, tvb, offset, 2, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_ntohs(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s%s%s",
                            (supported_features & 0x01) ? "Category1(Player/Recorder) " : "",
                            (supported_features & 0x02) ? "Category2(Monitor/Amplifier) " : "",
                            (supported_features & 0x04) ? "Category3(Tuner) " : "",
                            (supported_features & 0x08) ? "Category4(Menu) " : "",
                            (supported_features & 0x10) ? "PlayerApplicationSettings " : "",
                            (supported_features & 0x20) ? "GroupNavigation " : "",
                            (supported_features & 0x40) ? "Browsing " : "",
                            (supported_features & 0x80) ? "MultiplePlayers " : "",
                            (supported_features & 0x100) ? "CoverArt " : "");
                break;
                default:
                    found = false;
            }
            break;
        case BTSDP_HSP_SERVICE_UUID:
        case BTSDP_HSP_HS_SERVICE_UUID:
            switch (attribute) {
                case 0x302:
                    proto_tree_add_item(next_tree, hf_hsp_remote_audio_volume_control, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_GNSS_UUID:
        case BTSDP_GNSS_SERVER_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint(next_tree, hf_gnss_supported_features, tvb, offset, 2, ENC_BIG_ENDIAN, &supported_features);
                    wmem_strbuf_append_printf(info_buf, "reserved (0x%04x)", supported_features);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_PBAP_PSE_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_pbap_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN, &psm);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
                    if (!pinfo->fd->visited  && service_info)
                        save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
                    break;
                case 0x314:
                    proto_tree_add_bitmask_with_flags(next_tree, tvb, offset, hf_pbap_pse_supported_repositories, ett_btsdp_supported_features,  hfx_pbap_pse_supported_repositories, ENC_NA, BMT_NO_APPEND);
                    supported_features = tvb_get_uint8(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
                            (supported_features & 0x01) ? "LocalPhonebook " : "",
                            (supported_features & 0x02) ? "SIM " : "",
                            (supported_features & 0x04) ? "SpeedDial " : "",
                            (supported_features & 0x08) ? "Favourites " : "");
                    break;
                case 0x317:
                    proto_tree_add_bitmask_with_flags(next_tree, tvb, offset, hf_pbap_pse_supported_features, ett_btsdp_supported_features,  hfx_pbap_pse_supported_features, ENC_BIG_ENDIAN, BMT_NO_APPEND);
                    supported_features = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s%s%s%s",
                            (supported_features & 0x001) ? "Download " : "",
                            (supported_features & 0x002) ? "Browsing " : "",
                            (supported_features & 0x004) ? "DatabaseIdentifier " : "",
                            (supported_features & 0x008) ? "FolderVersionCounters " : "",
                            (supported_features & 0x010) ? "vCardSelecting " : "",
                            (supported_features & 0x020) ? "EnhancedMissedCalls " : "",
                            (supported_features & 0x040) ? "X-BT-UCIvCardProperty " : "",
                            (supported_features & 0x080) ? "X-BT-UIDvCardProperty " : "",
                            (supported_features & 0x100) ? "ContactReferencing " : "",
                            (supported_features & 0x200) ? "DefaultContactImageFormat " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_FAX_SERVICE_UUID:
            switch (attribute) {
                case 0x302:
                    proto_tree_add_item(next_tree, hf_fax_support_class_1, tvb, offset, 1, ENC_BIG_ENDIAN);
                    supported_features = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
                    break;
                case 0x303:
                    proto_tree_add_item(next_tree, hf_fax_support_class_2, tvb, offset, 1, ENC_BIG_ENDIAN);
                    supported_features = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
                    break;
                case 0x304:
                    proto_tree_add_item(next_tree, hf_fax_support_class_2_vendor, tvb, offset, 1, ENC_BIG_ENDIAN);
                    supported_features = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
                    break;
                case 0x305:
                    proto_tree_add_item(next_tree, hf_fax_support_audio_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
                    supported_features = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_FTP_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_ftp_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN, &psm);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
                    if (!pinfo->fd->visited  && service_info)
                        save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_MAP_SERVICE_UUID:
        case BTSDP_MAP_ACCESS_SRV_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_map_mas_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN, &psm);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
                    if (!pinfo->fd->visited  && service_info)
                        save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
                    break;
                case 0x315:
                    proto_tree_add_item(next_tree, hf_map_mas_instance_id, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", value, value);
                    break;
                case 0x316:
                    proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_mms, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_sms_cdma, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_sms_gsm, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_email, tvb, offset, 1, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
                            (supported_features & 0x01) ? "Email " : "",
                            (supported_features & 0x02) ? "SMS_GSM " : "",
                            (supported_features & 0x04) ? "SMS_CDMA " : "",
                            (supported_features & 0x08) ? "MMS " : "");
                    break;
                case 0x317:
                    proto_tree_add_bitmask_with_flags(next_tree, tvb, offset, hf_map_supported_features, ett_btsdp_supported_features,  hfx_map_supported_features, ENC_BIG_ENDIAN, BMT_NO_APPEND);
                    supported_features = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s",
                            (supported_features & 0x01) ? "NotificationRegistration Feature " : "",
                            (supported_features & 0x02) ? "NotificationFeature " : "",
                            (supported_features & 0x04) ? "BrowsingFeature " : "",
                            (supported_features & 0x08) ? "UploadingFeature " : "",
                            (supported_features & 0x10) ? "DeleteFeature " : "",
                            (supported_features & 0x20) ? "InstanceInformationFeature " : "",
                            (supported_features & 0x40) ? "ExtendedEventReport1.1 " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_MAP_NOTIFICATION_SRV_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_map_mns_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN, &psm);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
                    if (!pinfo->fd->visited  && service_info)
                        save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
                    break;
                case 0x317:
                    proto_tree_add_bitmask_with_flags(next_tree, tvb, offset, hf_map_supported_features, ett_btsdp_supported_features,  hfx_map_supported_features, ENC_BIG_ENDIAN, BMT_NO_APPEND);
                    supported_features = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s",
                            (supported_features & 0x01) ? "NotificationRegistration Feature " : "",
                            (supported_features & 0x02) ? "NotificationFeature " : "",
                            (supported_features & 0x04) ? "BrowsingFeature " : "",
                            (supported_features & 0x08) ? "UploadingFeature " : "",
                            (supported_features & 0x10) ? "DeleteFeature " : "",
                            (supported_features & 0x20) ? "InstanceInformationFeature " : "",
                            (supported_features & 0x40) ? "ExtendedEventReport1.1 " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_HCRP_SERVICE_UUID:
        case BTSDP_HCRP_PRINT_SERVICE_UUID:
        case BTSDP_HCRP_SCAN_SERVICE_UUID:
            switch (attribute) {
                case 0x300:
                    proto_tree_add_item_ret_string(next_tree, hf_hcrp_1284_id, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x302:
                    proto_tree_add_item_ret_string(next_tree, hf_hcrp_device_name, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x304:
                    proto_tree_add_item_ret_string(next_tree, hf_hcrp_friendly_name, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x306:
                    proto_tree_add_item_ret_string(next_tree, hf_hcrp_device_location, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_WAP_SERVICE_UUID:
        case BTSDP_WAP_CLIENT_SERVICE_UUID:
            switch (attribute) {
                case 0x306:
                    proto_tree_add_item(next_tree, hf_wap_network_address, tvb, offset, 4, ENC_BIG_ENDIAN);
                    wmem_strbuf_append(info_buf, tvb_ip_to_str(pinfo->pool, tvb, offset));
                    break;
                case 0x307:
                    proto_tree_add_item(next_tree, hf_wap_gateway, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, wap_gateway_vals, "Unknown"));
                    break;
                case 0x308:
                    proto_tree_add_item_ret_string(next_tree, hf_wap_homepage_url, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x309:
                    proto_tree_add_item(next_tree, hf_wap_stack_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, wap_stack_type_vals, "Unknown"));
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_HDP_SERVICE_UUID:
        case BTSDP_HDP_SOURCE_SERVICE_UUID:
        case BTSDP_HDP_SINK_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    i_feature = 1;
                    list_offset = offset;
                    while (list_offset - offset < size) {
                        entry_offset = get_type_length(tvb, list_offset, &entry_length);
                        feature_item = proto_tree_add_none_format(next_tree, hf_hdp_supported_features_data, tvb, entry_offset, entry_length, "Supported Feature #%u", i_feature);
                        feature_tree = proto_item_add_subtree(feature_item, ett_btsdp_supported_features);

                        dissect_data_element(feature_tree, &sub_tree, pinfo, tvb, list_offset);

                        entry_item = proto_tree_add_item(sub_tree, hf_hdp_supported_features_data_mdep_id, tvb, entry_offset, 0, ENC_NA);
                        entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_id);
                        dissect_data_element(entry_tree, &next_tree, pinfo, tvb, entry_offset);
                        new_offset = get_type_length(tvb, entry_offset, &length);
                        proto_item_set_len(entry_item, (new_offset - entry_offset) + length);
                        entry_offset = new_offset;

                        proto_tree_add_item_ret_uint8(next_tree, hf_hdp_supported_features_mdep_id, tvb, entry_offset, 1, ENC_BIG_ENDIAN, &mdep_id);
                        proto_item_append_text(entry_item, ": %u (0x%02x)", mdep_id, mdep_id);
                        entry_offset += length;

                        entry_item = proto_tree_add_item(sub_tree, hf_hdp_supported_features_data_mdep_data_type, tvb, entry_offset, 0, ENC_NA);
                        entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_data_type);

                        dissect_data_element(entry_tree, &next_tree, pinfo, tvb, entry_offset);
                        new_offset = get_type_length(tvb, entry_offset, &length);
                        proto_item_set_len(entry_item, (new_offset - entry_offset) + length);
                        entry_offset = new_offset;
                        if (service_hdp_data_exchange_specification == 0x01)
                            proto_tree_add_item(next_tree, hf_hdp_supported_features_mdep_data_type_01, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
                        else
                            proto_tree_add_item(next_tree, hf_hdp_supported_features_mdep_data_type, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
                        value = tvb_get_ntohs(tvb, entry_offset);
                        proto_item_append_text(entry_item, ": %u (0x%04x)", value, value);
                        entry_offset += length;

                        entry_item = proto_tree_add_item(sub_tree, hf_hdp_supported_features_data_mdep_role, tvb, entry_offset, 0, ENC_NA);
                        entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_role);

                        dissect_data_element(entry_tree, &next_tree, pinfo, tvb, entry_offset);
                        new_offset = get_type_length(tvb, entry_offset, &length);
                        proto_item_set_len(entry_item, (new_offset - entry_offset) + length);
                        entry_offset = new_offset;
                        proto_tree_add_item(next_tree, hf_hdp_supported_features_mdep_role, tvb, entry_offset, 1, ENC_BIG_ENDIAN);
                        value = tvb_get_uint8(tvb, entry_offset);
                        wmem_strbuf_append_printf(info_buf, "MDEP ID: %u (Role: %s) ", mdep_id, val_to_str_const(value, hdp_mdep_role_vals ,"Unknown"));
                        proto_item_append_text(entry_item, ": %s", val_to_str_const(value, hdp_mdep_role_vals ,"Unknown"));
                        entry_offset += length;

                        if (entry_length - (entry_offset - list_offset) > 0) {
                            const uint8_t* entry_str;

                            entry_item = proto_tree_add_item(sub_tree, hf_hdp_supported_features_data_mdep_description, tvb, entry_offset, entry_length, ENC_NA);
                            entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_description);

                            dissect_data_element(entry_tree, &next_tree, pinfo, tvb, entry_offset);
                            new_offset = get_type_length(tvb, entry_offset, &length);
                            proto_item_set_len(entry_item, (new_offset - entry_offset) + length);
                            entry_offset = new_offset;
                            proto_tree_add_item_ret_string(next_tree, hf_hdp_supported_features_mdep_description, tvb, entry_offset, length,
                                                            ENC_ASCII | ENC_NA, pinfo->pool, &entry_str);
                            proto_item_append_text(entry_item, ": %s", entry_str);
                            entry_offset += length;
                        }

                        list_offset = entry_offset;
                        i_feature += 1;
                    }
                    break;
                case 0x301:
                    proto_tree_add_item(next_tree, hf_hdp_data_exchange, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, hdp_data_exchange_specification_vals, "Unknown"));
                    break;
                case 0x302:
                    proto_tree_add_item(next_tree, hf_hdp_support_procedure_reserved_5_7, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hdp_support_procedure_sync_master_role, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hdp_support_procedure_clock_synchronization_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hdp_support_procedure_reconnect_acceptance, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hdp_support_procedure_reconnect_initiation, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hdp_support_procedure_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
                            (supported_features & 0x02) ? "ReconnectInitiation " : "",
                            (supported_features & 0x04) ? "ReconnectAcceptance " : "",
                            (supported_features & 0x08) ? "ClockSynchronizationProtocol " : "",
                            (supported_features & 0x10) ? "SyncMasterRole " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_PAN_GN_SERVICE_UUID:
            switch (attribute) {
                case 0x30A:
                    proto_tree_add_item(next_tree, hf_pan_sercurity_description, tvb, offset, 2, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohs(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, pan_security_description_vals, "Unknown"));
                    break;
                case 0x30D:
                case 0x200:
                    proto_tree_add_item_ret_string(next_tree, hf_pan_ipv4_subnet, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x30E:
                    proto_tree_add_item_ret_string(next_tree, hf_pan_ipv6_subnet, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_PAN_NAP_SERVICE_UUID:
            switch (attribute) {
                case 0x30A:
                    proto_tree_add_item(next_tree, hf_pan_sercurity_description, tvb, offset, 2, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohs(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, pan_security_description_vals, "Unknown"));
                    break;
                case 0x30B:
                    proto_tree_add_item(next_tree, hf_pan_net_access_type, tvb, offset, 2, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohs(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, pan_net_access_type_vals, "Unknown"));
                    break;
                case 0x30C:
                    proto_tree_add_item(next_tree, hf_pan_max_net_access_rate, tvb, offset, 4, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohl(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%08x)", value, value);
                    break;
                case 0x30D:
                case 0x200:
                    proto_tree_add_item_ret_string(next_tree, hf_pan_ipv4_subnet, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x30E:
                    proto_tree_add_item_ret_string(next_tree, hf_pan_ipv6_subnet, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_PAN_PANU_SERVICE_UUID:
            switch (attribute) {
                case 0x30A:
                    proto_tree_add_item(next_tree, hf_pan_sercurity_description, tvb, offset, 2, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohs(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, pan_security_description_vals, "Unknown"));
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_OPP_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_opp_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN, &psm);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
                    if (!pinfo->fd->visited && service_info)
                        save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
                    break;
                case 0x303:
                    list_offset = offset;
                    while (list_offset - offset < size) {
                        dissect_data_element(next_tree, &entry_tree, pinfo, tvb, list_offset);
                        list_offset = get_type_length(tvb, list_offset, &list_length);
                        proto_tree_add_item(entry_tree, hf_opp_supported_format, tvb, list_offset, 1, ENC_BIG_ENDIAN);
                        value = tvb_get_uint8(tvb, list_offset);

                        wmem_strbuf_append_printf(info_buf, "%s ", val_to_str_const(value, opp_supported_format_vals, "Unknown"));
                        list_offset += list_length;
                    }
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_DUN_SERVICE_UUID:
            switch (attribute) {
                case 0x305:
                    proto_tree_add_item(next_tree, hf_dun_support_audio_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
                    supported_features = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
                    break;
                case 0x306:
                    proto_tree_add_item_ret_string(next_tree, hf_dun_escape_sequence, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_HFP_SERVICE_UUID:
            switch (attribute) {
                case 0x311:
                    proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_wide_band_speech, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_remote_volume_control, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_voice_recognition_activation, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_cli_presentation_capability, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_call_waiting_or_three_way_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_ec_and_or_nr_function, tvb, offset, 2, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_ntohs(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s",
                            (supported_features & 0x01) ? "(EC and/or Nr Function) " : "",
                            (supported_features & 0x02) ? "(Call Waiting or Three Way Calling) " : "",
                            (supported_features & 0x04) ? "(CLI Presentation Capability) " : "",
                            (supported_features & 0x08) ? "(Voice Recognition Activation) " : "",
                            (supported_features & 0x10) ? "(Remote Volume Control) " : "",
                            (supported_features & 0x20) ? "(Wide Band Speech) " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_HFP_GW_SERVICE_UUID:
            switch (attribute) {
                case 0x301:
                    proto_tree_add_item(next_tree, hf_hfp_gw_network, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, hfp_gw_network_vals, "Unknown"));
                    break;
                case 0x311:
                    proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_wide_band_speech, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_attach_phone_number_to_voice_tag, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_inband_ring_tone_capability, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_voice_recognition_function, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_ec_and_or_nr_function, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_three_way_calling, tvb, offset, 2, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_ntohs(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s",
                            (supported_features & 0x01) ? "(Three Way Calling) " : "",
                            (supported_features & 0x02) ? "(EC and/or Nr Function) " : "",
                            (supported_features & 0x04) ? "(Voice Recognition Function) " : "",
                            (supported_features & 0x08) ? "(Inband Ring Tone Capability) " : "",
                            (supported_features & 0x10) ? "(Attach a Phone Number to a Voice Tag) " : "",
                            (supported_features & 0x20) ? "(Wide Band Speech) " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_HID_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_hid_device_release_number, tvb, offset, 2, ENC_BIG_ENDIAN, &version);
                    wmem_strbuf_append_printf(info_buf, "%x.%x.%x (0x%04x)", version >> 8, (version >> 4) & 0xF, version & 0xF, version);
                    break;
                case 0x201:
                    proto_tree_add_item_ret_uint16(next_tree, hf_hid_parser_version, tvb, offset, 2, ENC_BIG_ENDIAN, &version);
                    wmem_strbuf_append_printf(info_buf, "%x.%x.%x (0x%04x)", version >> 8, (version >> 4) & 0xF, version & 0xF, version);
                    break;
                case 0x202:
                    proto_tree_add_item(next_tree, hf_hid_device_subclass_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hid_device_subclass_subtype, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_hid_device_subclass_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%s, %s",
                            val_to_str_const(value >> 6, hid_device_subclass_type_vals, "Unknown"),
                            val_to_str_const(((value & 0x3C) >> 2) , hid_device_subclass_subtype_vals, "Unknown"));
                    break;
                case 0x203:
                    proto_tree_add_item(next_tree, hf_hid_country_code, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, val_to_str_const(value, hid_country_code_vals, "Unknown"));
                    break;
                case 0x204:
                    proto_tree_add_item(next_tree, hf_hid_virtual_cable, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x205:
                    proto_tree_add_item(next_tree, hf_hid_reconnect_initiate, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x206:
                    list_offset = offset;
                    i_feature = 1;
                    while (list_offset - offset < size) {
                        entry_item = proto_tree_add_none_format(next_tree, hf_hid_descriptor_list_descriptor_data, tvb, list_offset, size, "Descriptor #%u", i_feature);
                        entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);

                        dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
                        list_offset = get_type_length(tvb, list_offset, &entry_length);

                        dissect_data_element(sub_tree, &last_tree, pinfo, tvb, list_offset);
                        list_offset = get_type_length(tvb, list_offset, &entry_length);
                        proto_tree_add_item(last_tree, hf_hid_descriptor_list_type, tvb, list_offset, 1, ENC_BIG_ENDIAN);
                        value = tvb_get_uint8(tvb, list_offset);
                        wmem_strbuf_append(info_buf, val_to_str_const(value, descriptor_list_type_vals, "Unknown"));
                        proto_item_append_text(entry_item, ": %s", val_to_str_const(value, descriptor_list_type_vals, "Unknown"));
                        list_offset += entry_length;

                        dissect_data_element(sub_tree, &last_tree, pinfo, tvb, list_offset);
                        list_offset = get_type_length(tvb, list_offset, &entry_length);
                        proto_tree_add_item(last_tree, hf_hid_descriptor_list_descriptor, tvb, list_offset, entry_length, ENC_NA);
                        list_offset += entry_length;

                        i_feature += 1;

                        if (list_offset - offset < size)
                            wmem_strbuf_append(info_buf, ", ");
                    }
                    break;
                case 0x207:
                    list_offset = offset;
                    i_feature = 1;
                    while (list_offset - offset < size) {
                        wmem_strbuf_append(info_buf, "[");
                        entry_item = proto_tree_add_none_format(next_tree, hf_hid_lang, tvb, list_offset, size, "Language #%u", i_feature);
                        entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);

                        dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
                        list_offset = get_type_length(tvb, list_offset, &entry_length);

                        dissect_data_element(sub_tree, &last_tree, pinfo, tvb, list_offset);
                        list_offset = get_type_length(tvb, list_offset, &entry_length);
                        value = tvb_get_ntohs(tvb, list_offset);
                        wmem_strbuf_append_printf(info_buf, "Lang ID: %s", val_to_str_ext_const(value, &usb_langid_vals_ext, "Unknown"));
                        proto_item_append_text(entry_item, ": Lang ID: %s", val_to_str_ext_const(value, &usb_langid_vals_ext, "Unknown"));
                        proto_tree_add_item(last_tree, hf_sdp_lang_id, tvb, list_offset, entry_length, ENC_BIG_ENDIAN);
                        list_offset += entry_length;

                        dissect_data_element(sub_tree, &last_tree, pinfo, tvb, list_offset);
                        list_offset = get_type_length(tvb, list_offset, &entry_length);
                        value = tvb_get_ntohs(tvb, list_offset);
                        wmem_strbuf_append_printf(info_buf, ", Attribute Base: 0x%04x", value);
                        proto_item_append_text(entry_item, ", Attribute Base: 0x%04x", value);
                        proto_tree_add_item(last_tree, hf_sdp_lang_attribute_base, tvb, list_offset, 2, ENC_BIG_ENDIAN);
                        list_offset += entry_length;
                        i_feature += 1;

                        if (list_offset - offset < size)
                            wmem_strbuf_append(info_buf, "], ");
                        else
                            wmem_strbuf_append(info_buf, "]");
                    }
                    break;
                case 0x208:
                    proto_tree_add_item(next_tree, hf_hid_sdp_disable, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x209:
                    proto_tree_add_item(next_tree, hf_hid_battery_power, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x20A:
                    proto_tree_add_item(next_tree, hf_hid_remote_wake, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x20B:
                    proto_tree_add_item_ret_uint16(next_tree, hf_hid_profile_version, tvb, offset, 2, ENC_BIG_ENDIAN, &version);
                    wmem_strbuf_append_printf(info_buf, "%x.%x.%x (0x%04x)", version >> 8, (version >> 4) & 0xF, version & 0xF, version);
                    break;
                case 0x20C:
                    proto_tree_add_item_ret_uint(next_tree, hf_hid_supervision_timeout, tvb, offset, 2, ENC_BIG_ENDIAN, &value);
                    wmem_strbuf_append_printf(info_buf, "%u", value);
                    break;
                case 0x20D:
                    proto_tree_add_item(next_tree, hf_hid_normally_connectable, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x20E:
                    proto_tree_add_item(next_tree, hf_hid_boot_device, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x20F:
                    proto_tree_add_item_ret_uint(next_tree, hf_hid_ssr_host_max_latency, tvb, offset, 2, ENC_BIG_ENDIAN, &value);
                    wmem_strbuf_append_printf(info_buf, "%u", value);
                    break;
                case 0x210:
                    proto_tree_add_item_ret_uint(next_tree, hf_hid_ssr_host_min_timeout, tvb, offset, 2, ENC_BIG_ENDIAN, &value);
                    wmem_strbuf_append_printf(info_buf, "%u", value);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_BIP_SERVICE_UUID:
        case BTSDP_BIP_RESPONDER_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_bip_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN, &psm);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
                    if (!pinfo->fd->visited && service_info)
                        save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
                    break;
                case 0x310:
                    proto_tree_add_item(next_tree, hf_bip_supported_capabilities_reserved_4_7, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_capabilities_displaying, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_capabilities_printing, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_capabilities_capturing, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_capabilities_genering_imaging, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
                            (value & 0x01) ? "GeneringImaging " : "",
                            (value & 0x02) ? "Capturing " : "",
                            (value & 0x04) ? "Printing " : "",
                            (value & 0x08) ? "Displaying " : "");
                    break;
                case 0x311:
                    proto_tree_add_item(next_tree, hf_bip_supported_features_reserved_9_15, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_remote_display, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_remote_camera, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_automatic_archive, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_advanced_image_printing, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_image_pull, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_image_push_display, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_image_push_print, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_image_push_store, tvb, offset, 2, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_features_image_push, tvb, offset, 2, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohs(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s%s%s",
                            (value & 0x001) ? "ImagePush " : "",
                            (value & 0x002) ? "ImagePushStore " : "",
                            (value & 0x004) ? "ImagePushPrint " : "",
                            (value & 0x008) ? "ImagePushDisplay " : "",
                            (value & 0x010) ? "ImagePull " : "",
                            (value & 0x020) ? "AdvancedImagePrinting " : "",
                            (value & 0x040) ? "AutomatingArchive " : "",
                            (value & 0x080) ? "RemoteCamera " : "",
                            (value & 0x100) ? "RemoteDisplay " : "");
                    break;
                case 0x312:
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_17_31, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_status, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_15, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_monitoring_image, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_start_archive, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_12, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_start_print, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_delete_image, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_linked_attachment, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_linked_thumbnail, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_image, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_image_property, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_images_list, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_remote_display, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_put_linked_thumbnail, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_put_linked_attachment, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_put_image, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohl(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                            (value & 0x001) ? "GetCapabilities " : "",
                            (value & 0x002) ? "PutImage " : "",
                            (value & 0x004) ? "PutLinkedAttachment " : "",
                            (value & 0x008) ? "PutLinkedThumbnail " : "",
                            (value & 0x010) ? "RemoteDisplay " : "",
                            (value & 0x020) ? "GetImageList " : "",
                            (value & 0x040) ? "GetImageProperty " : "",
                            (value & 0x080) ? "GetImage " : "",
                            (value & 0x100) ? "GetLinkedThumbnail " : "",
                            (value & 0x200) ? "GetLinkedAttachment " : "",
                            (value & 0x400) ? "DeleteImage " : "",
                            (value & 0x800) ? "StartPrint " : "",
                            (value & 0x2000) ? "StartArchive " : "",
                            (value & 0x4000) ? "GetMonitoringImage " : "",
                            (value & 0x10000) ? "GetStatus " : "");
                    break;
                case 0x313:
                    proto_tree_add_item(next_tree, hf_bip_total_imaging_data_capacity, tvb, offset, 8, ENC_BIG_ENDIAN);
                    value_64 = tvb_get_ntoh64(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%"PRIu64, value_64);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_BIP_REF_OBJ_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_bip_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN, &psm);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
                    if (!pinfo->fd->visited && service_info)
                        save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
                    break;
                case 0x312:
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_13_31, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_partial_image, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_1_11, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohl(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%s%s",
                            (value & 0x0001) ? "GetCapabilities " : "",
                            (value & 0x1000) ? "GetPartialImage " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_BIP_AUTO_ARCH_SERVICE_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_item_ret_uint16(next_tree, hf_bip_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN, &psm);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
                    if (!pinfo->fd->visited)
                        save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
                    break;
                case 0x312:
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_11_31, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_delete_image, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_linked_attachment, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_linked_thumbnail, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_image, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_image_property, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_images_list, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_1_4, tvb, offset, 4, ENC_BIG_ENDIAN);
                    proto_tree_add_item(next_tree, hf_bip_supported_functions_get_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohl(tvb, offset);

                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s",
                            (value & 0x001) ? "GetCapabilities " : "",
                            (value & 0x020) ? "GetImageList " : "",
                            (value & 0x040) ? "GetImageProperty " : "",
                            (value & 0x080) ? "GetImage " : "",
                            (value & 0x100) ? "GetLinkedThumbnail " : "",
                            (value & 0x200) ? "GetLinkedAttachment " : "",
                            (value & 0x400) ? "DeleteImage " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_BPP_SERVICE_UUID:
        case BTSDP_BPP_STATUS_SERVICE_UUID:
        case BTSDP_BPP_DIRECT_PRINTING_SERVICE_UUID:
        case BTSDP_BPP_REFERENCE_PRINTING_SERVICE_UUID:
            switch (attribute) {
                case 0x350:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_document_formats_supported, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x352:
                    proto_tree_add_item(next_tree, hf_bpp_character_repertoires_support, tvb, offset, size, ENC_NA);
                    new_str = (const uint8_t*)tvb_bytes_to_str(pinfo->pool, tvb, offset, size);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x354:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_xhtml_print_image_formats_supported, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x356:
                    proto_tree_add_item(next_tree, hf_bpp_color_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x358:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_1284_id, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x35A:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_printer_name, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x35C:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_printer_location, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x35E:
                    proto_tree_add_item(next_tree, hf_bpp_duplex_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x360:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_media_types_supported, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x362:
                    proto_tree_add_item(next_tree, hf_bpp_max_media_width, tvb, offset, 2, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohs(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%u", value);
                    break;
                case 0x364:
                    proto_tree_add_item(next_tree, hf_bpp_max_media_length, tvb, offset, 2, ENC_BIG_ENDIAN);
                    value = tvb_get_ntohs(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%u", value);
                    break;
                case 0x366:
                    proto_tree_add_item(next_tree, hf_bpp_enhanced_layout_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x368:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_rui_formats_supported, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x370:
                    proto_tree_add_item(next_tree, hf_bpp_reference_printing_rui_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x372:
                    proto_tree_add_item(next_tree, hf_bpp_direct_printing_rui_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append(info_buf, value ? "true" : "false");
                    break;
                case 0x374:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_reference_printing_top_url, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x376:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_direct_printing_top_url, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x37A:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_device_name, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_BPP_REFLECTED_UI_SERVICE_UUID:
            switch (attribute) {
                case 0x368:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_rui_formats_supported, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                case 0x378:
                    proto_tree_add_item_ret_string(next_tree, hf_bpp_printer_admin_rui_top_url, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                    wmem_strbuf_append(info_buf, (const char*)new_str);
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_CTN_ACCESS_SERVICE_UUID:
        case BTSDP_CTN_NOTIFICATION_SERVICE_UUID:
            if (service_uuid.bt_uuid == BTSDP_CTN_NOTIFICATION_SERVICE_UUID && attribute != 0x317) {
                found = false;
                break;
            }
            switch (attribute) {
                case 0x315:
                    proto_tree_add_item(next_tree, hf_ctn_instance_id, tvb, offset, 1, ENC_NA);
                    value = tvb_get_uint8(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", value, value);

                    break;
                case 0x317:
                    proto_tree_add_bitmask(next_tree, tvb, offset, hf_ctn_supported_features, ett_btsdp_supported_features,  hfx_ctn_supported_features, ENC_BIG_ENDIAN);

                    supported_features = tvb_get_ntohl(tvb, offset);
                    wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s",
                            (supported_features & 0x01) ? "AccountManager " : "",
                            (supported_features & 0x02) ? "Notification " : "",
                            (supported_features & 0x04) ? "Browsing " : "",
                            (supported_features & 0x08) ? "Downloading " : "",
                            (supported_features & 0x10) ? "Uploading " : "",
                            (supported_features & 0x20) ? "Delete " : "",
                            (supported_features & 0x40) ? "Forward " : "");
                    break;
                default:
                    found = false;
            }
            break;
        case BTSDP_MULTI_PROFILE_UUID:
        case BTSDP_MULTI_PROFILE_SC_UUID:
            switch (attribute) {
                case 0x200:
                    proto_tree_add_bitmask(next_tree, tvb, offset, hf_mps_mpsd_scenarios, ett_btsdp_supported_features,  hfx_mps_mpsd_scenarios, ENC_BIG_ENDIAN);

                    break;
                case 0x201:
                    proto_tree_add_bitmask(next_tree, tvb, offset, hf_mps_mpmd_scenarios, ett_btsdp_supported_features,  hfx_mps_mpmd_scenarios, ENC_BIG_ENDIAN);

                    break;
                case 0x202:
                    proto_tree_add_bitmask(next_tree, tvb, offset, hf_mps_supported_profile_and_protocol_dependency, ett_btsdp_supported_features,  hfx_mps_supported_profile_and_protocol_dependency, ENC_BIG_ENDIAN);

                    break;
                default:
                    found = false;
            }
            break;
        default:
            found = false;
    }

    if  (!found) {
        found = true;
        switch (attribute) {
        case 0x000:
            proto_tree_add_item(next_tree, hf_sdp_service_record_handle, tvb, offset, 4, ENC_BIG_ENDIAN);
            value = tvb_get_ntohl(tvb, offset);
            wmem_strbuf_append_printf(info_buf, "0x%08x (%u)", value, value);
            break;
        case 0x001:
            list_offset = offset;
            while (list_offset - offset < size) {
                dissect_data_element(next_tree, &entry_tree, pinfo, tvb, list_offset);
                list_offset = get_type_length(tvb, list_offset, &list_length);

                dissect_uuid(entry_tree, pinfo, tvb, list_offset, list_length, &uuid);

                wmem_strbuf_append(info_buf, print_bluetooth_uuid(&uuid));
                list_offset += list_length;

                if (list_offset - offset < size)
                    wmem_strbuf_append(info_buf, " -> ");
            }
            break;
        case 0x002:
            proto_tree_add_item(next_tree, hf_sdp_service_record_state, tvb, offset, 4, ENC_BIG_ENDIAN);
            value = tvb_get_ntohl(tvb, offset);
            wmem_strbuf_append_printf(info_buf, "0x%08x (%u)", value, value);
            break;
        case 0x003:
            dissect_uuid(next_tree, pinfo, tvb, offset, size, &uuid);
            wmem_strbuf_append(info_buf, print_bluetooth_uuid(&uuid));
            break;
        case 0x004:
            protocol_order = 0;
            dissect_protocol_descriptor_list(next_tree, tvb, pinfo,
                    offset, size, info_buf, service_info, &protocol_order);
            break;
        case 0x005:
            list_offset = offset;
            while (list_offset - offset < size) {
                dissect_data_element(next_tree, &entry_tree, pinfo, tvb, list_offset);
                list_offset = get_type_length(tvb, list_offset, &list_length);

                dissect_uuid(entry_tree, pinfo, tvb, list_offset, list_length, &uuid);

                wmem_strbuf_append(info_buf, print_bluetooth_uuid(&uuid));
                list_offset += list_length;

                if (list_offset - offset < size)
                    wmem_strbuf_append(info_buf, ", ");
            }
            break;
        case 0x006:
            list_offset = offset;
            i_feature = 1;
            while (list_offset - offset < size) {
                wmem_strbuf_append(info_buf, "(");
                entry_item = proto_tree_add_none_format(next_tree, hf_sdp_lang, tvb, list_offset, size, "Language #%u", i_feature);
                entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);

                dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
                list_offset = get_type_length(tvb, list_offset, &entry_length);
                proto_tree_add_item_ret_string(sub_tree, hf_sdp_lang_code, tvb, list_offset, entry_length, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
                wmem_strbuf_append_printf(info_buf, "Lang: %s", (const char*)new_str);
                proto_item_append_text(entry_item, ": Lang: %s", (const char*)new_str);
                list_offset += entry_length;

                dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
                list_offset = get_type_length(tvb, list_offset, &entry_length);
                value = tvb_get_ntohs(tvb, list_offset);
                wmem_strbuf_append_printf(info_buf, ", Encoding: %s", val_to_str_ext_const(value, &mibenum_vals_character_sets_ext, "Unknown"));
                proto_item_append_text(entry_item, ", Encoding: %s", val_to_str_ext_const(value, &mibenum_vals_character_sets_ext, "Unknown"));
                proto_tree_add_item(sub_tree, hf_sdp_lang_encoding, tvb, list_offset, 2, ENC_BIG_ENDIAN);
                list_offset += entry_length;

                dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
                list_offset = get_type_length(tvb, list_offset, &entry_length);
                value = tvb_get_ntohs(tvb, list_offset);
                wmem_strbuf_append_printf(info_buf, ", Attribute Base: 0x%04x", value);
                proto_item_append_text(entry_item, ", Attribute Base: 0x%04x", value);
                proto_tree_add_item(sub_tree, hf_sdp_lang_attribute_base, tvb, list_offset, 2, ENC_BIG_ENDIAN);
                list_offset += entry_length;
                i_feature += 1;

                if (list_offset - offset < size)
                    wmem_strbuf_append(info_buf, "), ");
                else
                    wmem_strbuf_append(info_buf, ")");
            }
            break;
        case 0x007:
            proto_tree_add_item(next_tree, hf_sdp_service_info_time_to_live, tvb, offset, 4, ENC_BIG_ENDIAN);
            value = tvb_get_ntohl(tvb, offset);
            wmem_strbuf_append_printf(info_buf, "%u (0x%08x)", value, value);
            break;
        case 0x008:
            proto_tree_add_item(next_tree, hf_sdp_service_availability, tvb, offset, 1, ENC_BIG_ENDIAN);
            value = tvb_get_uint8(tvb, offset);
            wmem_strbuf_append_printf(info_buf, "0x%02x (%u)", value, value);
            break;
        case 0x009:
            list_offset = offset;
            i_protocol = 1;
            while (list_offset - offset < size) {
                entry_offset = get_type_length(tvb, list_offset, &entry_length);
                dissect_data_element(next_tree, &sub_tree, pinfo, tvb, list_offset);
                entry_item = proto_tree_add_none_format(sub_tree, hf_profile_descriptor_list, tvb, entry_offset, entry_length, "Profile Descriptor List #%u", i_protocol);
                entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);

                dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
                entry_offset = get_type_length(tvb, entry_offset, &entry_length);

                dissect_uuid(sub_tree, pinfo, tvb, entry_offset, entry_length, &uuid);

                uuid_str = print_bluetooth_uuid(&uuid);
                wmem_strbuf_append(info_buf, uuid_str);
                proto_item_append_text(entry_item, ": %s", uuid_str);

                entry_offset += entry_length;

                dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
                entry_offset = get_type_length(tvb, entry_offset, &entry_length);
                value = tvb_get_ntohs(tvb, entry_offset);

                wmem_strbuf_append_printf(info_buf, " %x.%x", value >> 8, value & 0xFF);
                proto_item_append_text(entry_item, ", Version %x.%x", value >> 8, value & 0xFF);
                proto_tree_add_item(sub_tree, hf_sdp_protocol_version, tvb, entry_offset, 2, ENC_BIG_ENDIAN);

                entry_offset += entry_length;

                list_offset = entry_offset;

                if (list_offset - offset < size)
                    wmem_strbuf_append(info_buf, ", ");
                i_protocol += 1;
            }
            break;
        case 0x00A:
            proto_tree_add_item_ret_string(next_tree, hf_sdp_service_documentation_url, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
            wmem_strbuf_append(info_buf, (const char*)new_str);
            break;
        case 0x00B:
            proto_tree_add_item_ret_string(next_tree, hf_sdp_service_client_executable_url, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
            wmem_strbuf_append(info_buf, (const char*)new_str);
            break;
        case 0x00C:
            proto_tree_add_item_ret_string(next_tree, hf_sdp_service_icon_url, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
            wmem_strbuf_append(info_buf, (const char*)new_str);
            break;
        case 0x00D:
            protocol_order = 1;
            list_offset = offset;
            i_protocol = 1;
            while (list_offset - offset < size) {
                entry_offset = get_type_length(tvb, list_offset, &entry_length);
                dissect_data_element(next_tree, &sub_tree, pinfo, tvb, list_offset);
                entry_item = proto_tree_add_none_format(sub_tree, hf_profile_descriptor_list, tvb, entry_offset, entry_length, "Protocol Descriptor List #%u", i_protocol);
                entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);

                list_offset = get_type_length(tvb, list_offset, &list_length);

                wmem_strbuf_append(info_buf, "[");
                dissect_protocol_descriptor_list(entry_tree, tvb,
                        pinfo, list_offset, list_length, info_buf,
                        service_info, &protocol_order);

                list_offset += list_length;

                wmem_strbuf_append(info_buf, "] ");
                i_protocol += 1;
            }
            break;
        case 0x100:
            proto_tree_add_item_ret_string(next_tree, hf_sdp_service_name, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
            wmem_strbuf_append(info_buf, (const char*)new_str);
            break;
        case 0x101:
            proto_tree_add_item_ret_string(next_tree, hf_sdp_service_description, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
            wmem_strbuf_append(info_buf, (const char*)new_str);
            break;
        case 0x102:
            proto_tree_add_item_ret_string(next_tree, hf_sdp_service_provider_name, tvb, offset, size, ENC_ASCII | ENC_NA, pinfo->pool, &new_str);
            wmem_strbuf_append(info_buf, (const char*)new_str);
            break;
        default:
            found = false;
        }
    }

    if (!found) switch (type) {
    case 0:
        proto_tree_add_item(next_tree, hf_data_element_value_nil, tvb, offset, size, ENC_NA);
        wmem_strbuf_append(info_buf, "Nil ");
        break;
    case 1: {
        uint32_t val = get_uint_by_size(tvb, offset, size_index);
        proto_tree_add_item(next_tree, hf_data_element_value_unsigned_int, tvb, offset, size, ENC_BIG_ENDIAN);
        wmem_strbuf_append_printf(info_buf, "%u ", val);
        break;
    }
    case 2: {
        uint32_t val = get_int_by_size(tvb, offset, size_index);
        proto_tree_add_item(next_tree, hf_data_element_value_signed_int, tvb, offset, size, ENC_BIG_ENDIAN);
        wmem_strbuf_append_printf(info_buf, "%d ", val);
        break;
    }
    case 3:
        dissect_uuid(next_tree, pinfo, tvb, offset, size, &uuid);
        wmem_strbuf_append_printf(info_buf, ": %s", print_bluetooth_uuid(&uuid));
        break;
    case 8: /* fall through */
    case 4: {
        const uint8_t *ptr;

        proto_tree_add_item_ret_string(next_tree, (type == 8) ? hf_data_element_value_url : hf_data_element_value_string, tvb, offset, size, ENC_NA | ENC_ASCII, pinfo->pool, &ptr);
        wmem_strbuf_append_printf(info_buf, "%s ", ptr);
        break;
    }
    case 5: {
        uint8_t var = tvb_get_uint8(tvb, offset);

        proto_tree_add_item(next_tree, hf_data_element_value_boolean, tvb, offset, size, ENC_BIG_ENDIAN);
        wmem_strbuf_append_printf(info_buf, "%s ", var ? "true" : "false");
        break;
    }
    case 6: /* Data Element sequence */
    case 7: /* Data Element alternative */ {
        proto_tree    *st;
        proto_item    *ti;
        int            bytes_to_go = size;
        int            first       = 1;
        wmem_strbuf_t *substr;
        tvbuff_t      *next_tvb = tvb_new_subset_length(tvb, offset, size);
        int            next_offset = 0;

        ti = proto_tree_add_item(next_tree, (type == 6) ? hf_data_element_value_sequence : hf_data_element_value_alternative,
                tvb, offset, size, ENC_NA);
        st = proto_item_add_subtree(ti, ett_btsdp_des);

        wmem_strbuf_append(info_buf, "{ ");

        increment_dissection_depth(pinfo);
        while (bytes_to_go > 0) {
            if (!first) {
                wmem_strbuf_append(info_buf, ", ");
            } else {
                first = 0;
            }

            size = dissect_sdp_type(st, pinfo, next_tvb, next_offset,
                    attribute, service_uuid,
                    service_did_vendor_id, service_did_vendor_id_source,
                    service_hdp_data_exchange_specification, service_info, &substr);
            if (size < 1) {
                break;
            }
            wmem_strbuf_append_printf(info_buf, "%s ", wmem_strbuf_finalize(substr));
            next_offset += size;
            bytes_to_go -= size;
        }
        decrement_dissection_depth(pinfo);

        wmem_strbuf_append(info_buf, "} ");
        break;
    }
    }

    return new_offset - start_offset;
}


static int
dissect_sdp_service_attribute(proto_tree *tree, tvbuff_t *tvb, unsigned offset,
        packet_info *pinfo, bluetooth_uuid_t uuid, unsigned service_offset,
        service_info_t  *service_info, unsigned number_of_attributes, bool attribute_only)
{
    proto_tree          *attribute_tree;
    proto_item          *attribute_item;
    proto_tree          *attribute_id_tree;
    proto_item          *attribute_id_item;
    proto_tree          *attribute_value_tree;
    proto_item          *attribute_value_item;
    proto_tree          *next_tree;
    unsigned            size = 0;
    const char          *attribute_name;
    wmem_strbuf_t       *attribute_value = NULL;
    uint16_t             id;
    int                  service_did_vendor_id = -1;
    int                  service_did_vendor_id_source = -1;
    int                  service_hdp_data_exchange_specification = -1;
    int                  hfx_attribute_id = hf_service_attribute_id_generic;
    const value_string  *name_vals = NULL;
    const char          *profile_specific = "";
    unsigned             new_offset;
    unsigned             old_offset;
    uint8_t              type;

    type = tvb_get_uint8(tvb, offset);
    id = tvb_get_ntohs(tvb, offset + 1);

    switch (uuid.bt_uuid) {
        case BTSDP_DID_SERVICE_UUID:
            name_vals = vs_did_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_did;
            profile_specific = "(DID) ";

            if (number_of_attributes > 1) {
                service_did_vendor_id_source = findUintAttribute(tvb, service_offset, number_of_attributes, 0x205);
                service_did_vendor_id = findUintAttribute(tvb, service_offset, number_of_attributes, 0x201);
            }
            break;
        case BTSDP_HID_SERVICE_UUID:
            name_vals = vs_hid_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_hid;
            profile_specific = "(HID) ";
            break;
        case BTSDP_SYNC_SERVICE_UUID:
            name_vals = vs_synch_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_synch;
            profile_specific = "(SYNCH) ";
            break;
        case BTSDP_PBAP_PSE_SERVICE_UUID:
        case BTSDP_PBAP_SERVICE_UUID:
            name_vals = vs_pbap_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_pbap;
            profile_specific = "(PBAP) ";
            break;
        case BTSDP_PAN_NAP_SERVICE_UUID:
            name_vals = vs_pan_nap_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_pan_nap;
            profile_specific = "(PAN NAP) ";
            break;
        case BTSDP_PAN_GN_SERVICE_UUID:
            name_vals = vs_pan_gn_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_pan_gn;
            profile_specific = "(PAN GN) ";
            break;
        case BTSDP_PAN_PANU_SERVICE_UUID:
            name_vals = vs_pan_panu_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_pan_panu;
            profile_specific = "(PAN PANU) ";
            break;
        case BTSDP_OPP_SERVICE_UUID:
            name_vals = vs_opp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_opp;
            profile_specific = "(OPP) ";
            break;
        case BTSDP_MAP_SERVICE_UUID:
        case BTSDP_MAP_ACCESS_SRV_SERVICE_UUID:
            name_vals = vs_map_mas_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_map_mas;
            profile_specific = "(MAP MAS) ";
            break;
        case BTSDP_MAP_NOTIFICATION_SRV_SERVICE_UUID:
            name_vals = vs_map_mns_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_map_mns;
            profile_specific = "(MAP MNS) ";
            break;
        case BTSDP_WAP_SERVICE_UUID:
        case BTSDP_WAP_CLIENT_SERVICE_UUID:
            name_vals = vs_wap_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_wap;
            profile_specific = "(WAP) ";
            break;
        case BTSDP_HDP_SERVICE_UUID:
        case BTSDP_HDP_SOURCE_SERVICE_UUID:
        case BTSDP_HDP_SINK_SERVICE_UUID:
            name_vals = vs_hdp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_hdp;
            profile_specific = "(HDP) ";

            if (number_of_attributes > 1) {
                service_hdp_data_exchange_specification = findUintAttribute(tvb, service_offset, number_of_attributes, 0x301);
            }
            break;
        case BTSDP_HSP_SERVICE_UUID:
        case BTSDP_HSP_HS_SERVICE_UUID:
            name_vals = vs_hsp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_hsp;
            profile_specific = "(HSP) ";
            break;
        case BTSDP_HCRP_SERVICE_UUID:
        case BTSDP_HCRP_PRINT_SERVICE_UUID:
        case BTSDP_HCRP_SCAN_SERVICE_UUID:
            name_vals = vs_hcrp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_hcrp;
            profile_specific = "(HCRP) ";
            break;
        case BTSDP_HFP_SERVICE_UUID:
            name_vals = vs_hfp_gw_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_hfp_hf;
            profile_specific = "(HFP HS) ";
            break;
        case BTSDP_HFP_GW_SERVICE_UUID:
            name_vals = vs_hfp_ag_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_hfp_ag;
            profile_specific = "(HFP AG) ";
            break;
        case BTSDP_GNSS_UUID:
        case BTSDP_GNSS_SERVER_UUID:
            name_vals = vs_gnss_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_gnss;
            profile_specific = "(GNSS) ";
            break;
        case BTSDP_FTP_SERVICE_UUID:
            name_vals = vs_ftp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_ftp;
            profile_specific = "(FTP) ";
            break;
        case BTSDP_FAX_SERVICE_UUID:
            name_vals = vs_fax_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_fax;
            profile_specific = "(FAX) ";
            break;
        case BTSDP_CTP_SERVICE_UUID:
            name_vals = vs_ctp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_ctp;
            profile_specific = "(CTP) ";
            break;
        case BTSDP_A2DP_SOURCE_SERVICE_UUID:
        case BTSDP_A2DP_SINK_SERVICE_UUID:
        case BTSDP_A2DP_DISTRIBUTION_SERVICE_UUID:
            name_vals = vs_a2dp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_a2dp;
            profile_specific = "(A2DP) ";
            break;
        case BTSDP_AVRCP_TG_SERVICE_UUID:
        case BTSDP_AVRCP_SERVICE_UUID:
        case BTSDP_AVRCP_CT_SERVICE_UUID:
            name_vals = vs_avrcp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_avrcp;
            profile_specific = "(AVRCP) ";
            break;
        case BTSDP_BIP_SERVICE_UUID:
        case BTSDP_BIP_RESPONDER_SERVICE_UUID:
            name_vals = vs_bip_imaging_responder_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_bip_imaging_responder;
            profile_specific = "(BIP IR) ";
            break;
        case BTSDP_BIP_AUTO_ARCH_SERVICE_UUID:
            name_vals = vs_bip_imaging_other_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_bip_imaging_other;
            profile_specific = "(BIP IAA) ";
            break;
        case BTSDP_BIP_REF_OBJ_SERVICE_UUID:
            name_vals = vs_bip_imaging_other_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_bip_imaging_other;
            profile_specific = "(BIP IRO) ";
            break;
        case BTSDP_BPP_SERVICE_UUID:
        case BTSDP_BPP_STATUS_SERVICE_UUID:
        case BTSDP_BPP_DIRECT_PRINTING_SERVICE_UUID:
        case BTSDP_BPP_REFERENCE_PRINTING_SERVICE_UUID:
            name_vals = vs_bpp_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_bpp;
            profile_specific = "(BPP) ";
            break;
        case BTSDP_BPP_REFLECTED_UI_SERVICE_UUID:
            name_vals = vs_bpp_reflected_ui_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_bpp_rui;
            profile_specific = "(BPP RUI) ";
            break;
        case BTSDP_DUN_SERVICE_UUID:
            name_vals = vs_dun_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_dun;
            profile_specific = "(DUN) ";
            break;
        case BTSDP_CTN_ACCESS_SERVICE_UUID:
            name_vals = vs_ctn_as_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_ctn_as;
            profile_specific = "(CTN AS) ";
            break;
        case BTSDP_CTN_NOTIFICATION_SERVICE_UUID:
            name_vals = vs_ctn_ns_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_ctn_ns;
            profile_specific = "(CTN NS) ";
            break;
        case BTSDP_MULTI_PROFILE_UUID:
        case BTSDP_MULTI_PROFILE_SC_UUID:
            name_vals = vs_mps_attribute_id;
            hfx_attribute_id = hf_service_attribute_id_mps;
            profile_specific = "(MPS) ";
            break;
    }

    if (name_vals && try_val_to_str(id, name_vals)) {
        attribute_name = val_to_str_const(id, name_vals, "Unknown");
    } else {
        attribute_name = val_to_str_const(id, vs_general_attribute_id, "Unknown");
        profile_specific = "";
        hfx_attribute_id = hf_service_attribute_id_generic;
    }

    if (!attribute_only) {
        attribute_item = proto_tree_add_none_format(tree, hf_service_attribute, tvb, offset, tvb_reported_length_remaining(tvb, offset),
                        "Service Attribute: %s%s (0x%x)", profile_specific, attribute_name, id);
        attribute_tree = proto_item_add_subtree(attribute_item, ett_btsdp_attribute);
    } else {
        attribute_tree = tree;
    }

    if (attribute_only && type == 0x0a) {
        dissect_data_element(attribute_tree, &next_tree, pinfo, tvb, offset);
        offset += 1;

        attribute_id_item = proto_tree_add_item(next_tree, hf_attribute_id_range, tvb, offset, 4, ENC_BIG_ENDIAN);
        attribute_id_tree = proto_item_add_subtree(attribute_id_item, ett_btsdp_attribute_id);

        col_append_fstr(pinfo->cinfo, COL_INFO, "Attribute Range (0x%04x - 0x%04x) ",
                            tvb_get_ntohs(tvb, offset), tvb_get_ntohs(tvb, offset + 2));

        proto_tree_add_item(attribute_id_tree, hf_attribute_id_range_from, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        proto_tree_add_item(attribute_id_tree, hf_attribute_id_range_to, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
    } else {
        attribute_id_item = proto_tree_add_none_format(attribute_tree, hf_service_attribute_id, tvb, offset, 3, "Attribute ID: %s", attribute_name);
        attribute_id_tree = proto_item_add_subtree(attribute_id_item, ett_btsdp_attribute_id);

        new_offset = dissect_data_element(attribute_id_tree, &next_tree, pinfo, tvb, offset);
        proto_tree_add_item(next_tree, hfx_attribute_id, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
        offset = new_offset;

        if (!attribute_only){
            attribute_value_item = proto_tree_add_item(attribute_tree, hf_service_attribute_value, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
            attribute_value_tree = proto_item_add_subtree(attribute_value_item, ett_btsdp_attribute_value);

            dissect_sdp_type(attribute_value_tree, pinfo, tvb, offset, id, uuid,
                    service_did_vendor_id, service_did_vendor_id_source,
                    service_hdp_data_exchange_specification, service_info,
                    &attribute_value);
            old_offset = offset;
            offset = get_type_length(tvb, offset, &size);
            proto_item_append_text(attribute_item, ", value = %s", wmem_strbuf_get_str(attribute_value));

            proto_item_set_len(attribute_item, 3 + size + (offset - old_offset));
            proto_item_set_len(attribute_value_item, size + (offset - old_offset));
        } else {
            proto_item_append_text(attribute_id_item, " %s", profile_specific);
            col_append_fstr(pinfo->cinfo, COL_INFO, "[%s%s 0x%04x] ", profile_specific, attribute_name, id);
        }
    }

    return offset + size;
}


static unsigned
dissect_attribute_id_list(proto_tree *tree, tvbuff_t *tvb, unsigned offset,
        packet_info *pinfo, bluetooth_uuid_t *uuid)
{
    proto_item  *list_item;
    proto_tree  *list_tree;
    proto_tree  *sub_tree;
    unsigned     start_offset;
    unsigned     previous_offset;
    unsigned     service_offset;
    unsigned     bytes_to_go;
    bluetooth_uuid_t empty_uuid;

    if (!uuid)
        memset(&empty_uuid, 0, sizeof(bluetooth_uuid_t));

    start_offset = offset;
    list_item = proto_tree_add_item(tree, hf_attribute_id_list, tvb, offset, 0, ENC_NA);
    list_tree = proto_item_add_subtree(list_item, ett_btsdp_attribute_idlist);

    dissect_data_element(list_tree, &sub_tree, pinfo, tvb, offset);

    offset = get_type_length(tvb, offset, &bytes_to_go);
    service_offset = offset;
    proto_item_set_len(list_item, offset - start_offset + bytes_to_go);

    previous_offset = offset;
    while (bytes_to_go > 0) {
        offset = dissect_sdp_service_attribute(sub_tree, tvb, offset, pinfo, (uuid) ? *uuid : empty_uuid, service_offset, NULL, 1, true);
        bytes_to_go -= offset - previous_offset;
        previous_offset = offset;
    }

    return offset - start_offset;
}


static unsigned
dissect_sdp_error_response(proto_tree *tree, tvbuff_t *tvb, unsigned offset)
{
    proto_tree_add_item(tree, hf_error_code, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    return offset;
}


static unsigned
dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, unsigned offset,
        packet_info *pinfo, bluetooth_uuid_t *service_uuid, btl2cap_data_t *l2cap_data)
{
    proto_item      *list_item;
    proto_tree      *list_tree;
    proto_tree      *next_tree;
    unsigned         start_offset = offset;
    unsigned         search_offset;
    unsigned         search_length;
    unsigned         len;
    unsigned         number_of_attributes;
    uint16_t         attribute;
    unsigned         element_length;
    unsigned         new_offset;
    unsigned         service_offset;
    bluetooth_uuid_t uuid;
    wmem_tree_key_t  key[10];
    uint32_t         k_interface_id;
    uint32_t         k_adapter_id;
    uint32_t         k_sdp_psm;
    uint32_t         k_direction;
    uint32_t         k_bd_addr_oui;
    uint32_t         k_bd_addr_id;
    uint32_t         k_service_type;
    uint32_t         k_service_channel;
    uint32_t         k_frame_number;
    service_info_t  *service_info;
    wmem_array_t    *uuid_array;

    uuid_array = wmem_array_new(pinfo->pool, sizeof(bluetooth_uuid_t));

    offset = get_type_length(tvb, offset, &len);
    memset(&uuid, 0, sizeof(bluetooth_uuid_t));

    list_item = proto_tree_add_item(tree, hf_attribute_list, tvb,
            start_offset, len + (offset - start_offset), ENC_NA);
    list_tree = proto_item_add_subtree(list_item, ett_btsdp_attribute);
    dissect_data_element(list_tree, &next_tree, pinfo, tvb, start_offset);

    /* search for main service uuid */
    search_offset = offset;
    number_of_attributes = 0;

    while ((search_offset - start_offset) < len) {
        search_offset = get_type_length(tvb, search_offset, &search_length);
        attribute = tvb_get_ntohs(tvb, search_offset);

        search_offset += search_length;
        search_offset = get_type_length(tvb, search_offset, &search_length);

        if (attribute == 0x01) {
            new_offset = 0;
            while (new_offset <= search_offset) {
                new_offset = get_type_length(tvb, search_offset, &element_length);
                dissect_uuid(NULL, pinfo, tvb, new_offset, element_length, &uuid);
                wmem_array_append_one(uuid_array, uuid);
                new_offset += element_length;
            }
        }

        search_offset += search_length;
        number_of_attributes += 1;
    }

    uuid = get_specified_uuid(pinfo->pool, uuid_array);
    if (uuid.size == 0 && service_uuid)
        uuid = *service_uuid;

    if (!pinfo->fd->visited) {
        service_info = (service_info_t *) wmem_new(wmem_file_scope(), service_info_t);
        service_info->interface_id   = l2cap_data->interface_id;
        service_info->adapter_id     = l2cap_data->adapter_id;
        service_info->sdp_psm        = l2cap_data->psm;
        service_info->direction      = pinfo->p2p_dir;
        if (service_info->direction == P2P_DIR_RECV) {
            service_info->bd_addr_oui = l2cap_data->remote_bd_addr_oui;
            service_info->bd_addr_id  = l2cap_data->remote_bd_addr_id;
        } else {
            service_info->bd_addr_oui = 0;
            service_info->bd_addr_id  = 0;
        }

        service_info->uuid           = uuid;

        service_info->type           = 0;
        service_info->channel        = 0;
        service_info->protocol_order = 0;
        service_info->protocol       = -1;
        service_info->parent_info    = NULL;
    } else {
        service_info = NULL;
    }

    service_offset = offset;
    while ((offset - start_offset) < len) {
        offset = dissect_sdp_service_attribute(next_tree, tvb, offset, pinfo,
                uuid, service_offset, service_info, number_of_attributes, false);
    }

    if (!pinfo->fd->visited && service_info) {
        k_interface_id    = l2cap_data->interface_id;
        k_adapter_id      = l2cap_data->adapter_id;
        k_sdp_psm         = l2cap_data->psm;
        k_direction       = service_info->direction;
        k_bd_addr_oui     = service_info->bd_addr_oui;
        k_bd_addr_id      = service_info->bd_addr_id;
        k_service_type    = service_info->type;
        k_service_channel = service_info->channel;
        k_frame_number    = pinfo->num;

        key[0].length = 1;
        key[0].key = &k_interface_id;
        key[1].length = 1;
        key[1].key = &k_adapter_id;
        key[2].length = 1;
        key[2].key = &k_sdp_psm;
        key[3].length = 1;
        key[3].key = &k_direction;
        key[4].length = 1;
        key[4].key = &k_bd_addr_oui;
        key[5].length = 1;
        key[5].key = &k_bd_addr_id;
        key[6].length = 1;
        key[6].key = &k_service_type;
        key[7].length = 1;
        key[7].key = &k_service_channel;
        key[8].length = 1;
        key[8].key = &k_frame_number;
        key[9].length = 0;
        key[9].key = NULL;

        wmem_tree_insert32_array(service_infos, key, service_info);
    }

    proto_item_set_len(list_item, offset - start_offset);

    if (uuid.size)
        proto_item_append_text(list_tree, " [count = %2u] (%s%s)",
                number_of_attributes, (uuid.bt_uuid) ? "" : "CustomUUID: ", print_bluetooth_uuid(&uuid));
    else
        proto_item_append_text(list_tree, " [count = %2u]",
                number_of_attributes);

    return offset;
}


static unsigned
dissect_sdp_service_attribute_list_array(proto_tree *tree, tvbuff_t *tvb,
    unsigned offset, packet_info *pinfo, unsigned attribute_list_byte_count,
        bluetooth_uuid_t *service_uuid, btl2cap_data_t *l2cap_data)
{
    proto_item   *lists_item;
    proto_tree   *lists_tree;
    proto_tree   *next_tree;
    unsigned      start_offset;
    unsigned      len;
    unsigned      number_of_attributes;

    start_offset = offset;

    offset = get_type_length(tvb, offset, &len);

    lists_item = proto_tree_add_item(tree, hf_attribute_lists, tvb, start_offset,
            attribute_list_byte_count, ENC_NA);
    lists_tree = proto_item_add_subtree(lists_item, ett_btsdp_attribute);
    dissect_data_element(lists_tree, &next_tree, pinfo, tvb, start_offset);

    number_of_attributes = 0;

    while (offset - start_offset < attribute_list_byte_count) {
        number_of_attributes += 1;

        offset = dissect_sdp_service_attribute_list(next_tree, tvb, offset,
                pinfo, service_uuid, l2cap_data);
    }

    proto_item_append_text(lists_tree, " [count = %2u]", number_of_attributes);

    return offset;
}


static unsigned
dissect_sdp_service_search_request(proto_tree *tree, tvbuff_t *tvb, unsigned offset,
        packet_info *pinfo, uint16_t tid, btl2cap_data_t *l2cap_data)
{
    unsigned     start_offset;
    unsigned     bytes_to_go;
    unsigned     size;
    proto_item   *ti;
    proto_tree   *st;
    proto_tree   *sub_tree = NULL;
    bluetooth_uuid_t empty_uuid;
    wmem_array_t *uuid_array = NULL;

    start_offset = offset;
    memset(&empty_uuid, 0, sizeof(bluetooth_uuid_t));
    if (!pinfo->fd->visited)
        uuid_array = wmem_array_new(wmem_file_scope(), sizeof(bluetooth_uuid_t));

    ti = proto_tree_add_item(tree, hf_service_search_pattern, tvb, offset, 0, ENC_NA);
    st = proto_item_add_subtree(ti, ett_btsdp_service_search_pattern);

    dissect_data_element(st, &sub_tree, pinfo, tvb, offset);
    offset = get_type_length(tvb, offset, &bytes_to_go);
    proto_item_set_len(ti, offset - start_offset + bytes_to_go);

    while (bytes_to_go > 0) {
        wmem_strbuf_t  *str = NULL;
        unsigned        entry_offset;
        unsigned        entry_size;
        bluetooth_uuid_t uuid;

        size = dissect_sdp_type(sub_tree, pinfo, tvb, offset, -1, empty_uuid, 0, 0, -1, NULL, &str);

        entry_offset = get_type_length(tvb, offset, &entry_size);
        dissect_uuid(NULL, pinfo, tvb, entry_offset, entry_size, &uuid);
        if (uuid_array)
            wmem_array_append_one(uuid_array, uuid);

        proto_item_append_text(ti, " %s", wmem_strbuf_get_str(str));
        col_append_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(str));

        if (size < 1)
            break;

        offset      += size;
        bytes_to_go -= size;
    }

    proto_tree_add_item(tree, hf_maximum_service_record_count, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    reassemble_continuation_state(tvb, pinfo, offset, tid, true,
            0, 0, PDU_TYPE_SERVICE_SEARCH, NULL, NULL, NULL, &uuid_array, NULL, l2cap_data);

    offset = dissect_continuation_state(tvb, tree, pinfo, offset);

    return offset;
}


static unsigned
dissect_sdp_service_search_response(proto_tree *tree, tvbuff_t *tvb,
        unsigned offset, packet_info *pinfo, uint16_t tid, btl2cap_data_t *l2cap_data)
{
    proto_tree   *st;
    proto_item   *ti;
    uint16_t      current_count;
    bool          is_first;
    bool          is_continued;
    tvbuff_t     *new_tvb;
    unsigned      i_record;
    wmem_array_t *uuid_array = NULL;
    wmem_array_t *record_handle_array = NULL;

    proto_tree_add_item(tree, hf_ssr_total_count, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    proto_tree_add_item_ret_uint16(tree, hf_ssr_current_count, tvb, offset, 2, ENC_BIG_ENDIAN, &current_count);
    offset += 2;

    ti = proto_tree_add_none_format(tree, hf_service_record_handle_list, tvb, offset,
                 current_count * 4, "Service Record Handle List [count = %u]", current_count);
    st = proto_item_add_subtree(ti, ett_btsdp_ssr);

    if (!pinfo->fd->visited)
        record_handle_array = wmem_array_new(pinfo->pool, sizeof(uint32_t));

    while (current_count > 0) {
        proto_tree_add_item(st, hf_sdp_service_record_handle, tvb, offset, 4, ENC_BIG_ENDIAN);

        if (record_handle_array) {
            uint32_t value;

            value = tvb_get_ntohl(tvb, offset);
            wmem_array_append_one(record_handle_array, value);
        }

        offset += 4;
        current_count -= 1;
    }

    reassemble_continuation_state(tvb, pinfo, offset, tid, false,
            offset - current_count * 4, current_count * 4, PDU_TYPE_SERVICE_SEARCH,
            &new_tvb, &is_first, &is_continued, &uuid_array, NULL, l2cap_data);

    if (is_continued)
        col_append_str(pinfo->cinfo, COL_INFO, "(fragment)");

    if (!pinfo->fd->visited) {
        record_handle_service_t  *record_handle_service;
        wmem_tree_key_t           key[7];
        uint32_t                  k_interface_id;
        uint32_t                  k_adapter_id;
        uint32_t                  k_chandle;
        uint32_t                  k_psm;
        uint32_t                  k_record_handle;
        uint32_t                  k_frame_number;
        uint32_t                  interface_id;
        uint32_t                  adapter_id;
        uint32_t                  chandle;
        uint32_t                  psm;
        uint32_t                  record_handle;
        uint32_t                  frame_number;

        interface_id = l2cap_data->interface_id;
        adapter_id   = l2cap_data->adapter_id;
        chandle      = l2cap_data->chandle;
        psm          = l2cap_data->psm;
        frame_number = pinfo->num;

        k_interface_id = interface_id;
        k_adapter_id   = adapter_id;
        k_chandle      = chandle;
        k_psm          = psm;
        k_frame_number = frame_number;

        for (i_record = 0; i_record < wmem_array_get_count(record_handle_array); ++i_record) {

            record_handle = *((uint32_t *)wmem_array_index(record_handle_array, i_record));
            k_record_handle = record_handle;

            key[0].length = 1;
            key[0].key    = &k_interface_id;
            key[1].length = 1;
            key[1].key    = &k_adapter_id;
            key[2].length = 1;
            key[2].key    = &k_chandle;
            key[3].length = 1;
            key[3].key    = &k_psm;
            key[4].length = 1;
            key[4].key    = &k_record_handle;
            key[5].length = 1;
            key[5].key    = &k_frame_number;
            key[6].length = 0;
            key[6].key    = NULL;

            record_handle_service = (record_handle_service_t *) wmem_new(wmem_file_scope(), record_handle_service_t);
            record_handle_service->interface_id  = interface_id;
            record_handle_service->adapter_id    = adapter_id;
            record_handle_service->chandle       = chandle;
            record_handle_service->psm           = psm;
            record_handle_service->record_handle = record_handle;

            record_handle_service->uuid_array   = uuid_array;

            wmem_tree_insert32_array(record_handle_services, key, record_handle_service);
        }
    }

    offset = dissect_continuation_state(tvb, tree, pinfo, offset);

    if (!is_first && new_tvb) {
        proto_item *reassembled_item;
        proto_tree *reassembled_tree;
        int         new_offset = 0;
        int         new_length;

        new_length = tvb_reported_length(new_tvb);

        reassembled_item = proto_tree_add_item(tree, (is_continued) ? hf_partial_record_handle_list : hf_reassembled_record_handle_list,new_tvb, 0, new_length, ENC_NA);
        proto_item_append_text(reassembled_item, " [count = %u]", new_length / 4);
        reassembled_tree = proto_item_add_subtree(reassembled_item, ett_btsdp_reassembled);
        proto_item_set_generated(reassembled_item);

        while (new_length > 0) {
            proto_tree_add_item(reassembled_tree, hf_sdp_service_record_handle, new_tvb,
                    new_offset, 4, ENC_BIG_ENDIAN);
            new_offset  += 4;
            new_length -= 4;
        }
    }

    return offset;
}


static unsigned
dissect_sdp_service_attribute_request(proto_tree *tree, tvbuff_t *tvb,
    unsigned offset, packet_info *pinfo, uint16_t tid, btl2cap_data_t *l2cap_data)
{
    uint32_t       record_handle;
    wmem_array_t  *uuid_array;
    bluetooth_uuid_t uuid;

    proto_tree_add_item_ret_uint(tree, hf_sdp_service_record_handle, tvb, offset, 4, ENC_BIG_ENDIAN, &record_handle);
    col_append_fstr(pinfo->cinfo, COL_INFO, ": 0x%08x - ", record_handle);
    offset += 4;

    proto_tree_add_item(tree, hf_maximum_attribute_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    uuid_array = get_uuids(pinfo, record_handle, l2cap_data);
    uuid = get_specified_uuid(pinfo->pool, uuid_array);

    offset += dissect_attribute_id_list(tree, tvb, offset, pinfo, &uuid);

    reassemble_continuation_state(tvb, pinfo, offset, tid, true,
            0, 0, PDU_TYPE_SERVICE_ATTRIBUTE, NULL, NULL, NULL, NULL, &record_handle, l2cap_data);

    offset = dissect_continuation_state(tvb, tree, pinfo, offset);

    return offset;
}


static int
dissect_sdp_service_attribute_response(proto_tree *tree, tvbuff_t *tvb,
        unsigned offset, packet_info *pinfo, uint16_t tid, btl2cap_data_t *l2cap_data)
{
    unsigned       attribute_list_byte_count;
    bool           is_first;
    bool           is_continued;
    tvbuff_t      *new_tvb;
    uint32_t       record_handle = 0;
    bluetooth_uuid_t uuid;

    proto_tree_add_item_ret_uint(tree, hf_attribute_list_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN, &attribute_list_byte_count);
    offset += 2;

    reassemble_continuation_state(tvb, pinfo,
            offset + attribute_list_byte_count, tid, false,
            offset, attribute_list_byte_count,
            PDU_TYPE_SERVICE_ATTRIBUTE, &new_tvb, &is_first,
            &is_continued, NULL, &record_handle, l2cap_data);

    if (!is_continued) {
        wmem_array_t  *uuid_array;

        uuid_array = get_uuids(pinfo, record_handle, l2cap_data);
        uuid = get_specified_uuid(pinfo->pool, uuid_array);
    } else {
        memset(&uuid, 0, sizeof(bluetooth_uuid_t));
    }

    if (is_first && !is_continued) {
        dissect_sdp_service_attribute_list(tree, tvb, offset, pinfo, &uuid, l2cap_data);
    } else {
        proto_tree_add_item(tree, hf_fragment, tvb, offset,
                attribute_list_byte_count, ENC_NA);
    }

    if (is_continued)
        col_append_str(pinfo->cinfo, COL_INFO, "(fragment)");

    offset = dissect_continuation_state(tvb, tree, pinfo, offset + attribute_list_byte_count);

    if (!is_first && new_tvb) {
        proto_item *reassembled_item;
        proto_tree *reassembled_tree;

        add_new_data_source(pinfo, new_tvb, (is_continued) ? "Partial Reassembled SDP" : "Reassembled SDP");

        reassembled_item = proto_tree_add_item(tree,
                (is_continued) ? hf_partial_attribute_list : hf_reassembled_attribute_list,
                new_tvb, 0, tvb_reported_length(new_tvb), ENC_NA);
        reassembled_tree = proto_item_add_subtree(reassembled_item, ett_btsdp_reassembled);
        proto_item_set_generated(reassembled_item);

        if (!is_continued) {
            dissect_sdp_service_attribute_list(reassembled_tree, new_tvb, 0,
                pinfo, &uuid, l2cap_data);
        }
    }

    return offset;
}


static int
dissect_sdp_service_search_attribute_request(proto_tree *tree, tvbuff_t *tvb,
        unsigned offset, packet_info *pinfo, uint16_t tid, btl2cap_data_t *l2cap_data)
{
    proto_tree     *ptree;
    proto_item     *pitem;
    proto_tree     *next_tree;
    unsigned        start_offset;
    unsigned        size;
    unsigned        bytes_to_go;
    wmem_strbuf_t  *info_buf = NULL;
    bluetooth_uuid_t empty_uuid;
    wmem_array_t   *uuid_array = NULL;
    bluetooth_uuid_t uuid;

    memset(&empty_uuid, 0, sizeof(bluetooth_uuid_t));
    if (!pinfo->fd->visited)
        uuid_array = wmem_array_new(wmem_file_scope(), sizeof(bluetooth_uuid_t));
    else
        uuid_array = wmem_array_new(pinfo->pool, sizeof(bluetooth_uuid_t));

    start_offset = offset;
    pitem = proto_tree_add_item(tree, hf_service_search_pattern, tvb, offset, 0, ENC_NA);
    ptree = proto_item_add_subtree(pitem, ett_btsdp_attribute);

    dissect_data_element(ptree, &next_tree, pinfo, tvb, offset);
    offset = get_type_length(tvb, offset, &bytes_to_go);
    proto_item_set_len(pitem, bytes_to_go + (offset - start_offset));

    while (bytes_to_go > 0) {
        unsigned        entry_offset;
        unsigned        entry_size;
        bluetooth_uuid_t a_uuid;

        memset(&a_uuid, 0, sizeof(bluetooth_uuid_t));

        size = dissect_sdp_type(next_tree, pinfo, tvb, offset, -1, empty_uuid, 0, 0, -1, NULL, &info_buf);
        proto_item_append_text(pitem,"%s", wmem_strbuf_get_str(info_buf));
        col_append_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(info_buf));

        entry_offset = get_type_length(tvb, offset, &entry_size);
        dissect_uuid(NULL, pinfo, tvb, entry_offset, entry_size, &a_uuid);
        if (uuid_array)
            wmem_array_append_one(uuid_array, a_uuid);

        offset      += size;
        bytes_to_go -= size;
    }

    col_append_str(pinfo->cinfo, COL_INFO, ": ");

    proto_tree_add_item(tree, hf_maximum_attribute_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    uuid = get_specified_uuid(pinfo->pool, uuid_array);

    offset += dissect_attribute_id_list(tree, tvb, offset, pinfo, &uuid);

    reassemble_continuation_state(tvb, pinfo, offset, tid, true,
            0, 0, PDU_TYPE_SERVICE_SEARCH_ATTRIBUTE, NULL, NULL, NULL, &uuid_array, NULL, l2cap_data);

    offset = dissect_continuation_state(tvb, tree, pinfo, offset);

    return offset;
}


static unsigned
dissect_sdp_service_search_attribute_response(proto_tree *tree, tvbuff_t *tvb,
    unsigned offset, packet_info *pinfo, uint16_t tid, btl2cap_data_t *l2cap_data)
{
    unsigned       attribute_list_byte_count;
    bool           is_first;
    bool           is_continued;
    tvbuff_t      *new_tvb;
    bluetooth_uuid_t uuid;
    wmem_array_t  *uuid_array = NULL;

    proto_tree_add_item_ret_uint(tree, hf_attribute_list_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN, &attribute_list_byte_count);
    offset += 2;

    reassemble_continuation_state(tvb, pinfo,
            offset + attribute_list_byte_count, tid, false,
            offset, attribute_list_byte_count,
            PDU_TYPE_SERVICE_SEARCH_ATTRIBUTE, &new_tvb, &is_first,
            &is_continued, &uuid_array, NULL, l2cap_data);

    uuid = get_specified_uuid(pinfo->pool, uuid_array);

    if (is_first && !is_continued) {
        dissect_sdp_service_attribute_list_array(tree, tvb, offset, pinfo,
                attribute_list_byte_count, &uuid, l2cap_data);
    } else {
        proto_tree_add_item(tree, hf_fragment, tvb, offset,
                attribute_list_byte_count, ENC_NA);
    }

    if (is_continued)
        col_append_str(pinfo->cinfo, COL_INFO, "(fragment)");

    offset = dissect_continuation_state(tvb, tree, pinfo, offset + attribute_list_byte_count);

    if (!is_first && new_tvb) {
        proto_item *reassembled_item;
        proto_tree *reassembled_tree;

        add_new_data_source(pinfo, new_tvb, (is_continued) ? "Partial Reassembled SDP" : "Reassembled SDP");

        reassembled_item = proto_tree_add_item(tree,
                (is_continued) ? hf_partial_attribute_list : hf_reassembled_attribute_list,
                new_tvb, 0, tvb_reported_length(new_tvb), ENC_NA);
        reassembled_tree = proto_item_add_subtree(reassembled_item, ett_btsdp_reassembled);
        proto_item_set_generated(reassembled_item);

        if (!is_continued)
            dissect_sdp_service_attribute_list_array(reassembled_tree, new_tvb, 0,
                    pinfo, tvb_reported_length(new_tvb), &uuid, l2cap_data);
    }

    return offset;
}


static int
dissect_btsdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item    *ti;
    proto_tree    *st;
    unsigned      offset = 0;
    uint8_t       pdu_id;
    uint16_t      tid;
    btl2cap_data_t   *l2cap_data;

    /* Reject the packet if data is NULL */
    if (data == NULL)
        return 0;
    l2cap_data = (btl2cap_data_t *) data;

    ti = proto_tree_add_item(tree, proto_btsdp, tvb, 0, tvb_captured_length(tvb), ENC_NA);
    st = proto_item_add_subtree(ti, ett_btsdp);

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SDP");

    switch (pinfo->p2p_dir) {
        case P2P_DIR_SENT:
            col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
            break;
        case P2P_DIR_RECV:
            col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
            break;
        default:
            col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
            break;
    }

    proto_tree_add_item_ret_uint8(st, hf_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN, &pdu_id);
    offset += 1;

    col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
            val_to_str_const(pdu_id, vs_pduid, "Unknown"));

    proto_tree_add_item_ret_uint16(st, hf_tid, tvb, offset, 2, ENC_BIG_ENDIAN, &tid);
    offset += 2;

    proto_tree_add_item(st, hf_parameter_length, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    switch (pdu_id) {
        case 0x01:
            offset = dissect_sdp_error_response(st, tvb, offset);
            break;
        case 0x02:
            offset = dissect_sdp_service_search_request(st, tvb, offset, pinfo, tid, l2cap_data);
            break;
        case 0x03:
            offset = dissect_sdp_service_search_response(st, tvb, offset, pinfo, tid, l2cap_data);
            break;
        case 0x04:
            offset = dissect_sdp_service_attribute_request(st, tvb, offset, pinfo, tid, l2cap_data);
            break;
        case 0x05:
            offset = dissect_sdp_service_attribute_response(st, tvb, offset, pinfo, tid, l2cap_data);
            break;
        case 0x06:
            offset = dissect_sdp_service_search_attribute_request(st, tvb, offset, pinfo, tid, l2cap_data);
            break;
        case 0x07:
            offset = dissect_sdp_service_search_attribute_response(st, tvb, offset, pinfo, tid, l2cap_data);
            break;
    }

    return offset;
}

void
proto_register_btsdp(void)
{
    module_t *module;
    expert_module_t *expert_btsdp;

    static hf_register_info hf[] = {
        { &hf_pdu_id,
            { "PDU",                             "btsdp.pdu",
            FT_UINT8, BASE_HEX, VALS(vs_pduid), 0,
            "PDU type", HFILL }
        },
        { &hf_tid,
            { "Transaction Id",                  "btsdp.tid",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL}
        },
        { &hf_parameter_length,
          { "Parameter Length",                  "btsdp.len",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL}
        },
        { &hf_error_code,
            { "Error Code",                      "btsdp.error_code",
            FT_UINT16, BASE_HEX, VALS(vs_error_code), 0,
            NULL, HFILL}
        },
        { &hf_ssr_total_count,
            { "Total Service Record Count",      "btsdp.ssr.total_count",
            FT_UINT16, BASE_DEC, NULL, 0,
            "Total count of service records", HFILL}
        },
        { &hf_ssr_current_count,
            { "Current Service Record Count",    "btsdp.ssr.current_count",
            FT_UINT16, BASE_DEC, NULL, 0,
            "Count of service records in this message", HFILL}
        },
        { &hf_attribute_id_list,
            { "Attribute ID List",               "btsdp.attribute_id_list",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_attribute_id_range,
            { "Attribute Range",                 "btsdp.attribute_range",
            FT_UINT32, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_attribute_id_range_from,
            { "Attribute Range From",            "btsdp.attribute_range.from",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_attribute_id_range_to,
            { "Attribute Range To",              "btsdp.attribute_range.to",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_attribute_list_byte_count,
            { "Attribute List Byte Count",       "btsdp.attribute_list_byte_count",
            FT_UINT16, BASE_DEC, NULL, 0,
            "Count of bytes in attribute list response", HFILL}
        },
        { &hf_maximum_service_record_count,
            {"Maximum Service Record Count",     "btsdp.maximum_service_record_count",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL}
        },
        { &hf_maximum_attribute_byte_count,
            {"Maximum Attribute Byte Count",     "btsdp.maximum_attribute_byte_count",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL}
        },
        { &hf_service_attribute,
            { "Service Attribute",               "btsdp.service_attribute",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id,
            { "Attribute",                       "btsdp.service_attribute.attribute",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_value,
            { "Value",                           "btsdp.service_attribute.value",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_profile_descriptor_list,
            { "Profile Descriptor List",         "btsdp.profile_descriptor_list",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_attribute_list,
            { "Attribute List",                  "btsdp.attribute_list",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_attribute_lists,
            { "Attribute Lists",                  "btsdp.attribute_lists",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_service_search_pattern,
            { "Service Search Pattern",          "btsdp.service_search_pattern",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_service_record_handle_list,
            { "Service Record Handle List",      "btsdp.service_record_handle_list",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_continuation_state,
            { "Continuation State",              "btsdp.continuation_state",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_continuation_state_length,
            { "Continuation State Length",       "btsdp.continuation_state.length",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_continuation_state_value,
            { "Continuation State Value",        "btsdp.continuation_state.value",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element,
            { "Data Element",                    "btsdp.data_element",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_type,
            { "Data Element Type",               "btsdp.data_element.type",
            FT_UINT8, BASE_DEC, VALS(vs_data_element_type), 0xF8,
            NULL, HFILL }
        },
        { &hf_data_element_size,
            { "Data Element Size",               "btsdp.data_element.size",
            FT_UINT8, BASE_DEC, VALS(vs_data_element_size), 0x07,
            NULL, HFILL }
        },
        { &hf_data_element_var_size,
            { "Data Element Var Size",           "btsdp.data_element.var_size",
            FT_UINT32, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value,
            { "Data Value",                      "btsdp.data_element.value",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_nil,
            { "Value: Nil",                      "btsdp.data_element.value.nil",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_signed_int,
            { "Value: Signed Int",               "btsdp.data_element.value.signed_int",
            FT_INT64, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_unsigned_int,
            { "Value: Unsigned Int",             "btsdp.data_element.value.unsigned_int",
            FT_UINT64, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_boolean,
            { "Value: Boolean",                  "btsdp.data_element.value.boolean",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_string,
            { "Value: String",                   "btsdp.data_element.value.string",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_url,
            { "Value: URL",                      "btsdp.data_element.value.url",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_uuid_16,
            { "Value: UUID",                     "btsdp.data_element.value.uuid_16",
            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bluetooth_uuid_vals_ext, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_uuid_32,
            { "Value: UUID",                     "btsdp.data_element.value.uuid_32",
            FT_UINT32, BASE_HEX | BASE_EXT_STRING, &bluetooth_uuid_vals_ext, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_uuid_128,
            { "Value: UUID",                     "btsdp.data_element.value.uuid_128",
            FT_BYTES, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_uuid,
            { "Value: Custom UUID",              "btsdp.data_element.value.custom_uuid",
            FT_BYTES, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_sequence,
            { "Value: Sequence",                 "btsdp.data_element.value.sequence",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_data_element_value_alternative,
            { "Value: Alternative",              "btsdp.data_element.value.alternative",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_fragment,
            { "Data Fragment",                   "btsdp.fragment",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_partial_attribute_list,
            { "Partial Attribute List",          "btsdp.partial_attribute_list",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_reassembled_attribute_list,
            { "Reassembled Attribute List",      "btsdp.reassembled_attribute_list",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_partial_record_handle_list,
            { "Partial Record Handle List",      "btsdp.partial_record_handle_list",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_reassembled_record_handle_list,
            { "Reassembled Record Handle List",  "btsdp.reassembled_record_handle_list",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_generic,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_general_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_a2dp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_a2dp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_avrcp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_avrcp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_bip_imaging_responder,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_bip_imaging_responder_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_bip_imaging_other,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_bip_imaging_other_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_bpp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_bpp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_bpp_rui,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_bpp_reflected_ui_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_ctp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_ctp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_did,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_did_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_dun,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_dun_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_fax,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_fax_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_ftp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_ftp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_gnss,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_gnss_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_hfp_hf,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_hfp_gw_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_hfp_ag,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_hfp_ag_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_hcrp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_hcrp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_hsp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_hsp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_hdp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_hdp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_hid,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_hid_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_wap,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_wap_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_map_mas,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_map_mas_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_map_mns,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_map_mns_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_opp,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_opp_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_pan_nap,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_pan_nap_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_pan_gn,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_pan_gn_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_pan_panu,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_pan_panu_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_pbap,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_pbap_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_synch,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_synch_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_ctn_as,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_ctn_as_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_ctn_ns,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_ctn_ns_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_service_attribute_id_mps,
            { "Attribute ID",                    "btsdp.service.attribute",
            FT_UINT16, BASE_HEX, VALS(vs_mps_attribute_id), 0,
            NULL, HFILL }
        },
        { &hf_did_specification_id,
            { "Specification ID",                "btsdp.service.did.specification_id",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_did_vendor_id,
            { "Vendor ID",                       "btsdp.service.did.vendor_id",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_did_vendor_id_bluetooth_sig,
            { "Vendor ID",                       "btsdp.service.did.vendor_id",
            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bluetooth_company_id_vals_ext, 0,
            NULL, HFILL }
        },
        { &hf_did_vendor_id_usb_forum,
            { "Vendor ID",                       "btsdp.service.did.vendor_id",
            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ext_usb_vendors_vals, 0,
            NULL, HFILL }
        },
        { &hf_did_product_id,
            { "Product ID",                      "btsdp.service.did.product_id",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_did_primary_record,
            { "Primary Record",                  "btsdp.service.did.primary_record",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_did_version,
            { "Version",                         "btsdp.service.did.version",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_did_vendor_id_source,
            { "Vendor ID Source",                "btsdp.service.did.vendor_id_source",
            FT_UINT16, BASE_HEX, VALS(did_vendor_id_source_vals), 0,
            NULL, HFILL }
        },
        { &hf_a2dp_sink_supported_features_reserved,
            { "Supported Features: Reserved",    "btsdp.service.a2dp.sink.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0xFFF0,
            NULL, HFILL }
        },
        { &hf_a2dp_sink_supported_features_amplifier,
            { "Supported Features: Amplifier",   "btsdp.service.a2dp.sink.supported_features.amplifier",
            FT_BOOLEAN, 16, NULL, 0x0008,
            NULL, HFILL }
        },
        { &hf_a2dp_sink_supported_features_recorder,
            { "Supported Features: Recorder",    "btsdp.service.a2dp.sink.supported_features.recorder",
            FT_BOOLEAN, 16, NULL, 0x0004,
            NULL, HFILL }
        },
        { &hf_a2dp_sink_supported_features_speaker,
            { "Supported Features: Speaker",     "btsdp.service.a2dp.sink.supported_features.speaker",
            FT_BOOLEAN, 16, NULL, 0x0002,
            NULL, HFILL }
        },
        { &hf_a2dp_sink_supported_features_headphone,
            { "Supported Features: Headphone",   "btsdp.service.a2dp.sink.supported_features.headphone",
            FT_BOOLEAN, 16, NULL, 0x0001,
            NULL, HFILL }
        },
        { &hf_a2dp_source_supported_features_reserved,
            { "Supported Features: Reserved",    "btsdp.service.a2dp.source.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0xFFF0,
            NULL, HFILL }
        },
        { &hf_a2dp_source_supported_features_mixer,
            { "Supported Features: Mixer",       "btsdp.service.a2dp.source.supported_features.mixer",
            FT_BOOLEAN, 16, NULL, 0x0008,
            NULL, HFILL }
        },
        { &hf_a2dp_source_supported_features_tuner,
            { "Supported Features: Tuner",       "btsdp.service.a2dp.source.supported_features.tuner",
            FT_BOOLEAN, 16, NULL, 0x0004,
            NULL, HFILL }
        },
        { &hf_a2dp_source_supported_features_microphone,
            { "Supported Features: Microphone",  "btsdp.service.a2dp.source.supported_features.microphone",
            FT_BOOLEAN, 16, NULL, 0x0002,
            NULL, HFILL }
        },
        { &hf_a2dp_source_supported_features_player,
            { "Supported Features: Player",      "btsdp.service.a2dp.source.supported_features.player",
            FT_BOOLEAN, 16, NULL, 0x0001,
            NULL, HFILL }
        },
        { &hf_synch_supported_data_store,
            { "Supported Data Store",            "btsdp.service.synch.supported_data_store",
            FT_UINT8, BASE_HEX, VALS(synch_supported_data_store_vals), 0,
            NULL, HFILL }
        },
        { &hf_ctp_external_network,
            { "External Network",                "btsdp.service.ctp.external_network",
            FT_UINT8, BASE_HEX, VALS(ctp_external_network_vals), 0,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_reserved_10_15,
            { "Supported Features: Reserved",      "btsdp.service.avrcp.ct.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0xFC00,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_cover_art_get_linked_thumbnail,
            { "Supported Features: Cover Art - Get Linked Thumbnail",      "btsdp.service.avrcp.ct.supported_features.cover_art_get_linked_thumbnail",
            FT_BOOLEAN, 16, NULL, 0x0200,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_cover_art_get_image,
            { "Supported Features: Cover Art - Get Image",      "btsdp.service.avrcp.ct.supported_features.cover_art_get_image",
            FT_BOOLEAN, 16, NULL, 0x0100,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_cover_art_get_image_properties,
            { "Supported Features: Cover Art - Get Image Properties",      "btsdp.service.avrcp.ct.supported_features.cover_art_get_image_properties",
            FT_BOOLEAN, 16, NULL, 0x0080,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_browsing,
            { "Supported Features: Browsing",      "btsdp.service.avrcp.ct.supported_features.browsing",
            FT_BOOLEAN, 16, NULL, 0x0040,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_reserved_4_5,
            { "Supported Features: Reserved",      "btsdp.service.avrcp.ct.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0x0030,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_category_4,
            { "Supported Features: Category 4: Menu",                "btsdp.service.avrcp.ct.supported_features.category_4",
            FT_BOOLEAN, 16, NULL, 0x0008,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_category_3,
            { "Supported Features: Category 3: Tuner",               "btsdp.service.avrcp.ct.supported_features.category_3",
            FT_BOOLEAN, 16, NULL, 0x0004,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_category_2,
            { "Supported Features: Category 2: Monitor/Amplifier",   "btsdp.service.avrcp.ct.supported_features.category_2",
            FT_BOOLEAN, 16, NULL, 0x0002,
            NULL, HFILL }
        },
        { &hf_avrcp_ct_supported_features_category_1,
            { "Supported Features: Category 1: Player/Recorder",     "btsdp.service.avrcp.ct.supported_features.category_1",
            FT_BOOLEAN, 16, NULL, 0x0001,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_reserved_9_15,
            { "Supported Features: Reserved",                        "btsdp.service.avrcp.tg.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0xFE00,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_cover_art,
            { "Supported Features: Cover Art",                 "btsdp.service.avrcp.tg.supported_features.cover_art",
            FT_BOOLEAN, 16, NULL, 0x0100,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_multiple_player,
            { "Supported Features: Multiple Player",                 "btsdp.service.avrcp.tg.supported_features.multiple_player",
            FT_BOOLEAN, 16, NULL, 0x0080,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_browsing,
            { "Supported Features: Browsing",                        "btsdp.service.avrcp.tg.supported_features.browsing",
            FT_BOOLEAN, 16, NULL, 0x0040,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_group_navigation,
            { "Supported Features: Group Navigation",                "btsdp.service.avrcp.tg.supported_features.group_navigation",
            FT_BOOLEAN, 16, NULL, 0x0020,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_settings,
            { "Supported Features: Settings",                        "btsdp.service.avrcp.tg.supported_features.settings",
            FT_BOOLEAN, 16, NULL, 0x0010,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_category_4,
            { "Supported Features: Category 4: Menu",                "btsdp.service.avrcp.tg.supported_features.category_4",
            FT_BOOLEAN, 16, NULL, 0x0008,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_category_3,
            { "Supported Features: Category 3: Tuner",               "btsdp.service.avrcp.tg.supported_features.category_3",
            FT_BOOLEAN, 16, NULL, 0x0004,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_category_2,
            { "Supported Features: Category 2: Monitor/Amplifier",   "btsdp.service.avrcp.tg.supported_features.category_2",
            FT_BOOLEAN, 16, NULL, 0x0002,
            NULL, HFILL }
        },
        { &hf_avrcp_tg_supported_features_category_1,
            { "Supported Features: Category 1: Player/Recorder",     "btsdp.service.avrcp.tg.supported_features.category_1",
            FT_BOOLEAN, 16, NULL, 0x0001,
            NULL, HFILL }
        },
        { &hf_hsp_remote_audio_volume_control,
            { "Remote Audio Volume Control",     "btsdp.service.hsp.remote_audio_volume_control",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_gnss_supported_features,
            { "Supported Features: Reserved",    "btsdp.service.gnss.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_repositories,
            { "Supported Repositories",     "btsdp.service.pbap.pse.supported_repositories",
            FT_UINT8, BASE_HEX, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_repositories_reserved,
            { "Reserved",                   "btsdp.service.pbap.pse.supported_repositories.reserved",
            FT_UINT8, BASE_HEX, NULL, 0xF0,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_repositories_favourites,
            { "Favourites",                 "btsdp.service.pbap.pse.supported_repositories.favourites",
            FT_BOOLEAN, 8, NULL, 0x08,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_repositories_speed_dial,
            { "Speed Dial",                 "btsdp.service.pbap.pse.supported_repositories.speed_dial",
            FT_BOOLEAN, 8, NULL, 0x04,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_repositories_sim_card,
            { "SIM Card",                   "btsdp.service.pbap.pse.supported_repositories.sim_card",
            FT_BOOLEAN, 8, NULL, 0x02,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_repositories_local_phonebook,
            { "Local Phonebook",            "btsdp.service.pbap.pse.supported_repositories.local_phonebook",
            FT_BOOLEAN, 8, NULL, 0x01,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features,
            { "Supported Features",              "btsdp.service.pbap.pse.supported_features",
            FT_UINT32, BASE_HEX, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_reserved,
            { "Reserved",                        "btsdp.service.pbap.pse.supported_features.reserved",
            FT_UINT32, BASE_HEX, NULL, 0xFFFFFC00,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_default_contact_image_format,
            { "Default Contact Image Format",    "btsdp.service.pbap.pse.supported_features.default_contact_image_format",
            FT_BOOLEAN, 32, NULL, 0x00000200,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_contact_referencing,
            { "Contact Referencing",             "btsdp.service.pbap.pse.supported_features.contact_referencing",
            FT_BOOLEAN, 32, NULL, 0x00000100,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_x_bt_uid_vcard_property,
            { "X-BT-UID vCard Property",         "btsdp.service.pbap.pse.supported_features.x_bt_uid_vcard_property",
            FT_BOOLEAN, 32, NULL, 0x00000080,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_x_bt_uci_vcard_property,
            { "X-BT-UCI vCard Property",         "btsdp.service.pbap.pse.supported_features.x_bt_uci_vcard_property",
            FT_BOOLEAN, 32, NULL, 0x00000040,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_enhanced_missed_calls,
            { "Enhanced Missed Calls",           "btsdp.service.pbap.pse.supported_features.enhanced_missed_calls",
            FT_BOOLEAN, 32, NULL, 0x00000020,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_vcard_selecting,
            { "vCard Selecting",                 "btsdp.service.pbap.pse.supported_features.vcard_selecting",
            FT_BOOLEAN, 32, NULL, 0x00000010,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_folder_version_counters,
            { "Folder Version Counters",         "btsdp.service.pbap.pse.supported_features.folder_version_counters",
            FT_BOOLEAN, 32, NULL, 0x00000008,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_database_identifier,
            { "Database Identifier",             "btsdp.service.pbap.pse.supported_features.database_identifier",
            FT_BOOLEAN, 32, NULL, 0x00000004,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_browsing,
            { "Browsing",                        "btsdp.service.pbap.pse.supported_features.browsing",
            FT_BOOLEAN, 32, NULL, 0x00000002,
            NULL, HFILL }
        },
        { &hf_pbap_pse_supported_features_download,
            { "Download",                        "btsdp.service.pbap.pse.supported_features.download",
            FT_BOOLEAN, 32, NULL, 0x00000001,
            NULL, HFILL }
        },
        { &hf_pbap_goep_l2cap_psm,
            { "GOEP L2CAP PSM",                  "btsdp.pbap.goep_l2cap_psm",
            FT_UINT16, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_dun_support_audio_feedback,
            { "Support: Audio Feedback",         "btsdp.dun.support.audio_feedback",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_dun_escape_sequence,
            { "Escape Sequence",                 "btsdp.dun.support.escape_sequence",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_fax_support_class_1,
            { "Support: Fax Class 1",            "btsdp.fax.support.class_1",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_fax_support_class_2,
            { "Support: Fax Class 2.0",          "btsdp.fax.support.class_2",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_fax_support_class_2_vendor,
            { "Support: Fax Class 2 Vendor",     "btsdp.fax.support.class_2_vendor",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_fax_support_audio_feedback,
            { "Support: Audio Feedback",         "btsdp.fax.support.audio_feedback",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_ftp_goep_l2cap_psm,
            { "GOEP L2CAP PSM",                  "btsdp.ftp.goep_l2cap_psm",
            FT_UINT16, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_map_mas_instance_id,
            { "MAS Instance ID",                 "btsdp.map.mas.instance_id",
            FT_UINT8, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_map_mas_goep_l2cap_psm,
            { "GOEP L2CAP PSM",                  "btsdp.map.mas.goep_l2cap_psm",
            FT_UINT16, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_map_mns_goep_l2cap_psm,
            { "GOEP L2CAP PSM",                  "btsdp.map.mns.goep_l2cap_psm",
            FT_UINT16, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_map_mas_supported_message_types_reserved,
            { "Supported Message Types: Reserved",         "btsdp.map.mas.supported_message_types.reserved",
            FT_UINT8, BASE_DEC_HEX, NULL, 0xF0,
            NULL, HFILL }
        },
        { &hf_map_mas_supported_message_types_mms,
            { "Supported Message Types: MMS",              "btsdp.map.mas.supported_message_types.mms",
            FT_BOOLEAN, 8, NULL, 0x08,
            NULL, HFILL }
        },
        { &hf_map_mas_supported_message_types_sms_cdma,
            { "Supported Message Types: SMS CDMA",         "btsdp.map.mas.supported_message_types.sms_cdma",
            FT_BOOLEAN, 8, NULL, 0x04,
            NULL, HFILL }
        },
        { &hf_map_mas_supported_message_types_sms_gsm,
            { "Supported Message Types: SMS GSM",          "btsdp.map.mas.supported_message_types.sms_gsm",
            FT_BOOLEAN, 8, NULL, 0x02,
            NULL, HFILL }
        },
        { &hf_map_mas_supported_message_types_email,
            { "Supported Message Types: Email",              "btsdp.map.mas.supported_message_types.email",
            FT_BOOLEAN, 8, NULL, 0x01,
            NULL, HFILL }
        },
        { &hf_hcrp_1284_id,
            { "1284 ID",                         "btsdp.hcrp.1284_id",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hcrp_device_location,
            { "Service Location",                 "btsdp.hcrp.device_location",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hcrp_device_name,
            { "Device Name",                     "btsdp.hcrp.device_name",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hcrp_friendly_name,
            { "Friendly Name",                   "btsdp.hcrp.friendly_name",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_wap_network_address,
            { "Network Address",                 "btsdp.wap.network_address",
            FT_IPv4, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_wap_homepage_url,
            { "Homepage URL",                    "btsdp.wap.homepage_url",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_wap_gateway,
            { "Gateway",                         "btsdp.wap.gateway",
            FT_UINT8, BASE_HEX, VALS(wap_gateway_vals), 0,
            NULL, HFILL }
        },
        { &hf_wap_stack_type,
            { "Stack Type",                      "btsdp.wap.stack_type",
            FT_UINT8, BASE_HEX, VALS(wap_stack_type_vals), 0,
            NULL, HFILL }
        },
        { &hf_hdp_support_procedure_reserved_5_7,
            { "Support: Reserved_5_7",           "btsdp.hdp.support.reserved_5_7",
            FT_UINT8, BASE_HEX, NULL, 0xE0,
            NULL, HFILL }
        },
        { &hf_hdp_support_procedure_sync_master_role,
            { "Support: SyncMaster Role",        "btsdp.hdp.support.sync_master_role",
            FT_BOOLEAN, 8, NULL, 0x10,
            NULL, HFILL }
        },
        { &hf_hdp_support_procedure_clock_synchronization_protocol,
            { "Support: Clock Synchronization Protocol",   "btsdp.hdp.support.clock_synchronization_protocol",
            FT_BOOLEAN, 8, NULL, 0x08,
            NULL, HFILL }
        },
        { &hf_hdp_support_procedure_reconnect_acceptance,
            { "Support: Reconnect Acceptance",   "btsdp.hdp.support.reconnect_acceptance",
            FT_BOOLEAN, 8, NULL, 0x04,
            NULL, HFILL }
        },
        { &hf_hdp_support_procedure_reconnect_initiation,
            { "Support: Reconnect Initiation",   "btsdp.hdp.support.reconnect_initiation",
            FT_BOOLEAN, 8, NULL, 0x02,
            NULL, HFILL }
        },
        { &hf_hdp_support_procedure_reserved,
            { "Support: Reserved",               "btsdp.hdp.support.reserved",
            FT_BOOLEAN, 8, NULL, 0x01,
            NULL, HFILL }
        },
        { &hf_hdp_data_exchange,
            { "Data Exchange Specification",     "btsdp.hdp.data_exchange_specification",
            FT_UINT8, BASE_HEX, VALS(hdp_data_exchange_specification_vals), 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_data,
            { "Supported Features",              "btsdp.hdp.supported_features_data",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_data_mdep_id,
            { "MDEP ID",                         "btsdp.hdp.supported_features_data.mdep_id",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_data_mdep_data_type,
            { "MDEP Data Type",                  "btsdp.hdp.supported_features_data.mdep_data_type",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_data_mdep_role,
            { "MDEP Role",                       "btsdp.hdp.supported_features_data.mdep_role",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_data_mdep_description,
            { "MDEP Description",                "btsdp.hdp.supported_features_data.mdep_description",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_mdep_id,
            { "MDEP ID",                         "btsdp.hdp.supported_features.mdep_id",
            FT_UINT8, BASE_DEC_HEX|BASE_RANGE_STRING, RVALS(hdp_mdep_id_rvals), 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_mdep_data_type_01,
            { "MDEP Data Type",                  "btsdp.hdp.supported_features.mdep_data_type",
            FT_UINT16, BASE_HEX, VALS(hdp_mdep_data_type_01_vals), 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_mdep_data_type,
            { "MDEP Data Type",                  "btsdp.hdp.supported_features.mdep_data_type",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_mdep_role,
            { "MDEP Role",                       "btsdp.hdp.supported_features.mdep_role",
            FT_UINT8, BASE_HEX, VALS(hdp_mdep_role_vals), 0,
            NULL, HFILL }
        },
        { &hf_hdp_supported_features_mdep_description,
            { "MDEP Description",                "btsdp.hdp.supported_features.mdep_description",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_pan_sercurity_description,
            { "Security Description",            "btsdp.pan.security_description",
            FT_UINT16, BASE_HEX, VALS(pan_security_description_vals), 0,
            NULL, HFILL }
        },
        { &hf_pan_ipv4_subnet,
            { "IPv4 Subnet",                     "btsdp.pan.ipv4_subnet",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_pan_ipv6_subnet,
            { "IPv6 Subnet",                     "btsdp.pan.ipv6_subnet",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_pan_net_access_type,
            { "Net Access Type",                 "btsdp.pan.net_access_type",
            FT_UINT16, BASE_HEX, VALS(pan_net_access_type_vals), 0,
            NULL, HFILL }
        },
        { &hf_pan_max_net_access_rate,
            { "Max Net Access Rate",             "btsdp.pan.max_net_access_rate",
            FT_UINT32, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_opp_goep_l2cap_psm,
            { "GOEP L2CAP PSM",                  "btsdp.opp.goep_l2cap_psm",
            FT_UINT16, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_opp_supported_format,
            { "Supported Format",                  "btsdp.opp.supported_format",
            FT_UINT8, BASE_HEX, VALS(opp_supported_format_vals), 0,
            NULL, HFILL }
        },
        { &hf_hfp_hf_supported_features_reserved,
            { "Supported Features: Reserved",                             "btsdp.service.hfp.hf.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0xFFC0,
            NULL, HFILL }
        },
        { &hf_hfp_hf_supported_features_wide_band_speech,
            { "Supported Features: Wide Band Speech",                     "btsdp.service.hfp.hf.supported_features.wide_band_speech",
            FT_BOOLEAN, 16, NULL, 0x0020,
            NULL, HFILL }
        },
        { &hf_hfp_hf_supported_features_remote_volume_control,
            { "Supported Features: Remote Volume Control",                "btsdp.service.hfp.hf.supported_features.remote_volume_control",
            FT_BOOLEAN, 16, NULL, 0x0010,
            NULL, HFILL }
        },
        { &hf_hfp_hf_supported_features_voice_recognition_activation,
            { "Supported Features: Voice Recognition Activation",         "btsdp.service.hfp.hf.supported_features.voice_recognition_activation",
            FT_BOOLEAN, 16, NULL, 0x0008,
            NULL, HFILL }
        },
        { &hf_hfp_hf_supported_features_cli_presentation_capability,
            { "Supported Features: CLI Presentation Capability",          "btsdp.service.hfp.hf.supported_features.cli_presentation_capability",
            FT_BOOLEAN, 16, NULL, 0x0004,
            NULL, HFILL }
        },
        { &hf_hfp_hf_supported_features_call_waiting_or_three_way_calling,
            { "Supported Features: Call Waiting or Three Way Calling",    "btsdp.service.hfp.hf.supported_features.call_waiting_or_three_way_calling",
            FT_BOOLEAN, 16, NULL, 0x0002,
            NULL, HFILL }
        },
        { &hf_hfp_hf_supported_features_ec_and_or_nr_function,
            { "Supported Features: EC and/or Nr Function",                "btsdp.service.hfp.hf.supported_features.ec_and_or_nr_function",
            FT_BOOLEAN, 16, NULL, 0x0001,
            NULL, HFILL }
        },
        { &hf_hfp_gw_supported_features_reserved,
            { "Supported Features: Reserved",                             "btsdp.service.hfp.gw.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0xFFC0,
            NULL, HFILL }
        },
        { &hf_hfp_gw_supported_features_wide_band_speech,
            { "Supported Features: Wide Band Speech",                     "btsdp.service.hfp.gw.supported_features.wide_band_speech",
            FT_BOOLEAN, 16, NULL, 0x0020,
            NULL, HFILL }
        },
        { &hf_hfp_gw_supported_features_attach_phone_number_to_voice_tag,
            { "Supported Features: Attach a Phone Number to a Voice Tag", "btsdp.service.hfp.gw.supported_features.attach_a_phone_number_to_a_voice_tag",
            FT_BOOLEAN, 16, NULL, 0x0010,
            NULL, HFILL }
        },
        { &hf_hfp_gw_supported_features_inband_ring_tone_capability,
            { "Supported Features: Inband Ring Tone Capability",          "btsdp.service.hfp.gw.supported_features.inband_ring_tone_capability",
            FT_BOOLEAN, 16, NULL, 0x0008,
            NULL, HFILL }
        },
        { &hf_hfp_gw_supported_features_voice_recognition_function,
            { "Supported Features: Voice Recognition Function",           "btsdp.service.hfp.gw.supported_features.voice_recognition_function",
            FT_BOOLEAN, 16, NULL, 0x0004,
            NULL, HFILL }
        },
        { &hf_hfp_gw_supported_features_ec_and_or_nr_function,
            { "Supported Features: EC and/or Nr Function",                "btsdp.service.hfp.gw.supported_features.ec_and_or_nr_function",
            FT_BOOLEAN, 16, NULL, 0x0002,
            NULL, HFILL }
        },
        { &hf_hfp_gw_supported_features_three_way_calling,
            { "Supported Features: Three Way Calling",                    "btsdp.service.hfp.gw.supported_features.three_way_calling",
            FT_BOOLEAN, 16, NULL, 0x0001,
            NULL, HFILL }
        },
        { &hf_hfp_gw_network,
            { "Network",                                                  "btsdp.service.hfp.gw.network",
            FT_UINT8, BASE_HEX, VALS(hfp_gw_network_vals), 0,
            NULL, HFILL }
        },
        { &hf_ctn_instance_id,
            { "Instance ID",                     "btsdp.ctn.instance_id",
            FT_UINT8, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features,
            { "Supported Features",              "btsdp.ctn.supported_features",
            FT_UINT32, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features_reserved,
            { "Reserved",                        "btsdp.ctn.supported_features.reserved",
            FT_BOOLEAN, 32, NULL, 0xFFFFFF80,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features_forward,
            { "Forward",                         "btsdp.ctn.supported_features.forward",
            FT_BOOLEAN, 32, NULL, 0x00000040,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features_delete,
            { "Delete",                          "btsdp.ctn.supported_features.delete",
            FT_BOOLEAN, 32, NULL, 0x00000020,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features_uploading,
            { "Uploading",                       "btsdp.ctn.supported_features.uploading",
            FT_BOOLEAN, 32, NULL, 0x00000010,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features_downloading,
            { "Downloading",                     "btsdp.ctn.supported_features.downloading",
            FT_BOOLEAN, 32, NULL, 0x00000008,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features_browsing,
            { "Browsing",                        "btsdp.ctn.supported_features.browsing",
            FT_BOOLEAN, 32, NULL, 0x00000004,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features_notification,
            { "Notification",                    "btsdp.ctn.supported_features.notification",
            FT_BOOLEAN, 32, NULL, 0x00000002,
            NULL, HFILL }
        },
        { &hf_ctn_supported_features_account_management,
            { "Account Management",              "btsdp.ctn.supported_features.account_management",
            FT_BOOLEAN, 32, NULL, 0x00000001,
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios,
            { "Supported Profile and Protocol Dependency",                                                   "btsdp.mps.mpsd_scenarios",
            FT_UINT64, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_reserved,
            { "Reserved",                                                                                    "btsdp.mps.mpsd_scenarios.reserved",
            FT_UINT64, BASE_HEX, NULL, UINT64_C(0xFFFFFFC000000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_37,
            { "Phonebook Download during Audio Streaming (A2DP-SNK_PBAP-Client)",                            "btsdp.mps.mpsd_scenarios.37",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000002000000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_36,
            { "Phonebook Download during Audio Streaming (A2DP-SRC_PBAP-Server)",                            "btsdp.mps.mpsd_scenarios.36",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000001000000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_35,
            { "Data communication establishment in Personal Area Network during Audio Streaming (A2DP-SNK_PAN_PANU)",  "btsdp.mps.mpsd_scenarios.35",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000800000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_34,
            { "Data communication establishment in Personal Area Network during Audio Streaming (A2DP-SRC_PAN-NAP)",   "btsdp.mps.mpsd_scenarios.34",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000400000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_33,
            { "Start Audio Streaming during Data communication in Personal Area Network (A2DP-SNK_PAN-PANU)",          "btsdp.mps.mpsd_scenarios.33",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000200000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_32,
            { "Start Audio Streaming during Data communication in Personal Area Network (A2DP-SRC_PAN-NAP)",           "btsdp.mps.mpsd_scenarios.32",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000100000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_31,
            { "Incoming voice call during Data communication in Personal Area Network (HFP-HF_PAN-PANU)",              "btsdp.mps.mpsd_scenarios.31",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000080000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_30,
            { "Incoming voice call during Data communication in Personal Area Network (HFP-AG_PAN-NAP)",               "btsdp.mps.mpsd_scenarios.30",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000040000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_29,
            { "Outgoing voice call during Data communication in Personal Area Network (HFP-HF_PAN-PANU)",              "btsdp.mps.mpsd_scenarios.29",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000020000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_28,
            { "Outgoing voice call during Data communication in Personal Area Network (HFP-AG_PAN-NAP)",               "btsdp.mps.mpsd_scenarios.28",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000010000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_27,
            { "Data communication in Personal Area Network during active voice call (HFP-HF_PAN-PANU)",                "btsdp.mps.mpsd_scenarios.27",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000008000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_26,
            { "Data communication in Personal Area Network during active voice call (HFP-AG_PAN-NAP)",                 "btsdp.mps.mpsd_scenarios.26",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000004000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_25,
            { "Terminate voice call / data call during data communication and voice call (HFP-HF_DUN-DT)",             "btsdp.mps.mpsd_scenarios.25",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000002000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_24,
            { "Terminate voice call / data call during data communication and voice call (HFP-AG_DUN-GW)",             "btsdp.mps.mpsd_scenarios.24",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000001000000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_23,
            { "Data communication establishment under PSDM (DUN) during Audio Streaming (A2DP-SNK_DUN-DT)",            "btsdp.mps.mpsd_scenarios.23",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000800000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_22,
            { "Data communication establishment under PSDM (DUN) during Audio Streaming (A2DP-SRC_DUN-GW)",            "btsdp.mps.mpsd_scenarios.22",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000400000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_21,
            { "Start Audio Streaming during Data communication under PSDM (DUN) (A2DP-SNK_DUN-DT)",                    "btsdp.mps.mpsd_scenarios.21",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000200000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_20,
            { "Start Audio Streaming during Data communication under PSDM (DUN) (A2DP-SRC_DUN-GW)",                    "btsdp.mps.mpsd_scenarios.20",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000100000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_19,
            { "Incoming voice call during Data communication under PSDM (DUN) (HFP-HF_DUN-DT)",                        "btsdp.mps.mpsd_scenarios.19",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000080000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_18,
            { "Incoming voice call during Data communication under PSDM (DUN) (HFP-AG_DUN-GW)",                        "btsdp.mps.mpsd_scenarios.18",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000040000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_17,
            { "Outgoing voice call during Data communication under PSDM (DUN) (HFP-HF_DUN-DT)",                        "btsdp.mps.mpsd_scenarios.17",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000020000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_16,
            { "Outgoing voice call during Data communication under PSDM (DUN) (HFP-AG_DUN-GW)",                        "btsdp.mps.mpsd_scenarios.16",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000010000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_15,
            { "Data communication under PSDM (DUN) during active voice call (HFP-HF_DUN-DT)",                          "btsdp.mps.mpsd_scenarios.15",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000008000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_14,
            { "Data communication under PSDM (DUN) during active voice call (HFP-AG_DUN-GW)",                          "btsdp.mps.mpsd_scenarios.14",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000004000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_13,
            { "Suspend Audio Streaming after AVRCP Pause/Stop (HFP-HF_A2DP-SNK)",                            "btsdp.mps.mpsd_scenarios.13",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000002000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_12,
            { "Suspend Audio Streaming after AVRCP Pause/Stop (HFP-AG_A2DP-SRC)",                            "btsdp.mps.mpsd_scenarios.12",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000001000),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_11,
            { "Start Audio Streaming after AVRCP Play Command (HFP-HF_A2DP-SNK)",                            "btsdp.mps.mpsd_scenarios.11",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000800),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_10,
            { "Start Audio Streaming after AVRCP Play Command (HFP-AG_A2DP-SRC)",                            "btsdp.mps.mpsd_scenarios.10",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000400),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_9,
            { "Press Play on Audio Player during active call (HFP-HF_A2DP-SNK)",                             "btsdp.mps.mpsd_scenarios.9",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000200),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_8,
            { "Press Play on Audio Player during active call (HFP-AG_A2DP-SRC)",                             "btsdp.mps.mpsd_scenarios.8",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000100),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_7,
            { "HFP call termination during AVP connection (HFP-HF_A2DP-SNK)",                                "btsdp.mps.mpsd_scenarios.7",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000080),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_6,
            { "HFP call termination during AVP connection (HFP-AG_A2DP-SRC)",                                "btsdp.mps.mpsd_scenarios.6",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000040),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_5,
            { "Reject/Ignore Incoming Call during Audio Streaming (HFP-HF_A2DP-SNK)",                        "btsdp.mps.mpsd_scenarios.5",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000020),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_4,
            { "Reject/Ignore Incoming Call during Audio Streaming (HFP-AG_A2DP-SRC)",                        "btsdp.mps.mpsd_scenarios.4",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000010),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_3,
            { "Outgoing Call during Audio Streaming (HFP-HF_A2DP-SNK)",                                      "btsdp.mps.mpsd_scenarios.3",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000008),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_2,
            { "Outgoing Call during Audio Streaming (HFP-AG_A2DP-SRC)",                                      "btsdp.mps.mpsd_scenarios.2",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000004),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_1,
            { "Answer Incoming Call during Audio Streaming (HFP-HF_A2DP-SNK)",                               "btsdp.mps.mpsd_scenarios.1",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000002),
            NULL, HFILL }
        },
        { &hf_mps_mpsd_scenarios_0,
            { "Answer Incoming Call during Audio Streaming (HFP-AG_A2DP-SRC)",                               "btsdp.mps.mpsd_scenarios.0",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000001),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios,
            { "Supported Profile and Protocol Dependency",                                                   "btsdp.mps.mpmd_scenarios",
            FT_UINT64, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_reserved,
            { "Reserved",                                                                                    "btsdp.mps.mpmd_scenarios.reserved",
            FT_UINT64, BASE_HEX, NULL, UINT64_C(0xFFFFFFFFFFF80000),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_18,
            { "Start Packet data communication during Audio streaming (A2DP-SNK_AVRCP-CT_DUN-DT)",           "btsdp.mps.mpmd_scenarios.18",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000040000),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_17,
            { "Start Packet data communication during Audio streaming (A2DP-SRC_AVRCP-TG)",                  "btsdp.mps.mpmd_scenarios.17",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000020000),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_16,
            { "Start Audio streaming during Data communication under PSDM (A2DP-SNK_AVRCP-CT_DUN-DT)",       "btsdp.mps.mpmd_scenarios.16",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000010000),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_15,
            { "Start Audio streaming during Data communication under PSDM (A2DP-SRC_AVRCP-TG)",              "btsdp.mps.mpmd_scenarios.15",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000008000),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_14,
            { "Suspend Audio Streaming after AVRCP Pause/Stop (A2DP-SRC_AVRCP-TG)",                          "btsdp.mps.mpmd_scenarios.14",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000004000),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_13,
            { "Suspend Audio Streaming after AVRCP Pause/Stop (AVRCP-CT where the same device does not carry out the role of an A2DP SNK)",     "btsdp.mps.mpmd_scenarios.13",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000002000),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_12,
            { "Start Audio Streaming after AVRCP Play Command (A2DP-SRC_AVRCP-TG)",                                                             "btsdp.mps.mpmd_scenarios.12",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000001000),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_11,
            { "Start Audio Streaming after AVRCP Play Command (AVRCP-CT where the same device does not carry out the role of an A2DP SNK)",     "btsdp.mps.mpmd_scenarios.11",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000800),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_10,
            { "Press Play on Audio Player during active call (A2DP-SRC_AVRCP-TG)",                 "btsdp.mps.mpmd_scenarios.10",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000400),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_9,
            { "Press Play on Audio Player during active call (HFP-HF_A2DP-SNK_AVRCP-CT)",          "btsdp.mps.mpmd_scenarios.9",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000200),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_8,
            { "HFP Call termination during AVP connection (A2DP-SRC_AVRCP-TG)",                    "btsdp.mps.mpmd_scenarios.8",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000100),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_7,
            { "HFP Call termination during AVP connection (HFP-HF_ A2DP-SNK_AVRCP-CT)",            "btsdp.mps.mpmd_scenarios.7",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000080),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_6,
            { "HFP Call termination during AVP connection (HFP-AG)",                               "btsdp.mps.mpmd_scenarios.6",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000040),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_5,
            { "Reject/Ignore Incoming Call during Audio Streaming (A2DP-SRC_AVRCP-TG)",            "btsdp.mps.mpmd_scenarios.5",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000020),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_4,
            { "Reject/Ignore Incoming Call during Audio Streaming (HFP-HF_A2DP-SNK_AVRCP-CT)",     "btsdp.mps.mpmd_scenarios.4",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000010),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_3,
            { "Outgoing Call during Audio Streaming (A2DP-SRC_AVRCP-TG)",                          "btsdp.mps.mpmd_scenarios.3",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000008),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_2,
            { "Outgoing Call during Audio Streaming (HFP-HF_A2DP-SNK_AVRCP-CT)",                   "btsdp.mps.mpmd_scenarios.2",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000004),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_1,
            { "Answer Incoming Call during Audio Streaming (A2DP-SRC_AVRCP-TG)",                   "btsdp.mps.mpmd_scenarios.1",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000002),
            NULL, HFILL }
        },
        { &hf_mps_mpmd_scenarios_0,
            { "Answer Incoming Call during Audio Streaming (HFP-HF_A2DP-SNK_AVRCP-CT)",            "btsdp.mps.mpmd_scenarios.0",
            FT_BOOLEAN, 64, NULL, UINT64_C(0x0000000000000001),
            NULL, HFILL }
        },
        { &hf_mps_supported_profile_and_protocol_dependency,
            { "Supported Profile and Protocol Dependency",           "btsdp.mps.supported_profile_and_protocol_dependency",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_mps_supported_profile_and_protocol_dependency_reserved,
            { "Reserved",                                  "btsdp.mps.supported_profile_and_protocol_dependency.reserved",
            FT_UINT16, BASE_HEX, NULL, 0xFFF8,
            NULL, HFILL }
        },
        { &hf_mps_supported_profile_and_protocol_dependency_dis_connection_order_behaviour,
            { "(Dis)Connection Order/Behaviour",           "btsdp.mps.supported_profile_and_protocol_dependency.dis_connection_order_behaviour",
            FT_BOOLEAN, 16, NULL, 0x0004,
            NULL, HFILL }
        },
        { &hf_mps_supported_profile_and_protocol_dependency_gavdp_requirements,
            { "GAVDP Requirements",                        "btsdp.mps.supported_profile_and_protocol_dependency.gavdp_requirements",
            FT_BOOLEAN, 16, NULL, 0x0002,
            NULL, HFILL }
        },
        { &hf_mps_supported_profile_and_protocol_dependency_sniff_mode_during_streaming,
            { "Sniff Mode During Streaming",               "btsdp.mps.supported_profile_and_protocol_dependency.sniff_mode_during_streaming",
            FT_BOOLEAN, 16, NULL, 0x0001,
            NULL, HFILL }
        },
        { &hf_map_supported_features,
            { "Supported Features",    "btsdp.map.supported_features",
            FT_UINT32, BASE_HEX, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_map_supported_features_reserved,
            { "Reserved",              "btsdp.map.supported_features.reserved",
            FT_UINT32, BASE_HEX, NULL, 0xFFFFFF80,
            NULL, HFILL }
        },
        { &hf_map_supported_features_extended_event_report_1_1,
            { "Extended Event Report 1.1",  "btsdp.map.supported_features.extended_event_report_1_1",
            FT_BOOLEAN, 32, NULL, 0x00000040,
            NULL, HFILL }
        },
        { &hf_map_supported_features_instance_information_feature,
            { "Instance Information Feature",  "btsdp.map.supported_features.instance_information_feature",
            FT_BOOLEAN, 32, NULL, 0x00000020,
            NULL, HFILL }
        },
        { &hf_map_supported_features_delete_feature,
            { "Delete Feature",  "btsdp.map.supported_features.delete_feature",
            FT_BOOLEAN, 32, NULL, 0x00000010,
            NULL, HFILL }
        },
        { &hf_map_supported_features_uploading_feature,
            { "Uploading Feature",  "btsdp.map.supported_features.uploading_feature",
            FT_BOOLEAN, 32, NULL, 0x00000008,
            NULL, HFILL }
        },
        { &hf_map_supported_features_browsing_feature,
            { "Browsing Feature",  "btsdp.map.supported_features.browsing_feature",
            FT_BOOLEAN, 32, NULL, 0x00000004,
            NULL, HFILL }
        },
        { &hf_map_supported_features_notification_feature,
            { "Notification Feature",  "btsdp.map.supported_features.notification_feature",
            FT_BOOLEAN, 32, NULL, 0x00000002,
            NULL, HFILL }
        },
        { &hf_map_supported_features_notification_registration_feature,
            { "Notification Registration Feature",  "btsdp.map.supported_features.notification_registration_feature",
            FT_BOOLEAN, 32, NULL, 0x00000001,
            NULL, HFILL }
        },
        { &hf_sdp_protocol_item,
            { "Protocol",                        "btsdp.protocol_item",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_protocol,
            { "Protocol Entry",                  "btsdp.protocol",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_protocol_psm,
            { "L2CAP PSM",                       "btsdp.protocol.psm",
            FT_UINT16, BASE_DEC_HEX | BASE_EXT_STRING, &ext_psm_vals, 0,
            NULL, HFILL }
        },
        { &hf_sdp_protocol_channel,
            { "RFCOMM Channel",                  "btsdp.protocol.channel",
            FT_UINT8, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_protocol_gatt_handle_start,
            { "GATT Handle Start",               "btsdp.protocol.gatt_handle_start",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_protocol_gatt_handle_end,
            { "GATT Handle Start",               "btsdp.protocol.gatt_handle_end",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_protocol_version,
            { "Protocol Version",                "btsdp.protocol.version",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_protocol_bnep_type,
            { "BNEP Type",                       "btsdp.protocol.bnep_type",
            FT_UINT16, BASE_HEX, VALS(etype_vals), 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_record_handle,
            { "Service Record Handle",           "btsdp.service_record_handle",
            FT_UINT32, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_record_state,
            { "Service Record State",            "btsdp.service_record_state",
            FT_UINT32, BASE_HEX_DEC, NULL, 0,
            NULL, HFILL }
        },

        { &hf_sdp_service_info_time_to_live,
            { "Service Info Time to Live",       "btsdp.service_info_time_to_live",
            FT_UINT32, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_availability,
            { "Service Availability",            "btsdp.service_availability",
            FT_UINT8, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_documentation_url,
            { "Documentation URL",               "btsdp.documentation_url",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_client_executable_url,
            { "Service Client Executable URL",   "btsdp.service_client_executable_url",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_icon_url,
            { "Icon URL",                        "btsdp.icon_url",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_name,
            { "Service Name",                    "btsdp.service_name",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_description,
            { "Service Description",             "btsdp.service_description",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_service_provider_name,
            { "Provider Name",                   "btsdp.provider_name",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_lang,
            { "Language",                        "btsdp.lang",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_lang_code,
            { "Language Code",                   "btsdp.lang.code",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_sdp_lang_id,
            { "Language ID",                     "btsdp.lang.id",
            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &usb_langid_vals_ext, 0,
            NULL, HFILL }
        },
        { &hf_sdp_lang_encoding,
            { "Language Encoding",               "btsdp.lang.encoding",
            FT_UINT16, BASE_DEC | BASE_EXT_STRING, &mibenum_vals_character_sets_ext, 0,
            NULL, HFILL }
        },
        { &hf_sdp_lang_attribute_base,
            { "Attribute Base",                  "btsdp.lang.attribute_base",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_device_release_number,
            { "Device Release Number",           "btsdp.service.hid.device_release_number",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_parser_version,
            { "Parser Version",                  "btsdp.service.hid.parser_version",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_device_subclass_type,
            { "Device Subclass: Type",           "btsdp.service.hid.device_subclass.type",
            FT_UINT8, BASE_HEX, VALS(hid_device_subclass_type_vals), 0xC0,
            NULL, HFILL }
        },
        { &hf_hid_device_subclass_subtype,
            { "Device Subclass: SubType",        "btsdp.service.hid.device_subclass.subtype",
            FT_UINT8, BASE_HEX, VALS(hid_device_subclass_subtype_vals), 0x3C,
            NULL, HFILL }
        },
        { &hf_hid_device_subclass_reserved,
            { "Device Subclass: Reserved",       "btsdp.service.hid.device_subclass.reserved",
            FT_UINT8, BASE_HEX, NULL, 0x03,
            NULL, HFILL }
        },
        { &hf_hid_country_code,
            { "Country Code",                    "btsdp.service.hid.country_code",
            FT_UINT8, BASE_DEC_HEX, VALS(hid_country_code_vals), 0,
            NULL, HFILL }
        },
        { &hf_hid_virtual_cable,
            { "Virtual Cable",                   "btsdp.service.hid.virtual_cable",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_reconnect_initiate,
            { "Reconnect Initiate",              "btsdp.service.hid.reconnect_initiate",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_sdp_disable,
            { "SDP Disable",                     "btsdp.service.hid.sdp_disable",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_battery_power,
            { "Battery Power",                    "btsdp.service.hid.battery_power",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_remote_wake,
            { "Remote Wake",                     "btsdp.service.hid.remote_wake",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_normally_connectable,
            { "Normally Connectable",            "btsdp.service.hid.normally_connectable",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_boot_device,
            { "Boot Device",                     "btsdp.service.hid.boot_device",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_profile_version,
            { "Profile Version",                 "btsdp.service.hid.profile_version",
            FT_UINT16, BASE_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_supervision_timeout,
            { "Supervision Timeout",             "btsdp.service.hid.supervision_timeout",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_ssr_host_max_latency,
            { "SSR Host Max Latency",            "btsdp.service.hid.ssr_host_max_latency",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_ssr_host_min_timeout,
            { "SSR Host Min Timeout",            "btsdp.service.hid.ssr_host_min_timeout",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_descriptor_list_type,
            { "Descriptor Type",                 "btsdp.service.hid.descriptor.type",
            FT_UINT8, BASE_HEX, VALS(descriptor_list_type_vals), 0,
            NULL, HFILL }
        },
        { &hf_hid_lang,
            { "Language",                        "btsdp.service.hid.lang",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_descriptor_list_descriptor_data,
            { "Descriptor",                      "btsdp.service.hid.descriptor_list.descriptor_data",
            FT_NONE, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_hid_descriptor_list_descriptor,
            { "Descriptor",                      "btsdp.service.hid.descriptor_list.descriptor",
            FT_BYTES, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bip_supported_capabilities_reserved_4_7,
            { "Supported Capabilities: Reserved",          "btsdp.service.bip.supported_capabilities.reserved",
            FT_UINT8, BASE_HEX, NULL, 0xF0,
            NULL, HFILL }
        },
        { &hf_bip_supported_capabilities_displaying,
            { "Supported Capabilities: Displaying",        "btsdp.service.bip.supported_capabilities.displaying",
            FT_BOOLEAN, 8, NULL, 0x08,
            NULL, HFILL }
        },
        { &hf_bip_supported_capabilities_printing,
            { "Supported Capabilities: Printing",          "btsdp.service.bip.supported_capabilities.printing",
            FT_BOOLEAN, 8, NULL, 0x04,
            NULL, HFILL }
        },
        { &hf_bip_supported_capabilities_capturing,
            { "Supported Capabilities: Capturing",         "btsdp.service.bip.supported_capabilities.capturing",
            FT_BOOLEAN, 8, NULL, 0x02,
            NULL, HFILL }
        },
        { &hf_bip_supported_capabilities_genering_imaging,
            { "Supported Capabilities: Genering Imaging",  "btsdp.service.bip.supported_capabilities.genering_imaging",
            FT_BOOLEAN, 8, NULL, 0x01,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_reserved_9_15,
            { "Supported Features: Reserved",              "btsdp.service.bip.supported_features.reserved",
            FT_UINT16, BASE_HEX, NULL, 0xFE00,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_remote_display,
            { "Supported Features: Remote Display",        "btsdp.service.bip.supported_features.remote_display",
            FT_BOOLEAN, 16, NULL, 0x0100,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_remote_camera,
            { "Supported Features: Remote Camera",         "btsdp.service.bip.supported_features.remote_camera",
            FT_BOOLEAN, 16, NULL, 0x0080,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_automatic_archive,
            { "Supported Features: Automatic Archive",     "btsdp.service.bip.supported_features.automatic_archive",
            FT_BOOLEAN, 16, NULL, 0x0040,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_advanced_image_printing,
            { "Supported Features: Advanced Image Printing","btsdp.service.bip.supported_features.advanced_image_printing",
            FT_BOOLEAN, 16, NULL, 0x0020,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_image_pull,
            { "Supported Features: Image Pull",            "btsdp.service.bip.supported_features.image_pull",
            FT_BOOLEAN, 16, NULL, 0x0010,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_image_push_display,
            { "Supported Features: Image Push Display",    "btsdp.service.bip.supported_features.image_push_display",
            FT_BOOLEAN, 16, NULL, 0x0008,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_image_push_print,
            { "Supported Features: Image Push Print",     "btsdp.service.bip.supported_features.image_push_print",
            FT_BOOLEAN, 16, NULL, 0x0004,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_image_push_store,
            { "Supported Features: Image Push Store",      "btsdp.service.bip.supported_features.image_push_store",
            FT_BOOLEAN, 16, NULL, 0x0002,
            NULL, HFILL }
        },
        { &hf_bip_supported_features_image_push,
            { "Supported Features: Image Push",            "btsdp.service.bip.supported_features.image_push",
            FT_BOOLEAN, 16, NULL, 0x0001,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_reserved_17_31,
            { "Supported Functions: Reserved",            "btsdp.service.bip.supported_functions.reserved",
            FT_UINT32, BASE_HEX, NULL, 0xFFFE0000,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_reserved_13_31,
            { "Supported Functions: Reserved",            "btsdp.service.bip.supported_functions.reserved",
            FT_UINT32, BASE_HEX, NULL, 0xFFFFE000,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_reserved_11_31,
            { "Supported Functions: Reserved",            "btsdp.service.bip.supported_functions.reserved",
            FT_UINT32, BASE_HEX, NULL, 0xFFFFF800,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_reserved_1_11,
            { "Supported Functions: Reserved",            "btsdp.service.bip.supported_functions.reserved",
            FT_UINT32, BASE_HEX, NULL, 0x00000FFE,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_reserved_1_4,
            { "Supported Functions: Reserved",            "btsdp.service.bip.supported_functions.reserved",
            FT_UINT32, BASE_HEX, NULL, 0x0000001E,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_status,
            { "Supported Functions: Get Status",           "btsdp.service.bip.supported_functions.get_status",
            FT_BOOLEAN, 32, NULL, 0x00010000,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_reserved_15,
            { "Supported Functions: Reserved",             "btsdp.service.bip.supported_functions.reserved_15",
            FT_BOOLEAN, 32, NULL, 0x00008000,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_monitoring_image,
            { "Supported Functions: Get Monitoring Image", "btsdp.service.bip.supported_functions.get_monitoring_image",
            FT_BOOLEAN, 32, NULL, 0x00004000,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_start_archive,
            { "Supported Functions: Start Archive",        "btsdp.service.bip.supported_functions.start_archive",
            FT_BOOLEAN, 32, NULL, 0x00002000,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_reserved_12,
            { "Supported Functions: Reserved",             "btsdp.service.bip.supported_functions.reserved_12",
            FT_BOOLEAN, 32, NULL, 0x00001000,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_partial_image,
            { "Supported Functions: Get Partial Image",    "btsdp.service.bip.supported_functions.get_partial_image",
            FT_BOOLEAN, 32, NULL, 0x00001000,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_start_print,
            { "Supported Functions: Start Print",          "btsdp.service.bip.supported_functions.start_print",
            FT_BOOLEAN, 32, NULL, 0x00000800,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_delete_image,
            { "Supported Functions: Delete Image",         "btsdp.service.bip.supported_functions.delete_image",
            FT_BOOLEAN, 32, NULL, 0x00000400,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_linked_attachment,
            { "Supported Functions: Get Linked Attachment","btsdp.service.bip.supported_functions.get_linked_attachment",
            FT_BOOLEAN, 32, NULL, 0x00000200,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_linked_thumbnail,
            { "Supported Functions: Get Linked Thumbnail", "btsdp.service.bip.supported_functions.get_linked_thumbnail",
            FT_BOOLEAN, 32, NULL, 0x00000100,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_image,
            { "Supported Functions: Get Image",            "btsdp.service.bip.supported_functions.get_image",
            FT_BOOLEAN, 32, NULL, 0x00000080,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_image_property,
            { "Supported Functions: Get Image Property",   "btsdp.service.bip.supported_functions.get_image_property",
            FT_BOOLEAN, 32, NULL, 0x00000040,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_images_list,
            { "Supported Functions: Get Images List",      "btsdp.service.bip.supported_functions.get_images_list",
            FT_BOOLEAN, 32, NULL, 0x00000020,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_remote_display,
            { "Supported Functions: Remote Display",       "btsdp.service.bip.supported_functions.remote_display",
            FT_BOOLEAN, 32, NULL, 0x00000010,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_put_linked_thumbnail,
            { "Supported Functions: Put Linked Thumbnail", "btsdp.service.bip.supported_functions.put_linked_thumbnail",
            FT_BOOLEAN, 32, NULL, 0x00000008,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_put_linked_attachment,
            { "Supported Functions: Put Linked Attachment","btsdp.service.bip.supported_functions.put_linked_attachment",
            FT_BOOLEAN, 32, NULL, 0x00000004,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_put_image,
            { "Supported Functions: Put Image",            "btsdp.service.bip.supported_functions.put_image",
            FT_BOOLEAN, 32, NULL, 0x00000002,
            NULL, HFILL }
        },
        { &hf_bip_supported_functions_get_capabilities,
            { "Supported Functions: Get Capabilities",     "btsdp.service.bip.supported_functions.get_capabilities",
            FT_BOOLEAN, 32, NULL, 0x00000001,
            NULL, HFILL }
        },
        { &hf_bip_total_imaging_data_capacity,
            { "Total Imaging Data Capacity",     "btsdp.bip.total_imaging_data_capacity",
            FT_UINT64, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bip_goep_l2cap_psm,
            { "GOEP L2CAP PSM",                  "btsdp.bip.goep_l2cap_psm",
            FT_UINT16, BASE_DEC_HEX, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_document_formats_supported,
            { "Document Formats Supported",       "btsdp.service.bpp.document_formats_supported",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_character_repertoires_support,
            { "Character Repertoires Support",   "btsdp.service.bpp.character_repertoires_support",
            FT_BYTES, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_xhtml_print_image_formats_supported,
            { "XHTML Print Image Formats Supported",       "btsdp.service.bpp.xhtml_print_image_formats_supported",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_color_supported,
            { "Color Supported",                 "btsdp.service.bpp.color_supported",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_1284_id,
            { "1284 ID",                         "btsdp.service.bpp.1284_id",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_printer_name,
            { "Printer Name",                    "btsdp.service.bpp.printer_name",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_printer_location,
            { "Printer Location",                "btsdp.service.bpp.location",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_duplex_supported,
            { "Duplex Supported",                "btsdp.service.bpp.duplex_supported",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_media_types_supported,
            { "Media Types Supported",           "btsdp.service.bpp.media_types_supported",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_max_media_width,
            { "Max Media Width",                 "btsdp.service.bpp.max_media_width",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_max_media_length,
            { "Max Media Length",                "btsdp.service.bpp.max_media_length",
            FT_UINT16, BASE_DEC, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_enhanced_layout_supported,
            { "Enhanced Layout Supported",       "btsdp.service.bpp.enhanced_layout_supported",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_rui_formats_supported,
            { "RUI Formats Supported",           "btsdp.service.bpp.rui_formats_supported",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_reference_printing_rui_supported,
            { "Reference Printing RUI Supported","btsdp.service.bpp.reference_printing_rui_supported",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_direct_printing_rui_supported,
            { "Direct Printing RUI Supported",   "btsdp.service.bpp.direct_printing_rui_supported",
            FT_BOOLEAN, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_reference_printing_top_url,
            { "Reference Printing Top URL",      "btsdp.service.bpp.reference_printing_top_url",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_direct_printing_top_url,
            { "Direct Printing Top URL",         "btsdp.service.bpp.direct_printing_top_url",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_device_name,
            { "Device Name",                     "btsdp.service.bpp.device_name",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        },
        { &hf_bpp_printer_admin_rui_top_url,
            { "Printer Admin RUI Top URL",       "btsdp.service.bpp.printer_admin_rui_top_url",
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
        }
    };

    static int *ett[] = {
        &ett_btsdp,
        &ett_btsdp_ssr,
        &ett_btsdp_des,
        &ett_btsdp_attribute,
        &ett_btsdp_attribute_id,
        &ett_btsdp_attribute_value,
        &ett_btsdp_service_search_pattern,
        &ett_btsdp_attribute_idlist,
        &ett_btsdp_continuation_state,
        &ett_btsdp_data_element,
        &ett_btsdp_data_element_value,
        &ett_btsdp_reassembled,
        &ett_btsdp_supported_features,
        &ett_btsdp_supported_features_mdep_id,
        &ett_btsdp_supported_features_mdep_data_type,
        &ett_btsdp_supported_features_mdep_role,
        &ett_btsdp_supported_features_mdep_description,
        &ett_btsdp_protocol
    };

    static ei_register_info ei[] = {
        { &ei_btsdp_continuation_state_none,  { "btsdp.expert.continuation_state_none",  PI_MALFORMED, PI_WARN,      "There is no Continuation State", EXPFILL }},
        { &ei_btsdp_continuation_state_large, { "btsdp.expert.continuation_state_large", PI_MALFORMED, PI_WARN,      "Continuation State data is longer than 16", EXPFILL }},
        { &ei_data_element_value_large,       { "btsdp.expert.data_element.value.large", PI_MALFORMED, PI_WARN,      "Data size exceeds the length of payload", EXPFILL }},
        { &ei_length_bad,      { "btsdp.expert.length.bad",      PI_MALFORMED, PI_WARN, "Invalid length", EXPFILL }},
    };

    proto_btsdp = proto_register_protocol("Bluetooth SDP Protocol", "BT SDP", "btsdp");
    btsdp_handle = register_dissector("btsdp", dissect_btsdp, proto_btsdp);

    proto_register_field_array(proto_btsdp, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));
    expert_btsdp = expert_register_protocol(proto_btsdp);
    expert_register_field_array(expert_btsdp, ei, array_length(ei));

    tid_requests = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
    continuation_states = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
    record_handle_services = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());

    service_infos = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());

    module = prefs_register_protocol_subtree("Bluetooth", proto_btsdp, NULL);
    prefs_register_static_text_preference(module, "bnep.version",
            "Bluetooth Protocol SDP version from Core 4.0",
            "Version of protocol supported by this dissector.");
}


void
proto_reg_handoff_btsdp(void)
{
    dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_SDP, btsdp_handle);
    dissector_add_for_decode_as("btl2cap.cid", btsdp_handle);
}

/*
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 4
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 *
 * vi: set shiftwidth=4 tabstop=8 expandtab:
 * :indentSize=4:tabSize=8:noTabs=true:
 */
