Bluetooth/Ubertooth improvements. Bug 9606 (https://bugs.wireshark.org/bugzilla...
authormmann <mmann@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 12 Jan 2014 00:50:41 +0000 (00:50 +0000)
committermmann <mmann@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 12 Jan 2014 00:50:41 +0000 (00:50 +0000)
From Michal Labedski

1. add support for new btsnoop "format" introduced by BlueZ team in "btmon" tool
2. Bluetooth: Make EIR, AD and COD more generic
3. Bluetooth: HCI/LL: Update Error Codes to Core 4.1  Specification
4. Ubertooth: Fix response command handling
5. Ubertooth: Update to support firmware version
6. Ubertooth: Dissect by Vendor Id/Product Id

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@54699 f5534014-38df-0310-8fa8-9805f1628bb7

13 files changed:
epan/CMakeLists.txt
epan/dissectors/Makefile.common
epan/dissectors/packet-bluetooth-hci.h
epan/dissectors/packet-bthci_cmd.c
epan/dissectors/packet-bthci_evt.c
epan/dissectors/packet-btle.c
epan/dissectors/packet-btsdp.c
epan/dissectors/packet-btsdp.h
epan/dissectors/packet-hci_mon.c [new file with mode: 0644]
epan/dissectors/packet-ubertooth.c
wiretap/btsnoop.c
wiretap/wtap.c
wiretap/wtap.h

index 1ecaad13c6f56eddfc34f7a619926369da14948c..0a47ae65006899583ffc5dc3ef519cbca1e1f349 100644 (file)
@@ -731,6 +731,7 @@ set(DISSECTOR_SRC
        dissectors/packet-hazelcast.c
        dissectors/packet-hci_h1.c
        dissectors/packet-hci_h4.c
+       dissectors/packet-hci_mon.c
        dissectors/packet-hci_usb.c
        dissectors/packet-hclnfsd.c
        dissectors/packet-hdcp.c
index 0145dd56ee6fe5448b9c837acada92b82a282a15..007077813c3eba372817f9925e7e7e17255f9082 100644 (file)
@@ -654,6 +654,7 @@ DISSECTOR_SRC = \
        packet-hazelcast.c      \
        packet-hci_h1.c         \
        packet-hci_h4.c         \
+       packet-hci_mon.c        \
        packet-hci_usb.c        \
        packet-hclnfsd.c        \
        packet-hdcp.c           \
index 658cd5f54f919b870cb7bd936ac44cea3e02f5ce..c1929accfbba61f9e2c77f635d07175fe7ef25e0 100644 (file)
@@ -67,19 +67,6 @@ extern value_string_ext bthci_cmd_auth_req_vals_ext;
 extern value_string_ext bthci_cmd_appearance_vals_ext;
 extern value_string_ext bthci_evt_comp_id_ext;
 
-extern value_string_ext bthci_cmd_cod_major_device_class_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_computer_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_phone_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_lan_net_load_factor_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_lan_net_type_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_audio_video_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_peripheral_class_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_peripheral_type_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_imaging_type_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_wearable_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_toy_vals_ext;
-extern value_string_ext bthci_cmd_cod_minor_device_class_health_vals_ext;
-
 extern const value_string bthci_cmd_io_capability_vals[];
 extern const value_string bthci_cmd_oob_data_present_vals[];
 extern const value_string bthci_cmd_address_types_vals[];
@@ -103,6 +90,7 @@ extern const value_string bthci_cmd_notification_types[];
 #define HCI_INTERFACE_H4   1
 #define HCI_INTERFACE_USB  2
 #define HCI_INTERFACE_AMP  3
+#define HCI_INTERFACE_MON  4
 
 #define HCI_ADAPTER_DEFAULT 0
 
@@ -144,4 +132,7 @@ typedef struct _localhost_name_entry_t {
     gchar    *name;
 } localhost_name_entry_t;
 
+/* In "packet-btle.c" */
+extern gint dissect_bd_addr(gint hf_bd_addr, proto_tree *tree, tvbuff_t *tvb, gint offset);
+
 #endif
index 738cffb173802954ab13ee9fbddaa15872ab080e..95e3bc165695b8b27f05faf3a15f88830833693d 100644 (file)
 #include <epan/prefs.h>
 
 #include "packet-bluetooth-hci.h"
+#include "packet-btsdp.h"
 
-/* Initialize the protocol and registered fields */
 static int proto_bthci_cmd = -1;
+
 static int hf_bthci_cmd_opcode = -1;
 static int hf_bthci_cmd_ogf = -1;
 static int hf_bthci_cmd_ocf = -1;
@@ -115,36 +116,7 @@ static int hf_bthci_cmd_link_policy_setting_park = -1;
 static int hf_bthci_cmd_filter_type = -1;
 static int hf_bthci_cmd_inquiry_result_filter_condition_type = -1;
 static int hf_bthci_cmd_connection_setup_filter_condition_type = -1;
-static int hf_bthci_cmd_class_of_device = -1;
-static int hf_bthci_cmd_cod_format_type = -1;
-static int hf_bthci_cmd_cod_major_service_class_information = -1;
-static int hf_bthci_cmd_cod_major_service_class_telephony = -1;
-static int hf_bthci_cmd_cod_major_service_class_audio = -1;
-static int hf_bthci_cmd_cod_major_service_class_object_transfer = -1;
-static int hf_bthci_cmd_cod_major_service_class_capturing = -1;
-static int hf_bthci_cmd_cod_major_service_class_rendering = -1;
-static int hf_bthci_cmd_cod_major_service_class_networking = -1;
-static int hf_bthci_cmd_cod_major_service_class_positioning = -1;
-static int hf_bthci_cmd_cod_major_service_class_reserved = -1;
-static int hf_bthci_cmd_cod_major_service_class_limited_discoverable_mode = -1;
-static int hf_bthci_cmd_cod_major_device_class = -1;
-static int hf_bthci_cmd_cod_minor_device_class_computer = -1;
-static int hf_bthci_cmd_cod_minor_device_class_phone = -1;
-static int hf_bthci_cmd_cod_minor_device_class_lan_net_load_factor = -1;
-static int hf_bthci_cmd_cod_minor_device_class_lan_net_type = -1;
-static int hf_bthci_cmd_cod_minor_device_class_audio_video = -1;
-static int hf_bthci_cmd_cod_minor_device_class_peripheral_class = -1;
-static int hf_bthci_cmd_cod_minor_device_class_peripheral_type = -1;
-static int hf_bthci_cmd_cod_minor_device_class_imaging_class_printer = -1;
-static int hf_bthci_cmd_cod_minor_device_class_imaging_class_scanner = -1;
-static int hf_bthci_cmd_cod_minor_device_class_imaging_class_camera = -1;
-static int hf_bthci_cmd_cod_minor_device_class_imaging_class_display = -1;
-static int hf_bthci_cmd_cod_minor_device_class_imaging_type = -1;
-static int hf_bthci_cmd_cod_minor_device_class_wearable = -1;
-static int hf_bthci_cmd_cod_minor_device_class_toy = -1;
-static int hf_bthci_cmd_cod_minor_device_class_health = -1;
-static int hf_bthci_cmd_cod_minor_device_class_unknown = -1;
-static int hf_bthci_cmd_class_of_device_mask = -1;
+static int hf_bthci_cmd_cod_class_of_device_mask = -1;
 static int hf_bthci_cmd_cod_minor_device_class_mask= -1;
 static int hf_bthci_cmd_cod_format_type_mask = -1;
 static int hf_bthci_cmd_cod_major_service_class_information_mask = -1;
@@ -270,12 +242,6 @@ static int hf_bthci_cmd_hash_c = -1;
 static int hf_bthci_cmd_simple_pairing_mode = -1;
 static int hf_bthci_cmd_simple_pairing_debug_mode = -1;
 static int hf_bthci_cmd_notification_type = -1;
-static int hf_bthci_cmd_eir_data = -1;
-static int hf_bthci_cmd_eir_struct_length = -1;
-static int hf_bthci_cmd_eir_struct_type = -1;
-static int hf_bthci_cmd_sc_uuid16 = -1;
-static int hf_bthci_cmd_sc_uuid32 = -1;
-static int hf_bthci_cmd_sc_uuid128 = -1;
 static int hf_bthci_cmd_physical_link_handle = -1;
 static int hf_bthci_cmd_dedicated_amp_key_length = -1;
 static int hf_bthci_cmd_dedicated_amp_key_type = -1;
@@ -358,45 +324,7 @@ static int hf_bthci_cmd_rx_freqency = -1;
 static int hf_bthci_cmd_tx_freqency = -1;
 static int hf_bthci_cmd_test_data_length = -1;
 static int hf_bthci_cmd_test_packet_payload = -1;
-static int hf_bthci_cmd_appearance = -1;
-static int hf_bthci_cmd_flags_limited_disc_mode = -1;
-static int hf_bthci_cmd_flags_general_disc_mode = -1;
-static int hf_bthci_cmd_flags_bredr_not_support = -1;
-static int hf_bthci_cmd_flags_le_bredr_support_ctrl = -1;
-static int hf_bthci_cmd_flags_le_bredr_support_host = -1;
-static int hf_bthci_cmd_flags_le_oob_data_present = -1;
-static int hf_bthci_cmd_flags_le_oob_le_supported_host = -1;
-static int hf_bthci_cmd_flags_le_oob_le_bredr_support = -1;
-static int hf_bthci_cmd_flags_le_oob_address_type = -1;
-static int hf_bthci_cmd_eir_ad_advertising_interval = -1;
-static int hf_bthci_cmd_eir_ad_ssp_oob_length = -1;
-static int hf_bthci_cmd_eir_ad_company_id = -1;
-static int hf_eir_ad_item = -1;
-static int hf_extended_inquiry_response_data = -1;
-static int hf_advertising_data = -1;
-static int hf_3ds_association_notification = -1;
-static int hf_3ds_battery_level_reporting = -1;
-static int hf_3ds_send_battery_level_report_on_startup = -1;
-static int hf_3ds_reserved = -1;
-static int hf_3ds_factory_test_mode = -1;
-static int hf_3ds_path_loss_threshold = -1;
-static int hf_3ds_legacy_fixed = -1;
-static int hf_3ds_legacy_3d_capable_tv = -1;
-static int hf_3ds_legacy_ignored_1_3 = -1;
-static int hf_3ds_legacy_fixed_4 = -1;
-static int hf_3ds_legacy_ignored_5 = -1;
-static int hf_3ds_legacy_fixed_6 = -1;
-static int hf_3ds_legacy_test_mode = -1;
-static int hf_3ds_legacy_path_loss_threshold = -1;
-static int hf_did_vendor_id = -1;
-static int hf_did_vendor_id_bluetooth_sig = -1;
-static int hf_did_vendor_id_usb_forum = -1;
-static int hf_did_product_id = -1;
-static int hf_did_version = -1;
-static int hf_did_vendor_id_source = -1;
-
-static expert_field ei_eir_undecoded                                  = EI_INIT;
-static expert_field ei_eir_unknown                                    = EI_INIT;
+
 static expert_field ei_command_undecoded                              = EI_INIT;
 static expert_field ei_command_unknown                                = EI_INIT;
 static expert_field ei_command_parameter_unexpected                   = EI_INIT;
@@ -404,12 +332,106 @@ static expert_field ei_command_parameter_unexpected                   = EI_INIT;
 /* Initialize the subtree pointers */
 static gint ett_bthci_cmd = -1;
 static gint ett_opcode = -1;
-static gint ett_cod = -1;
 static gint ett_cod_mask = -1;
-static gint ett_eir_subtree = -1;
-static gint ett_eir_struct_subtree = -1;
 static gint ett_flow_spec_subtree = -1;
 
+static gint proto_btcommon = -1;
+static gint hf_btcommon_eir_ad_entry = -1;
+static gint hf_btcommon_eir_ad_advertising_data = -1;
+static gint hf_btcommon_eir_ad_extended_inquiry_response_data = -1;
+static gint hf_btcommon_eir_ad_unused = -1;
+static gint hf_btcommon_eir_ad_data = -1;
+static gint hf_btcommon_eir_ad_length = -1;
+static gint hf_btcommon_eir_ad_type = -1;
+static gint hf_btcommon_eir_ad_company_id = -1;
+static gint hf_btcommon_eir_ad_flags_reserved = -1;
+static gint hf_btcommon_eir_ad_flags_le_bredr_support_host = -1;
+static gint hf_btcommon_eir_ad_flags_le_bredr_support_controller = -1;
+static gint hf_btcommon_eir_ad_flags_bredr_not_support = -1;
+static gint hf_btcommon_eir_ad_flags_le_general_discoverable_mode = -1;
+static gint hf_btcommon_eir_ad_flags_le_limited_discoverable_mode = -1;
+static gint hf_btcommon_eir_ad_uuid_16 = -1;
+static gint hf_btcommon_eir_ad_uuid_32 = -1;
+static gint hf_btcommon_eir_ad_uuid_128 = -1;
+static gint hf_btcommon_eir_ad_custom_uuid = -1;
+static gint hf_btcommon_eir_ad_name = -1;
+static gint hf_btcommon_eir_ad_tx_power = -1;
+static gint hf_btcommon_eir_ad_ssp_oob_length = -1;
+static gint hf_btcommon_eir_ad_bd_addr = -1;
+static gint hf_btcommon_eir_ad_le_bd_addr_reserved = -1;
+static gint hf_btcommon_eir_ad_le_bd_addr_type = -1;
+static gint hf_btcommon_eir_ad_le_role = -1;
+static gint hf_btcommon_eir_ad_did_vendor_id = -1;
+static gint hf_btcommon_eir_ad_did_vendor_id_bluetooth_sig = -1;
+static gint hf_btcommon_eir_ad_did_vendor_id_usb_forum = -1;
+static gint hf_btcommon_eir_ad_did_product_id = -1;
+static gint hf_btcommon_eir_ad_did_version = -1;
+static gint hf_btcommon_eir_ad_did_vendor_id_source = -1;
+static gint hf_btcommon_eir_ad_3ds_association_notification = -1;
+static gint hf_btcommon_eir_ad_3ds_battery_level_reporting = -1;
+static gint hf_btcommon_eir_ad_3ds_send_battery_level_report_on_startup = -1;
+static gint hf_btcommon_eir_ad_3ds_reserved = -1;
+static gint hf_btcommon_eir_ad_3ds_factory_test_mode = -1;
+static gint hf_btcommon_eir_ad_3ds_path_loss_threshold = -1;
+static gint hf_btcommon_eir_ad_3ds_legacy_fixed = -1;
+static gint hf_btcommon_eir_ad_3ds_legacy_3d_capable_tv = -1;
+static gint hf_btcommon_eir_ad_3ds_legacy_ignored_1_3 = -1;
+static gint hf_btcommon_eir_ad_3ds_legacy_fixed_4 = -1;
+static gint hf_btcommon_eir_ad_3ds_legacy_ignored_5 = -1;
+static gint hf_btcommon_eir_ad_3ds_legacy_fixed_6 = -1;
+static gint hf_btcommon_eir_ad_3ds_legacy_test_mode = -1;
+static gint hf_btcommon_eir_ad_3ds_legacy_path_loss_threshold = -1;
+static gint hf_btcommon_eir_ad_advertising_interval = -1;
+static gint hf_btcommon_eir_ad_appearance = -1;
+static gint hf_btcommon_eir_ad_hash_c = -1;
+static gint hf_btcommon_eir_ad_randomizer_r = -1;
+static gint hf_btcommon_eir_ad_oob_flags_data_present = -1;
+static gint hf_btcommon_eir_ad_oob_flags_le_supported_host = -1;
+static gint hf_btcommon_eir_ad_oob_flags_le_bredr_support = -1;
+static gint hf_btcommon_eir_ad_oob_flags_address_type = -1;
+static gint hf_btcommon_eir_ad_oob_flags_reserved = -1;
+static gint hf_btcommon_eir_ad_connection_interval_min = -1;
+static gint hf_btcommon_eir_ad_connection_interval_max = -1;
+static gint hf_btcommon_cod_class_of_device = -1;
+static gint hf_btcommon_cod_format_type = -1;
+static gint hf_btcommon_cod_major_service_class_information = -1;
+static gint hf_btcommon_cod_major_service_class_telephony = -1;
+static gint hf_btcommon_cod_major_service_class_audio = -1;
+static gint hf_btcommon_cod_major_service_class_object_transfer = -1;
+static gint hf_btcommon_cod_major_service_class_capturing = -1;
+static gint hf_btcommon_cod_major_service_class_rendering = -1;
+static gint hf_btcommon_cod_major_service_class_networking = -1;
+static gint hf_btcommon_cod_major_service_class_positioning = -1;
+static gint hf_btcommon_cod_major_service_class_reserved = -1;
+static gint hf_btcommon_cod_major_service_class_limited_discoverable_mode = -1;
+static gint hf_btcommon_cod_major_device_class = -1;
+static gint hf_btcommon_cod_minor_device_class_computer = -1;
+static gint hf_btcommon_cod_minor_device_class_phone = -1;
+static gint hf_btcommon_cod_minor_device_class_lan_net_load_factor = -1;
+static gint hf_btcommon_cod_minor_device_class_lan_net_type = -1;
+static gint hf_btcommon_cod_minor_device_class_audio_video = -1;
+static gint hf_btcommon_cod_minor_device_class_peripheral_class = -1;
+static gint hf_btcommon_cod_minor_device_class_peripheral_type = -1;
+static gint hf_btcommon_cod_minor_device_class_imaging_class_printer = -1;
+static gint hf_btcommon_cod_minor_device_class_imaging_class_scanner = -1;
+static gint hf_btcommon_cod_minor_device_class_imaging_class_camera = -1;
+static gint hf_btcommon_cod_minor_device_class_imaging_class_display = -1;
+static gint hf_btcommon_cod_minor_device_class_imaging_type = -1;
+static gint hf_btcommon_cod_minor_device_class_wearable = -1;
+static gint hf_btcommon_cod_minor_device_class_toy = -1;
+static gint hf_btcommon_cod_minor_device_class_health = -1;
+static gint hf_btcommon_cod_minor_device_class_unknown = -1;
+
+static gint ett_cod = -1;
+static gint ett_eir_ad = -1;
+static gint ett_eir_ad_entry = -1;
+
+static expert_field ei_eir_ad_undecoded                               = EI_INIT;
+static expert_field ei_eir_ad_unknown                                 = EI_INIT;
+
+static dissector_handle_t btcommon_cod_handle;
+static dissector_handle_t btcommon_eir_handle;
+static dissector_handle_t btcommon_ad_handle;
 static dissector_handle_t bthci_cmd_handle;
 
 extern value_string_ext ext_usb_vendors_vals;
@@ -714,44 +736,44 @@ value_string_ext bthci_cmd_opcode_vals_ext = VALUE_STRING_EXT_INIT(bthci_cmd_opc
 static const value_string bthci_cmd_status_vals[] = {
     {0x00, "Success"},
     {0x01, "Unknown HCI Command"},
-    {0x02, "No Connection"},
+    {0x02, "Unknown Connection Identifier"},
     {0x03, "Hardware Failure"},
     {0x04, "Page Timeout"},
     {0x05, "Authentication Failure"},
-    {0x06, "Key Missing"},
-    {0x07, "Memory Full"},
+    {0x06, "PIN or Key Missing"},
+    {0x07, "Memory Capacity Exceeded"},
     {0x08, "Connection Timeout"},
-    {0x09, "Max Number Of Connections"},
-    {0x0A, "Max Number Of SCO Connections To A Device"},
-    {0x0B, "ACL connection already exists"},
+    {0x09, "Connection Limit Exceeded"},
+    {0x0A, "Synchronous Connection Limit To A Device Exceeded"},
+    {0x0B, "ACL Connection Already Exists"},
     {0x0C, "Command Disallowed"},
-    {0x0D, "Host Rejected due to limited resources"},
-    {0x0E, "Host Rejected due to security reasons"},
-    {0x0F, "Host Rejected due to remote device is only a personal device"},
-    {0x10, "Host Timeout"},
+    {0x0D, "Connection Rejected due to Limited Resources"},
+    {0x0E, "Connection Rejected due To Security Reasons"},
+    {0x0F, "Connection Rejected due to Unacceptable BD_ADDR"},
+    {0x10, "Connection Accept Timeout Exceeded"},
     {0x11, "Unsupported Feature or Parameter Value"},
     {0x12, "Invalid HCI Command Parameters"},
-    {0x13, "Other End Terminated Connection: User Ended Connection"},
-    {0x14, "Other End Terminated Connection: Low Resources"},
-    {0x15, "Other End Terminated Connection: About to Power Off"},
+    {0x13, "Remote User Terminated Connection"},
+    {0x14, "Remote Device Terminated Connection due to Low Resources"},
+    {0x15, "Remote Device Terminated Connection due to Power Off"},
     {0x16, "Connection Terminated by Local Host"},
     {0x17, "Repeated Attempts"},
     {0x18, "Pairing Not Allowed"},
     {0x19, "Unknown LMP PDU"},
-    {0x1A, "Unsupported Remote Feature"},
+    {0x1A, "Unsupported Remote/LMP Feature"},
     {0x1B, "SCO Offset Rejected"},
     {0x1C, "SCO Interval Rejected"},
     {0x1D, "SCO Air Mode Rejected"},
-    {0x1E, "Invalid LMP Parameters"},
+    {0x1E, "Invalid LMP/LL Parameters"},
     {0x1F, "Unspecified Error"},
-    {0x20, "Unsupported LMP Parameter Value"},
+    {0x20, "Unsupported LMP/LL Parameter Value"},
     {0x21, "Role Change Not Allowed"},
-    {0x22, "LMP Response Timeout"},
+    {0x22, "LMP/LL Response Timeout"},
     {0x23, "LMP Error Transaction Collision"},
     {0x24, "LMP PDU Not Allowed"},
     {0x25, "Encryption Mode Not Acceptable"},
-    {0x26, "Unit Key Used"},
-    {0x27, "QoS is Not Supported"},
+    {0x26, "Link Key cannot be Changed"},
+    {0x27, "Requested QoS Not Supported"},
     {0x28, "Instant Passed"},
     {0x29, "Pairing with Unit Key Not Supported"},
     {0x2A, "Different Transaction Collision"},
@@ -760,21 +782,20 @@ static const value_string bthci_cmd_status_vals[] = {
     {0x2E, "Channel Classification Not Supported"},
     {0x2F, "Insufficient Security"},
     {0x30, "Parameter Out Of Mandatory Range"},
-    {0x31, "Unknown"},
     {0x32, "Role Switch Pending"},
-    {0x33, "Unknown"},
     {0x34, "Reserved Slot Violation"},
     {0x35, "Role Switch Failed"},
     {0x36, "Extended Inquiry Response Too Large"},
     {0x37, "Secure Simple Pairing Not Supported By Host"},
     {0x38, "Host Busy - Pairing"},
-    {0x39, "Connection Rejected - No Suitable Channel Found"},
-    {0x3a, "Controller Busy"},
-    {0x3b, "Unacceptable Connection Interval"},
-    {0x3c, "Directed Advertising Timeout"},
-    {0x3d, "Connection Terminated - MIC Failure"},
-    {0x3e, "Connection Failed To Be Established"},
-    {0x3f, "MAC Connection Failed"},
+    {0x39, "Connection Rejected due to No Suitable Channel Found"},
+    {0x3A, "Controller Busy"},
+    {0x3B, "Unacceptable Connection Parameters"},
+    {0x3C, "Directed Advertising Timeout"},
+    {0x3D, "Connection Terminated due to MIC Failure"},
+    {0x3E, "Connection Failed to be Established"},
+    {0x3F, "MAC Connection Failed"},
+    {0x40, "Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging"},
     {0, NULL }
 };
 value_string_ext bthci_cmd_status_vals_ext = VALUE_STRING_EXT_INIT(bthci_cmd_status_vals);
@@ -1045,58 +1066,74 @@ static const value_string bthci_cmd_eir_data_type_vals[] = {
     {0x12, "Slave Connection Interval Range" },
     {0x14, "List of 16-bit Service Solicitation UUIDs" },
     {0x15, "List of 128-bit Service Solicitation UUIDs" },
-    {0x16, "Service Data" },
+    {0x16, "Service Data - 16 bit UUID" },
     {0x17, "Public Target Address" },
     {0x18, "Random Target Address" },
     {0x19, "Appearance" },
     {0x1A, "Advertising Interval" },
+    {0x1B, "LE Bluetooth Device Address" },
+    {0x1C, "LE Role" },
+    {0x1D, "Simple Pairing Hash C-256" },
+    {0x1E, "Simple Pairing Randomizer R-256" },
+    {0x1F, "List of 32-bit Service Solicitation UUIDs" },
+    {0x20, "Service Data - 32 bit UUID" },
+    {0x21, "Service Data - 128 bit UUID" },
     {0x3D, "3D Information Data" },
     {0xFF, "Manufacturer Specific" },
     {   0, NULL }
 };
 value_string_ext bthci_cmd_eir_data_type_vals_ext = VALUE_STRING_EXT_INIT(bthci_cmd_eir_data_type_vals);
 
+/* Updating based on https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml  */
 static const value_string bthci_cmd_appearance_vals[] = {
-    { 0x0000, "Unknown" },
-    { 0x0040, "Generic Phone" },
-    { 0x0080, "Generic Computer" },
-    { 0x00C0, "Generic Watch" },
-    { 0x00C1, "Sports Watch" },
-    { 0x0100, "Generic Clock" },
-    { 0x0140, "Generic Display" },
-    { 0x0180, "Generic Remote Control" },
-    { 0x01C0, "Generic Eye-glasses" },
-    { 0x0200, "Generic Tag" },
-    { 0x0240, "Generic Keyring" },
-    { 0x0280, "Generic Media Player" },
-    { 0x02C0, "Generic Barcode Scanner" },
-    { 0x0300, "Generic Thermometer" },
-    { 0x0301, "Ear Thermometer" },
-    { 0x0340, "Generic Heart Rate Sensor" },
-    { 0x0341, "Heart Rate Belt Sensor" },
-    { 0x0380, "Generic Blood Pressure" },
-    { 0x0381, "Arm Blood Pressure" },
-    { 0x0382, "Wrist Blood Pressure" },
-    { 0x03C0, "Human Interface Device (HID)" },
-    { 0x03C1, "Keyboard" },
-    { 0x03C2, "Mouse" },
-    { 0x03C3, "Joystick" },
-    { 0x03C4, "Gamepad" },
-    { 0x03C5, "Digitizer Tablet" },
-    { 0x03C6, "Card Reader" },
-    { 0x03C7, "Digital Pen" },
-    { 0x03C8, "Barcode Scanner" },
-    { 0x0400, "Generic Glucose Meter" },
-    { 0x0440, "Generic Running/Walking Sensor" },
-    { 0x0441, "In-shoe Running/Walking Sensor" },
-    { 0x0442, "On-shoe Running/Walking Sensor" },
-    { 0x0443, "On-hip Running/Walking Sensor" },
-    { 0x0480, "Generic Cycling Sensor" },
-    { 0x0481, "Cycling Computer" },
-    { 0x0482, "Cycling Speed Sensor" },
-    { 0x0483, "Cycling Cadence Sensor" },
-    { 0x0484, "Cycling Power Sensor" },
-    { 0x0485, "Cycling Speed and Cadence Sensor" },
+    {    0,  "Unknown" },
+    {   64,  "Generic Phone" },
+    {  128,  "Generic Computer" },
+    {  192,  "Generic Watch" },
+    {  193,  "Watch: Sports Watch" },
+    {  256,  "Generic Clock" },
+    {  320,  "Generic Display" },
+    {  384,  "Generic Remote Control" },
+    {  448,  "Generic Eye-glasses" },
+    {  512,  "Generic Tag" },
+    {  576,  "Generic Keyring" },
+    {  640,  "Generic Media Player" },
+    {  704,  "Generic Barcode Scanner" },
+    {  768,  "Generic Thermometer" },
+    {  769,  "Thermometer: Ear" },
+    {  832,  "Generic Heart rate Sensor" },
+    {  833,  "Heart Rate Sensor: Heart Rate Belt" },
+    {  896,  "Generic Blood Pressure" },
+    {  897,  "Blood Pressure: Arm" },
+    {  898,  "Blood Pressure: Wrist" },
+    {  960,  "Human Interface Device (HID)" },
+    {  961,  "Keyboard" },
+    {  962,  "Mouse" },
+    {  963,  "Joystick" },
+    {  964,  "Gamepad" },
+    {  965,  "Digitizer Tablet" },
+    {  966,  "Card Reader" },
+    {  967,  "Digital Pen" },
+    {  968,  "Barcode Scanner" },
+    { 1024,  "Generic Glucose Meter" },
+    { 1088,  "Generic: Running Walking Sensor" },
+    { 1089,  "Running Walking Sensor: In-Shoe" },
+    { 1090,  "Running Walking Sensor: On-Shoe" },
+    { 1091,  "Running Walking Sensor: On-Hip" },
+    { 1152,  "Generic: Cycling" },
+    { 1153,  "Cycling: Cycling Computer" },
+    { 1154,  "Cycling: Speed Sensor" },
+    { 1155,  "Cycling: Cadence Sensor" },
+    { 1156,  "Cycling: Power Sensor" },
+    { 1157,  "Cycling: Speed and Cadence Sensor" },
+    { 3136,  "Generic" },
+    { 3137,  "Fingertip" },
+    { 3138,  "Wrist Worn" },
+    { 5184,  "Generic" },
+    { 5185,  "Location Display Device" },
+    { 5186,  "Location and Navigation Display Device" },
+    { 5187,  "Location Pod" },
+    { 5188,  "Location and Navigation Pod" },
     { 0, NULL }
 };
 value_string_ext bthci_cmd_appearance_vals_ext = VALUE_STRING_EXT_INIT(bthci_cmd_appearance_vals);
@@ -1425,128 +1462,69 @@ static const value_string cmd_le_test_pkt_payload[] = {
     { 0, NULL }
 };
 
+static const value_string le_role_vals[] = {
+    { 0x00, "Only Peripheral Role Supported" },
+    { 0x01, "Only Central Role Supported" },
+    { 0x02, "Peripheral and Central Role supported, Peripheral Role preferred for connection establishment" },
+    { 0x03, "Peripheral and Central Role supported, Central Role preferred for connection establishment" },
+    { 0, NULL }
+};
+value_string_ext le_role_vals_ext = VALUE_STRING_EXT_INIT(le_role_vals);
+
+
 void proto_register_bthci_cmd(void);
 void proto_reg_handoff_bthci_cmd(void);
+void proto_register_btcommon(void);
 
-static int
-dissect_bthci_cmd_bd_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+static void
+save_local_device_name(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+        guint8 size, hci_data_t *hci_data)
 {
-    guint8 bd_addr[6];
-
-    bd_addr[5] = tvb_get_guint8(tvb, offset);
-    bd_addr[4] = tvb_get_guint8(tvb, offset + 1);
-    bd_addr[3] = tvb_get_guint8(tvb, offset + 2);
-    bd_addr[2] = tvb_get_guint8(tvb, offset + 3);
-    bd_addr[1] = tvb_get_guint8(tvb, offset + 4);
-    bd_addr[0] = tvb_get_guint8(tvb, offset + 5);
+    gint                    i = 0;
+    guint8                  length;
+    wmem_tree_key_t         key[4];
+    guint32                 k_interface_id;
+    guint32                 k_adapter_id;
+    guint32                 k_frame_number;
+    gchar                   *name;
+    localhost_name_entry_t  *localhost_name_entry;
+
+    if (!(!pinfo->fd->flags.visited && hci_data)) return;
+
+    while (i < size) {
+        length = tvb_get_guint8(tvb, offset + i);
+        if (length == 0) break;
 
-    proto_tree_add_ether(tree, hf_bthci_cmd_bd_addr, tvb, offset, 6, bd_addr);
-    offset += 6;
+        switch(tvb_get_guint8(tvb, offset + i + 1)) {
+        case 0x08: /* Device Name, shortened */
+        case 0x09: /* Device Name, full */
+            name = tvb_get_string(wmem_packet_scope(), tvb, offset + i + 2, length - 1);
 
-    return offset;
-}
+            k_interface_id = hci_data->interface_id;
+            k_adapter_id = hci_data->adapter_id;
+            k_frame_number = pinfo->fd->num;
 
-static int
-dissect_bthci_cmd_cod(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
-{
-    guint16      major_service_classes;
-    guint8       major_device_class;
-    guint8       minor_device_class;
-    const gchar *minor_device_class_name;
-    proto_item  *cod_item;
-    proto_item  *cod_tree;
+            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_frame_number;
+            key[3].length = 0;
+            key[3].key    = NULL;
 
-    cod_item = proto_tree_add_item(tree, hf_bthci_cmd_class_of_device, tvb, offset, 3, ENC_LITTLE_ENDIAN);
-    cod_tree = proto_item_add_subtree(cod_item, ett_cod);
+            localhost_name_entry = (localhost_name_entry_t *) wmem_new(wmem_file_scope(), localhost_name_entry_t);
+            localhost_name_entry->interface_id = k_interface_id;
+            localhost_name_entry->adapter_id = k_adapter_id;
+            localhost_name_entry->name = wmem_strdup(wmem_file_scope(), name);
 
-    major_device_class = tvb_get_guint8(tvb, offset + 1) & 0x1F;
-    minor_device_class = tvb_get_guint8(tvb, offset) >> 2;
+            wmem_tree_insert32_array(hci_data->localhost_name, key, localhost_name_entry);
 
-    switch(major_device_class) {
-    case 0x01: /* Computer */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_computer, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_computer_vals_ext, "Unknown");
-        break;
-    case 0x02: /* Phone */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_phone, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_phone_vals_ext, "Unknown");
-        break;
-    case 0x03: /* LAN/Network Access Point */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_lan_net_load_factor, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_lan_net_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_lan_net_load_factor_vals_ext, "Unknown");
-        break;
-    case 0x04: /* Audio/Video */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_audio_video, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_audio_video_vals_ext, "Unknown");
-        break;
-    case 0x05: /* Peripheral */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_peripheral_class, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_peripheral_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_peripheral_class_vals_ext, "Unknown");
-        break;
-    case 0x06: /* Imaging */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_imaging_class_printer, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_imaging_class_scanner, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_imaging_class_camera, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_imaging_class_display, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+            break;
+        }
 
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_imaging_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, "Unknown");
-        break;
-    case 0x07: /* Wearable */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_wearable, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_wearable_vals_ext, "Unknown");
-        break;
-    case 0x08: /* Toy */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_toy, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_toy_vals_ext, "Unknown");
-        break;
-    case 0x09: /* Health */
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_health, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_health_vals_ext, "Unknown");
-        break;
-    default:
-        minor_device_class_name = "Unknown";
-        proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_minor_device_class_unknown, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        i += length + 1;
     }
-
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_format_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-    offset += 1;
-
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_information, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_telephony, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_audio, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_object_transfer, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_capturing, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_rendering, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_networking, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_positioning, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_service_class_limited_discoverable_mode, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    major_service_classes = tvb_get_letohs(tvb, offset) >> 5;
-
-    proto_tree_add_item(cod_tree, hf_bthci_cmd_cod_major_device_class, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    offset += 2;
-
-    proto_item_append_text(cod_item, " (%s:%s - services:",
-            val_to_str_ext_const(major_device_class, &bthci_cmd_cod_major_device_class_vals_ext, "Unknown"),
-            minor_device_class_name);
-
-    if (major_service_classes & 0x001) proto_item_append_text(cod_item, " LimitedDiscoverableMode");
-    if (major_service_classes & 0x008) proto_item_append_text(cod_item, " Positioning");
-    if (major_service_classes & 0x010) proto_item_append_text(cod_item, " Networking");
-
-    if (major_service_classes & 0x020) proto_item_append_text(cod_item, " Rendering");
-    if (major_service_classes & 0x040) proto_item_append_text(cod_item, " Capturing");
-    if (major_service_classes & 0x080) proto_item_append_text(cod_item, " ObjectTransfer");
-    if (major_service_classes & 0x100) proto_item_append_text(cod_item, " Audio");
-    if (major_service_classes & 0x200) proto_item_append_text(cod_item, " Telephony");
-    if (major_service_classes & 0x400) proto_item_append_text(cod_item, " Information");
-
-    proto_item_append_text(cod_item, ")");
-
-    return offset;
 }
 
 static int
@@ -1555,7 +1533,7 @@ dissect_bthci_cmd_cod_mask(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, pr
     proto_item  *cod_mask_item;
     proto_item  *cod_mask_tree;
 
-    cod_mask_item = proto_tree_add_item(tree, hf_bthci_cmd_class_of_device_mask, tvb, offset, 3, ENC_LITTLE_ENDIAN);
+    cod_mask_item = proto_tree_add_item(tree, hf_bthci_cmd_cod_class_of_device_mask, tvb, offset, 3, ENC_LITTLE_ENDIAN);
     cod_mask_tree = proto_item_add_subtree(cod_mask_item, ett_cod_mask);
 
     proto_tree_add_item(cod_mask_tree, hf_bthci_cmd_cod_minor_device_class_mask, tvb, offset, 1, ENC_LITTLE_ENDIAN);
@@ -1579,228 +1557,6 @@ dissect_bthci_cmd_cod_mask(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, pr
     return offset;
 }
 
-static int
-dissect_bthci_eir_ad_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 size)
-{
-    guint8 length, type, data_size = size;
-    guint16 i, j;
-    proto_item *item, *ti_data = NULL;
-    proto_tree *ti_data_subtree = NULL;
-    proto_item  *sub_item;
-
-    if (tree) {
-        ti_data = proto_tree_add_item(tree, (size == 240) ? hf_extended_inquiry_response_data : hf_advertising_data,
-                tvb, offset, data_size, ENC_NA);
-        ti_data_subtree = proto_item_add_subtree(ti_data, ett_eir_subtree);
-    }
-
-    i=0;
-    while (i < data_size) {
-        length = tvb_get_guint8(tvb, offset + i);
-        if (length != 0) {
-
-            proto_item *ti_data_struct;
-            proto_tree *ti_data_struct_subtree;
-
-            type = tvb_get_guint8(tvb, offset + i + 1);
-
-            ti_data_struct = proto_tree_add_none_format(ti_data_subtree, hf_eir_ad_item, tvb, offset + i, length + 1, "%s",
-                    val_to_str_const(type, bthci_cmd_eir_data_type_vals, "Unknown"));
-            ti_data_struct_subtree = proto_item_add_subtree(ti_data_struct, ett_eir_struct_subtree);
-
-            proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_eir_struct_length, tvb, offset + i, 1, ENC_LITTLE_ENDIAN);
-            proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_eir_struct_type, tvb, offset + i + 1, 1, ENC_LITTLE_ENDIAN);
-
-            switch (type) {
-                case 0x01: /* flags */
-                    if (length > 1)
-                    {
-                        proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_limited_disc_mode, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_general_disc_mode, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_bredr_not_support, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_le_bredr_support_ctrl, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_le_bredr_support_host, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    }
-                    break;
-                case 0x02: /* 16-bit Service Class UUIDs, incomplete list */
-                case 0x03: /* 16-bit Service Class UUIDs, complete list */
-                case 0x14: /* 16-bit Service Solicitation UUIDs */
-                    j=0;
-                    while(j<(length-1))
-                    {
-                        proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_sc_uuid16, tvb, offset+i+j+2, 2, ENC_LITTLE_ENDIAN);
-                        j+=2;
-                    }
-                    break;
-                case 0x04: /* 32-bit Service Class UUIDs, incomplete list */
-                case 0x05: /* 32-bit Service Class UUIDs, complete list */
-                    j=0;
-                    while(j<(length-1))
-                    {
-                        proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_sc_uuid32, tvb, offset+i+j+2, 4, ENC_LITTLE_ENDIAN);
-                        j+=4;
-                    }
-                    break;
-                case 0x06: /* 128-bit Service Class UUIDs, incomplete list */
-                case 0x07: /* 128-bit Service Class UUIDs, complete list */
-                case 0x15: /* 128-bit Service Solicitation UUIDs */
-                    j=0;
-                    while(j<(length-1))
-                    {
-                        proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_sc_uuid128, tvb, offset+i+j+2, 16, ENC_NA);
-                        j+=16;
-                    }
-                    break;
-                case 0x08: /* Device Name, shortened */
-                case 0x09: /* Device Name, full */
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_device_name, tvb, offset+i+2, length-1, ENC_ASCII|ENC_NA);
-                    proto_item_append_text(ti_data_struct,": %s", tvb_format_text(tvb,offset+i+2,length-1));
-                    break;
-                case 0x0A: /* Tx Power Level */
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_tx_power, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    break;
-                case 0x0B: /* OOB Optional Data Length */
-                    /* From CSS v3.pdf */
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_eir_ad_ssp_oob_length, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
-                    break;
-                case 0x0C: /* BD_ADDR */
-                    /* From CSS v3.pdf */
-                    dissect_bthci_cmd_bd_addr(tvb, offset + i + 2, pinfo, tree);
-                    break;
-                case 0x0D: /* Class of Device */
-                    dissect_bthci_cmd_cod(tvb, offset+i+2, pinfo, ti_data_struct_subtree);
-                    break;
-                case 0x0E: /* Simple Pairing Hash C */
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_hash_c, tvb, offset+i+2, 16, ENC_NA);
-                    break;
-                case 0x0F: /* Simple Pairing Randomizer R */
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_randomizer_r, tvb, offset + i + 2, 16, ENC_NA);
-                    break;
-                case 0x10: /* Device ID / Security Manager TK Value */
-#if 0
-/* XXX: Need to know how to check (or is it possible) that is le_physical_channel or not */
-                    if (le_physical_channel) { /* Security Manager TK Value - Value as used in pairing over LE Physical channel. */
-                        sub_item = proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_eir_data, tvb, offset + i + 2, 16, ENC_NA);
-                        expert_add_info(pinfo, sub_item, &ei_eir_undecoded);
-                    }
-                    break;
-#endif
-                    {
-                    /* DID */
-                    guint16       vendor_id_source;
-                    guint16       vendor_id;
-                    guint16       product_id;
-                    const gchar  *str_val;
-
-                    proto_tree_add_item(ti_data_struct_subtree, hf_did_vendor_id_source, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
-                    vendor_id_source = tvb_get_letohs(tvb, offset + i + 2);
-
-                    if (vendor_id_source == DID_VENDOR_ID_SOURCE_BLUETOOTH_SIG) {
-                        proto_tree_add_item(ti_data_struct_subtree, hf_did_vendor_id_bluetooth_sig, tvb, offset + i + 2 + 2, 2, ENC_LITTLE_ENDIAN);
-                    } else if (vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
-                        proto_tree_add_item(ti_data_struct_subtree, hf_did_vendor_id_usb_forum, tvb, offset + i + 2 + 2, 2, ENC_LITTLE_ENDIAN);
-                    } else {
-                        proto_tree_add_item(ti_data_struct_subtree, hf_did_vendor_id, tvb, offset + i + 2 + 2, 2, ENC_LITTLE_ENDIAN);
-                    }
-                    vendor_id = tvb_get_letohs(tvb, offset + i + 2 + 2);
-
-                    sub_item = proto_tree_add_item(ti_data_struct_subtree, hf_did_product_id, tvb, offset + i + 2 + 4, 2, ENC_LITTLE_ENDIAN);
-                    product_id = tvb_get_letohs(tvb, offset + i + 2 + 4);
-
-                    if (vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
-                        str_val = val_to_str_ext_const(vendor_id << 16 | product_id, &ext_usb_products_vals, "Unknown");
-                        proto_item_append_text(sub_item, " (%s)", str_val);
-                    }
-
-                    proto_tree_add_item(ti_data_struct_subtree, hf_did_version, tvb, offset + i + 2 + 6, 2, ENC_LITTLE_ENDIAN);
-                    }
-                    break;
-                case 0x11: /* Security Manager OOB Flags */
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_le_oob_data_present, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_le_oob_le_supported_host, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_le_oob_le_bredr_support, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_flags_le_oob_address_type, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    break;
-                case 0x12: /* Slave Connection Interval Range */
-                    item = proto_tree_add_item(tree, hf_bthci_cmd_le_con_interval_min, tvb, offset+i+2, 2, ENC_LITTLE_ENDIAN);
-                    proto_item_append_text(item, " (%g msec)",  tvb_get_letohs(tvb, offset+i+2)*1.25);
-                    item = proto_tree_add_item(tree, hf_bthci_cmd_le_con_interval_max, tvb, offset+i+4, 2, ENC_LITTLE_ENDIAN);
-                    proto_item_append_text(item, " (%g msec)",  tvb_get_letohs(tvb, offset+i+4)*1.25);
-                    proto_item_append_text(ti_data_struct,": %g - %g msec", tvb_get_letohs(tvb, offset+i+2)*1.25, tvb_get_letohs(tvb, offset+i+4)*1.25);
-                    break;
-                case 0x16: /* Service Data */
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_sc_uuid16, tvb, offset+i+2, 2, ENC_LITTLE_ENDIAN);
-                    break;
-                case 0x17: /* Public Target Address */
-                case 0x18: /* Random Target Address */
-                {
-                    j=0;
-                    while(j<(length-1))
-                    {
-                        dissect_bthci_cmd_bd_addr(tvb, offset+i+j+2, pinfo, ti_data_struct_subtree);
-                        j+=6;
-                    }
-                    break;
-                }
-                case 0x19: /* Appearance */
-                {
-                    guint16 appearance = tvb_get_letohs(tvb, offset+i+2);
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_appearance, tvb, offset+i+2, 2, ENC_LITTLE_ENDIAN);
-                    proto_item_append_text(ti_data_struct,": %s", val_to_str(appearance, bthci_cmd_appearance_vals, "Unknown"));
-                    break;
-                }
-                case 0x1A: /* Advertising Interval */
-                    /* From CSS v3.pdf */
-                    sub_item = proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_eir_ad_advertising_interval, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
-                    proto_item_append_text(sub_item, " (%g msec)", tvb_get_letohs(tvb, offset + i + 2) * 0.625);
-                    break;
-                case 0x3D: /* 3D Information Data */
-                    proto_tree_add_item(ti_data_struct_subtree, hf_3ds_factory_test_mode, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_data_struct_subtree, hf_3ds_reserved, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_data_struct_subtree, hf_3ds_send_battery_level_report_on_startup, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_data_struct_subtree, hf_3ds_battery_level_reporting, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_data_struct_subtree, hf_3ds_association_notification, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-
-                    proto_tree_add_item(ti_data_struct_subtree, hf_3ds_path_loss_threshold, tvb, offset + i + 2 + 1, 1, ENC_LITTLE_ENDIAN);
-
-                    break;
-                case 0xFF: /* Manufacturer Specific */ {
-                    guint16  company_id;
-
-                    proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_eir_ad_company_id, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
-                    company_id = tvb_get_letohs(tvb, offset + i + 2);
-                    if (company_id == 0x000F && tvb_get_guint8(tvb, offset + i + 2 + 2) == 0) { /* 3DS profile Legacy Devices */
-                        proto_tree_add_item(ti_data_struct_subtree, hf_3ds_legacy_fixed, tvb, offset + i + 2 + 2, 1, ENC_LITTLE_ENDIAN);
-
-                        proto_tree_add_item(ti_data_struct_subtree, hf_3ds_legacy_3d_capable_tv, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_3ds_legacy_ignored_1_3, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_3ds_legacy_fixed_4, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_3ds_legacy_ignored_5, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_3ds_legacy_fixed_6, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_data_struct_subtree, hf_3ds_legacy_test_mode, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-
-                        proto_tree_add_item(ti_data_struct_subtree, hf_3ds_legacy_path_loss_threshold, tvb, offset + i + 2 + 4, 1, ENC_LITTLE_ENDIAN);
-                    } else {
-                        sub_item = proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_eir_data, tvb, offset + i + 2, length - 1, ENC_NA);
-                        expert_add_info(pinfo, sub_item, &ei_eir_undecoded);
-                    }
-                    }
-                    break;
-                default:
-                    sub_item = proto_tree_add_item(ti_data_struct_subtree, hf_bthci_cmd_eir_data, tvb, offset + i + 2, length - 1, ENC_NA);
-                    expert_add_info(pinfo, sub_item, &ei_eir_unknown);
-                    break;
-            }
-            i += length+1;
-        }
-        else {
-            break;
-        }
-    }
-
-    return offset+data_size;
-}
-
 static int
 dissect_bthci_cmd_flow_spec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, gboolean tx)
 {
@@ -1860,7 +1616,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
             break;
 
         case 0x0005: /* Create Connection */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_packet_type_2dh1, tvb, offset, 2, ENC_LITTLE_ENDIAN);
             proto_tree_add_item(tree, hf_bthci_cmd_packet_type_3dh1, tvb, offset, 2, ENC_LITTLE_ENDIAN);
@@ -1909,36 +1665,36 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
             break;
 
         case 0x0008: /* Create Connection Cancel Request */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             break;
 
         case 0x0009: /* Accept Connection Request */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_role, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
             break;
 
         case 0x000a: /* Reject Connection Request */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
             break;
 
         case 0x000b: /* Link Key Request Reply */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_link_key, tvb, offset, 16, ENC_NA);
             offset+=16;
             break;
 
         case 0x000c: /* Link Key Request Negative Reply */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             break;
 
         case 0x000d: /* PIN Code Request Reply */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_pin_code_length ,tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
@@ -1947,7 +1703,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
             break;
 
         case 0x000e: /* PIN Code Request Negative Reply */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             break;
 
         case 0x000f: /* Change Connection Packet Type */
@@ -1986,7 +1742,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
             break;
 
         case 0x0019: /* Remote Name Request */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_page_scan_repetition_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
@@ -2002,7 +1758,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
             break;
 
         case 0x001a: /* Remote Name Request Cancel */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             break;
 
         case 0x001c: /* Read Remote Extended Features */
@@ -2018,7 +1774,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
                 proto_tree_add_item(tree, hf_bthci_cmd_connection_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                 offset+=2;
             } else {
-                offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+                offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             }
 
             proto_tree_add_item(tree, hf_bthci_cmd_transmit_bandwidth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
@@ -2054,7 +1810,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
             offset+=2;
             break;
         case 0x002a: /* Reject Synchronous Connection Request */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
@@ -2070,7 +1826,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
             break;
 
         case 0x002b: /* IO Capability Response */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_io_capability, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
@@ -2081,7 +1837,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
             break;
 
         case 0x0034: /* IO Capability Request Negative Reply */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             proto_tree_add_item(tree, hf_bthci_cmd_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
             break;
@@ -2090,18 +1846,18 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
         case 0x002d: /* User Confirmation Request Negative Reply */
         case 0x002f: /* User Passkey Request Negative Reply */
         case 0x0033: /* Remote OOB Data Request Negative Reply */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             break;
 
         case 0x002e: /* User Passkey Request Reply */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_passkey, tvb, offset, 4, ENC_LITTLE_ENDIAN);
             offset+=4;
             break;
 
         case 0x0030: /* Remote OOB Data Request Reply */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_hash_c, tvb, offset, 16, ENC_NA);
             offset+=16;
@@ -2178,7 +1934,7 @@ dissect_link_control_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tr
 }
 
 static int
-dissect_link_policy_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 cmd_ocf)
+dissect_link_policy_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint16 cmd_ocf)
 {
     proto_item *item;
     guint16     timeout;
@@ -2250,7 +2006,7 @@ dissect_link_policy_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
             break;
 
         case 0x000b: /* Switch Role */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_role, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
@@ -2320,7 +2076,7 @@ dissect_link_policy_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
 
 static int
 dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo,
-        proto_tree *tree, guint16 cmd_ocf)
+        proto_tree *tree, guint16 cmd_ocf, hci_data_t *hci_data)
 {
     proto_item *item;
     guint16     timeout;
@@ -2406,12 +2162,14 @@ dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pin
                     offset++;
                     switch (filter_condition_type) {
                         case 0x01:
-                            offset=dissect_bthci_cmd_cod(tvb, offset, pinfo, tree);
+                            call_dissector(btcommon_cod_handle, tvb_new_subset(tvb, offset, 3, 3), pinfo, tree);
+                            offset += 3;
+
                             offset=dissect_bthci_cmd_cod_mask(tvb, offset, pinfo, tree);
                             break;
 
                         case 0x02:
-                            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+                            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
                             break;
 
                         default:
@@ -2432,7 +2190,9 @@ dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pin
                             break;
 
                         case 0x01:
-                            offset=dissect_bthci_cmd_cod(tvb, offset, pinfo, tree);
+                            call_dissector(btcommon_cod_handle, tvb_new_subset(tvb, offset, 3, 3), pinfo, tree);
+                            offset += 3;
+
                             offset=dissect_bthci_cmd_cod_mask(tvb, offset, pinfo, tree);
 
                             proto_tree_add_item(tree, hf_bthci_cmd_auto_acc_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
@@ -2440,7 +2200,7 @@ dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pin
                             break;
 
                         case 0x02:
-                            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+                            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
                             proto_tree_add_item(tree, hf_bthci_cmd_auto_acc_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
                             offset++;
@@ -2464,7 +2224,7 @@ dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pin
             break;
 
         case 0x000d: /* Read Stored Link Key */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_read_all_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
@@ -2473,24 +2233,55 @@ dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pin
         case 0x0011: /* Write Stored Link Key */
             proto_tree_add_item(tree, hf_bthci_cmd_num_link_keys, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             num8 = tvb_get_guint8(tvb, offset);
-            offset++;
-            for (i=0; i<num8; i++) {
-                dissect_bthci_cmd_bd_addr(tvb, offset+(i*22), pinfo, tree);
-                proto_tree_add_item(tree, hf_bthci_cmd_link_key, tvb, offset+6+(i*22), 16, ENC_NA);
+            offset += 1;
+
+            for (i = 0; i < num8; i++) {
+                offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
+                proto_tree_add_item(tree, hf_bthci_cmd_link_key, tvb, offset, 16, ENC_NA);
+                offset += 16;
             }
             break;
 
         case 0x0012: /* Delete Stored Link Key */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_delete_all_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
             break;
 
         case 0x0013: /* Change Local Name */
-            proto_tree_add_item(tree, hf_bthci_cmd_device_name,
-                    tvb, offset, 248, ENC_ASCII|ENC_NA);
-            offset+=248;
+            proto_tree_add_item(tree, hf_bthci_cmd_device_name, tvb, offset, 248, ENC_ASCII | ENC_NA);
+            if (!pinfo->fd->flags.visited) {
+                wmem_tree_key_t         key[4];
+                guint32                 k_interface_id;
+                guint32                 k_adapter_id;
+                guint32                 k_frame_number;
+                gchar                   *name;
+                localhost_name_entry_t  *localhost_name_entry;
+
+                k_interface_id = hci_data->interface_id;
+                k_adapter_id = hci_data->adapter_id;
+                k_frame_number = pinfo->fd->num;
+
+                name = tvb_get_string(wmem_packet_scope(), tvb, offset, 248);
+
+                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_frame_number;
+                key[3].length = 0;
+                key[3].key    = NULL;
+
+                localhost_name_entry = (localhost_name_entry_t *) wmem_new(wmem_file_scope(), localhost_name_entry_t);
+                localhost_name_entry->interface_id = k_interface_id;
+                localhost_name_entry->adapter_id = k_adapter_id;
+                localhost_name_entry->name = wmem_strdup(wmem_file_scope(), name);
+
+                wmem_tree_insert32_array(hci_data->localhost_name, key, localhost_name_entry);
+            }
+            offset += 248;
             break;
 
         case 0x0016: /* Write Connection Accept Timeout */
@@ -2529,7 +2320,8 @@ dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pin
             break;
 
         case 0x0024: /* Write Class of Device */
-            offset=dissect_bthci_cmd_cod(tvb, offset, pinfo, tree);
+            call_dissector(btcommon_cod_handle, tvb_new_subset(tvb, offset, 3, 3), pinfo, tree);
+            offset += 3;
             break;
 
         case 0x0026: /* Write Voice Setting */
@@ -2708,7 +2500,10 @@ dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pin
         case 0x0052: /* Write Extended Inquiry Response */
             proto_tree_add_item(tree, hf_bthci_cmd_fec_required, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
-            offset=dissect_bthci_eir_ad_data(tvb, offset, pinfo, tree, 240);
+
+            call_dissector(btcommon_eir_handle, tvb_new_subset(tvb, offset, 240, 240), pinfo, tree);
+            save_local_device_name(tvb, offset, pinfo, 240, hci_data);
+            offset += 240;
             break;
 
         case 0x0053: /* Refresh Encryption Key */
@@ -2739,7 +2534,7 @@ dissect_host_controller_baseband_cmd(tvbuff_t *tvb, int offset, packet_info *pin
             break;
 
         case 0x0060: /* Send Keypress Notification */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
 
             proto_tree_add_item(tree, hf_bthci_cmd_notification_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
@@ -3001,7 +2796,7 @@ dissect_testing_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tre
 }
 
 static gint
-dissect_le_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 cmd_ocf)
+dissect_le_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint16 cmd_ocf, hci_data_t *hci_data)
 {
     proto_item *item;
 
@@ -3017,7 +2812,7 @@ dissect_le_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
             break;
 
         case 0x0005: /* LE Set Random Address */
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             break;
 
         case 0x0006: /* LE Set Advertising Parameters */
@@ -3033,7 +2828,7 @@ dissect_le_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
             offset++;
             proto_tree_add_item(tree, hf_bthci_cmd_le_direct_address_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             proto_tree_add_item(tree, hf_bthci_cmd_le_advts_channel_map_1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             proto_tree_add_item(tree, hf_bthci_cmd_le_advts_channel_map_2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             proto_tree_add_item(tree, hf_bthci_cmd_le_advts_channel_map_3, tvb, offset, 1, ENC_LITTLE_ENDIAN);
@@ -3046,7 +2841,10 @@ dissect_le_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
         case 0x0009: /* LE Set Scan Response Data */
             proto_tree_add_item(tree, hf_bthci_cmd_le_data_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
-            offset = dissect_bthci_eir_ad_data(tvb, offset, pinfo, tree, 31);
+
+            call_dissector(btcommon_ad_handle, tvb_new_subset(tvb, offset, 31, 31), pinfo, tree);
+            save_local_device_name(tvb, offset, pinfo, 31, hci_data);
+            offset += 31;
             break;
 
         case 0x000a: /* LE Set Advertise Enable */
@@ -3087,7 +2885,7 @@ dissect_le_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
             offset++;
             proto_tree_add_item(tree, hf_bthci_cmd_le_peer_address_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             proto_tree_add_item(tree, hf_bthci_cmd_le_own_address_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
             item = proto_tree_add_item(tree, hf_bthci_cmd_le_con_interval_min, tvb, offset, 2, ENC_LITTLE_ENDIAN);
@@ -3114,7 +2912,7 @@ dissect_le_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
         case 0x0012: /* LE Remove Device From White List */
             proto_tree_add_item(tree, hf_bthci_cmd_le_address_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset++;
-            offset = dissect_bthci_cmd_bd_addr(tvb, offset, pinfo, tree);
+            offset = dissect_bd_addr(hf_bthci_cmd_bd_addr, tree, tvb, offset);
             break;
 
         case 0x0013: /* LE Connection Update */
@@ -3210,7 +3008,7 @@ dissect_le_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
 
 /* Code to actually dissect the packets */
 static gint
-dissect_bthci_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+dissect_bthci_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
     proto_item  *ti_cmd;
     proto_tree  *bthci_cmd_tree;
@@ -3222,6 +3020,12 @@ dissect_bthci_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
     proto_item  *ti_opcode;
     proto_tree  *opcode_tree;
     gint         hfx;
+    hci_data_t  *hci_data;
+
+    /* Reject the packet if data is NULL */
+    if (data == NULL)
+        return 0;
+    hci_data = (hci_data_t *) data;
 
     ti_cmd = proto_tree_add_item(tree, proto_bthci_cmd, tvb, offset, -1, ENC_NA);
     bthci_cmd_tree = proto_item_add_subtree(ti_cmd, ett_bthci_cmd);
@@ -3293,7 +3097,7 @@ dissect_bthci_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
                 break;
 
             case HCI_OGF_HOST_CONTROLLER:
-                offset = dissect_host_controller_baseband_cmd(tvb, offset, pinfo, bthci_cmd_tree, ocf);
+                offset = dissect_host_controller_baseband_cmd(tvb, offset, pinfo, bthci_cmd_tree, ocf, hci_data);
                 break;
 
             case HCI_OGF_INFORMATIONAL:
@@ -3309,7 +3113,7 @@ dissect_bthci_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
                 break;
 
             case HCI_OGF_LOW_ENERGY:
-                offset = dissect_le_cmd(tvb, offset, pinfo, bthci_cmd_tree, ocf);
+                offset = dissect_le_cmd(tvb, offset, pinfo, bthci_cmd_tree, ocf, hci_data);
                 break;
 
             default:
@@ -3704,152 +3508,7 @@ proto_register_bthci_cmd(void)
             FT_UINT8, BASE_HEX, VALS(cmd_connection_setup_filter_condition_types), 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_class_of_device,
-          { "Class of Device", "bthci_cmd.class_of_device",
-            FT_UINT24, BASE_HEX, NULL, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_information,
-          { "Major Service Classes: Information", "bthci_cmd.class_of_device.major_service_classes.information",
-            FT_BOOLEAN, 16, NULL, 0x8000,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_telephony,
-          { "Major Service Classes: Telephony", "bthci_cmd.class_of_device.major_service_classes.telephony",
-            FT_BOOLEAN, 16, NULL, 0x4000,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_audio,
-          { "Major Service Classes: Audio", "bthci_cmd.class_of_device.major_service_classes.audio",
-            FT_BOOLEAN, 16, NULL, 0x2000,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_object_transfer,
-          { "Major Service Classes: Object Transfer", "bthci_cmd.class_of_device.major_service_classes.object_transfer",
-            FT_BOOLEAN, 16, NULL, 0x1000,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_capturing,
-          { "Major Service Classes: Capturing", "bthci_cmd.class_of_device.major_service_classes.capturing",
-            FT_BOOLEAN, 16, NULL, 0x0800,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_rendering,
-          { "Major Service Classes: Rendering", "bthci_cmd.class_of_device.major_service_classes.rendering",
-            FT_BOOLEAN, 16, NULL, 0x0400,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_networking,
-          { "Major Service Classes: Networking", "bthci_cmd.class_of_device.major_service_classes.networking",
-            FT_BOOLEAN, 16, NULL, 0x0200,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_positioning,
-          { "Major Service Classes: Positioning", "bthci_cmd.class_of_device.major_service_classes.positioning",
-            FT_BOOLEAN, 16, NULL, 0x0100,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_reserved,
-          { "Major Service Classes: Reserved", "bthci_cmd.class_of_device.major_service_classes.reserved",
-            FT_UINT16, BASE_HEX, NULL, 0x00C0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_service_class_limited_discoverable_mode,
-          { "Major Service Classes: Limited Discoverable Mode", "bthci_cmd.class_of_device.major_service_classes.limited_discoverable_mode",
-            FT_BOOLEAN, 16, NULL, 0x0020,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_major_device_class,
-          { "Major Device Class", "bthci_cmd.class_of_device.major_device_class",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_major_device_class_vals_ext, 0x1F,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_computer,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_computer_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_phone,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_phone_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_lan_net_load_factor,
-          { "Minor Device Class: Load Factor", "bthci_cmd.class_of_device.minor_device_class.load_factor",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_lan_net_load_factor_vals_ext, 0xE0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_lan_net_type,
-          { "Minor Device Class: Type", "bthci_cmd.class_of_device.minor_device_class.type",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_lan_net_type_vals_ext, 0x1C,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_audio_video,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_audio_video_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_peripheral_class,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_peripheral_class_vals_ext, 0xC0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_peripheral_type,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_peripheral_type_vals_ext, 0x3C,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_imaging_class_printer,
-          { "Minor Device Class: Class: Printer", "bthci_cmd.class_of_device.minor_device_class.class.printer",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x80,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_imaging_class_scanner,
-          { "Minor Device Class: Class: Scanner", "bthci_cmd.class_of_device.minor_device_class.class.scanner",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x40,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_imaging_class_camera,
-          { "Minor Device Class: Class: Camera", "bthci_cmd.class_of_device.minor_device_class.class.camera",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x20,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_imaging_class_display,
-          { "Minor Device Class: Class: Display", "bthci_cmd.class_of_device.minor_device_class.class.display",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x10,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_imaging_type,
-          { "Minor Device Class: Type", "bthci_cmd.class_of_device.minor_device_class.type",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x0C,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_wearable,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_wearable_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_toy,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_toy_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_health,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_health_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_minor_device_class_unknown,
-          { "Minor Device Class", "bthci_cmd.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX, NULL, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_cod_format_type,
-          { "Format Type", "bthci_cmd.class_of_device.format_type",
-            FT_UINT8, BASE_HEX, NULL, 0x03,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_class_of_device_mask,
+        { &hf_bthci_cmd_cod_class_of_device_mask,
           { "Class of Device Mask", "bthci_cmd.class_of_device_mask",
             FT_UINT24, BASE_HEX, NULL, 0x0,
             "Bit Mask used to determine which bits of the Class of Device parameter are of interest.", HFILL }
@@ -4480,36 +4139,6 @@ proto_register_bthci_cmd(void)
            FT_UINT8, BASE_DEC, VALS(bthci_cmd_notification_types), 0x0,
            NULL, HFILL}
         },
-        { &hf_bthci_cmd_eir_data,
-          {"Data", "bthci_cmd.eir_data",
-           FT_BYTES, BASE_NONE, NULL, 0x0,
-           NULL, HFILL}
-        },
-        { &hf_bthci_cmd_eir_struct_length,
-          { "Length",           "bthci_cmd.eir_struct_length",
-            FT_UINT8, BASE_DEC, NULL, 0x0,
-            "Structure Length", HFILL }
-        },
-        { &hf_bthci_cmd_eir_struct_type,
-          { "Type",           "bthci_cmd.eir_data_type",
-            FT_UINT8, BASE_HEX|BASE_EXT_STRING, &bthci_cmd_eir_data_type_vals_ext, 0x0,
-            "Data Type", HFILL }
-        },
-        { &hf_bthci_cmd_sc_uuid16,
-          { "UUID",           "bthci_cmd.service_class_uuid16",
-            FT_UINT16, BASE_HEX|BASE_EXT_STRING, &bthci_cmd_service_class_type_vals_ext, 0x0,
-            "16-bit Service Class UUID", HFILL }
-        },
-        { &hf_bthci_cmd_sc_uuid32,
-          { "UUID",           "bthci_cmd.service_class_uuid32",
-            FT_UINT32, BASE_HEX, NULL, 0x0,
-            "32-bit Service Class UUID", HFILL }
-        },
-        { &hf_bthci_cmd_sc_uuid128,
-          { "UUID",           "bthci_cmd.service_class_uuid128",
-            FT_BYTES, BASE_NONE, NULL, 0x0,
-            "128-bit Service Class UUID", HFILL }
-        },
         { &hf_bthci_cmd_physical_link_handle,
           {"Physical Link Handle", "bthci_cmd.physical_link_handle",
             FT_UINT8, BASE_HEX, NULL, 0x0,
@@ -4921,261 +4550,979 @@ proto_register_bthci_cmd(void)
             FT_UINT8, BASE_HEX, VALS(cmd_le_test_pkt_payload), 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_appearance,
-          { "Appearance", "bthci_cmd.le_appearance",
-            FT_UINT16, BASE_HEX, VALS(bthci_cmd_appearance_vals), 0x0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_cmd_flags_limited_disc_mode,
-          { "LE Limited Discoverable Mode",        "bthci_cmd.le_flags_limit_disc_mode",
-            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x01,
-            NULL, HFILL }
+    };
+
+    static ei_register_info ei[] = {
+        { &ei_command_unknown,              { "bthci_cmd.expert.command.unknown.", PI_PROTOCOL, PI_WARN, "Unknown command", EXPFILL }},
+        { &ei_command_parameter_unexpected, { "bthci_cmd.expert.parameter.unexpected", PI_PROTOCOL, PI_WARN, "Unexpected command parameter", EXPFILL }},
+        { &ei_command_undecoded,            { "bthci_cmd.expert.command.undecoded", PI_PROTOCOL, PI_UNDECODED, "Command undecoded", EXPFILL }}
+    };
+
+    static gint *ett[] = {
+        &ett_bthci_cmd,
+        &ett_opcode,
+        &ett_cod,
+        &ett_cod_mask,
+        &ett_flow_spec_subtree
+    };
+
+    /* Dynamically fill "bthci_cmd_opcode_vals" */
+    static const struct _opcode_value_string_arrays {
+        guint                ogf;
+        const value_string  *string_array;
+        guint                length;
+    } opcode_value_string_arrays[] = {
+        { 0x01, bthci_cmd_ocf_link_control_vals, array_length(bthci_cmd_ocf_link_control_vals) },
+        { 0x02, bthci_cmd_ocf_link_policy_vals, array_length(bthci_cmd_ocf_link_policy_vals) },
+        { 0x03, bthci_cmd_ocf_host_controller_and_baseband_vals, array_length(bthci_cmd_ocf_host_controller_and_baseband_vals) },
+        { 0x04, bthci_cmd_ocf_informational_vals, array_length(bthci_cmd_ocf_informational_vals) },
+        { 0x05, bthci_cmd_ocf_status_vals, array_length(bthci_cmd_ocf_status_vals) },
+        { 0x06, bthci_cmd_ocf_testing_vals, array_length(bthci_cmd_ocf_testing_vals) },
+        { 0x08, bthci_cmd_ocf_low_energy_vals, array_length(bthci_cmd_ocf_low_energy_vals) },
+    };
+
+    bthci_cmd_opcode_vals[i_opcode].value = 0;
+    bthci_cmd_opcode_vals[i_opcode].strptr = "No Operation";
+    i_opcode += 1;
+    for (i_array = 0; i_array < array_length(opcode_value_string_arrays); i_array += 1) {
+        for (i_string_array = 0; i_string_array < opcode_value_string_arrays[i_array].length - 1; i_string_array += 1) {
+            bthci_cmd_opcode_vals[i_opcode].value = opcode_value_string_arrays[i_array].string_array[i_string_array].value | (opcode_value_string_arrays[i_array].ogf << 10);
+            bthci_cmd_opcode_vals[i_opcode].strptr = opcode_value_string_arrays[i_array].string_array[i_string_array].strptr;
+            i_opcode += 1;
+        }
+    }
+
+    proto_bthci_cmd = proto_register_protocol("Bluetooth HCI Command", "HCI_CMD", "bthci_cmd");
+    bthci_cmd_handle = new_register_dissector("bthci_cmd", dissect_bthci_cmd, proto_bthci_cmd);
+
+    /* Required function calls to register the header fields and subtrees used */
+    proto_register_field_array(proto_bthci_cmd, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+
+    expert_bthci_cmd = expert_register_protocol(proto_bthci_cmd);
+    expert_register_field_array(expert_bthci_cmd, ei, array_length(ei));
+
+    module = prefs_register_protocol(proto_bthci_cmd, NULL);
+    prefs_register_static_text_preference(module, "hci_cmd.version",
+            "Bluetooth HCI version: 4.0 (Core)",
+            "Version of protocol supported by this dissector.");
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+   This format is required because a script is used to find these routines and
+   create the code that calls these routines.
+   */
+void
+proto_reg_handoff_bthci_cmd(void)
+{
+    dissector_add_uint("hci_h4.type", HCI_H4_TYPE_CMD, bthci_cmd_handle);
+    dissector_add_uint("hci_h1.type", BTHCI_CHANNEL_COMMAND, bthci_cmd_handle);
+}
+
+
+static gint
+dissect_eir_ad_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    proto_item  *entry_item;
+    proto_tree  *entry_tree;
+    proto_item  *sub_item;
+    gint         offset = 0;
+    guint8       length;
+    guint8       type;
+    guint8       data_size;
+    gint         end_offset;
+    guint        i_uuid;
+
+    data_size = tvb_length(tvb);
+
+    while (offset < data_size) {
+        length = tvb_get_guint8(tvb, offset);
+        if (length <= 0) break;
+
+        type = tvb_get_guint8(tvb, offset + 1);
+
+        entry_item = proto_tree_add_none_format(tree, hf_btcommon_eir_ad_entry, tvb, offset, length + 1, "%s",
+                val_to_str_const(type, bthci_cmd_eir_data_type_vals, "Unknown"));
+        entry_tree = proto_item_add_subtree(entry_item, ett_eir_ad_entry);
+
+        proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_length, tvb, offset, 1, ENC_NA);
+        offset += 1;
+
+        proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_type, tvb, offset, 1, ENC_NA);
+        offset += 1;
+        length -= 1;
+
+        switch (type) {
+        case 0x01: /* Flags */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_flags_reserved, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_flags_le_bredr_support_host, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_flags_le_bredr_support_controller, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_flags_bredr_not_support, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_flags_le_general_discoverable_mode, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_flags_le_limited_discoverable_mode, tvb, offset, 1, ENC_NA);
+            offset += 1;
+
+            break;
+        case 0x02: /* 16-bit Service Class UUIDs (incomplete) */
+        case 0x03: /* 16-bit Service Class UUIDs */
+        case 0x14: /* List of 16-bit Service Solicitation UUIDs */
+        case 0x16: /* Service Data - 16 bit UUID  */
+            end_offset = offset + length;
+            while (offset < end_offset) {
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_uuid_16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                offset += 2;
+            }
+
+            break;
+        case 0x04: /* 32-bit Service Class UUIDs (incomplete) */
+        case 0x05: /* 32-bit Service Class UUIDs */
+        case 0x1F: /* List of 32-bit Service Solicitation UUIDs */
+        case 0x20: /* Service Data - 32 bit UUID */
+            end_offset = offset + length;
+            while (offset < end_offset) {
+                if (tvb_get_ntohs(tvb, offset) == 0x0000) {
+                    sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_uuid_32, tvb, offset, 4, ENC_NA);
+                    proto_item_append_text(sub_item, " (%s)", val_to_str_ext_const(tvb_get_ntohs(tvb, offset + 2), &vs_service_classes_ext, "Unknown"));
+                } else {
+                    sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_custom_uuid, tvb, offset, 4, ENC_NA);
+
+                    i_uuid = 0;
+                    while (custom_uuid[i_uuid].name) {
+                        if (custom_uuid[i_uuid].size != 4) {
+                            i_uuid += 1;
+                            continue;
+                        }
+
+                        if (tvb_memeql(tvb, offset, custom_uuid[i_uuid].uuid, 4) == 0) {
+                            proto_item_append_text(sub_item, " (%s)", custom_uuid[i_uuid].name);
+                            break;
+                        }
+
+                        i_uuid += 1;
+                    }
+                }
+
+                offset += 4;
+            }
+
+            break;
+        case 0x06: /* 128-bit Service Class UUIDs (incomplete) */
+        case 0x07: /* 128-bit Service Class UUIDs */
+        case 0x15: /* List of 128-bit Service Solicitation UUIDs */
+        case 0x21: /* Service Data - 128 bit UUID */
+            end_offset = offset + length;
+            while (offset < end_offset) {
+                if (tvb_get_ntohs(tvb, offset) == 0x0000 &&
+                        tvb_get_ntohl(tvb, offset + 4) == 0x1000 &&
+                        tvb_get_ntoh64(tvb, offset + 8) == G_GUINT64_CONSTANT(0x800000805F9B34FB)) {
+                    sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_uuid_128, tvb, offset, 16, ENC_NA);
+                    proto_item_append_text(sub_item, " (%s)", val_to_str_ext_const(tvb_get_ntohs(tvb, offset + 2), &vs_service_classes_ext, "Unknown"));
+                } else {
+                    sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_custom_uuid, tvb, offset, 16, ENC_NA);
+
+                    i_uuid = 0;
+                    while (custom_uuid[i_uuid].name) {
+                        if (custom_uuid[i_uuid].size != 16) {
+                            i_uuid += 1;
+                            continue;
+                        }
+
+                        if (tvb_memeql(tvb, offset, custom_uuid[i_uuid].uuid, 16) == 0) {
+                            proto_item_append_text(sub_item, " (%s)", custom_uuid[i_uuid].name);
+                            break;
+                        }
+
+                        i_uuid += 1;
+                    }
+                }
+
+                offset += 16;
+            }
+
+            break;
+
+        case 0x08: /* Device Name (shortened) */
+        case 0x09: /* Device Name */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_name, tvb, offset, length, ENC_ASCII | ENC_NA);
+            proto_item_append_text(entry_item, ": %s", tvb_format_text(tvb,offset, length));
+            offset += length;
+
+            break;
+        case 0x10: /* Device ID / Security Manager TK Value */
+            if (length == 16) { /* little heuristic for recognize Security Manager TK Value */
+                sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_data, tvb, offset, 16, ENC_NA);
+                expert_add_info(pinfo, sub_item, &ei_eir_ad_undecoded);
+            } else if (length == 8) { /* DID */
+                guint16       vendor_id_source;
+                guint16       vendor_id;
+                guint16       product_id;
+                const gchar  *str_val;
+
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_did_vendor_id_source, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                vendor_id_source = tvb_get_letohs(tvb, offset);
+                offset += 2;
+
+                if (vendor_id_source == DID_VENDOR_ID_SOURCE_BLUETOOTH_SIG) {
+                    proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_did_vendor_id_bluetooth_sig, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                } else if (vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
+                    proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_did_vendor_id_usb_forum, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                } else {
+                    proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_did_vendor_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                }
+                vendor_id = tvb_get_letohs(tvb, offset);
+                offset += 2;
+
+                sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_did_product_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                product_id = tvb_get_letohs(tvb, offset);
+                offset += 2;
+
+                if (vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
+                    str_val = val_to_str_ext_const(vendor_id << 16 | product_id, &ext_usb_products_vals, "Unknown");
+                    proto_item_append_text(sub_item, " (%s)", str_val);
+                }
+
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_did_version, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                offset += 2;
+            } else {
+                sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_data, tvb, offset, length, ENC_NA);
+                expert_add_info(pinfo, sub_item, &ei_command_unknown);
+            }
+
+            break;
+        case 0x0A: /* Tx Power Level */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_tx_power, tvb, offset, 1, ENC_NA);
+            offset += 1;
+
+            break;
+        case 0x0B: /* OOB Optional Data Length */
+            /* From CSS v3.pdf */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_ssp_oob_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+            offset += 2;
+
+            break;
+        case 0x0C: /* BD_ADDR */
+            /* From CSS v3.pdf */
+            offset = dissect_bd_addr(hf_btcommon_eir_ad_bd_addr, tree, tvb, offset);
+
+            break;
+
+        case 0x0D: /* Class Of Device */
+            call_dissector(btcommon_cod_handle, tvb_new_subset(tvb, offset, 3, 3), pinfo, entry_tree);
+            offset += 3;
+
+            break;
+        case 0x0E: /* Simple Pairing Hash C */
+        case 0x1D: /* Simple Pairing Hash C-256 */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_hash_c, tvb, offset, 16, ENC_NA);
+            offset += 16;
+
+            break;
+        case 0x0F: /* Simple Pairing Randomizer R */
+        case 0x1E: /* Simple Pairing Randomizer R-256 */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_randomizer_r, tvb, offset, 16, ENC_NA);
+            offset += 16;
+
+            break;
+        case 0x11: /* Security Manager Out of Band Flags */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_oob_flags_reserved, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_oob_flags_address_type, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_oob_flags_le_bredr_support, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_oob_flags_le_supported_host, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_oob_flags_data_present, tvb, offset, 1, ENC_NA);
+            offset += 1;
+
+            break;
+        case 0x12: /* Slave Connection Interval Range */
+            sub_item = proto_tree_add_item(tree, hf_btcommon_eir_ad_connection_interval_min, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+            proto_item_append_text(sub_item, " (%g msec)",  tvb_get_letohs(tvb, offset) * 1.25);
+            offset += 2;
+
+            sub_item = proto_tree_add_item(tree, hf_btcommon_eir_ad_connection_interval_max, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+            proto_item_append_text(sub_item, " (%g msec)",  tvb_get_letohs(tvb, offset) * 1.25);
+            offset += 2;
+
+            proto_item_append_text(entry_item, ": %g - %g msec", tvb_get_letohs(tvb, offset - 4) * 1.25, tvb_get_letohs(tvb, offset - 2) * 1.25);
+
+            break;
+        case 0x17: /* Public Target Address */
+        case 0x18: /* Random Target Address */
+            end_offset = offset + length;
+            while (offset < end_offset) {
+                offset = dissect_bd_addr(hf_btcommon_eir_ad_bd_addr, entry_tree, tvb, offset);
+            }
+
+            break;
+        case 0x19: /* Appearance */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_appearance, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+            proto_item_append_text(entry_item,": %s", val_to_str(tvb_get_letohs(tvb, offset), bthci_cmd_appearance_vals, "Unknown"));
+            offset += 2;
+
+            break;
+        case 0x1A: /* Advertising Interval */
+            /* From CSS v3.pdf */
+            sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_advertising_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+            proto_item_append_text(sub_item, " (%g msec)", tvb_get_letohs(tvb, offset) * 0.625);
+            offset += 2;
+
+            break;
+        case 0x1B: /* LE Bluetooth Device Address */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_le_bd_addr_reserved, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_le_bd_addr_type, tvb, offset, 1, ENC_NA);
+            offset += 1;
+
+            offset = dissect_bd_addr(hf_btcommon_eir_ad_bd_addr, entry_tree, tvb, offset);
+
+            break;
+        case 0x1C: /* LE Role */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_le_role, tvb, offset, 1, ENC_NA);
+            offset += 1;
+
+            break;
+        case 0x3D: /* 3D Information Data */
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_factory_test_mode, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_reserved, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_send_battery_level_report_on_startup, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_battery_level_reporting, tvb, offset, 1, ENC_NA);
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_association_notification, tvb, offset, 1, ENC_NA);
+            offset += 1;
+
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_path_loss_threshold, tvb, offset, 1, ENC_NA);
+            offset += 1;
+
+            break;
+        case 0xFF: /* Manufacturer Specific */ {
+            guint16  company_id;
+
+            proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_company_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+            company_id = tvb_get_letohs(tvb, offset);
+            offset += 2;
+            length -= 2;
+
+            if (company_id == 0x000F && tvb_get_guint8(tvb, offset) == 0) { /* 3DS profile Legacy Devices */
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_legacy_fixed, tvb, offset, 1, ENC_NA);
+                offset += 1;
+
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_legacy_test_mode, tvb, offset, 1, ENC_NA);
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_legacy_fixed_6, tvb, offset, 1, ENC_NA);
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_legacy_ignored_5, tvb, offset, 1, ENC_NA);
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_legacy_fixed_4, tvb, offset, 1, ENC_NA);
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_legacy_ignored_1_3, tvb, offset, 1, ENC_NA);
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_legacy_3d_capable_tv, tvb, offset, 1, ENC_NA);
+                offset += 1;
+
+                proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_3ds_legacy_path_loss_threshold, tvb, offset, 1, ENC_NA);
+                offset += 1;
+            } else {
+                sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_data, tvb, offset, length, ENC_NA);
+                expert_add_info(pinfo, sub_item, &ei_eir_ad_undecoded);
+                offset += length;
+            }
+            }
+            break;
+        default:
+            sub_item = proto_tree_add_item(entry_tree, hf_btcommon_eir_ad_data, tvb, offset, length, ENC_NA);
+            expert_add_info(pinfo, sub_item, &ei_eir_ad_unknown);
+            offset += length;
+        }
+    }
+
+    if (tvb_length_remaining(tvb, offset) > 0) {
+        proto_tree_add_item(tree, hf_btcommon_eir_ad_unused, tvb, offset, -1, ENC_NA);
+        offset = tvb_length(tvb);
+    }
+
+    return offset + data_size;
+}
+
+static gint
+dissect_btcommon_cod(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+{
+    proto_item  *cod_item;
+    proto_item  *cod_tree;
+    guint16      major_service_classes;
+    guint8       major_device_class;
+    guint8       minor_device_class;
+    const gchar *minor_device_class_name;
+    gint         offset = 0;
+
+    cod_item = proto_tree_add_item(tree, hf_btcommon_cod_class_of_device, tvb, offset, 3, ENC_LITTLE_ENDIAN);
+    cod_tree = proto_item_add_subtree(cod_item, ett_cod);
+
+    major_device_class = tvb_get_guint8(tvb, offset + 1) & 0x1F;
+    minor_device_class = tvb_get_guint8(tvb, offset) >> 2;
+
+    switch(major_device_class) {
+    case 0x01: /* Computer */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_computer, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_computer_vals_ext, "Unknown");
+        break;
+    case 0x02: /* Phone */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_phone, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_phone_vals_ext, "Unknown");
+        break;
+    case 0x03: /* LAN/Network Access Point */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_lan_net_load_factor, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_lan_net_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_lan_net_load_factor_vals_ext, "Unknown");
+        break;
+    case 0x04: /* Audio/Video */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_audio_video, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_audio_video_vals_ext, "Unknown");
+        break;
+    case 0x05: /* Peripheral */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_peripheral_class, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_peripheral_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_peripheral_class_vals_ext, "Unknown");
+        break;
+    case 0x06: /* Imaging */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_imaging_class_printer, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_imaging_class_scanner, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_imaging_class_camera, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_imaging_class_display, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_imaging_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, "Unknown");
+        break;
+    case 0x07: /* Wearable */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_wearable, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_wearable_vals_ext, "Unknown");
+        break;
+    case 0x08: /* Toy */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_toy, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_toy_vals_ext, "Unknown");
+        break;
+    case 0x09: /* Health */
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_health, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_health_vals_ext, "Unknown");
+        break;
+    default:
+        minor_device_class_name = "Unknown";
+        proto_tree_add_item(cod_tree, hf_btcommon_cod_minor_device_class_unknown, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+    }
+
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_format_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+    offset += 1;
+
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_information, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_telephony, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_audio, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_object_transfer, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_capturing, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_rendering, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_networking, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_positioning, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_service_class_limited_discoverable_mode, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    major_service_classes = tvb_get_letohs(tvb, offset) >> 5;
+
+    proto_tree_add_item(cod_tree, hf_btcommon_cod_major_device_class, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    offset += 2;
+
+    proto_item_append_text(cod_item, " (%s:%s - services:",
+            val_to_str_ext_const(major_device_class, &bthci_cmd_cod_major_device_class_vals_ext, "Unknown"),
+            minor_device_class_name);
+
+    if (major_service_classes & 0x001) proto_item_append_text(cod_item, " LimitedDiscoverableMode");
+    if (major_service_classes & 0x008) proto_item_append_text(cod_item, " Positioning");
+    if (major_service_classes & 0x010) proto_item_append_text(cod_item, " Networking");
+
+    if (major_service_classes & 0x020) proto_item_append_text(cod_item, " Rendering");
+    if (major_service_classes & 0x040) proto_item_append_text(cod_item, " Capturing");
+    if (major_service_classes & 0x080) proto_item_append_text(cod_item, " ObjectTransfer");
+    if (major_service_classes & 0x100) proto_item_append_text(cod_item, " Audio");
+    if (major_service_classes & 0x200) proto_item_append_text(cod_item, " Telephony");
+    if (major_service_classes & 0x400) proto_item_append_text(cod_item, " Information");
+
+    proto_item_append_text(cod_item, ")");
+
+    return offset;
+}
+
+static gint
+dissect_btcommon_ad(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+    proto_item *main_item;
+    proto_tree *main_tree;
+
+    main_item = proto_tree_add_item(tree, hf_btcommon_eir_ad_advertising_data, tvb, 0, -1, ENC_NA);
+    main_tree = proto_item_add_subtree(main_item, ett_eir_ad);
+
+    return dissect_eir_ad_data(tvb, pinfo, main_tree);
+}
+
+static gint
+dissect_btcommon_eir(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+    proto_item *main_item;
+    proto_tree *main_tree;
+
+    main_item = proto_tree_add_item(tree, hf_btcommon_eir_ad_extended_inquiry_response_data, tvb, 0, -1, ENC_NA);
+    main_tree = proto_item_add_subtree(main_item, ett_eir_ad);
+
+    return dissect_eir_ad_data(tvb, pinfo, main_tree);
+}
+
+void
+proto_register_btcommon(void)
+{
+    module_t         *module;
+    expert_module_t  *expert_module;
+
+    static hf_register_info hf[] = {
+        { &hf_btcommon_eir_ad_extended_inquiry_response_data,
+          { "Extended Inquiry Response Data",    "btcommon.eir_ad.extended_inquiry_response_data",
+            FT_NONE, BASE_NONE, NULL, 0x0,
+            NULL, HFILL }
         },
-        { &hf_bthci_cmd_flags_general_disc_mode,
-          { "LE General Discoverable Mode",        "bthci_cmd.le_flags_general_disc_mode",
-            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x02,
+        { &hf_btcommon_eir_ad_advertising_data,
+          { "Advertising Data",                  "btcommon.eir_ad.advertising_data",
+            FT_NONE, BASE_NONE, NULL, 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_flags_bredr_not_support,
-          { "BR/EDR Not Supported",                "bthci_cmd.le_flags_bredr_not_supported",
-            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x04,
+        { &hf_btcommon_eir_ad_entry,
+          { "Entry",                             "btcommon.eir_ad.entry",
+            FT_NONE, BASE_NONE, NULL, 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_flags_le_bredr_support_ctrl,
-          { "Simultaneous LE and BR/EDR to Same Device Capable (Controller)",  "bthci_cmd.le_flags_bredr_support_ctrl",
-            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x08,
+        { &hf_btcommon_eir_ad_unused,
+        { "Unused",                              "btcommon.eir_ad.unused",
+            FT_NONE, BASE_NONE, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_data,
+          {"Data",                               "btcommon.eir_ad.entry.data",
+           FT_BYTES, BASE_NONE, NULL, 0x0,
+           NULL, HFILL}
+        },
+        { &hf_btcommon_eir_ad_length,
+          { "Length",                            "btcommon.eir_ad.entry.length",
+            FT_UINT8, BASE_DEC, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_type,
+          { "Type",                              "btcommon.eir_ad.entry.type",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_eir_data_type_vals_ext, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_company_id,
+          { "Company ID",                        "btcommon.eir_ad.entry.company_id",
+            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_evt_comp_id_ext, 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_flags_le_bredr_support_host,
-          { "Simultaneous LE and BR/EDR to Same Device Capable (Host)",        "bthci_cmd.le_flags_bredr_support_host",
+        { &hf_btcommon_eir_ad_flags_reserved,
+          { "Reserved",                          "btcommon.eir_ad.entry.flags.reserved",
+            FT_UINT8, BASE_HEX, NULL, 0xE0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_flags_le_bredr_support_host,
+          { "Simultaneous LE and BR/EDR to Same Device Capable (Host)",        "btcommon.eir_ad.entry.flags.le_bredr_support_host",
             FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x10,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_flags_le_oob_data_present,
-          { "OOB Data Present",                            "bthci_cmd.le_flags_le_oob_data_present",
-            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x01,
+        { &hf_btcommon_eir_ad_flags_le_bredr_support_controller,
+          { "Simultaneous LE and BR/EDR to Same Device Capable (Controller)",  "btcommon.eir_ad.entry.flags.le_bredr_support_controller",
+            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x08,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_flags_le_oob_le_supported_host,
-          { "LE Supported By Host",                        "bthci_cmd.le_flags_le_oob_le_supported_host",
+        { &hf_btcommon_eir_ad_flags_bredr_not_support,
+          { "BR/EDR Not Supported",              "btcommon.eir_ad.entry.flags.bredr_not_supported",
+            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x04,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_flags_le_general_discoverable_mode,
+          { "LE General Discoverable Mode",      "btcommon.eir_ad.entry.flags.le_general_discoverable_mode",
             FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x02,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_flags_le_oob_le_bredr_support,
-          { "Simultaneous LE and BR/EDR to Same Device Capable (Host)",   "bthci_cmd.le_flags_le_oob_le_bredr_support",
-            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x04,
+        { &hf_btcommon_eir_ad_flags_le_limited_discoverable_mode,
+          { "LE Limited Discoverable Mode",      "btcommon.eir_ad.entry.flags.le_limited_discoverable_mode",
+            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x01,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_flags_le_oob_address_type,
-          { "Address Type",                                "bthci_cmd.le_flags_le_oob_address_type",
-            FT_UINT8, BASE_HEX, VALS(bthci_cmd_address_types_vals), 0x08,
+        { &hf_btcommon_eir_ad_uuid_16,
+            { "UUID 16",                         "btcommon.eir_ad.entry.uuid_16",
+            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &vs_service_classes_ext, 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_eir_ad_ssp_oob_length,
-          { "SSP OOB Length",                              "bthci_cmd.eir_ad.ssp_oob_length",
-            FT_UINT16, BASE_DEC, NULL, 0x0,
+        { &hf_btcommon_eir_ad_uuid_32,
+            { "UUID 32",                         "btcommon.eir_ad.entry.uuid_32",
+            FT_UINT32, BASE_HEX | BASE_EXT_STRING, &vs_service_classes_ext, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_uuid_128,
+            { "UUID 128",                        "btcommon.eir_ad.entry.uuid_128",
+            FT_BYTES, BASE_NONE, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_custom_uuid,
+            { "Custom UUID",                     "btcommon.eir_ad.entry.custom_uuid",
+            FT_BYTES, BASE_NONE, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_name,
+          { "Device Name",                       "btcommon.eir_ad.entry.device_name",
+            FT_STRING, BASE_NONE, NULL, 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_eir_ad_advertising_interval,
-          { "Advertising Interval",                        "bthci_cmd.eir_ad.advertising_interval",
+        { &hf_btcommon_eir_ad_tx_power,
+          {"Power Level (dBm)",                  "btcommon.eir_ad.entry.power_level",
+           FT_INT8, BASE_DEC, NULL, 0x0,
+           NULL, HFILL}
+        },
+        { &hf_btcommon_eir_ad_ssp_oob_length,
+          { "SSP OOB Length",                    "btcommon.eir_ad.entry.ssp_oob_length",
             FT_UINT16, BASE_DEC, NULL, 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_cmd_eir_ad_company_id,
-          { "Company ID",                                  "bthci_cmd.eir_ad.company_id",
+        { &hf_btcommon_eir_ad_bd_addr,
+            { "BD_ADDR",                         "btcommon.eir_ad.entry.bd_addr",
+            FT_ETHER, BASE_NONE, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_le_bd_addr_reserved,
+            { "Reserved",                        "btcommon.eir_ad.entry.le_bd_addr.reserved",
+            FT_BOOLEAN, 8, NULL, 0xFE,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_le_bd_addr_type,
+            { "Type",                            "btcommon.eir_ad.entry.le_bd_addr.type",
+            FT_BOOLEAN, 8, NULL, 0x01,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_le_role,
+            { "Type",                            "btcommon.eir_ad.entry.le_role",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &le_role_vals_ext, 0x01,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_did_vendor_id_source,
+            { "Vendor ID Source",                "btcommon.eir_ad.entry.did.vendor_id_source",
+            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &did_vendor_id_source_vals_ext, 0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_did_vendor_id,
+            { "Vendor ID",                       "btcommon.eir_ad.entry.did.vendor_id",
+            FT_UINT16, BASE_HEX, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_did_vendor_id_bluetooth_sig,
+            { "Vendor ID",                       "btcommon.eir_ad.entry.did.vendor_id",
             FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_evt_comp_id_ext, 0x0,
             NULL, HFILL }
         },
-        { &hf_eir_ad_item,
-          { "Item",                                        "bthci_cmd.eir_ad",
-            FT_NONE, BASE_NONE, NULL, 0x0,
+        { &hf_btcommon_eir_ad_did_vendor_id_usb_forum,
+            { "Vendor ID",                       "btcommon.eir_ad.entry.did.vendor_id",
+            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ext_usb_vendors_vals, 0x0,
             NULL, HFILL }
         },
-        { &hf_extended_inquiry_response_data,
-          { "Extended Inquiry Response Data",              "bthci_cmd.extended_inquiry_response_data",
-            FT_NONE, BASE_NONE, NULL, 0x0,
+        { &hf_btcommon_eir_ad_did_product_id,
+            { "Product ID",                      "btcommon.eir_ad.entry.did.product_id",
+            FT_UINT16, BASE_HEX, NULL, 0x0,
             NULL, HFILL }
         },
-        { &hf_advertising_data,
-          { "Advertising Data",                            "bthci_cmd.advertising_data",
-            FT_NONE, BASE_NONE, NULL, 0x0,
+        { &hf_btcommon_eir_ad_did_version,
+            { "Version",                         "btcommon.eir_ad.entry.did.version",
+            FT_UINT16, BASE_HEX, NULL, 0x0,
             NULL, HFILL }
         },
-        { &hf_3ds_association_notification,
-          { "3DS Association Notification",                "bthci_cmd.eir_ad.3ds.association_notification",
+        { &hf_btcommon_eir_ad_3ds_association_notification,
+          { "3DS Association Notification",                "btcommon.eir_ad.entry.3ds.association_notification",
             FT_BOOLEAN, 8, NULL, 0x01,
             NULL, HFILL }
         },
-        { &hf_3ds_battery_level_reporting,
-          { "3DS Battery Level Reporting",                 "bthci_cmd.eir_ad.3ds.battery_level_reporting",
+        { &hf_btcommon_eir_ad_3ds_battery_level_reporting,
+          { "3DS Battery Level Reporting",                 "btcommon.eir_ad.entry.3ds.battery_level_reporting",
             FT_BOOLEAN, 8, NULL, 0x02,
             NULL, HFILL }
         },
-        { &hf_3ds_send_battery_level_report_on_startup,
-          { "3DS Send Battery Level Report on Startup",    "bthci_cmd.eir_ad.3ds.send_battery_level_report_on_startup",
+        { &hf_btcommon_eir_ad_3ds_send_battery_level_report_on_startup,
+          { "3DS Send Battery Level Report on Startup",    "btcommon.eir_ad.entry.3ds.send_battery_level_report_on_startup",
             FT_BOOLEAN, 8, NULL, 0x04,
             NULL, HFILL }
         },
-        { &hf_3ds_reserved,
-          { "Reserved",                                    "bthci_cmd.eir_ad.3ds.reserved",
+        { &hf_btcommon_eir_ad_3ds_reserved,
+          { "Reserved",                                    "btcommon.eir_ad.entry.3ds.reserved",
             FT_BOOLEAN, 8, NULL, 0x78,
             NULL, HFILL }
         },
-        { &hf_3ds_factory_test_mode,
-          { "3DS Factory Test Mode",                       "bthci_cmd.eir_ad.3ds.factory_test_mode",
+        { &hf_btcommon_eir_ad_3ds_factory_test_mode,
+          { "3DS Factory Test Mode",                       "btcommon.eir_ad.entry.3ds.factory_test_mode",
             FT_BOOLEAN, 8, NULL, 0x80,
             NULL, HFILL }
         },
-        { &hf_3ds_path_loss_threshold,
-          { "3DS Path Loss Threshold",                     "bthci_cmd.eir_ad.3ds.path_loss_threshold",
+        { &hf_btcommon_eir_ad_3ds_path_loss_threshold,
+          { "3DS Path Loss Threshold",                     "btcommon.eir_ad.entry.3ds.path_loss_threshold",
             FT_UINT8, BASE_DEC, NULL, 0x00,
             NULL, HFILL }
         },
-        { &hf_3ds_legacy_fixed,
-          { "3DS Legacy Fixed",                            "bthci_cmd.eir_ad.3ds_legacy.fixed_byte",
+        { &hf_btcommon_eir_ad_3ds_legacy_fixed,
+          { "3DS Legacy Fixed",                            "btcommon.eir_ad.entry.3ds_legacy.fixed_byte",
             FT_UINT8, BASE_DEC, NULL, 0x00,
             NULL, HFILL }
         },
-        { &hf_3ds_legacy_3d_capable_tv,
-          { "3DS Legacy Capable TV",                       "bthci_cmd.eir_ad.3ds_legacy.capable_tv",
+        { &hf_btcommon_eir_ad_3ds_legacy_3d_capable_tv,
+          { "3DS Legacy Capable TV",                       "btcommon.eir_ad.entry.3ds_legacy.capable_tv",
             FT_BOOLEAN, 8, NULL, 0x01,
             NULL, HFILL }
         },
-        { &hf_3ds_legacy_ignored_1_3,
-          { "3DS Legacy Ignored",                          "bthci_cmd.eir_ad.3ds_legacy.ignored.1_3",
+        { &hf_btcommon_eir_ad_3ds_legacy_ignored_1_3,
+          { "3DS Legacy Ignored",                          "btcommon.eir_ad.entry.3ds_legacy.ignored.1_3",
             FT_BOOLEAN, 8, NULL, 0x0E,
             NULL, HFILL }
         },
-        { &hf_3ds_legacy_fixed_4,
-          { "3DS Legacy Fixed",                            "bthci_cmd.eir_ad.3ds_legacy.fixed.4",
+        { &hf_btcommon_eir_ad_3ds_legacy_fixed_4,
+          { "3DS Legacy Fixed",                            "btcommon.eir_ad.entry.3ds_legacy.fixed.4",
             FT_BOOLEAN, 8, NULL, 0x10,
             NULL, HFILL }
         },
-        { &hf_3ds_legacy_ignored_5,
-          { "3DS Legacy Ignored",                          "bthci_cmd.eir_ad.3ds_legacy.ignored.5",
+        { &hf_btcommon_eir_ad_3ds_legacy_ignored_5,
+          { "3DS Legacy Ignored",                          "btcommon.eir_ad.entry.3ds_legacy.ignored.5",
             FT_BOOLEAN, 8, NULL, 0x20,
             NULL, HFILL }
         },
-        { &hf_3ds_legacy_fixed_6,
-          { "3DS Legacy Fixed",                            "bthci_cmd.eir_ad.3ds_legacy.fixed.4",
+        { &hf_btcommon_eir_ad_3ds_legacy_fixed_6,
+          { "3DS Legacy Fixed",                            "btcommon.eir_ad.entry.3ds_legacy.fixed.4",
             FT_BOOLEAN, 8, NULL, 0x40,
             NULL, HFILL }
         },
-        { &hf_3ds_legacy_test_mode,
-          { "3DS Legacy Test Mode",                        "bthci_cmd.eir_ad.3ds_legacy.test_mode",
+        { &hf_btcommon_eir_ad_3ds_legacy_test_mode,
+          { "3DS Legacy Test Mode",                        "btcommon.eir_ad.entry.3ds_legacy.test_mode",
             FT_BOOLEAN, 8, NULL, 0x80,
             NULL, HFILL }
         },
-        { &hf_3ds_legacy_path_loss_threshold,
-          { "3DS Legacy Path Loss Threshold",              "bthci_cmd.eir_ad.3ds_legacy.path_loss_threshold",
+        { &hf_btcommon_eir_ad_3ds_legacy_path_loss_threshold,
+          { "3DS Legacy Path Loss Threshold",              "btcommon.eir_ad.entry.3ds_legacy.path_loss_threshold",
             FT_UINT8, BASE_DEC, NULL, 0x00,
             NULL, HFILL }
         },
-        { &hf_did_vendor_id_source,
-            { "Vendor ID Source",                          "bthci_cmd.eir_ad.did.vendor_id_source",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &did_vendor_id_source_vals_ext, 0,
+        { &hf_btcommon_eir_ad_advertising_interval,
+          { "Advertising Interval",              "btcommon.eir_ad.entry.advertising_interval",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
             NULL, HFILL }
         },
-        { &hf_did_vendor_id,
-            { "Vendor ID",                                 "bthci_cmd.eir_ad.did.vendor_id",
-            FT_UINT16, BASE_HEX, NULL, 0,
+        { &hf_btcommon_eir_ad_appearance,
+          { "Appearance",                        "btcommon.eir_ad.entry.appearance",
+            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_appearance_vals_ext, 0x0,
             NULL, HFILL }
         },
-        { &hf_did_vendor_id_bluetooth_sig,
-            { "Vendor ID",                                 "bthci_cmd.eir_ad.did.vendor_id",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_evt_comp_id_ext, 0,
+        { &hf_btcommon_eir_ad_hash_c,
+          {"Hash C",                             "btcommon.eir_ad.entry.hash_c",
+           FT_BYTES, BASE_NONE, NULL, 0x0,
+           NULL, HFILL}
+        },
+        { &hf_btcommon_eir_ad_randomizer_r,
+          {"Randomizer R",                       "btcommon.eir_ad.entry.randomizer_r",
+           FT_BYTES, BASE_NONE, NULL, 0x0,
+           NULL, HFILL}
+        },
+        { &hf_btcommon_eir_ad_oob_flags_reserved,
+          { "Reserved",                                                   "btcommon.eir_ad.entry.oob_flags.oob_reserved",
+            FT_UINT8, BASE_HEX, NULL, 0xF0,
             NULL, HFILL }
         },
-        { &hf_did_vendor_id_usb_forum,
-            { "Vendor ID",                                 "bthci_cmd.eir_ad.did.vendor_id",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ext_usb_vendors_vals, 0,
+        { &hf_btcommon_eir_ad_oob_flags_address_type,
+          { "Address Type",                                               "btcommon.eir_ad.entry.oob_flags.oob_address_type",
+            FT_UINT8, BASE_HEX, VALS(bthci_cmd_address_types_vals), 0x08,
             NULL, HFILL }
         },
-        { &hf_did_product_id,
-            { "Product ID",                                "bthci_cmd.eir_ad.did.product_id",
-            FT_UINT16, BASE_HEX, NULL, 0,
+        { &hf_btcommon_eir_ad_oob_flags_le_bredr_support,
+          { "Simultaneous LE and BR/EDR to Same Device Capable (Host)",   "btcommon.eir_ad.entry.oob_flags.oob_le_bredr_support",
+            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x04,
             NULL, HFILL }
         },
-        { &hf_did_version,
-            { "Version",                                   "bthci_cmd.eir_ad.did.version",
-            FT_UINT16, BASE_HEX, NULL, 0,
+        { &hf_btcommon_eir_ad_oob_flags_le_supported_host,
+          { "LE Supported By Host",                                       "btcommon.eir_ad.entry.oob_flags.oob_le_supported_host",
+            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x02,
             NULL, HFILL }
-        }
-    };
-
-    static ei_register_info ei[] = {
-        { &ei_eir_undecoded,                { "bthci_cmd.expert.eir.undecoded", PI_PROTOCOL, PI_UNDECODED, "Undecoded", EXPFILL }},
-        { &ei_eir_unknown,                  { "bthci_cmd.expert.eir.unknown", PI_PROTOCOL, PI_WARN, "Unknown data", EXPFILL }},
-        { &ei_command_unknown,              { "bthci_cmd.expert.command.unknown.", PI_PROTOCOL, PI_WARN, "Unknown command", EXPFILL }},
-        { &ei_command_parameter_unexpected, { "bthci_cmd.expert.parameter.unexpected", PI_PROTOCOL, PI_WARN, "Unexpected command parameter", EXPFILL }},
-        { &ei_command_undecoded,            { "bthci_cmd.expert.command.undecoded", PI_PROTOCOL, PI_UNDECODED, "Command undecoded", EXPFILL }}
+        },
+        { &hf_btcommon_eir_ad_oob_flags_data_present,
+          { "OOB Data Present",                                           "btcommon.eir_ad.entry.oob_flags.oob_data_present",
+            FT_UINT8, BASE_HEX, VALS(cmd_boolean), 0x01,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_connection_interval_min,
+          { "Connection Interval Min",           "btcommon.eir_ad.entry.connection_interval_min",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_eir_ad_connection_interval_max,
+          { "Connection Interval Max",           "btcommon.eir_ad.entry.connection_interval_max",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_class_of_device,
+          { "Class of Device", "btcommon.cod.class_of_device",
+            FT_UINT24, BASE_HEX, NULL, 0x0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_information,
+          { "Major Service Classes: Information", "btcommon.cod.major_service_classes.information",
+            FT_BOOLEAN, 16, NULL, 0x8000,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_telephony,
+          { "Major Service Classes: Telephony", "btcommon.cod.major_service_classes.telephony",
+            FT_BOOLEAN, 16, NULL, 0x4000,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_audio,
+          { "Major Service Classes: Audio", "btcommon.cod.major_service_classes.audio",
+            FT_BOOLEAN, 16, NULL, 0x2000,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_object_transfer,
+          { "Major Service Classes: Object Transfer", "btcommon.cod.major_service_classes.object_transfer",
+            FT_BOOLEAN, 16, NULL, 0x1000,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_capturing,
+          { "Major Service Classes: Capturing", "btcommon.cod.major_service_classes.capturing",
+            FT_BOOLEAN, 16, NULL, 0x0800,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_rendering,
+          { "Major Service Classes: Rendering", "btcommon.cod.major_service_classes.rendering",
+            FT_BOOLEAN, 16, NULL, 0x0400,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_networking,
+          { "Major Service Classes: Networking", "btcommon.cod.major_service_classes.networking",
+            FT_BOOLEAN, 16, NULL, 0x0200,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_positioning,
+          { "Major Service Classes: Positioning", "btcommon.cod.major_service_classes.positioning",
+            FT_BOOLEAN, 16, NULL, 0x0100,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_reserved,
+          { "Major Service Classes: Reserved", "btcommon.cod.major_service_classes.reserved",
+            FT_UINT16, BASE_HEX, NULL, 0x00C0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_service_class_limited_discoverable_mode,
+          { "Major Service Classes: Limited Discoverable Mode", "btcommon.cod.major_service_classes.limited_discoverable_mode",
+            FT_BOOLEAN, 16, NULL, 0x0020,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_major_device_class,
+          { "Major Device Class", "btcommon.cod.major_device_class",
+            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_major_device_class_vals_ext, 0x1F,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_computer,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_computer_vals_ext, 0xFC,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_phone,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_phone_vals_ext, 0xFC,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_lan_net_load_factor,
+          { "Minor Device Class: Load Factor", "btcommon.cod.minor_device_class.load_factor",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_lan_net_load_factor_vals_ext, 0xE0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_lan_net_type,
+          { "Minor Device Class: Type", "btcommon.cod.minor_device_class.type",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_lan_net_type_vals_ext, 0x1C,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_audio_video,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_audio_video_vals_ext, 0xFC,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_peripheral_class,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_peripheral_class_vals_ext, 0xC0,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_peripheral_type,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_peripheral_type_vals_ext, 0x3C,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_imaging_class_printer,
+          { "Minor Device Class: Class: Printer", "btcommon.cod.minor_device_class.class.printer",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x80,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_imaging_class_scanner,
+          { "Minor Device Class: Class: Scanner", "btcommon.cod.minor_device_class.class.scanner",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x40,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_imaging_class_camera,
+          { "Minor Device Class: Class: Camera", "btcommon.cod.minor_device_class.class.camera",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x20,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_imaging_class_display,
+          { "Minor Device Class: Class: Display", "btcommon.cod.minor_device_class.class.display",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x10,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_imaging_type,
+          { "Minor Device Class: Type", "btcommon.cod.minor_device_class.type",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x0C,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_wearable,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_wearable_vals_ext, 0xFC,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_toy,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_toy_vals_ext, 0xFC,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_health,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_health_vals_ext, 0xFC,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_minor_device_class_unknown,
+          { "Minor Device Class", "btcommon.cod.minor_device_class",
+            FT_UINT8, BASE_HEX, NULL, 0xFC,
+            NULL, HFILL }
+        },
+        { &hf_btcommon_cod_format_type,
+          { "Format Type", "btcommon.cod.format_type",
+            FT_UINT8, BASE_HEX, NULL, 0x03,
+            NULL, HFILL }
+        },
     };
 
-    /* Setup protocol subtree array */
     static gint *ett[] = {
-        &ett_bthci_cmd,
-        &ett_opcode,
-        &ett_cod,
-        &ett_cod_mask,
-        &ett_eir_subtree,
-        &ett_eir_struct_subtree,
-        &ett_flow_spec_subtree
+        &ett_eir_ad,
+        &ett_eir_ad_entry,
     };
 
-    /* Dynamically fill "bthci_cmd_opcode_vals" */
-    static const struct _opcode_value_string_arrays {
-        guint                ogf;
-        const value_string  *string_array;
-        guint                length;
-    } opcode_value_string_arrays[] = {
-        { 0x01, bthci_cmd_ocf_link_control_vals, array_length(bthci_cmd_ocf_link_control_vals) },
-        { 0x02, bthci_cmd_ocf_link_policy_vals, array_length(bthci_cmd_ocf_link_policy_vals) },
-        { 0x03, bthci_cmd_ocf_host_controller_and_baseband_vals, array_length(bthci_cmd_ocf_host_controller_and_baseband_vals) },
-        { 0x04, bthci_cmd_ocf_informational_vals, array_length(bthci_cmd_ocf_informational_vals) },
-        { 0x05, bthci_cmd_ocf_status_vals, array_length(bthci_cmd_ocf_status_vals) },
-        { 0x06, bthci_cmd_ocf_testing_vals, array_length(bthci_cmd_ocf_testing_vals) },
-        { 0x08, bthci_cmd_ocf_low_energy_vals, array_length(bthci_cmd_ocf_low_energy_vals) },
+    static ei_register_info ei[] = {
+        { &ei_eir_ad_undecoded,       { "btcommon.eir_ad.undecoded", PI_PROTOCOL, PI_UNDECODED, "Undecoded", EXPFILL }},
+        { &ei_eir_ad_unknown,         { "btcommon.eir_ad.unknown", PI_PROTOCOL, PI_WARN, "Unknown data", EXPFILL }},
     };
 
-    bthci_cmd_opcode_vals[i_opcode].value = 0;
-    bthci_cmd_opcode_vals[i_opcode].strptr = "No Operation";
-    i_opcode += 1;
-    for (i_array = 0; i_array < array_length(opcode_value_string_arrays); i_array += 1) {
-        for (i_string_array = 0; i_string_array < opcode_value_string_arrays[i_array].length - 1; i_string_array += 1) {
-            bthci_cmd_opcode_vals[i_opcode].value = opcode_value_string_arrays[i_array].string_array[i_string_array].value | (opcode_value_string_arrays[i_array].ogf << 10);
-            bthci_cmd_opcode_vals[i_opcode].strptr = opcode_value_string_arrays[i_array].string_array[i_string_array].strptr;
-            i_opcode += 1;
-        }
-    }
+    proto_btcommon = proto_register_protocol("Bluetooth Common", "BT Common", "btcommon");
 
-    /* Register the protocol name and description */
-    proto_bthci_cmd = proto_register_protocol("Bluetooth HCI Command", "HCI_CMD", "bthci_cmd");
-
-    bthci_cmd_handle = new_register_dissector("bthci_cmd", dissect_bthci_cmd, proto_bthci_cmd);
-
-    /* Required function calls to register the header fields and subtrees used */
-    proto_register_field_array(proto_bthci_cmd, hf, array_length(hf));
+    proto_register_field_array(proto_btcommon, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
 
-    expert_bthci_cmd = expert_register_protocol(proto_bthci_cmd);
-    expert_register_field_array(expert_bthci_cmd, ei, array_length(ei));
+    expert_module = expert_register_protocol(proto_btcommon);
+    expert_register_field_array(expert_module, ei, array_length(ei));
 
-    module = prefs_register_protocol(proto_bthci_cmd, NULL);
+    module = prefs_register_protocol(proto_btcommon, NULL);
     prefs_register_static_text_preference(module, "hci_cmd.version",
-            "Bluetooth HCI version: 4.0 (Core)",
+            "Bluetooth EIR/AD version: 4.0 (Core)",
             "Version of protocol supported by this dissector.");
-}
 
-
-/* If this dissector uses sub-dissector registration add a registration routine.
-   This format is required because a script is used to find these routines and
-   create the code that calls these routines.
-   */
-void
-proto_reg_handoff_bthci_cmd(void)
-{
-    dissector_add_uint("hci_h4.type", HCI_H4_TYPE_CMD, bthci_cmd_handle);
-    dissector_add_uint("hci_h1.type", BTHCI_CHANNEL_COMMAND, bthci_cmd_handle);
+    btcommon_ad_handle  = new_register_dissector("btcommon.eir_ad.ad",  dissect_btcommon_ad,  proto_btcommon);
+    btcommon_eir_handle = new_register_dissector("btcommon.eir_ad.eir", dissect_btcommon_eir, proto_btcommon);
+    btcommon_cod_handle = new_register_dissector("btcommon.cod",        dissect_btcommon_cod, proto_btcommon);
 }
 
 /*
index 44b064e6cc2c4a75eb58f1fbb446e16a062e8107..40e427451c48fed01f25e3eb02079d3ec4b1bf3d 100644 (file)
@@ -45,6 +45,9 @@
 
 static dissector_handle_t bthci_cmd_handle;
 static dissector_handle_t bthci_evt_handle;
+static dissector_handle_t btcommon_cod_handle;
+static dissector_handle_t btcommon_eir_handle;
+static dissector_handle_t btcommon_ad_handle;
 
 /* Initialize the protocol and registered fields */
 static int proto_bthci_evt = -1;
@@ -69,35 +72,6 @@ static int hf_bthci_evt_ocf_testing = -1;
 static int hf_bthci_evt_ocf_logo_testing = -1;
 static int hf_bthci_evt_ocf_low_energy = -1;
 static int hf_bthci_evt_bd_addr = -1;
-static int hf_bthci_evt_class_of_device = -1;
-static int hf_bthci_evt_cod_format_type = -1;
-static int hf_bthci_evt_cod_major_service_class_information = -1;
-static int hf_bthci_evt_cod_major_service_class_telephony = -1;
-static int hf_bthci_evt_cod_major_service_class_audio = -1;
-static int hf_bthci_evt_cod_major_service_class_object_transfer = -1;
-static int hf_bthci_evt_cod_major_service_class_capturing = -1;
-static int hf_bthci_evt_cod_major_service_class_rendering = -1;
-static int hf_bthci_evt_cod_major_service_class_networking = -1;
-static int hf_bthci_evt_cod_major_service_class_positioning = -1;
-static int hf_bthci_evt_cod_major_service_class_reserved = -1;
-static int hf_bthci_evt_cod_major_service_class_limited_discoverable_mode = -1;
-static int hf_bthci_evt_cod_major_device_class = -1;
-static int hf_bthci_evt_cod_minor_device_class_computer = -1;
-static int hf_bthci_evt_cod_minor_device_class_phone = -1;
-static int hf_bthci_evt_cod_minor_device_class_lan_net_load_factor = -1;
-static int hf_bthci_evt_cod_minor_device_class_lan_net_type = -1;
-static int hf_bthci_evt_cod_minor_device_class_audio_video = -1;
-static int hf_bthci_evt_cod_minor_device_class_peripheral_class = -1;
-static int hf_bthci_evt_cod_minor_device_class_peripheral_type = -1;
-static int hf_bthci_evt_cod_minor_device_class_imaging_class_printer = -1;
-static int hf_bthci_evt_cod_minor_device_class_imaging_class_scanner = -1;
-static int hf_bthci_evt_cod_minor_device_class_imaging_class_camera = -1;
-static int hf_bthci_evt_cod_minor_device_class_imaging_class_display = -1;
-static int hf_bthci_evt_cod_minor_device_class_imaging_type = -1;
-static int hf_bthci_evt_cod_minor_device_class_wearable = -1;
-static int hf_bthci_evt_cod_minor_device_class_toy = -1;
-static int hf_bthci_evt_cod_minor_device_class_health = -1;
-static int hf_bthci_evt_cod_minor_device_class_unknown = -1;
 static int hf_bthci_evt_link_type = -1;
 static int hf_bthci_evt_encryption_mode = -1;
 static int hf_bthci_evt_reason = -1;
@@ -287,14 +261,7 @@ static int hf_bthci_evt_auth_requirements = -1;
 static int hf_bthci_evt_numeric_value = -1;
 static int hf_bthci_evt_passkey = -1;
 static int hf_bthci_evt_notification_type = -1;
-static int hf_bthci_evt_data = -1;
-static int hf_bthci_evt_eir_struct_length = -1;
-static int hf_bthci_evt_eir_struct_type = -1;
-static int hf_bthci_evt_sc_uuid16 = -1;
-static int hf_bthci_evt_sc_uuid32 = -1;
-static int hf_bthci_evt_sc_uuid128 = -1;
 static int hf_bthci_evt_data_length = -1;
-
 static int hf_bthci_evt_location_domain_aware = -1;
 static int hf_bthci_evt_location_domain = -1;
 static int hf_bthci_evt_location_domain_options = -1;
@@ -349,17 +316,6 @@ static int hf_bthci_evt_encrypted_diversifier = -1;
 static int hf_bthci_evt_le_master_clock_accuracy = -1;
 static int hf_bthci_evt_num_reports = -1;
 static int hf_bthci_evt_advts_event_type = -1;
-static int hf_bthci_evt_appearance = -1;
-static int hf_bthci_evt_flags_limited_disc_mode = -1;
-static int hf_bthci_evt_flags_general_disc_mode = -1;
-static int hf_bthci_evt_flags_bredr_not_support = -1;
-static int hf_bthci_evt_flags_le_bredr_support_ctrl = -1;
-static int hf_bthci_evt_flags_le_bredr_support_host = -1;
-static int hf_bthci_evt_flags_reserved = -1;
-static int hf_bthci_evt_oob_flags_oob_data_present = -1;
-static int hf_bthci_evt_oob_flags_le_supported_host = -1;
-static int hf_bthci_evt_oob_flags_simultaneous_le_and_br_edr_host = -1;
-static int hf_bthci_evt_oob_flags_address_type = -1;
 static int hf_bthci_evt_le_states = -1;
 static int hf_bthci_evt_le_states_00 = -1;
 static int hf_bthci_evt_le_states_01 = -1;
@@ -390,47 +346,16 @@ static int hf_bthci_evt_le_states_31 = -1;
 static int hf_bthci_evt_le_states_32 = -1;
 static int hf_bthci_evt_le_states_33 = -1;
 static int hf_bthci_evt_le_states_34 = -1;
-static int hf_bthci_evt_eir_ad_ssp_oob_length = -1;
-static int hf_bthci_evt_eir_ad_advertising_interval = -1;
-static int hf_bthci_evt_eir_ad_company_id = -1;
-static int hf_eir_ad_item = -1;
-static int hf_extended_inquiry_response_data = -1;
-static int hf_advertising_data = -1;
 static int hf_usable_packet_types = -1;
-static int hf_3ds_association_notification = -1;
-static int hf_3ds_battery_level_reporting = -1;
-static int hf_3ds_send_battery_level_report_on_startup = -1;
-static int hf_3ds_reserved = -1;
-static int hf_3ds_factory_test_mode = -1;
-static int hf_3ds_path_loss_threshold = -1;
-static int hf_3ds_legacy_fixed = -1;
-static int hf_3ds_legacy_3d_capable_tv = -1;
-static int hf_3ds_legacy_ignored_1_3 = -1;
-static int hf_3ds_legacy_fixed_4 = -1;
-static int hf_3ds_legacy_ignored_5 = -1;
-static int hf_3ds_legacy_fixed_6 = -1;
-static int hf_3ds_legacy_test_mode = -1;
-static int hf_3ds_legacy_path_loss_threshold = -1;
-static int hf_did_vendor_id = -1;
-static int hf_did_vendor_id_bluetooth_sig = -1;
-static int hf_did_vendor_id_usb_forum = -1;
-static int hf_did_product_id = -1;
-static int hf_did_version = -1;
-static int hf_did_vendor_id_source = -1;
-
-static expert_field ei_eir_undecoded   = EI_INIT;
-static expert_field ei_eir_unknown     = EI_INIT;
+
 static expert_field ei_event_undecoded = EI_INIT;
 static expert_field ei_event_unknown   = EI_INIT;
 
 /* Initialize the subtree pointers */
 static gint ett_bthci_evt = -1;
 static gint ett_opcode = -1;
-static gint ett_cod = -1;
 static gint ett_lmp_subtree = -1;
 static gint ett_ptype_subtree = -1;
-static gint ett_eir_subtree = -1;
-static gint ett_eir_struct_subtree = -1;
 static gint ett_le_state_subtree = -1;
 
 extern value_string_ext ext_usb_vendors_vals;
@@ -980,107 +905,55 @@ dissect_bthci_evt_bd_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
     return offset;
 }
 
-static int
-dissect_bthci_evt_cod(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+static void
+save_remote_device_name(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+        guint8 size, guint8 *bd_addr, hci_data_t *hci_data)
 {
-    guint16      major_service_classes;
-    guint8       major_device_class;
-    guint8       minor_device_class;
-    const gchar *minor_device_class_name;
-    proto_item  *cod_item;
-    proto_item  *cod_tree;
-
-    cod_item = proto_tree_add_item(tree, hf_bthci_evt_class_of_device, tvb, offset, 3, ENC_LITTLE_ENDIAN);
-    cod_tree = proto_item_add_subtree(cod_item, ett_cod);
-
-    major_device_class = tvb_get_guint8(tvb, offset + 1) & 0x1F;
-    minor_device_class = tvb_get_guint8(tvb, offset) >> 2;
-
-    switch(major_device_class) {
-    case 0x01: /* Computer */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_computer, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_computer_vals_ext, "Unknown");
-        break;
-    case 0x02: /* Phone */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_phone, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_phone_vals_ext, "Unknown");
-        break;
-    case 0x03: /* LAN/Network Access Point */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_lan_net_load_factor, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_lan_net_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_lan_net_load_factor_vals_ext, "Unknown");
-        break;
-    case 0x04: /* Audio/Video */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_audio_video, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_audio_video_vals_ext, "Unknown");
-        break;
-    case 0x05: /* Peripheral */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_peripheral_class, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_peripheral_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_peripheral_class_vals_ext, "Unknown");
-        break;
-    case 0x06: /* Imaging */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_imaging_class_printer, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_imaging_class_scanner, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_imaging_class_camera, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_imaging_class_display, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_imaging_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, "Unknown");
-        break;
-    case 0x07: /* Wearable */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_wearable, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_wearable_vals_ext, "Unknown");
-        break;
-    case 0x08: /* Toy */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_toy, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_toy_vals_ext, "Unknown");
-        break;
-    case 0x09: /* Health */
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_health, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-        minor_device_class_name = val_to_str_ext_const(minor_device_class, &bthci_cmd_cod_minor_device_class_health_vals_ext, "Unknown");
-        break;
-    default:
-        minor_device_class_name = "Unknown";
-        proto_tree_add_item(cod_tree, hf_bthci_evt_cod_minor_device_class_unknown, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-    }
+    gint             i = 0;
+    guint8           length;
+    wmem_tree_key_t  key[4];
+    guint32          k_bd_addr_oui;
+    guint32          k_bd_addr_id;
+    guint32          k_frame_number;
+    gchar           *name;
+    device_name_t   *device_name;
 
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_format_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-    offset += 1;
+    if (!(!pinfo->fd->flags.visited && hci_data && bd_addr)) return;
 
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_information,               tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_telephony,                 tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_audio,                     tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_object_transfer,           tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_capturing,                 tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_rendering,                 tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_networking,                tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_positioning,               tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_reserved,                  tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_service_class_limited_discoverable_mode, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    major_service_classes = tvb_get_letohs(tvb, offset) >> 5;
-
-    proto_tree_add_item(cod_tree, hf_bthci_evt_cod_major_device_class, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-    offset += 2;
+    while (i < size) {
+        length = tvb_get_guint8(tvb, offset + i);
+        if (length == 0) break;
 
-    proto_item_append_text(cod_item, " (%s:%s - services:",
-            val_to_str_ext_const(major_device_class, &bthci_cmd_cod_major_device_class_vals_ext, "Unknown"),
-            minor_device_class_name);
+        switch(tvb_get_guint8(tvb, offset + i + 1)) {
+        case 0x08: /* Device Name, shortened */
+        case 0x09: /* Device Name, full */
+            name = tvb_get_string(wmem_packet_scope(), tvb, offset + i + 2, length - 1);
 
-    if (major_service_classes & 0x001) proto_item_append_text(cod_item, " LimitedDiscoverableMode");
-    if (major_service_classes & 0x008) proto_item_append_text(cod_item, " Positioning");
-    if (major_service_classes & 0x010) proto_item_append_text(cod_item, " Networking");
+            k_frame_number = pinfo->fd->num;
+            k_bd_addr_oui = bd_addr[0] << 16 | bd_addr[1] << 8 | bd_addr[2];
+            k_bd_addr_id  = bd_addr[3] << 16 | bd_addr[4] << 8 | bd_addr[5];
 
-    if (major_service_classes & 0x020) proto_item_append_text(cod_item, " Rendering");
-    if (major_service_classes & 0x040) proto_item_append_text(cod_item, " Capturing");
-    if (major_service_classes & 0x080) proto_item_append_text(cod_item, " ObjectTransfer");
-    if (major_service_classes & 0x100) proto_item_append_text(cod_item, " Audio");
-    if (major_service_classes & 0x200) proto_item_append_text(cod_item, " Telephony");
-    if (major_service_classes & 0x400) proto_item_append_text(cod_item, " Information");
+            key[0].length = 1;
+            key[0].key    = &k_bd_addr_id;
+            key[1].length = 1;
+            key[1].key    = &k_bd_addr_oui;
+            key[2].length = 1;
+            key[2].key    = &k_frame_number;
+            key[3].length = 0;
+            key[3].key    = NULL;
 
-    proto_item_append_text(cod_item, ")");
+            device_name = (device_name_t *) wmem_new(wmem_file_scope(), device_name_t);
+            device_name->bd_addr_oui =  bd_addr[0] << 16 | bd_addr[1] << 8 | bd_addr[2];
+            device_name->bd_addr_id =  bd_addr[3] << 16 | bd_addr[4] << 8 | bd_addr[5];
+            device_name->name = wmem_strdup(wmem_file_scope(), name);
 
-    return offset;
+            wmem_tree_insert32_array(hci_data->bdaddr_to_name_table, key, device_name);
+
+            break;
+        }
+
+        i += length + 1;
+    }
 }
 
 static int
@@ -1157,7 +1030,8 @@ dissect_bthci_evt_conn_request(tvbuff_t *tvb, int offset, packet_info *pinfo, pr
 {
     offset = dissect_bthci_evt_bd_addr(tvb, offset, pinfo, tree, NULL);
 
-    offset = dissect_bthci_evt_cod(tvb, offset, pinfo, tree);
+    call_dissector(btcommon_cod_handle, tvb_new_subset(tvb, offset, 3, 3), pinfo, tree);
+    offset += 3;
 
     proto_tree_add_item(tree, hf_bthci_evt_link_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
     offset += 1;
@@ -1743,7 +1617,8 @@ dissect_bthci_evt_inq_result_with_rssi(tvbuff_t *tvb, int offset,
         /* reserved byte */
         offset += 1;
 
-        offset = dissect_bthci_evt_cod(tvb, offset, pinfo, tree);
+        call_dissector(btcommon_cod_handle, tvb_new_subset(tvb, offset, 3, 3), pinfo, tree);
+        offset += 3;
 
         proto_tree_add_item(tree, hf_bthci_evt_clock_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
         offset += 2;
@@ -1756,264 +1631,6 @@ dissect_bthci_evt_inq_result_with_rssi(tvbuff_t *tvb, int offset,
     return offset;
 }
 
-static int
-dissect_bthci_evt_eir_ad_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
-        proto_tree *tree, guint8 size, guint8 *bd_addr, hci_data_t *hci_data)
-{
-    guint16      i, j;
-    guint8       length, type;
-    proto_item  *ti_eir = NULL;
-    proto_item  *ti_eir_subtree = NULL;
-    proto_item  *sub_item;
-
-    if (tree) {
-        ti_eir = proto_tree_add_item(tree, (size == 240) ? hf_extended_inquiry_response_data : hf_advertising_data,
-                tvb, offset, size, ENC_NA);
-        ti_eir_subtree = proto_item_add_subtree(ti_eir, ett_eir_subtree);
-    }
-
-    i = 0;
-    while (i < size) {
-        length = tvb_get_guint8(tvb, offset+i);
-        if (length != 0) {
-
-            proto_item *ti_eir_struct;
-            proto_tree *ti_eir_struct_subtree;
-
-            type = tvb_get_guint8(tvb, offset + i + 1);
-
-            ti_eir_struct = proto_tree_add_none_format(ti_eir_subtree, hf_eir_ad_item, tvb, offset + i, length + 1, "%s",
-                    val_to_str_ext_const(type, &bthci_cmd_eir_data_type_vals_ext, "Unknown"));
-            ti_eir_struct_subtree = proto_item_add_subtree(ti_eir_struct, ett_eir_struct_subtree);
-
-            proto_item_append_text(ti_eir_struct,"%s", val_to_str_ext_const(type, &bthci_cmd_eir_data_type_vals_ext, "Unknown"));
-
-            proto_tree_add_item(ti_eir_struct_subtree,hf_bthci_evt_eir_struct_length, tvb, offset + i, 1, ENC_LITTLE_ENDIAN);
-            proto_tree_add_item(ti_eir_struct_subtree,hf_bthci_evt_eir_struct_type, tvb, offset + i + 1, 1, ENC_LITTLE_ENDIAN);
-
-            switch(type) {
-                case 0x01: /* Flags */
-                    if (length > 1)
-                    {
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_flags_limited_disc_mode, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_flags_general_disc_mode, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_flags_bredr_not_support, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_flags_le_bredr_support_ctrl, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_flags_le_bredr_support_host, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_flags_reserved, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-
-                    }
-                    break;
-                case 0x02: /* 16-bit Service Class UUIDs, incomplete list */
-                case 0x03: /* 16-bit Service Class UUIDs, complete list */
-                case 0x14: /* 16-bit Service Solicitation UUIDs */
-                    j = 0;
-                    while (j < (guint8)(length - 1))
-                    {
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_sc_uuid16, tvb, offset+i+j+2, 2, ENC_LITTLE_ENDIAN);
-                        j += 2;
-                    }
-                    break;
-                case 0x04: /* 32-bit Service Class UUIDs, incomplete list */
-                case 0x05: /* 32-bit Service Class UUIDs, complete list */
-                    j = 0;
-                    while (j < (guint8)(length - 1))
-                    {
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_sc_uuid32, tvb, offset+i+j+2, 4, ENC_LITTLE_ENDIAN);
-                        j += 4;
-                    }
-                    break;
-                case 0x06: /* 128-bit Service Class UUIDs, incomplete list */
-                case 0x07: /* 128-bit Service Class UUIDs, complete list */
-                case 0x15: /* 128-bit Service Solicitation UUIDs */
-                    j = 0;
-                    while (j < (guint8)(length - 1))
-                    {
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_sc_uuid128, tvb, offset+i+j+2, 16, ENC_NA);
-                        j += 16;
-                    }
-                    break;
-                case 0x08: /* Device Name, shortened */
-                case 0x09: /* Device Name, full */
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_device_name, tvb, offset+i+2, length-1, ENC_ASCII|ENC_NA);
-                    proto_item_append_text(ti_eir_struct,": %s", tvb_format_text(tvb,offset+i+2,length-1));
-                    if (!pinfo->fd->flags.visited && hci_data != NULL && bd_addr) {
-                        wmem_tree_key_t  key[4];
-                        guint32          k_bd_addr_oui;
-                        guint32          k_bd_addr_id;
-                        guint32          k_frame_number;
-                        gchar           *name;
-                        device_name_t   *device_name;
-
-                        name = tvb_get_string(wmem_packet_scope(), tvb, offset+i+2, length-1);
-
-                        k_frame_number = pinfo->fd->num;
-                        k_bd_addr_oui = bd_addr[0] << 16 | bd_addr[1] << 8 | bd_addr[2];
-                        k_bd_addr_id = bd_addr[3] << 16 | bd_addr[4] << 8 | bd_addr[5];
-
-                        key[0].length = 1;
-                        key[0].key    = &k_bd_addr_id;
-                        key[1].length = 1;
-                        key[1].key    = &k_bd_addr_oui;
-                        key[2].length = 1;
-                        key[2].key    = &k_frame_number;
-                        key[3].length = 0;
-                        key[3].key    = NULL;
-
-                        device_name = (device_name_t *) wmem_new(wmem_file_scope(), device_name_t);
-                        device_name->bd_addr_oui =  bd_addr[0] << 16 | bd_addr[1] << 8 | bd_addr[2];
-                        device_name->bd_addr_id =  bd_addr[3] << 16 | bd_addr[4] << 8 | bd_addr[5];
-                        device_name->name = wmem_strdup(wmem_file_scope(), name);
-
-                        wmem_tree_insert32_array(hci_data->bdaddr_to_name_table, key, device_name);
-                    }
-                    break;
-                case 0x0A: /* Tx Power Level */
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_transmit_power_level, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    break;
-                case 0x0B: /* Secure Simple Pairing OOB Length */
-                    /* From CSS v3.pdf */
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_eir_ad_ssp_oob_length, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
-                    break;
-                case 0x0C: /* BD_ADDR */
-                    /* From CSS v3.pdf */
-                    dissect_bthci_evt_bd_addr(tvb, offset + i + 2, pinfo, tree, NULL);
-                    break;
-                case 0x0D: /* Class of Device */
-                    dissect_bthci_evt_cod(tvb, offset+i+2, pinfo, ti_eir_struct_subtree);
-                    break;
-                case 0x0E: /* Simple Pairing Hash C */
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_hash_c, tvb, offset+i+2, 16, ENC_NA);
-                    break;
-                case 0x0F: /* Simple Pairing Randomizer R */
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_randomizer_r, tvb, offset+i+2, 16, ENC_NA);
-                    break;
-                case 0x10: /* Device ID / Security Manager TK Value */
-#if 0
-/* XXX: Need to know how to check (or is it possible) that is le_physical_channel or not */
-                    if (le_physical_channel) { /* Security Manager TK Value - Value as used in pairing over LE Physical channel. */
-                        sub_item = proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_data, tvb, offset + i + 2, 16, ENC_NA);
-                        expert_add_info(pinfo, sub_item, &ei_eir_undecoded);
-                    }
-                    break;
-#endif
-                    {
-                    /* DID */
-                    guint16      vendor_id_source;
-                    guint16      vendor_id;
-                    guint16      product_id;
-                    const gchar *str_val;
-
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_did_vendor_id_source, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
-                    vendor_id_source = tvb_get_letohs(tvb, offset + i + 2);
-
-                    if (vendor_id_source == DID_VENDOR_ID_SOURCE_BLUETOOTH_SIG) {
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_did_vendor_id_bluetooth_sig, tvb, offset + i + 2 + 2, 2, ENC_LITTLE_ENDIAN);
-                    } else if (vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_did_vendor_id_usb_forum, tvb, offset + i + 2 + 2, 2, ENC_LITTLE_ENDIAN);
-                    } else {
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_did_vendor_id, tvb, offset + i + 2 + 2, 2, ENC_LITTLE_ENDIAN);
-                    }
-                    vendor_id = tvb_get_letohs(tvb, offset + i + 2 + 2);
-
-                    sub_item = proto_tree_add_item(ti_eir_struct_subtree, hf_did_product_id, tvb, offset + i + 2 + 4, 2, ENC_LITTLE_ENDIAN);
-                    product_id = tvb_get_letohs(tvb, offset + i + 2 + 4);
-
-                    if (vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
-                        str_val = val_to_str_ext_const(vendor_id << 16 | product_id, &ext_usb_products_vals, "Unknown");
-                        proto_item_append_text(sub_item, " (%s)", str_val);
-                    }
-
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_did_version, tvb, offset + i + 2 + 6, 2, ENC_LITTLE_ENDIAN);
-                    }
-                    break;
-                case 0x11: /* Security Manager OOB Flags */
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_oob_flags_oob_data_present, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_oob_flags_le_supported_host, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_oob_flags_simultaneous_le_and_br_edr_host, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_oob_flags_address_type, tvb, offset+i+2, 1, ENC_LITTLE_ENDIAN);
-                    break;
-                case 0x12: /* Slave Connection Interval Range */
-                    sub_item = proto_tree_add_item(tree, hf_bthci_evt_le_con_interval, tvb, offset+i+2, 2, ENC_LITTLE_ENDIAN);
-                    proto_item_append_text(sub_item, " Min (%g msec)",  tvb_get_letohs(tvb, offset+i+2)*1.25);
-
-                    sub_item = proto_tree_add_item(tree, hf_bthci_evt_le_con_interval, tvb, offset+i+4, 2, ENC_LITTLE_ENDIAN);
-                    proto_item_append_text(sub_item, " Max (%g msec)",  tvb_get_letohs(tvb, offset+i+4)*1.25);
-                    proto_item_append_text(ti_eir_struct,": %g - %g msec", tvb_get_letohs(tvb, offset+i+2)*1.25, tvb_get_letohs(tvb, offset+i+4)*1.25);
-                    break;
-                case 0x16: /* Service Data */
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_sc_uuid16, tvb, offset+i+2, 2, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_data, tvb, offset + i + 4, length - 3, ENC_NA);
-                    break;
-                case 0x17: /* Public Target Address */
-                case 0x18: /* Random Target Address */
-                {
-                    j = 0;
-                    while (j < (guint8)(length - 1))
-                    {
-                        dissect_bthci_evt_bd_addr(tvb, offset+i+j+2, pinfo, ti_eir_struct_subtree, NULL);
-                        j += 6;
-                    }
-                    break;
-                }
-                case 0x19: /* Appearance */
-                {
-                    guint16 appearance = tvb_get_letohs(tvb, offset+i+2);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_appearance, tvb, offset+i+2, 2, ENC_LITTLE_ENDIAN);
-                    proto_item_append_text(ti_eir_struct,": %s", val_to_str_ext(appearance, &bthci_cmd_appearance_vals_ext, "Unknown"));
-                    break;
-                }
-                case 0x1A: /* Advertising Interval */
-                    /* From CSS v3.pdf */
-                    sub_item = proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_eir_ad_advertising_interval, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
-                    proto_item_append_text(sub_item, " (%g msec)", tvb_get_letohs(tvb, offset + i + 2) * 0.625);
-                    break;
-                case 0x3D: /* 3D Information Data */
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_factory_test_mode, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_reserved, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_send_battery_level_report_on_startup, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_battery_level_reporting, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_association_notification, tvb, offset + i + 2, 1, ENC_LITTLE_ENDIAN);
-
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_path_loss_threshold, tvb, offset + i + 2 + 1, 1, ENC_LITTLE_ENDIAN);
-
-                    break;
-                case 0xFF: /* Manufacturer Specific */ {
-                    guint16  company_id;
-
-                    proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_eir_ad_company_id, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
-                    company_id = tvb_get_letohs(tvb, offset + i + 2);
-                    if (company_id == 0x000F && tvb_get_guint8(tvb, offset + i + 2 + 2) == 0) { /* 3DS profile Legacy Devices */
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_legacy_fixed, tvb, offset + i + 2 + 2, 1, ENC_LITTLE_ENDIAN);
-
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_legacy_3d_capable_tv, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_legacy_ignored_1_3, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_legacy_fixed_4, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_legacy_ignored_5, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_legacy_fixed_6, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_legacy_test_mode, tvb, offset + i + 2 + 3, 1, ENC_LITTLE_ENDIAN);
-
-                        proto_tree_add_item(ti_eir_struct_subtree, hf_3ds_legacy_path_loss_threshold, tvb, offset + i + 2 + 4, 1, ENC_LITTLE_ENDIAN);
-                    } else {
-                        sub_item = proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_data, tvb, offset + i + 2, length - 1, ENC_NA);
-                        expert_add_info(pinfo, sub_item, &ei_eir_undecoded);
-                    }
-                    }
-                    break;
-                default:
-                    sub_item = proto_tree_add_item(ti_eir_struct_subtree, hf_bthci_evt_data, tvb, offset + i + 2, length - 1, ENC_NA);
-                    expert_add_info(pinfo, sub_item, &ei_eir_unknown);
-            }
-            i += length+1;
-        }
-        else {
-            break;
-        }
-    }
-
-    return offset + size;
-}
-
 static int
 dissect_bthci_evt_io_capability_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
@@ -2148,6 +1765,7 @@ dissect_bthci_evt_le_meta(tvbuff_t *tvb, int offset, packet_info *pinfo,
         case 0x02: /* LE Advertising Report */
         {
             guint8 i, num_reports, length;
+            guint8 bd_addr[6];
 
             num_reports = tvb_get_guint8(tvb, offset);
             proto_tree_add_item(tree, hf_bthci_evt_num_reports,                   tvb, offset, 1, ENC_LITTLE_ENDIAN);
@@ -2157,11 +1775,15 @@ dissect_bthci_evt_le_meta(tvbuff_t *tvb, int offset, packet_info *pinfo,
                 offset += 1;
                 proto_tree_add_item(tree, hf_bthci_evt_le_peer_address_type,      tvb, offset, 1, ENC_LITTLE_ENDIAN);
                 offset += 1;
-                offset = dissect_bthci_evt_bd_addr(                               tvb, offset, pinfo, tree, NULL);
+                offset = dissect_bthci_evt_bd_addr(                               tvb, offset, pinfo, tree, bd_addr);
                 length = tvb_get_guint8(tvb, offset);
                 proto_tree_add_item(tree, hf_bthci_evt_data_length,               tvb, offset, 1, ENC_NA);
                 offset += 1;
-                offset = dissect_bthci_evt_eir_ad_data(                             tvb, offset, pinfo, tree, length, NULL, hci_data);
+
+                call_dissector(btcommon_ad_handle, tvb_new_subset(tvb, offset, length, length), pinfo, tree);
+                save_remote_device_name(tvb, offset, pinfo, length, bd_addr, hci_data);
+                offset += length;
+
                 proto_tree_add_item(tree, hf_bthci_evt_rssi,                      tvb, offset, 1, ENC_LITTLE_ENDIAN);
                 offset += 1;
                 }
@@ -2764,7 +2386,8 @@ dissect_bthci_evt_command_complete(tvbuff_t *tvb, int offset,
             proto_tree_add_item(tree, hf_bthci_evt_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset += 1;
 
-            offset = dissect_bthci_evt_cod(tvb, offset, pinfo, tree);
+            call_dissector(btcommon_cod_handle, tvb_new_subset(tvb, offset, 3, 3), pinfo, tree);
+            offset += 3;
 
             break;
 
@@ -2894,7 +2517,9 @@ dissect_bthci_evt_command_complete(tvbuff_t *tvb, int offset,
             proto_tree_add_item(tree, hf_bthci_evt_fec_required, tvb, offset, 1, ENC_LITTLE_ENDIAN);
             offset += 1;
 
-            offset = dissect_bthci_evt_eir_ad_data(tvb, offset, pinfo, tree, 240, NULL, hci_data);
+            call_dissector(btcommon_eir_handle, tvb_new_subset(tvb, offset, 240, 240), pinfo, tree);
+            offset += 240;
+
             break;
 
         case 0x0c55: /* Read Simple Pairing Mode */
@@ -3666,7 +3291,8 @@ dissect_bthci_evt_inq_result(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
         proto_tree_add_item(tree, hf_bthci_evt_page_scan_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
         offset += 1;
 
-        offset = dissect_bthci_evt_cod(tvb, offset, pinfo, tree);
+        call_dissector(btcommon_cod_handle, tvb_new_subset(tvb, offset, 3, 3), pinfo, tree);
+        offset += 3;
 
         proto_tree_add_item(tree, hf_bthci_evt_clock_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
         offset += 2;
@@ -3880,9 +3506,12 @@ dissect_bthci_evt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
             break;
 
         case 0x2f: /* Extended Inquiry Result */
-/* TODO: Get bd_addr from first and pass to second*/
             offset = dissect_bthci_evt_inq_result_with_rssi(tvb, offset, pinfo, bthci_evt_tree, bd_addr);
-            offset = dissect_bthci_evt_eir_ad_data(tvb, offset, pinfo, bthci_evt_tree, 240, bd_addr, hci_data);
+
+            call_dissector(btcommon_eir_handle, tvb_new_subset(tvb, offset, 240, 240), pinfo, bthci_evt_tree);
+            save_remote_device_name(tvb, offset, pinfo, 240, bd_addr, hci_data);
+            offset += 240;
+
             break;
 
         case 0x30: /* Encryption Key Refresh Complete */
@@ -4132,151 +3761,6 @@ proto_register_bthci_evt(void)
             FT_ETHER, BASE_NONE, NULL, 0x0,
             "Bluetooth Device Address", HFILL}
         },
-        { &hf_bthci_evt_class_of_device,
-          { "Class of Device", "bthci_evt.class_of_device",
-            FT_UINT24, BASE_HEX, NULL, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_information,
-          { "Major Service Classes: Information", "bthci_evt.class_of_device.major_service_classes.information",
-            FT_BOOLEAN, 16, NULL, 0x8000,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_telephony,
-          { "Major Service Classes: Telephony", "bthci_evt.class_of_device.major_service_classes.telephony",
-            FT_BOOLEAN, 16, NULL, 0x4000,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_audio,
-          { "Major Service Classes: Audio", "bthci_evt.class_of_device.major_service_classes.audio",
-            FT_BOOLEAN, 16, NULL, 0x2000,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_object_transfer,
-          { "Major Service Classes: Object Transfer", "bthci_evt.class_of_device.major_service_classes.object_transfer",
-            FT_BOOLEAN, 16, NULL, 0x1000,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_capturing,
-          { "Major Service Classes: Capturing", "bthci_evt.class_of_device.major_service_classes.capturing",
-            FT_BOOLEAN, 16, NULL, 0x0800,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_rendering,
-          { "Major Service Classes: Rendering", "bthci_evt.class_of_device.major_service_classes.rendering",
-            FT_BOOLEAN, 16, NULL, 0x0400,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_networking,
-          { "Major Service Classes: Networking", "bthci_evt.class_of_device.major_service_classes.networking",
-            FT_BOOLEAN, 16, NULL, 0x0200,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_positioning,
-          { "Major Service Classes: Positioning", "bthci_evt.class_of_device.major_service_classes.positioning",
-            FT_BOOLEAN, 16, NULL, 0x0100,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_reserved,
-          { "Major Service Classes: Reserved", "bthci_evt.class_of_device.major_service_classes.reserved",
-            FT_UINT16, BASE_HEX, NULL, 0x00C0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_service_class_limited_discoverable_mode,
-          { "Major Service Classes: Limited Discoverable Mode", "bthci_evt.class_of_device.major_service_classes.limited_discoverable_mode",
-            FT_BOOLEAN, 16, NULL, 0x0020,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_major_device_class,
-          { "Major Device Class", "bthci_evt.class_of_device.major_device_class",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_major_device_class_vals_ext, 0x1F,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_computer,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_computer_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_phone,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_phone_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_lan_net_load_factor,
-          { "Minor Device Class: Load Factor", "bthci_evt.class_of_device.minor_device_class.load_factor",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_lan_net_load_factor_vals_ext, 0xE0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_lan_net_type,
-          { "Minor Device Class: Type", "bthci_evt.class_of_device.minor_device_class.type",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_lan_net_type_vals_ext, 0x1C,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_audio_video,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_audio_video_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_peripheral_class,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_peripheral_class_vals_ext, 0xC0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_peripheral_type,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_peripheral_type_vals_ext, 0x3C,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_imaging_class_printer,
-          { "Minor Device Class: Class: Printer", "bthci_evt.class_of_device.minor_device_class.class.printer",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x80,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_imaging_class_scanner,
-          { "Minor Device Class: Class: Scanner", "bthci_evt.class_of_device.minor_device_class.class.scanner",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x40,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_imaging_class_camera,
-          { "Minor Device Class: Class: Camera", "bthci_evt.class_of_device.minor_device_class.class.camera",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x20,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_imaging_class_display,
-          { "Minor Device Class: Class: Display", "bthci_evt.class_of_device.minor_device_class.class.display",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x10,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_imaging_type,
-          { "Minor Device Class: Type", "bthci_evt.class_of_device.minor_device_class.type",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_imaging_type_vals_ext, 0x0C,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_wearable,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_wearable_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_toy,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_toy_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_health,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bthci_cmd_cod_minor_device_class_health_vals_ext, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_minor_device_class_unknown,
-          { "Minor Device Class", "bthci_evt.class_of_device.minor_device_class",
-            FT_UINT8, BASE_HEX, NULL, 0xFC,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_cod_format_type,
-          { "Format Type", "bthci_evt.class_of_device.format_type",
-            FT_UINT8, BASE_HEX, NULL, 0x03,
-            NULL, HFILL }
-        },
         { &hf_bthci_evt_link_type,
           { "Link Type", "bthci_evt.link_type",
             FT_UINT8, BASE_HEX, VALS(evt_link_types), 0x0,
@@ -5202,36 +4686,6 @@ proto_register_bthci_evt(void)
            FT_UINT8, BASE_DEC, VALS(bthci_cmd_notification_types), 0x0,
            NULL, HFILL}
         },
-        { &hf_bthci_evt_data,
-          {"Data", "bthci_evt.data",
-           FT_BYTES, BASE_NONE, NULL, 0x0,
-           NULL, HFILL}
-        },
-        { &hf_bthci_evt_eir_struct_length,
-          { "Length",           "bthci_evt.eir_struct_length",
-            FT_UINT8, BASE_DEC, NULL, 0x0,
-            "Structure Length", HFILL }
-        },
-        { &hf_bthci_evt_eir_struct_type,
-          { "Type",           "bthci_evt.eir_data_type",
-            FT_UINT8, BASE_HEX|BASE_EXT_STRING, &bthci_cmd_eir_data_type_vals_ext, 0x0,
-            "Data Type", HFILL }
-        },
-        { &hf_bthci_evt_sc_uuid16,
-          { "UUID",           "bthci_evt.service_class_uuid16",
-            FT_UINT16, BASE_HEX|BASE_EXT_STRING, &bthci_cmd_service_class_type_vals_ext, 0x0,
-            "16-bit Service Class UUID", HFILL }
-        },
-        { &hf_bthci_evt_sc_uuid32,
-          { "UUID",           "bthci_evt.service_class_uuid32",
-            FT_UINT32, BASE_HEX, NULL, 0x0,
-            "32-bit Service Class UUID", HFILL }
-        },
-        { &hf_bthci_evt_sc_uuid128,
-          { "UUID",           "bthci_evt.service_class_uuid128",
-            FT_BYTES, BASE_NONE, NULL, 0x0,
-            "128-bit Service Class UUID", HFILL }
-        },
         { &hf_bthci_evt_data_length,
           { "Data Length",           "bthci_evt.data_length",
             FT_UINT8, BASE_DEC, NULL, 0x0,
@@ -5527,61 +4981,6 @@ proto_register_bthci_evt(void)
             FT_UINT8, BASE_HEX, VALS(evt_le_advertising_evt_types), 0x0,
             NULL, HFILL }
         },
-        { &hf_bthci_evt_appearance,
-          { "Appearance", "bthci_evt.le_appearance",
-            FT_UINT16, BASE_HEX |BASE_EXT_STRING, &bthci_cmd_appearance_vals_ext, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_flags_limited_disc_mode,
-          { "LE Limited Discoverable Mode",        "bthci_evt.le_flags.limit_disc_mode",
-            FT_BOOLEAN, 8, NULL, 0x01,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_flags_general_disc_mode,
-          { "LE General Discoverable Mode",        "bthci_evt.le_flags.general_disc_mode",
-            FT_BOOLEAN, 8, NULL, 0x02,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_flags_bredr_not_support,
-          { "BR/EDR Not Supported",        "bthci_evt.le_flags.bredr_not_supported",
-            FT_BOOLEAN, 8, NULL, 0x04,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_flags_le_bredr_support_ctrl,
-          { "Simultaneous LE and BR/EDR to Same Device Capable (Controller)",        "bthci_evt.le_flags.bredr_support_ctrl",
-            FT_BOOLEAN, 8, NULL, 0x08,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_flags_le_bredr_support_host,
-          { "Simultaneous LE and BR/EDR to Same Device Capable (Host)",        "bthci_evt.le_flags.bredr_support_host",
-            FT_BOOLEAN, 8, NULL, 0x10,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_flags_reserved,
-          { "Reserved",        "bthci_evt.le_flags.reserved",
-            FT_BOOLEAN, 8, NULL, 0xE0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_oob_flags_oob_data_present,
-          { "OOB Data Present",        "bthci_evt.oob_flags.oob_data_present",
-            FT_BOOLEAN, 8, NULL, 0x01,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_oob_flags_le_supported_host,
-          { "LE Supported By Host",        "bthci_evt.oob_flags.le_supported_host",
-            FT_BOOLEAN, 8, NULL, 0x02,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_oob_flags_simultaneous_le_and_br_edr_host,
-          { "Simultaneous LE and BR/EDR to Same Device Capable (Host)",        "bthci_evt.oob_flags.simultaneous_le_and_br_edr_host",
-            FT_BOOLEAN, 8, NULL, 0x04,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_oob_flags_address_type,
-          { "Address Type",        "bthci_evt.oob_flags.address_type",
-            FT_UINT8, BASE_HEX, VALS(bthci_cmd_address_types_vals), 0x08,
-            NULL, HFILL }
-        },
         { &hf_bthci_evt_le_states,
           { "Supported LE States", "bthci_evt.le_states",
             FT_NONE, BASE_NONE, NULL, 0x00,
@@ -5732,146 +5131,14 @@ proto_register_bthci_evt(void)
             FT_BOOLEAN, 8, NULL, 0x10,
             NULL, HFILL }
         },
-        { &hf_bthci_evt_eir_ad_ssp_oob_length,
-          { "SSP OOB Length",                              "bthci_evt.eir_ad.ssp_oob_length",
-            FT_UINT16, BASE_DEC, NULL, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_eir_ad_advertising_interval,
-          { "Advertising Interval",                        "bthci_evt.eir_ad.advertising_interval",
-            FT_UINT16, BASE_DEC, NULL, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_bthci_evt_eir_ad_company_id,
-          { "Company ID",                                  "bthci_evt.eir_ad.company_id",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_evt_comp_id_ext, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_eir_ad_item,
-          { "Item",                                        "bthci_evt.eir_ad",
-            FT_NONE, BASE_NONE, NULL, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_extended_inquiry_response_data,
-          { "Extended Inquiry Response Data",              "bthci_evt.extended_inquiry_response_data",
-            FT_NONE, BASE_NONE, NULL, 0x0,
-            NULL, HFILL }
-        },
-        { &hf_advertising_data,
-          { "Advertising Data",                            "bthci_evt.advertising_data",
-            FT_NONE, BASE_NONE, NULL, 0x0,
-            NULL, HFILL }
-        },
         { &hf_usable_packet_types,
           { "Usable Packet Types",                            "bthci_evt.usable_packet_types",
             FT_NONE, BASE_NONE, NULL, 0x0,
             NULL, HFILL }
-        },
-        { &hf_3ds_association_notification,
-          { "3DS Association Notification",                "bthci_evt.eir_ad.3ds.association_notification",
-            FT_BOOLEAN, 8, NULL, 0x01,
-            NULL, HFILL }
-        },
-        { &hf_3ds_battery_level_reporting,
-          { "3DS Battery Level Reporting",                 "bthci_evt.eir_ad.3ds.battery_level_reporting",
-            FT_BOOLEAN, 8, NULL, 0x02,
-            NULL, HFILL }
-        },
-        { &hf_3ds_send_battery_level_report_on_startup,
-          { "3DS Send Battery Level Report on Startup",    "bthci_evt.eir_ad.3ds.send_battery_level_report_on_startup",
-            FT_BOOLEAN, 8, NULL, 0x04,
-            NULL, HFILL }
-        },
-        { &hf_3ds_reserved,
-          { "Reserved",                                    "bthci_evt.eir_ad.3ds.reserved",
-            FT_BOOLEAN, 8, NULL, 0x78,
-            NULL, HFILL }
-        },
-        { &hf_3ds_factory_test_mode,
-          { "3DS Factory Test Mode",                       "bthci_evt.eir_ad.3ds.factory_test_mode",
-            FT_BOOLEAN, 8, NULL, 0x80,
-            NULL, HFILL }
-        },
-        { &hf_3ds_path_loss_threshold,
-          { "3DS Path Loss Threshold",                     "bthci_evt.eir_ad.3ds.path_loss_threshold",
-            FT_UINT8, BASE_DEC, NULL, 0x00,
-            NULL, HFILL }
-        },
-        { &hf_3ds_legacy_fixed,
-          { "3DS Legacy Fixed",                            "bthci_evt.eir_ad.3ds_legacy.fixed_byte",
-            FT_UINT8, BASE_DEC, NULL, 0x00,
-            NULL, HFILL }
-        },
-        { &hf_3ds_legacy_3d_capable_tv,
-          { "3DS Legacy Capable TV",                       "bthci_evt.eir_ad.3ds_legacy.capable_tv",
-            FT_BOOLEAN, 8, NULL, 0x01,
-            NULL, HFILL }
-        },
-        { &hf_3ds_legacy_ignored_1_3,
-          { "3DS Legacy Ignored",                          "bthci_evt.eir_ad.3ds_legacy.ignored.1_3",
-            FT_BOOLEAN, 8, NULL, 0x0E,
-            NULL, HFILL }
-        },
-        { &hf_3ds_legacy_fixed_4,
-          { "3DS Legacy Fixed",                            "bthci_evt.eir_ad.3ds_legacy.fixed.4",
-            FT_BOOLEAN, 8, NULL, 0x10,
-            NULL, HFILL }
-        },
-        { &hf_3ds_legacy_ignored_5,
-          { "3DS Legacy Ignored",                          "bthci_evt.eir_ad.3ds_legacy.ignored.5",
-            FT_BOOLEAN, 8, NULL, 0x20,
-            NULL, HFILL }
-        },
-        { &hf_3ds_legacy_fixed_6,
-          { "3DS Legacy Fixed",                            "bthci_evt.eir_ad.3ds_legacy.fixed.4",
-            FT_BOOLEAN, 8, NULL, 0x40,
-            NULL, HFILL }
-        },
-        { &hf_3ds_legacy_test_mode,
-          { "3DS Legacy Test Mode",                        "bthci_evt.eir_ad.3ds_legacy.test_mode",
-            FT_BOOLEAN, 8, NULL, 0x80,
-            NULL, HFILL }
-        },
-        { &hf_3ds_legacy_path_loss_threshold,
-          { "3DS Legacy Path Loss Threshold",              "bthci_evt.eir_ad.3ds_legacy.path_loss_threshold",
-            FT_UINT8, BASE_DEC, NULL, 0x00,
-            NULL, HFILL }
-        },
-        { &hf_did_vendor_id_source,
-            { "Vendor ID Source",                          "bthci_evt.eir_ad.did.vendor_id_source",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &did_vendor_id_source_vals_ext, 0,
-            NULL, HFILL }
-        },
-        { &hf_did_vendor_id,
-            { "Vendor ID",                                 "bthci_evt.eir_ad.did.vendor_id",
-            FT_UINT16, BASE_HEX, NULL, 0,
-            NULL, HFILL }
-        },
-        { &hf_did_vendor_id_bluetooth_sig,
-            { "Vendor ID",                                 "bthci_evt.eir_ad.did.vendor_id",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_evt_comp_id_ext, 0,
-            NULL, HFILL }
-        },
-        { &hf_did_vendor_id_usb_forum,
-            { "Vendor ID",                                 "bthci_evt.eir_ad.did.vendor_id",
-            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ext_usb_vendors_vals, 0,
-            NULL, HFILL }
-        },
-        { &hf_did_product_id,
-            { "Product ID",                                "bthci_evt.eir_ad.did.product_id",
-            FT_UINT16, BASE_HEX, NULL, 0,
-            NULL, HFILL }
-        },
-        { &hf_did_version,
-            { "Version",                                   "bthci_evt.eir_ad.did.version",
-            FT_UINT16, BASE_HEX, NULL, 0,
-            NULL, HFILL }
         }
     };
 
     static ei_register_info ei[] = {
-        { &ei_eir_undecoded,            { "bthci_evt.expert.eir.undecoded", PI_PROTOCOL, PI_UNDECODED, "Undecoded", EXPFILL }},
-        { &ei_eir_unknown,              { "bthci_evt.expert.eir.unknown", PI_PROTOCOL, PI_WARN, "Undown data", EXPFILL }},
         { &ei_event_undecoded,          { "bthci_evt.expert.event.undecoded", PI_PROTOCOL, PI_UNDECODED, "Event undecoded", EXPFILL }},
         { &ei_event_unknown,            { "bthci_evt.expert.event.unknown", PI_PROTOCOL, PI_WARN, "Unknown event", EXPFILL }}
     };
@@ -5880,11 +5147,8 @@ proto_register_bthci_evt(void)
     static gint *ett[] = {
         &ett_bthci_evt,
         &ett_opcode,
-        &ett_cod,
         &ett_lmp_subtree,
         &ett_ptype_subtree,
-        &ett_eir_subtree,
-        &ett_eir_struct_subtree,
         &ett_le_state_subtree
     };
 
@@ -5913,7 +5177,10 @@ proto_reg_handoff_bthci_evt(void)
     dissector_add_uint("hci_h4.type", HCI_H4_TYPE_EVT, bthci_evt_handle);
     dissector_add_uint("hci_h1.type", BTHCI_CHANNEL_EVENT, bthci_evt_handle);
 
-    bthci_cmd_handle = find_dissector("bthci_cmd");
+    bthci_cmd_handle    = find_dissector("bthci_cmd");
+    btcommon_cod_handle = find_dissector("btcommon.cod");
+    btcommon_eir_handle = find_dissector("btcommon.eir_ad.eir");
+    btcommon_ad_handle  = find_dissector("btcommon.eir_ad.ad");
 }
 
 /*
index 57f5f34c1587824976a08ea6125a360396e10b45..b316a1aa88cf549e683cc8bc0047199041cb1877 100644 (file)
@@ -49,7 +49,6 @@ static int hf_advertising_header_length = -1;
 static int hf_advertising_header_rfu_2 = -1;
 static int hf_advertising_address = -1;
 static int hf_initiator_addresss = -1;
-static int hf_advertising_data = -1;
 static int hf_scanning_address = -1;
 static int hf_scan_response_data = -1;
 static int hf_link_layer_data = -1;
@@ -82,6 +81,7 @@ static gint ett_data_header = -1;
 static expert_field ei_unknown_data = EI_INIT;
 
 static dissector_handle_t btle_handle;
+static dissector_handle_t btcommon_ad_handle;
 static dissector_handle_t btl2cap_handle;
 
 static const value_string pdu_type_vals[] = {
@@ -146,7 +146,7 @@ void proto_register_btle(void);
 void proto_reg_handoff_btle(void);
 
 
-static gint
+gint
 dissect_bd_addr(gint hf_bd_addr, proto_tree *tree, tvbuff_t *tvb, gint offset)
 {
     guint8 bd_addr[6];
@@ -172,6 +172,7 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
     gint         offset = 0;
     guint32      access_address;
     guint8       length;
+    tvbuff_t    *next_tvb;
 
     col_set_str(pinfo->cinfo, COL_PROTOCOL, "LE LL");
 
@@ -228,8 +229,9 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
         case 0x06: /* ADV_SCAN_IND */
             offset = dissect_bd_addr(hf_advertising_address, btle_tree, tvb, offset);
 
-/* TODO: Dissect adverising data */
-            proto_tree_add_item(btle_tree, hf_advertising_data, tvb, offset, tvb_length_remaining(tvb, offset) - 3, ENC_NA);
+            next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset) - 3, tvb_length_remaining(tvb, offset) - 3);
+            call_dissector(btcommon_ad_handle, next_tvb, pinfo, btle_tree);
+
             offset += tvb_length_remaining(tvb, offset) - 3;
 
             break;
@@ -334,7 +336,6 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
                     proto_tree_add_item(btle_tree, hf_l2cap_fragment, tvb, offset, length, ENC_NA);
                     offset += length;
                 } else {
-                    tvbuff_t          *next_tvb;
                     bthci_acl_data_t  *acl_data;
 
                     col_append_str(pinfo->cinfo, COL_INFO, "L2CAP Data");
@@ -478,11 +479,6 @@ proto_register_btle(void)
             FT_ETHER, BASE_NONE, NULL, 0x0,
             NULL, HFILL }
         },
-        { &hf_advertising_data,
-            { "Advertising Data",                "btle.advertising.data",
-            FT_BYTES, BASE_NONE, NULL, 0x0,
-            NULL, HFILL }
-        },
         { &hf_scan_response_data,
             { "Scan Response Data",              "btle.scan_responce_data",
             FT_BYTES, BASE_NONE, NULL, 0x0,
@@ -630,6 +626,7 @@ proto_register_btle(void)
 void
 proto_reg_handoff_btle(void)
 {
+    btcommon_ad_handle = find_dissector("btcommon.eir_ad.ad");
     btl2cap_handle = find_dissector("btl2cap");
 
     dissector_add_uint("wtap_encap", WTAP_ENCAP_BLUETOOTH_LE_LL, btle_handle);
index d5f71d0ef0dc8027c43986a6ecb4de078cabc802..f6833ec2f5f136f512ac0c69e0f6489a3cda978c 100644 (file)
@@ -392,11 +392,6 @@ typedef struct _record_handle_service_t {
     wmem_array_t *uuid_array;
 } record_handle_service_t;
 
-typedef struct _custom_uuid_t {
-    const guint8  uuid[16];
-    const gchar  *name;
-} custom_uuid_t;
-
 #define PDU_TYPE_SERVICE_SEARCH            0x00
 #define PDU_TYPE_SERVICE_ATTRIBUTE         0x01
 #define PDU_TYPE_SERVICE_SEARCH_ATTRIBUTE  0x02
@@ -954,9 +949,10 @@ static const value_string vs_data_element_type[] = {
     { 0, NULL }
 };
 
-static const custom_uuid_t custom_uuid[] = {
-    { {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, "SyncML Server" },
-    { {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, "SyncML Client" }
+const custom_uuid_t custom_uuid[] = {
+    { {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, 16, "SyncML Server" },
+    { {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, 16, "SyncML Client" },
+    { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, NULL},
 };
 
 extern value_string_ext ext_psm_vals;
@@ -1000,14 +996,20 @@ print_uuid(uuid_t *uuid)
     if (uuid->bt_uuid) {
         return wmem_strdup(wmem_packet_scope(), val_to_str_const(uuid->bt_uuid, vs_service_classes, "Unknown"));
     } else {
-        if (uuid->size == 16) {
-            unsigned int i_uuid;
+        guint i_uuid;
 
-            for (i_uuid = 0; i_uuid < sizeof(custom_uuid) / sizeof(custom_uuid_t); ++i_uuid) {
-                if (memcmp(uuid->data, custom_uuid[i_uuid].uuid, 16) == 0) {
-                    return wmem_strdup(wmem_packet_scope(), custom_uuid[i_uuid].name);
-                }
+        i_uuid = 0;
+        while (custom_uuid[i_uuid].name) {
+            if (custom_uuid[i_uuid].size != uuid->size) {
+                i_uuid += 1;
+                continue;
+            }
+
+            if (memcmp(uuid->data, custom_uuid[i_uuid].uuid, uuid->size) == 0) {
+                return wmem_strdup(wmem_packet_scope(), custom_uuid[i_uuid].name);
             }
+
+            i_uuid += 1;
         }
 
         return bytes_to_ep_str(uuid->data, uuid->size);
@@ -1245,17 +1247,22 @@ dissect_uuid(proto_tree *tree, tvbuff_t *tvb, gint offset, gint size, uuid_t *uu
         uuid->bt_uuid = tvb_get_ntohs(tvb, offset + 2);
         proto_item_append_text(item, " (%s)", val_to_str_const(uuid->bt_uuid, vs_service_classes, "Unknown"));
     } else {
+        guint i_uuid;
         item = proto_tree_add_item(tree, hf_data_element_value_uuid, tvb, offset, size, ENC_NA);
 
-        if (size == 16) {
-            unsigned int i_uuid;
+        i_uuid = 0;
+        while (custom_uuid[i_uuid].name) {
+            if (custom_uuid[i_uuid].size != size) {
+                i_uuid += 1;
+                continue;
+            }
 
-            for (i_uuid = 0; i_uuid < sizeof(custom_uuid) / sizeof(custom_uuid_t); ++i_uuid) {
-                if (tvb_memeql(tvb, offset, custom_uuid[i_uuid].uuid, 16) == 0) {
-                    proto_item_append_text(item, " (%s)", custom_uuid[i_uuid].name);
-                    break;
-                }
+            if (tvb_memeql(tvb, offset, custom_uuid[i_uuid].uuid, 4) == 0) {
+                proto_item_append_text(item, " (%s)", custom_uuid[i_uuid].name);
+                break;
             }
+
+            i_uuid += 1;
         }
 
         uuid->bt_uuid = 0;
@@ -4520,7 +4527,7 @@ proto_register_btsdp(void)
         },
         { &hf_data_element_value_uuid_32,
             { "Value: UUID",                     "btsdp.data_element.value.uuid_32",
-            FT_UINT16, BASE_HEX, VALS(vs_service_classes), 0,
+            FT_UINT32, BASE_HEX, VALS(vs_service_classes), 0,
             NULL, HFILL }
         },
         { &hf_data_element_value_uuid_128,
index 1fca6d84889bce7edddd40b2ea1fe13d1c48a3f4..9e95d0230d8cdd175a619621d7328b6485fa0f13 100644 (file)
 #define BTSDP_LOCAL_SERVICE_FLAG_MASK                   0x0001
 #define BTSDP_SECONDARY_CHANNEL_FLAG_MASK               0x0002
 
+#define SDP_PSM_DEFAULT  1
+
 typedef struct _uuid_t {
     guint16  bt_uuid;
     guint8   size;
@@ -203,7 +205,14 @@ typedef struct _service_info_t {
     struct _service_info_t *parent_info;
 } service_info_t;
 
-#define SDP_PSM_DEFAULT  1
+
+typedef struct _custom_uuid_t {
+    const guint8  uuid[16];
+    const guint8  size;
+    const gchar  *name;
+} custom_uuid_t;
+
+extern const custom_uuid_t custom_uuid[];
 
 extern value_string_ext vs_service_classes_ext;
 
diff --git a/epan/dissectors/packet-hci_mon.c b/epan/dissectors/packet-hci_mon.c
new file mode 100644 (file)
index 0000000..3c0a538
--- /dev/null
@@ -0,0 +1,300 @@
+/* packet-hci_mon.c
+ * Routines for Bluetooth Linux Monitor dissection
+ *
+ * Copyright 2013, Michal Labedzki for Tieto Corporation
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/expert.h>
+#include <epan/wmem/wmem.h>
+#include <wiretap/wtap.h>
+
+#include "packet-bluetooth-hci.h"
+
+static int proto_hci_mon = -1;
+
+static int hf_adapter_id = -1;
+static int hf_opcode = -1;
+static int hf_type = -1;
+static int hf_bus = -1;
+static int hf_bd_addr = -1;
+static int hf_name = -1;
+
+static gint ett_hci_mon = -1;
+
+static expert_field ei_unknown_data = EI_INIT;
+
+static wmem_tree_t *chandle_to_bdaddr_table = NULL;
+static wmem_tree_t *bdaddr_to_name_table    = NULL;
+static wmem_tree_t *localhost_name          = NULL;
+static wmem_tree_t *localhost_bdaddr        = NULL;
+
+static dissector_handle_t hci_mon_handle;
+static dissector_handle_t bthci_cmd_handle;
+static dissector_handle_t bthci_evt_handle;
+static dissector_handle_t bthci_acl_handle;
+static dissector_handle_t bthci_sco_handle;
+
+static const value_string opcode_vals[] = {
+    { 0x00,  "New Index" },
+    { 0x01,  "Delete Index" },
+    { 0x02,  "HCI Command Packet" },
+    { 0x03,  "HCI Event Packet" },
+    { 0x04,  "ACL Tx Packet" },
+    { 0x05,  "ACL Rx Packet" },
+    { 0x06,  "SCO Tx Packet" },
+    { 0x07,  "SCO Rx Packet" },
+    { 0x00, NULL }
+};
+static value_string_ext(opcode_vals_ext) = VALUE_STRING_EXT_INIT(opcode_vals);
+
+static const value_string type_vals[] = {
+    { 0x00,  "Virtual" },
+    { 0x01,  "USB" },
+    { 0x02,  "PC Card" },
+    { 0x03,  "UART" },
+    { 0x04,  "RS232" },
+    { 0x05,  "PCI" },
+    { 0x06,  "SDIO" },
+    { 0x00, NULL }
+};
+static value_string_ext(type_vals_ext) = VALUE_STRING_EXT_INIT(type_vals);
+
+static const value_string bus_vals[] = {
+    { 0x00,  "BR/EDR" },
+    { 0x01,  "AMP" },
+    { 0x00, NULL }
+};
+static value_string_ext(bus_vals_ext) = VALUE_STRING_EXT_INIT(bus_vals);
+
+
+void proto_register_hci_mon(void);
+void proto_reg_handoff_hci_mon(void);
+
+static gint
+dissect_hci_mon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+    proto_tree     *hci_mon_item;
+    proto_item     *hci_mon_tree;
+    proto_item     *sub_item;
+    gint            offset = 0;
+    guint16         opcode;
+    guint16         adapter_id;
+    hci_data_t     *hci_data;
+    tvbuff_t       *next_tvb;
+
+    adapter_id = pinfo->pseudo_header->btmon.adapter_id;
+    opcode = pinfo->pseudo_header->btmon.opcode;
+
+    if (opcode == 0x00 || opcode == 0x01)
+        pinfo->p2p_dir = P2P_DIR_RECV;
+    else if (opcode % 2)
+        pinfo->p2p_dir = P2P_DIR_RECV;
+    else
+        pinfo->p2p_dir = P2P_DIR_SENT;
+
+    hci_mon_item = proto_tree_add_item(tree, proto_hci_mon, tvb, offset, -1, ENC_NA);
+    hci_mon_tree = proto_item_add_subtree(hci_mon_item, ett_hci_mon);
+
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_MON");
+
+    if (opcode == 0x00 || opcode == 0x01)
+        col_set_str(pinfo->cinfo, COL_INFO, "Info ");
+    else 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_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction ");
+        break;
+    }
+
+    sub_item = proto_tree_add_uint(hci_mon_tree, hf_adapter_id,  tvb, offset, 0, adapter_id);
+    PROTO_ITEM_SET_GENERATED(sub_item);
+
+    sub_item = proto_tree_add_uint(hci_mon_tree, hf_opcode, tvb, offset, 0, opcode);
+    PROTO_ITEM_SET_GENERATED(sub_item);
+
+    col_append_fstr(pinfo->cinfo, COL_INFO, "Adapter Id: %u, Opcode: %s",
+            adapter_id, val_to_str_ext_const(opcode, &opcode_vals_ext, "Unknown"));
+
+    hci_data = (hci_data_t *) wmem_new(wmem_packet_scope(), hci_data_t);
+    hci_data->interface_id = HCI_INTERFACE_MON;
+    hci_data->adapter_id = adapter_id;
+    hci_data->chandle_to_bdaddr_table = chandle_to_bdaddr_table;
+    hci_data->bdaddr_to_name_table = bdaddr_to_name_table;
+    hci_data->localhost_bdaddr = localhost_bdaddr;
+    hci_data->localhost_name = localhost_name;
+
+    pinfo->ptype = PT_BLUETOOTH;
+
+    next_tvb = tvb_new_subset_remaining(tvb, offset);
+
+    switch(opcode) {
+    case 0x00: /* New Index */
+        proto_tree_add_item(hci_mon_tree, hf_bus, tvb, offset, 1, ENC_NA);
+        offset += 1;
+
+        proto_tree_add_item(hci_mon_tree, hf_type, tvb, offset, 1, ENC_NA);
+        offset += 1;
+
+        offset = dissect_bd_addr(hf_bd_addr, hci_mon_tree, tvb, offset);
+
+        proto_tree_add_item(hci_mon_tree, hf_name, tvb, offset, 8, ENC_NA | ENC_ASCII);
+        offset += 8;
+
+        break;
+    case 0x01: /* Delete Index */
+        /* No parameters */
+
+        break;
+    case 0x02: /* HCI Command Packet */
+        call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, hci_data);
+        offset = tvb_length(tvb);
+
+        break;
+   case 0x03:  /* HCI Event Packet */
+        call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, hci_data);
+        offset = tvb_length(tvb);
+
+        break;
+   case 0x04:  /* ACL Tx Packet */
+   case 0x05:  /* ACL Rx Packet */
+        call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, hci_data);
+        offset = tvb_length(tvb);
+
+        break;
+   case 0x06:  /* SCO Tx Packet */
+   case 0x07:  /* SCO Rx Packet */
+        call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, hci_data);
+        offset = tvb_length(tvb);
+
+        break;
+    }
+
+    if (tvb_length_remaining(tvb, offset) > 0) {
+        proto_tree_add_expert(hci_mon_tree, pinfo, &ei_unknown_data, tvb, offset, -1);
+        offset = tvb_length(tvb);
+    }
+
+    return offset;
+}
+
+void
+proto_register_hci_mon(void)
+{
+    module_t *module;
+    expert_module_t  *expert_module;
+
+    static hf_register_info hf[] = {
+        {  &hf_adapter_id,
+            { "Adapter ID",                      "hci_mon.adapter_id",
+            FT_UINT16, BASE_DEC, NULL, 0x00,
+            NULL, HFILL }
+        },
+        {  &hf_opcode,
+            { "Opcode",                          "hci_mon.opcode",
+            FT_UINT16, BASE_HEX | BASE_EXT_STRING, &opcode_vals_ext, 0x00,
+            NULL, HFILL }
+        },
+        {  &hf_type,
+            { "Type",                            "hci_mon.type",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &type_vals_ext, 0x00,
+            NULL, HFILL }
+        },
+        {  &hf_bus,
+            { "Bus",                             "hci_mon.bus",
+            FT_UINT8, BASE_HEX | BASE_EXT_STRING, &bus_vals_ext, 0x00,
+            NULL, HFILL }
+        },
+        { &hf_bd_addr,
+          { "BD_ADDR",                           "hci_mon.bd_addr",
+            FT_ETHER, BASE_NONE, NULL, 0x0,
+            NULL, HFILL}
+        },
+        { &hf_name,
+          { "Adapter Name",                      "hci_mon.adapter_name",
+            FT_STRING, BASE_NONE, NULL, 0x0,
+            NULL, HFILL}
+        }
+    };
+
+    static ei_register_info ei[] = {
+        { &ei_unknown_data, { "hci_mon.unknown_data", PI_PROTOCOL, PI_WARN, "Unknown data", EXPFILL }},
+    };
+
+    static gint *ett[] = {
+        &ett_hci_mon,
+    };
+
+    chandle_to_bdaddr_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); /* adapter, chandle: bdaddr */
+    bdaddr_to_name_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); /* bdaddr: name */
+    localhost_bdaddr = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); /* adaper, frame: bdaddr */
+    localhost_name = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); /* adaper, frame: name */
+
+    proto_hci_mon = proto_register_protocol("Bluetooth Linux Monitor Transport", "HCI_MON", "hci_mon");
+    proto_register_field_array(proto_hci_mon, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+    hci_mon_handle = new_register_dissector("hci_mon", dissect_hci_mon, proto_hci_mon);
+
+    expert_module = expert_register_protocol(proto_hci_mon);
+    expert_register_field_array(expert_module, ei, array_length(ei));
+
+    module = prefs_register_protocol(proto_hci_mon, NULL);
+    prefs_register_static_text_preference(module, "bthci_mon.version",
+            "Bluetooth Linux Monitor Transport introduced in BlueZ 5.x",
+            "Version of protocol supported by this dissector.");
+}
+
+void
+proto_reg_handoff_hci_mon(void)
+{
+    bthci_cmd_handle = find_dissector("bthci_cmd");
+    bthci_evt_handle = find_dissector("bthci_evt");
+    bthci_acl_handle = find_dissector("bthci_acl");
+    bthci_sco_handle = find_dissector("bthci_sco");
+
+    dissector_add_uint("wtap_encap", WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR, hci_mon_handle);
+}
+
+/*
+ * Editor modelines  -  http://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:
+ */
index c142d4dfcd57463d06f0164ca33c9223c02ab2dd..8a8b61e44384f51b076bc688612db1a9717d2a90 100644 (file)
@@ -179,6 +179,7 @@ static const value_string command_vals[] = {
     { 53,  "Read Register" },
     { 54,  "BTLE Slave" },
     { 55,  "Get Compile Info" },
+    { 56,  "BTLE Set Target" },
     { 0x00, NULL }
 };
 static value_string_ext(command_vals_ext) = VALUE_STRING_EXT_INIT(command_vals);
@@ -384,6 +385,7 @@ dissect_ubertooth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
     usb_conv_info_t  *usb_conv_info = (usb_conv_info_t *)data;
     gint              p2p_dir_save;
     guint8            command;
+    gint16            command_response = -1;
     command_data_t   *command_data = NULL;
     wmem_tree_t      *wmem_tree;
     wmem_tree_key_t   key[5];
@@ -629,6 +631,7 @@ dissect_ubertooth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
         switch (command) {
             case 38: /* Set BDADDR */
             case 54: /* BTLE Slave */
+            case 56: /* BTLE Set Target */
                 proto_tree_add_item(main_tree, hf_bdaddr, tvb, offset, 6, ENC_NA);
                 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
                         get_ether_name((char *) tvb_memdup(wmem_packet_scope(), tvb, offset, 6)));
@@ -696,8 +699,10 @@ dissect_ubertooth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
     wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key);
    if (wmem_tree) {
         command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->fd->num);
-        command = command_data->command;
-        register_id = command_data->register_id;
+        if (command_data) {
+            command_response = command_data->command;
+            register_id = command_data->register_id;
+        }
    }
 
     if (!command_data) {
@@ -711,19 +716,19 @@ dissect_ubertooth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
     }
 
     col_append_fstr(pinfo->cinfo, COL_INFO, "Response: %s",
-            val_to_str_ext_const(command, &command_vals_ext, "Unknown"));
+            val_to_str_ext_const(command_response, &command_vals_ext, "Unknown"));
 
-    command_item = proto_tree_add_uint(main_tree, hf_response, tvb, offset, 0, command);
+    command_item = proto_tree_add_uint(main_tree, hf_response, tvb, offset, 0, command_response);
     command_tree = proto_item_add_subtree(command_item, ett_command);
     PROTO_ITEM_SET_GENERATED(command_item);
-    switch (command) {
+    switch (command_response) {
 
     case 1: /* Rx Symbols */
     case 27: /* Spectrum Analyzer */
         if (usb_conv_info->transfer_type == URB_BULK) {
 
             while (tvb_length_remaining(tvb, offset) > 0) {
-                offset = dissect_usb_rx_packet(tree, main_tree, pinfo, tvb, offset, command);
+                offset = dissect_usb_rx_packet(tree, main_tree, pinfo, tvb, offset, command_response);
             }
             break;
         }
@@ -759,6 +764,7 @@ dissect_ubertooth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
     case 51: /* Set AFH Map */
     case 52: /* Clear AFH Map */
     case 54: /* BTLE Slave */
+    case 56: /* BTLE Set Target */
         proto_tree_add_expert(command_tree, pinfo, &ei_unexpected_response, tvb, offset, 0);
         if (tvb_length_remaining(tvb, offset) > 0) {
             proto_tree_add_expert(main_tree, pinfo, &ei_unknown_data, tvb, offset, -1);
@@ -924,7 +930,7 @@ dissect_ubertooth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
             break;
         }
 
-        offset = dissect_usb_rx_packet(tree, main_tree, pinfo, tvb, offset, command);
+        offset = dissect_usb_rx_packet(tree, main_tree, pinfo, tvb, offset, command_response);
 
         break;
     case 53: /* Read Register */
@@ -1290,7 +1296,7 @@ proto_register_ubertooth(void)
 
     module = prefs_register_protocol(proto_ubertooth, NULL);
     prefs_register_static_text_preference(module, "version",
-            "Ubertooth Firmware: 2012-10-R1 (also latest git version pior to: d09308f48d9f94d1c55be5f72d9a2a271bb8a54b)",
+            "Ubertooth Firmware: 2012-10-R1 (also latest version prior to: git-4470774)",
             "Version of protocol supported by this dissector.");
 }
 
@@ -1299,8 +1305,10 @@ proto_reg_handoff_ubertooth(void)
 {
     btle_handle = find_dissector("btle");
 
+    dissector_add_uint("usb.product", (0x1d50 << 16) | 0x6000, ubertooth_handle); /* Ubertooth Zero */
+    dissector_add_uint("usb.product", (0x1d50 << 16) | 0x6002, ubertooth_handle); /* Ubertooth One */
+
     dissector_add_handle("usb.device",   ubertooth_handle);
-    dissector_add_handle("usb.product",  ubertooth_handle);
     dissector_add_handle("usb.protocol", ubertooth_handle);
 }
 
index 69aaf1d1089cb26c99acaaf9e62de7b98b6edcb0..9fc2cb06f488504af7032918af44eb4278056bf9 100644 (file)
@@ -63,8 +63,8 @@ struct btsnooprec_hdr {
 #define KHciLoggerDatalinkTypeBCSP             1003
 /* H5 is the official three wire serial protocol derived from BCSP*/
 #define KHciLoggerDatalinkTypeH5               1004
-/* BlueZ 5 Monitor */
-#define KHciLoggerDatalinkBlueZ5Monitor         2001
+/* Linux Monitor */
+#define KHciLoggerDatalinkLinuxMonitor  2001
 /* BlueZ 5 Simulator */
 #define KHciLoggerDatalinkBlueZ5Simulator      2002
 
@@ -140,10 +140,9 @@ int btsnoop_open(wtap *wth, int *err, gchar **err_info)
                *err = WTAP_ERR_UNSUPPORTED;
                *err_info = g_strdup_printf("btsnoop: H5 capture logs unsupported");
                return -1;
-       case KHciLoggerDatalinkBlueZ5Monitor:
-               *err = WTAP_ERR_UNSUPPORTED;
-               *err_info = g_strdup_printf("btsnoop: BlueZ 5 Monitor capture logs unsupported");
-               return -1;
+       case KHciLoggerDatalinkLinuxMonitor:
+               file_encap=WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR;
+               break;
        case KHciLoggerDatalinkBlueZ5Simulator:
                *err = WTAP_ERR_UNSUPPORTED;
                *err_info = g_strdup_printf("btsnoop: BlueZ 5 Simulator capture logs unsupported");
@@ -227,9 +226,7 @@ static gboolean btsnoop_read_record(wtap *wth, FILE_T fh,
        if(wth->file_encap == WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR)
        {
                phdr->pseudo_header.p2p.sent = (flags & KHciLoggerControllerToHost) ? FALSE : TRUE;
-       }
-       else if(wth->file_encap == WTAP_ENCAP_BLUETOOTH_HCI)
-       {
+       } else if(wth->file_encap == WTAP_ENCAP_BLUETOOTH_HCI) {
                phdr->pseudo_header.bthci.sent = (flags & KHciLoggerControllerToHost) ? FALSE : TRUE;
                if(flags & KHciLoggerCommandOrEvent)
                {
@@ -246,6 +243,9 @@ static gboolean btsnoop_read_record(wtap *wth, FILE_T fh,
                {
                        phdr->pseudo_header.bthci.channel = BTHCI_CHANNEL_ACL;
                }
+       } else  if (wth->file_encap == WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR) {
+               phdr->pseudo_header.btmon.opcode = flags & 0xFFFF;
+               phdr->pseudo_header.btmon.adapter_id = flags >> 16;
        }
 
 
@@ -261,8 +261,8 @@ int btsnoop_dump_can_write_encap(int encap)
     if (encap == WTAP_ENCAP_PER_PACKET)
         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
 
-    /* XXX - for now we only support WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR */
-    if (encap != WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR)
+    /* XXX - for now we only support WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR and WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR */
+    if (encap != WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR && encap != WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR)
         return WTAP_ERR_UNSUPPORTED_ENCAP;
 
     return 0;
index 64fbcf8d690eaa298008cac557d06306a0fb9b19..d5b4c89e6d49af80b2c15767f6e68c8f2ba7e40d 100644 (file)
@@ -695,6 +695,10 @@ static struct encap_type_info encap_table_base[] = {
 
        /* WTAP_ENCAP_NETLINK */
        { "Netlink", "Linux netlink" },
+
+       /* WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR */
+       { "Bluetooth Linux Monitor", "bluetooth-linux-monitor" },
+
 };
 
 WS_DLL_LOCAL
index d9dbae6e03c59ec7a649153d6b9c409c61524251..b70c893df7070d7282dd348162c8463e0e4af876 100644 (file)
@@ -252,6 +252,7 @@ extern "C" {
 #define WTAP_ENCAP_STANAG_4607                  157
 #define WTAP_ENCAP_STANAG_5066_D_PDU            158
 #define WTAP_ENCAP_NETLINK                      159
+#define WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR      160
 /* After adding new item here, please also add new item to encap_table_base array */
 
 #define WTAP_NUM_ENCAP_TYPES                    wtap_get_num_encap_types()
@@ -804,8 +805,8 @@ struct sita_phdr {
 
 /*pseudo header for Bluetooth HCI*/
 struct bthci_phdr {
-    gboolean sent;
-    guint8   channel;
+    gboolean  sent;
+    guint32   channel;
 };
 
 #define BTHCI_CHANNEL_COMMAND  1
@@ -813,6 +814,12 @@ struct bthci_phdr {
 #define BTHCI_CHANNEL_SCO      3
 #define BTHCI_CHANNEL_EVENT    4
 
+/* pseudo header for WTAP_ENCAP_BLUETOOTH_LINUX_MONITOR */
+struct btmon_phdr {
+    guint16   adapter_id;
+    guint16   opcode;
+};
+
 /* pseudo header for WTAP_ENCAP_LAYER1_EVENT */
 struct l1event_phdr {
     gboolean uton;
@@ -865,6 +872,7 @@ union wtap_pseudo_header {
     struct erf_mc_phdr  erf;
     struct sita_phdr    sita;
     struct bthci_phdr   bthci;
+    struct btmon_phdr   btmon;
     struct l1event_phdr l1event;
     struct i2c_phdr     i2c;
     struct gsm_um_phdr  gsm_um;