Bluetooth: AVDTP: Add support for Content Protection type SCMS-T (and some minor...
authorMichael Mann <mmann78@netscape.net>
Sun, 3 Nov 2013 15:25:52 +0000 (15:25 -0000)
committerMichael Mann <mmann78@netscape.net>
Sun, 3 Nov 2013 15:25:52 +0000 (15:25 -0000)
From Michal Labedzki

svn path=/trunk/; revision=53065

epan/dissectors/packet-btavdtp.c
epan/dissectors/packet-btavdtp.h
epan/dissectors/packet-hci_h1.c
epan/dissectors/packet-hci_h4.c
epan/dissectors/packet-rtp.c
epan/dissectors/packet-rtp.h
ui/rtp_stream.h
ui/tap-rtp-common.c

index a3160802975a20d06a943ad142c248d35ea6c78d..b86bfc6af369d14679e833b76100282059c29117 100644 (file)
@@ -34,6 +34,7 @@
 #include "packet-btl2cap.h"
 #include "packet-btsdp.h"
 #include "packet-btavdtp.h"
+#include "packet-rtp.h"
 
 #define AVDTP_MESSAGE_TYPE_MASK  0x03
 #define AVDTP_PACKET_TYPE_MASK   0x0C
@@ -250,21 +251,58 @@ static wmem_tree_t *sep_open          = NULL;
 static wmem_tree_t *cid_to_type_table = NULL;
 
 /* A2DP declarations */
-static int proto_bta2dp                        = -1;
-static gint ett_bta2dp                         = -1;
+static gint proto_bta2dp                        = -1;
+static gint ett_bta2dp                          = -1;
+static gint proto_bta2dp_cph_scms_t             = -1;
+static gint ett_bta2dp_cph_scms_t               = -1;
+
+static int hf_bta2dp_codec                              = -1;
+static int hf_bta2dp_content_protection                 = -1;
+static int hf_bta2dp_l_bit                              = -1;
+static int hf_bta2dp_cp_bit                             = -1;
+static int hf_bta2dp_reserved                           = -1;
 
 static dissector_handle_t sbc_handle;
 static dissector_handle_t mp2t_handle;
 static dissector_handle_t mpeg_audio_handle;
 static dissector_handle_t atrac_handle;
 
+static gboolean  force_a2dp_scms_t = FALSE;
+static gint      force_a2dp_codec = CODEC_SBC;
+
+static const enum_val_t pref_a2dp_codec[] = {
+    { "sbc",         "SBC",          CODEC_SBC },
+    { "mp2t",        "MPEG12 AUDIO", CODEC_MPEG12_AUDIO },
+    { "mpeg-audio",  "MPEG24 AAC",   CODEC_MPEG24_AAC },
+/* XXX: Not supported in Wireshark yet  { "atrac",      "ATRAC",                                  CODEC_ATRAC },*/
+    { NULL, NULL, 0 }
+};
+
+
 /* VDP declarations */
-static int proto_btvdp                         = -1;
-static gint ett_btvdp                          = -1;
+static gint proto_btvdp                         = -1;
+static gint ett_btvdp                           = -1;
+static gint proto_btvdp_cph_scms_t              = -1;
+static gint ett_btvdp_cph_scms_t                = -1;
+
+static int hf_btvdp_codec                              = -1;
+static int hf_btvdp_content_protection                 = -1;
+static int hf_btvdp_l_bit                              = -1;
+static int hf_btvdp_cp_bit                             = -1;
+static int hf_btvdp_reserved                           = -1;
 
 static dissector_handle_t h263_handle;
 static dissector_handle_t mp4v_es_handle;
 
+static gboolean  force_vdp_scms_t = FALSE;
+static gint      force_vdp_codec = CODEC_H263_BASELINE;
+
+static const enum_val_t pref_vdp_codec[] = {
+    { "h263",    "H263",      CODEC_H263_BASELINE },
+    { "mp4v-es", "MPEG4 VSP", CODEC_MPEG4_VSP },
+    { NULL, NULL, 0 }
+};
+
 
 static const value_string message_type_vals[] = {
     { 0x00,  "Command" },
@@ -392,6 +430,12 @@ static const value_string media_codec_video_type_vals[] = {
     { 0, NULL }
 };
 
+static const value_string content_protection_type_vals[] = {
+    { 0x01,  "DTCP" },
+    { 0x02,  "SCMS-T" },
+    { 0, NULL }
+};
+
 extern value_string_ext bthci_evt_comp_id_ext;
 
 enum sep_state {
@@ -405,6 +449,7 @@ typedef struct _sep_entry_t {
     guint8 type;
     guint8 media_type;
     gint   codec;
+    gint   content_protection_type;
     enum sep_state state;
 } sep_entry_t;
 
@@ -414,12 +459,20 @@ typedef struct _cid_type_data_t {
     sep_entry_t  *sep;
 } cid_type_data_t;
 
+
+typedef struct _sep_data_t {
+    gint   codec;
+    gint   content_protection_type;
+} sep_data_t;
+
 void proto_register_btavdtp(void);
 void proto_reg_handoff_btavdtp(void);
 void proto_register_bta2dp(void);
 void proto_reg_handoff_bta2dp(void);
+void proto_register_bta2dp_content_protection_header_scms_t(void);
 void proto_register_btvdp(void);
 void proto_reg_handoff_btvdp(void);
+void proto_register_btvdp_content_protection_header_scms_t(void);
 
 static const char *
 get_sep_type(guint32 frame_number, guint seid)
@@ -527,6 +580,7 @@ dissect_sep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
             sep_data->seid = seid;
             sep_data->type = type;
             sep_data->codec = -1;
+            sep_data->content_protection_type = 0;
             sep_data->media_type = media_type;
             if (in_use) {
                 sep_data->state = SEP_STATE_IN_USE;
@@ -700,7 +754,8 @@ dissect_codec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset,
 
 static gint
 dissect_capabilities(tvbuff_t *tvb, packet_info *pinfo,
-                                         proto_tree *tree, gint offset, gint *codec)
+        proto_tree *tree, gint offset, gint *codec,
+        gint *content_protection_type)
 {
     proto_item  *pitem                                        = NULL;
     proto_item  *ptree                                        = NULL;
@@ -805,13 +860,19 @@ dissect_capabilities(tvbuff_t *tvb, packet_info *pinfo,
                 losc = 0;
                 break;
             case SERVICE_CATEGORY_CONTENT_PROTECTION:
+                /* ENC_LITTLE_ENDIAN is correct here... */
                 proto_tree_add_item(service_tree, hf_btavdtp_content_protection_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                if (content_protection_type) {
+                    *content_protection_type = tvb_get_letohs(tvb, offset);
+                }
                 offset += 2;
                 losc -= 2;
 
-                proto_tree_add_item(service_tree, hf_btavdtp_data, tvb, offset, losc, ENC_NA);
-                offset += losc;
-                losc = 0;
+                if (losc > 0) {
+                    proto_tree_add_item(service_tree, hf_btavdtp_data, tvb, offset, losc, ENC_NA);
+                    offset += losc;
+                    losc = 0;
+                }
                 break;
             case SERVICE_CATEGORY_HEADER_COMPRESSION:
                 proto_tree_add_item(service_tree, hf_btavdtp_header_compression_backch,   tvb, offset, 1, ENC_BIG_ENDIAN);
@@ -950,7 +1011,8 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
     tvbuff_t         *next_tvb;
     guint32          seid;
     guint32          t_seid;
-    gint             codec;
+    gint             codec = -1;
+    gint             content_protection_type = 0;
 
     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AVDTP");
 
@@ -1047,11 +1109,21 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
                         get_sep_type(pinfo->fd->num, cid_type_data->sep->seid));
 
                 if (cid_type_data->sep->media_type == MEDIA_TYPE_AUDIO) {
+                    sep_data_t  sep_data;
+
+                    sep_data.codec = cid_type_data->sep->codec;
+                    sep_data.content_protection_type = cid_type_data->sep->content_protection_type;
+
                     next_tvb = tvb_new_subset_remaining(tvb, offset);
-                    call_dissector_with_data(bta2dp_handle, next_tvb, pinfo, tree, &cid_type_data->sep->codec);
+                    call_dissector_with_data(bta2dp_handle, next_tvb, pinfo, tree, &sep_data);
                 } else if (cid_type_data->sep->media_type == MEDIA_TYPE_VIDEO) {
+                    sep_data_t  sep_data;
+
+                    sep_data.codec = cid_type_data->sep->codec;
+                    sep_data.content_protection_type = cid_type_data->sep->content_protection_type;
+
                     next_tvb = tvb_new_subset_remaining(tvb, offset);
-                    call_dissector_with_data(btvdp_handle, next_tvb, pinfo, tree, &cid_type_data->sep->codec);
+                    call_dissector_with_data(btvdp_handle, next_tvb, pinfo, tree, &sep_data);
                 } else {
                     ti = proto_tree_add_item(tree, proto_btavdtp, tvb, offset, -1, ENC_NA);
                     btavdtp_tree = proto_item_add_subtree(ti, ett_btavdtp);
@@ -1129,13 +1201,13 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
                 proto_tree_add_item(btavdtp_tree, hf_btavdtp_error_code, tvb, offset, 1, ENC_BIG_ENDIAN);
                 break;
             }
-            offset = dissect_capabilities(tvb, pinfo, btavdtp_tree, offset, NULL);
+            offset = dissect_capabilities(tvb, pinfo, btavdtp_tree, offset, NULL, NULL);
             break;
         case SIGNAL_ID_SET_CONFIGURATION:
             if (message_type == MESSAGE_TYPE_COMMAND) {
                 offset = dissect_seid(tvb, pinfo, btavdtp_tree, offset, SEID_ACP, 0, &seid);
                 offset = dissect_seid(tvb, pinfo, btavdtp_tree, offset, SEID_INT, 0, NULL);
-                offset = dissect_capabilities(tvb, pinfo, btavdtp_tree, offset, &codec);
+                offset = dissect_capabilities(tvb, pinfo, btavdtp_tree, offset, &codec, &content_protection_type);
 
                 t_frame_number = pinfo->fd->num;
                 t_seid = seid;
@@ -1150,6 +1222,7 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
                 sep = (sep_entry_t *)wmem_tree_lookup32_array_le(sep_list, key);
                 if (sep && sep->seid == seid) {
                     sep->codec = codec;
+                    sep->content_protection_type = content_protection_type;
                 }
 
                 break;
@@ -1170,12 +1243,12 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
                 proto_tree_add_item(btavdtp_tree, hf_btavdtp_error_code, tvb, offset, 1, ENC_BIG_ENDIAN);
                 break;
             }
-            offset = dissect_capabilities(tvb, pinfo, btavdtp_tree, offset, NULL);
+            offset = dissect_capabilities(tvb, pinfo, btavdtp_tree, offset, NULL, NULL);
             break;
         case SIGNAL_ID_RECONFIGURE:
             if (message_type == MESSAGE_TYPE_COMMAND) {
                 offset = dissect_seid(tvb, pinfo, btavdtp_tree, offset, SEID_ACP, 0, &seid);
-                offset = dissect_capabilities(tvb, pinfo, btavdtp_tree, offset, &codec);
+                offset = dissect_capabilities(tvb, pinfo, btavdtp_tree, offset, &codec, &content_protection_type);
 
                 t_frame_number = pinfo->fd->num;
                 t_seid = seid;
@@ -1190,6 +1263,7 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
                 sep = (sep_entry_t *)wmem_tree_lookup32_array_le(sep_list, key);
                 if (sep && sep->seid == seid) {
                     sep->codec = codec;
+                    sep->content_protection_type = content_protection_type;
                 }
 
                 break;
@@ -1504,7 +1578,7 @@ proto_register_btavdtp(void)
         },
         { &hf_btavdtp_content_protection_type,
             { "Type",                           "btavdtp.content_protection_type",
-            FT_UINT16, BASE_HEX, NULL, 0x0000,
+            FT_UINT16, BASE_HEX, VALS(content_protection_type_vals), 0x0000,
             NULL, HFILL }
         },
         { &hf_btavdtp_media_codec_media_type,
@@ -2013,14 +2087,28 @@ dissect_bta2dp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
     proto_item          *ti;
     proto_tree          *bta2dp_tree;
     proto_item          *pitem;
-    gint                offset = 0;
-    gint                codec = -1;
-    void                *save_private_data;
-    dissector_handle_t  codec_dissector = NULL;
-    btavdtp_data_t      *btavdtp_data;
-
-    if (data)
-        codec = *((gint *) data);
+    gint                 offset = 0;
+    dissector_handle_t   codec_dissector = NULL;
+    bta2dp_codec_info_t  bta2dp_codec_info;
+    sep_data_t           sep_data;
+
+    sep_data.codec = CODEC_SBC;
+    sep_data.content_protection_type = 0;
+
+    if (force_a2dp_scms_t || force_a2dp_codec) {
+        if (force_a2dp_scms_t)
+            sep_data.content_protection_type = 2;
+        else if (data)
+            sep_data.content_protection_type = ((sep_data_t *) data)->content_protection_type;
+
+        if (force_a2dp_codec)
+            sep_data.codec = force_a2dp_codec;
+        else if (data)
+            sep_data.codec = ((sep_data_t *) data)->codec;
+    } else {
+        if (data)
+            sep_data = *((sep_data_t *) data);
+    }
 
     col_set_str(pinfo->cinfo, COL_PROTOCOL, "A2DP");
 
@@ -2046,15 +2134,19 @@ dissect_bta2dp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 
     ti = proto_tree_add_item(tree, proto_bta2dp, tvb, offset, -1, ENC_NA);
     col_append_fstr(pinfo->cinfo, COL_INFO, "Audio stream - %s",
-            val_to_str_const(codec, media_codec_audio_type_vals, "unknown codec"));
+            val_to_str_const(sep_data.codec, media_codec_audio_type_vals, "unknown codec"));
 
     bta2dp_tree = proto_item_add_subtree(ti, ett_bta2dp);
 
-    pitem = proto_tree_add_text(bta2dp_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Codec: %s",
-            val_to_str_const(codec, media_codec_audio_type_vals, "unknown codec"));
+    pitem = proto_tree_add_uint(bta2dp_tree, hf_bta2dp_codec, tvb, offset, 0, sep_data.codec);
     PROTO_ITEM_SET_GENERATED(pitem);
 
-    switch (codec) {
+    if (sep_data.content_protection_type > 0) {
+        pitem = proto_tree_add_uint(bta2dp_tree, hf_bta2dp_content_protection, tvb, offset, 0, sep_data.content_protection_type);
+        PROTO_ITEM_SET_GENERATED(pitem);
+    }
+
+    switch (sep_data.codec) {
         case CODEC_SBC:
             codec_dissector = sbc_handle;
             break;
@@ -2069,18 +2161,13 @@ dissect_bta2dp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
             break;
     }
 
-    save_private_data = pinfo->private_data;
-
-    btavdtp_data = wmem_new(wmem_packet_scope(), btavdtp_data_t);
-    btavdtp_data->codec_dissector = codec_dissector;
-
-    pinfo->private_data = btavdtp_data;
+    bta2dp_codec_info.codec_dissector = codec_dissector;
+    bta2dp_codec_info.content_protection_type = sep_data.content_protection_type;
 
+    bluetooth_add_address(pinfo, &pinfo->net_dst, "BT A2DP", pinfo->fd->num, FALSE, &bta2dp_codec_info);
     call_dissector(rtp_handle, tvb, pinfo, tree);
     offset += tvb_length_remaining(tvb, offset);
 
-    pinfo->private_data = save_private_data;
-
     return offset;
 }
 
@@ -2088,7 +2175,7 @@ void
 proto_register_bta2dp(void)
 {
     module_t *module;
-#if 0
+
     static hf_register_info hf[] = {
         { &hf_bta2dp_codec,
             { "Codec",                           "bta2dp.codec",
@@ -2101,16 +2188,13 @@ proto_register_bta2dp(void)
             NULL, HFILL }
         }
     };
-#endif
 
     static gint *ett[] = {
         &ett_bta2dp
     };
 
     proto_bta2dp = proto_register_protocol("Bluetooth A2DP Profile", "BT A2DP", "bta2dp");
-#if 0
     proto_register_field_array(proto_bta2dp, hf, array_length(hf));
-#endif
     proto_register_subtree_array(ett, array_length(ett));
 
     new_register_dissector("bta2dp", dissect_bta2dp, proto_bta2dp);
@@ -2119,6 +2203,16 @@ proto_register_bta2dp(void)
     prefs_register_static_text_preference(module, "a2dp.version",
             "Bluetooth Profile A2DP version: 1.3",
             "Version of profile supported by this dissector.");
+
+    prefs_register_bool_preference(module, "a2dp.content_protection.scms_t",
+            "Force SCMS-T decoding",
+            "Force decoding stream as A2DP with Content Protection SCMS-T ",
+            &force_a2dp_scms_t);
+
+    prefs_register_enum_preference(module, "a2dp.codec",
+            "Force codec",
+            "Force decoding stream as A2DP with specified codec",
+            &force_a2dp_codec, pref_a2dp_codec, FALSE);
 }
 
 void
@@ -2139,21 +2233,34 @@ proto_reg_handoff_bta2dp(void)
     dissector_add_handle("btl2cap.cid", bta2dp_handle);
 }
 
-
 static gint
 dissect_btvdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
     proto_item          *ti;
     proto_tree          *btvdp_tree;
     proto_item          *pitem;
-    gint                offset = 0;
-    gint                codec = -1;
-    void                *save_private_data;
-    dissector_handle_t  codec_dissector = NULL;
-    btavdtp_data_t      *btavdtp_data;
-
-    if (data)
-        codec = *((gint *) data);
+    gint                 offset = 0;
+    dissector_handle_t   codec_dissector = NULL;
+    btvdp_codec_info_t   btvdp_codec_info;
+    sep_data_t           sep_data;
+
+    sep_data.codec = CODEC_H263_BASELINE;
+    sep_data.content_protection_type = 0;
+
+    if (force_vdp_scms_t || force_vdp_codec) {
+        if (force_vdp_scms_t)
+            sep_data.content_protection_type = 2;
+        else if (data)
+            sep_data.content_protection_type = ((sep_data_t *) data)->content_protection_type;
+
+        if (force_vdp_codec)
+            sep_data.codec = force_vdp_codec;
+        else if (data)
+            sep_data.codec = ((sep_data_t *) data)->codec;
+    } else {
+        if (data)
+            sep_data = *((sep_data_t *) data);
+    }
 
     col_set_str(pinfo->cinfo, COL_PROTOCOL, "VDP");
 
@@ -2179,15 +2286,19 @@ dissect_btvdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 
     ti = proto_tree_add_item(tree, proto_btvdp, tvb, offset, -1, ENC_NA);
     col_append_fstr(pinfo->cinfo, COL_INFO, "Video stream - %s",
-            val_to_str_const(codec, media_codec_video_type_vals, "unknown codec"));
+            val_to_str_const(sep_data.codec, media_codec_video_type_vals, "unknown codec"));
 
     btvdp_tree = proto_item_add_subtree(ti, ett_btvdp);
 
-    pitem = proto_tree_add_text(btvdp_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Codec: %s",
-            val_to_str_const(codec, media_codec_video_type_vals, "unknown codec"));
+    pitem = proto_tree_add_uint(btvdp_tree, hf_btvdp_codec, tvb, offset, 0, sep_data.codec);
     PROTO_ITEM_SET_GENERATED(pitem);
 
-    switch (codec) {
+    if (sep_data.content_protection_type > 0) {
+        pitem = proto_tree_add_uint(btvdp_tree, hf_btvdp_content_protection, tvb, offset, 0, sep_data.content_protection_type);
+        PROTO_ITEM_SET_GENERATED(pitem);
+    }
+
+    switch (sep_data.codec) {
         case CODEC_H263_BASELINE:
         case CODEC_H263_PROFILE_3:
         case CODEC_H263_PROFILE_8:
@@ -2198,18 +2309,13 @@ dissect_btvdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
             break;
     }
 
-    save_private_data = pinfo->private_data;
-
-    btavdtp_data = wmem_new(wmem_packet_scope(), btavdtp_data_t);
-    btavdtp_data->codec_dissector = codec_dissector;
-
-    pinfo->private_data = btavdtp_data;
+    btvdp_codec_info.codec_dissector = codec_dissector;
+    btvdp_codec_info.content_protection_type = sep_data.content_protection_type;
 
+    bluetooth_add_address(pinfo, &pinfo->net_dst, "BT VDP", pinfo->fd->num, TRUE, &btvdp_codec_info);
     call_dissector(rtp_handle, tvb, pinfo, tree);
     offset += tvb_length_remaining(tvb, offset);
 
-    pinfo->private_data = save_private_data;
-
     return offset;
 }
 
@@ -2219,7 +2325,6 @@ proto_register_btvdp(void)
     module_t *module;
     expert_module_t* expert_btavdtp;
 
-#if 0
     static hf_register_info hf[] = {
         { &hf_btvdp_codec,
             { "Codec",                           "btvdp.codec",
@@ -2232,7 +2337,6 @@ proto_register_btvdp(void)
             NULL, HFILL }
         }
     };
-#endif
 
     static gint *ett[] = {
         &ett_btvdp
@@ -2246,9 +2350,7 @@ proto_register_btvdp(void)
 
     proto_btvdp = proto_register_protocol("Bluetooth VDP Profile", "BT VDP", "btvdp");
     new_register_dissector("btvdp", dissect_btvdp, proto_btvdp);
-#if 0
     proto_register_field_array(proto_bta2dp, hf, array_length(hf));
-#endif
     proto_register_subtree_array(ett, array_length(ett));
     expert_btavdtp = expert_register_protocol(proto_btvdp);
     expert_register_field_array(expert_btavdtp, ei, array_length(ei));
@@ -2257,6 +2359,16 @@ proto_register_btvdp(void)
     prefs_register_static_text_preference(module, "vdp.version",
             "Bluetooth Profile VDP version: 1.1",
             "Version of profile supported by this dissector.");
+
+    prefs_register_bool_preference(module, "vdp.content_protection.scms_t",
+            "Force SCMS-T decoding",
+            "Force decoding stream as VDP with Content Protection SCMS-T ",
+            &force_vdp_scms_t);
+
+    prefs_register_enum_preference(module, "vdp.codec",
+            "Force codec",
+            "Force decoding stream as VDP with specified codec",
+            &force_vdp_codec, pref_vdp_codec, FALSE);
 }
 
 void
@@ -2275,6 +2387,107 @@ proto_reg_handoff_btvdp(void)
 }
 
 
+
+static gint
+dissect_a2dp_cp_scms_t(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+{
+    proto_item  *main_item;
+    proto_tree  *main_tree;
+    gint         offset = 0;
+
+    main_item = proto_tree_add_item(tree, proto_bta2dp_cph_scms_t, tvb, offset, 1, ENC_NA);
+    main_tree = proto_item_add_subtree(main_item, ett_bta2dp_cph_scms_t);
+
+    proto_tree_add_item(main_tree, hf_bta2dp_reserved , tvb, offset, 1, ENC_BIG_ENDIAN);
+    proto_tree_add_item(main_tree, hf_bta2dp_cp_bit, tvb, offset, 1, ENC_BIG_ENDIAN);
+    proto_tree_add_item(main_tree, hf_bta2dp_l_bit , tvb, offset, 1, ENC_BIG_ENDIAN);
+    offset += 1;
+
+    return offset;
+}
+
+void
+proto_register_bta2dp_content_protection_header_scms_t(void)
+{
+    static hf_register_info hf[] = {
+        { &hf_bta2dp_l_bit,
+            { "L-bit",                           "bta2dp.content_protection_header.scms_t.l_bit",
+            FT_BOOLEAN, 8, NULL, 0x01,
+            NULL, HFILL }
+        },
+        { &hf_bta2dp_cp_bit,
+            { "Cp-bit",                          "bta2dp.content_protection_header.scms_t.cp_bit",
+            FT_BOOLEAN, 8, NULL, 0x02,
+            NULL, HFILL }
+        },
+        { &hf_bta2dp_reserved,
+            { "Reserved",                        "bta2dp.content_protection_header.scms_t.reserved",
+            FT_BOOLEAN, 8, NULL, 0xFC,
+            NULL, HFILL }
+        }
+    };
+
+    static gint *ett[] = {
+        &ett_bta2dp_cph_scms_t
+    };
+
+    proto_bta2dp_cph_scms_t = proto_register_protocol("Bluetooth A2DP Content Protection Header SCMS-T", "BT A2DP Content Protection Header SCMS-T", "bta2dp_content_protection_header_scms_t");
+    proto_register_field_array(proto_bta2dp_cph_scms_t, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+
+    new_register_dissector("bta2dp_content_protection_header_scms_t", dissect_a2dp_cp_scms_t, proto_bta2dp_cph_scms_t);
+}
+
+static gint
+dissect_vdp_cp_scms_t(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
+{
+    proto_item  *main_item;
+    proto_tree  *main_tree;
+    gint         offset = 0;
+
+    main_item = proto_tree_add_item(tree, proto_btvdp_cph_scms_t, tvb, offset, 1, ENC_NA);
+    main_tree = proto_item_add_subtree(main_item, ett_btvdp_cph_scms_t);
+
+    proto_tree_add_item(main_tree, hf_btvdp_reserved , tvb, offset, 1, ENC_BIG_ENDIAN);
+    proto_tree_add_item(main_tree, hf_btvdp_cp_bit, tvb, offset, 1, ENC_BIG_ENDIAN);
+    proto_tree_add_item(main_tree, hf_btvdp_l_bit , tvb, offset, 1, ENC_BIG_ENDIAN);
+    offset += 1;
+
+    return offset;
+}
+
+void
+proto_register_btvdp_content_protection_header_scms_t(void)
+{
+    static hf_register_info hf[] = {
+        { &hf_btvdp_l_bit,
+            { "L-bit",                           "btvdp.content_protection_header.scms_t.l_bit",
+            FT_BOOLEAN, 8, NULL, 0x01,
+            NULL, HFILL }
+        },
+        { &hf_btvdp_cp_bit,
+            { "Cp-bit",                          "btvdp.content_protection_header.scms_t.cp_bit",
+            FT_BOOLEAN, 8, NULL, 0x02,
+            NULL, HFILL }
+        },
+        { &hf_btvdp_reserved,
+            { "Reserved",                        "btvdp.content_protection_header.scms_t.reserved",
+            FT_BOOLEAN, 8, NULL, 0xFC,
+            NULL, HFILL }
+        }
+    };
+
+    static gint *ett[] = {
+        &ett_btvdp_cph_scms_t
+    };
+
+    proto_btvdp_cph_scms_t = proto_register_protocol("Bluetooth VDP Content Protection Header SCMS-T", "BT VDP Content Protection Header SCMS-T", "btvdp_content_protection_header_scms_t");
+    proto_register_field_array(proto_btvdp_cph_scms_t, hf, array_length(hf));
+    proto_register_subtree_array(ett, array_length(ett));
+
+    new_register_dissector("btvdp_content_protection_header_scms_t", dissect_vdp_cp_scms_t, proto_btvdp_cph_scms_t);
+}
+
 /*
  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
  *
index c84757133231ef8d1193227bdacfb923f9bcd426..0fa9cb4e264fe298a9ca5002a02fb7a87120a556 100644 (file)
 #ifndef __PACKET_BTAVDTP_H__
 #define __PACKET_BTAVDTP_H__
 
-typedef struct _btavdtp_data_t {
+#define BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T  0x02
+
+typedef struct _bta2dp_codec_info_t {
+    dissector_handle_t  codec_dissector;
+    gint                content_protection_type;
+} bta2dp_codec_info_t;
+
+typedef struct _btvdp_codec_info_t {
     dissector_handle_t  codec_dissector;
-} btavdtp_data_t;
+    gint                content_protection_type;
+} btvdp_codec_info_t;
 
 #endif
 
index f0200b7261bd7e895bf94cf7f7cafd595db876d7..a72657f6b96fb88f3d89f214be926451b33a71a5 100644 (file)
@@ -114,6 +114,8 @@ dissect_hci_h1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
     hci_data->localhost_bdaddr = localhost_bdaddr;
     hci_data->localhost_name = localhost_name;
 
+    pinfo->ptype = PT_BLUETOOTH;
+
     ti = proto_tree_add_int(hci_h1_tree, hf_hci_h1_direction, tvb, 0, 0, pinfo->p2p_dir);
     PROTO_ITEM_SET_GENERATED(ti);
 
index 655a8f9ecbbdd31c0d718240ad80f10d8931ec7c..1b79e3e508471411dc22aebf06c3f63268c750ce 100644 (file)
@@ -110,6 +110,8 @@ dissect_hci_h4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
     hci_data->localhost_bdaddr = localhost_bdaddr;
     hci_data->localhost_name = localhost_name;
 
+    pinfo->ptype = PT_BLUETOOTH;
+
     ti = proto_tree_add_uint(hci_h4_tree, hf_hci_h4_direction, tvb, 0, 0, pinfo->p2p_dir);
     PROTO_ITEM_SET_GENERATED(ti);
 
index bb4aa81c5a428c29c449205f945f09b04d91f5e1..1f4b04375d83cb1992dbfca74f08fa1eeb0097aa 100644 (file)
 #include <epan/packet.h>
 
 #include "packet-rtp.h"
+
 #include <epan/rtp_pt.h>
 #include <epan/conversation.h>
 #include <epan/reassemble.h>
 #include <epan/tap.h>
-
+#include <epan/epan_dissect.h>
 #include <epan/prefs.h>
 #include <epan/wmem/wmem.h>
 #include <epan/strutil.h>
@@ -142,6 +143,12 @@ static dissector_handle_t zrtp_handle;
 static dissector_handle_t sprt_handle;
 static dissector_handle_t v150fw_handle;
 
+static dissector_handle_t bta2dp_content_protection_header_scms_t;
+static dissector_handle_t btvdp_content_protection_header_scms_t;
+static dissector_handle_t bta2dp_handle;
+static dissector_handle_t btvdp_handle;
+static dissector_handle_t sbc_handle;
+
 static int rtp_tap = -1;
 
 static dissector_table_t rtp_pt_dissector_table;
@@ -266,11 +273,12 @@ static gint global_rtp_version0_type = 0;
 static dissector_handle_t data_handle;
 
 /* Forward declaration we need below */
+void proto_register_rtp(void);
 void proto_reg_handoff_rtp(void);
+void proto_register_pkt_ccc(void);
 void proto_reg_handoff_pkt_ccc(void);
 
-static void dissect_rtp( tvbuff_t *tvb, packet_info *pinfo,
-    proto_tree *tree );
+static gint dissect_rtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
 static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
 static void get_conv_info(packet_info *pinfo, struct _rtp_info *rtp_info);
 
@@ -806,12 +814,94 @@ rtp_free_hash_dyn_payload(GHashTable *rtp_dyn_payload)
        rtp_dyn_payload = NULL;
 }
 
+
+void
+bluetooth_add_address(packet_info *pinfo, address *addr,
+                const gchar *setup_method, guint32 setup_frame_number,
+                gboolean is_video, void *data)
+{
+       address null_addr;
+       conversation_t* p_conv;
+       struct _rtp_conversation_info *p_conv_data = NULL;
+       /*
+        * If this isn't the first time this packet has been processed,
+        * we've already done this work, so we don't need to do it
+        * again.
+        */
+       if (pinfo->fd->flags.visited)
+       {
+               return;
+       }
+
+       SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
+
+       /*
+        * Check if the ip address and port combination is not
+        * already registered as a conversation.
+        */
+       p_conv = find_conversation(setup_frame_number, addr, &null_addr, PT_BLUETOOTH, 0, 0,
+                                  NO_ADDR_B | NO_PORT_B);
+
+       /*
+        * If not, create a new conversation.
+        */
+       if (!p_conv || p_conv->setup_frame != setup_frame_number) {
+               p_conv = conversation_new(setup_frame_number, addr, &null_addr, PT_BLUETOOTH, 0, 0,
+                                  NO_ADDR2 | NO_PORT2);
+       }
+
+       /* Set dissector */
+       conversation_set_dissector(p_conv, rtp_handle);
+
+       /*
+        * Check if the conversation has data associated with it.
+        */
+       p_conv_data = (struct _rtp_conversation_info *)conversation_get_proto_data(p_conv, proto_rtp);
+
+       /*
+        * If not, add a new data item.
+        */
+       if (! p_conv_data) {
+               /* Create conversation data */
+               p_conv_data = wmem_new(wmem_file_scope(), struct _rtp_conversation_info);
+               p_conv_data->rtp_dyn_payload = NULL;
+
+               /* start this at 0x10000 so that we cope gracefully with the
+                * first few packets being out of order (hence 0,65535,1,2,...)
+                */
+               p_conv_data->extended_seqno = 0x10000;
+               p_conv_data->rtp_conv_info = wmem_new(wmem_file_scope(), rtp_private_conv_info);
+               p_conv_data->rtp_conv_info->multisegment_pdus = wmem_tree_new(wmem_file_scope());
+               conversation_add_proto_data(p_conv, proto_rtp, p_conv_data);
+
+               if (is_video) {
+                       p_conv_data->bta2dp_info = NULL;
+                       p_conv_data->btvdp_info = (btvdp_codec_info_t *) wmem_memdup(wmem_file_scope(), data, sizeof(btvdp_codec_info_t));
+               } else {
+                       p_conv_data->bta2dp_info = (bta2dp_codec_info_t *) wmem_memdup(wmem_file_scope(), data, sizeof(bta2dp_codec_info_t));
+                       p_conv_data->btvdp_info = NULL;
+               }
+       }
+
+       /*
+        * Update the conversation data.
+        */
+       /* Free the hash if already exists */
+       rtp_free_hash_dyn_payload(p_conv_data->rtp_dyn_payload);
+
+       g_strlcpy(p_conv_data->method, setup_method, MAX_RTP_SETUP_METHOD_SIZE+1);
+       p_conv_data->frame_number = setup_frame_number;
+       p_conv_data->is_video = is_video;
+       p_conv_data->rtp_dyn_payload = NULL;
+       p_conv_data->srtp_info = NULL;
+}
+
 /* Set up an SRTP conversation */
 void
 srtp_add_address(packet_info *pinfo, address *addr, int port, int other_port,
                 const gchar *setup_method, guint32 setup_frame_number,
                 gboolean is_video _U_, GHashTable *rtp_dyn_payload,
-                 struct srtp_info *srtp_info)
+                struct srtp_info *srtp_info)
 {
        address null_addr;
        conversation_t* p_conv;
@@ -887,6 +977,8 @@ srtp_add_address(packet_info *pinfo, address *addr, int port, int other_port,
        p_conv_data->is_video = is_video;
        p_conv_data->rtp_dyn_payload = rtp_dyn_payload;
        p_conv_data->srtp_info = srtp_info;
+       p_conv_data->bta2dp_info = NULL;
+       p_conv_data->btvdp_info = NULL;
 }
 
 /* Set up an RTP conversation */
@@ -899,7 +991,7 @@ rtp_add_address(packet_info *pinfo, address *addr, int port, int other_port,
 }
 
 static gboolean
-dissect_rtp_heur_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_destport)
+dissect_rtp_heur_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data, gboolean check_destport)
 {
        guint8       octet1;
        unsigned int version;
@@ -954,20 +1046,20 @@ dissect_rtp_heur_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gbo
                return FALSE;
        }
 
-       dissect_rtp( tvb, pinfo, tree );
+       dissect_rtp( tvb, pinfo, tree, data );
        return TRUE;
 }
 
 static gboolean
-dissect_rtp_heur_udp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
+dissect_rtp_heur_udp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data )
 {
-       return dissect_rtp_heur_common(tvb, pinfo, tree, TRUE);
+       return dissect_rtp_heur_common(tvb, pinfo, tree, data, TRUE);
 }
 
 static gboolean
-dissect_rtp_heur_stun( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
+dissect_rtp_heur_stun( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data )
 {
-       return dissect_rtp_heur_common(tvb, pinfo, tree, FALSE);
+       return dissect_rtp_heur_common(tvb, pinfo, tree, data, FALSE);
 }
 
 /*
@@ -975,14 +1067,13 @@ dissect_rtp_heur_stun( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
  */
 static void
 process_rtp_payload(tvbuff_t *newtvb, packet_info *pinfo, proto_tree *tree,
-                   proto_tree *rtp_tree,
-                   unsigned int payload_type)
+                   proto_tree *rtp_tree, unsigned int payload_type)
 {
        struct _rtp_conversation_info *p_conv_data = NULL;
        gboolean found_match = FALSE;
        int payload_len;
        struct srtp_info *srtp_info;
-       int offset=0;
+       int offset = 0;
 
        payload_len = tvb_length_remaining(newtvb, offset);
 
@@ -1015,10 +1106,9 @@ process_rtp_payload(tvbuff_t *newtvb, packet_info *pinfo, proto_tree *tree,
                        proto_tree_add_item(rtp_tree, hf_srtp_auth_tag, newtvb, offset, srtp_info->auth_tag_len, ENC_NA);
                        /*offset += srtp_info->auth_tag_len;*/
                }
-       }
-
-       /* if the payload type is dynamic, we check if the conv is set and we look for the pt definition */
-       else if ( (payload_type >= PT_UNDF_96 && payload_type <= PT_UNDF_127) ) {
+       } else if (p_conv_data && !p_conv_data->bta2dp_info && !p_conv_data->btvdp_info &&
+                       payload_type >= PT_UNDF_96 && payload_type <= PT_UNDF_127) {
+               /* if the payload type is dynamic, we check if the conv is set and we look for the pt definition */
                if (p_conv_data && p_conv_data->rtp_dyn_payload) {
                        gchar *payload_type_str = NULL;
                        encoding_name_and_rate_t *encoding_name_and_rate_pt = NULL;
@@ -1041,6 +1131,34 @@ process_rtp_payload(tvbuff_t *newtvb, packet_info *pinfo, proto_tree *tree,
                        }
 
                }
+       } else if (p_conv_data && p_conv_data->bta2dp_info) {
+               tvbuff_t  *nexttvb;
+               gint       suboffset = 0;
+
+               found_match = TRUE;
+
+               if (p_conv_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
+                       nexttvb = tvb_new_subset(newtvb, 0, 1, 1);
+                        call_dissector(bta2dp_content_protection_header_scms_t, nexttvb, pinfo, tree);
+                       suboffset = 1;
+               }
+
+               nexttvb = tvb_new_subset_remaining(newtvb, suboffset);
+               call_dissector(p_conv_data->bta2dp_info->codec_dissector, nexttvb, pinfo, tree);
+       } else if (p_conv_data && p_conv_data->btvdp_info) {
+               tvbuff_t  *nexttvb;
+               gint       suboffset = 0;
+
+               found_match = TRUE;
+
+               if (p_conv_data->btvdp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
+                       nexttvb = tvb_new_subset(newtvb, 0, 1, 1);
+                       call_dissector(bta2dp_content_protection_header_scms_t, nexttvb, pinfo, tree);
+                       suboffset = 1;
+               }
+
+               nexttvb = tvb_new_subset_remaining(newtvb, suboffset);
+               call_dissector(p_conv_data->btvdp_info->codec_dissector, nexttvb, pinfo, tree);
        }
 
        /* if we don't found, it is static OR could be set static from the preferences */
@@ -1265,7 +1383,7 @@ dissect_rtp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 static void
 dissect_rtp_rfc2198(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       int offset = 0;
+       gint offset = 0;
        guint8 octet1;
        int cnt;
        gboolean hdr_follow = TRUE;
@@ -1355,7 +1473,7 @@ dissect_rtp_rfc2198(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
 static void
 dissect_rtp_hext_rfc5215_onebyte( tvbuff_t *tvb, packet_info *pinfo,
-    proto_tree *rtp_hext_tree )
+               proto_tree *rtp_hext_tree )
 {
        proto_item *ti = NULL;
        proto_tree *rtp_hext_rfc5285_tree = NULL;
@@ -1409,7 +1527,7 @@ dissect_rtp_hext_rfc5215_onebyte( tvbuff_t *tvb, packet_info *pinfo,
 
 static void
 dissect_rtp_hext_rfc5215_twobytes(tvbuff_t *parent_tvb, guint id_offset,
-    guint8 id, tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtp_hext_tree)
+               guint8 id, tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtp_hext_tree)
 {
        proto_item *ti = NULL;
        proto_tree *rtp_hext_rfc5285_tree = NULL;
@@ -1454,8 +1572,8 @@ dissect_rtp_hext_rfc5215_twobytes(tvbuff_t *parent_tvb, guint id_offset,
        }
 }
 
-static void
-dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+static gint
+dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
 {
        proto_item *ti            = NULL;
        proto_tree *volatile rtp_tree = NULL;
@@ -1485,8 +1603,8 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
        /*struct srtp_info *srtp_info = NULL;*/
        /*unsigned int srtp_offset;*/
        unsigned int hdrext_offset = 0;
-       tvbuff_t *newtvb = NULL;
-
+       tvbuff_t     *newtvb = NULL;
+       const char   *pt = NULL;
        /* Can tap up to 4 RTP packets within same packet */
        static struct _rtp_info rtp_info_arr[4];
        static int rtp_info_current=0;
@@ -1506,24 +1624,24 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                switch (global_rtp_version0_type) {
                case RTP0_STUN:
                        call_dissector(stun_handle, tvb, pinfo, tree);
-                       return;
+                       return tvb_length(tvb);
                case RTP0_CLASSICSTUN:
                        call_dissector(classicstun_handle, tvb, pinfo, tree);
-                       return;
+                       return tvb_length(tvb);
 
                case RTP0_T38:
                        call_dissector(t38_handle, tvb, pinfo, tree);
-                       return;
+                       return tvb_length(tvb);
 
                case RTP0_SPRT:
                        call_dissector(sprt_handle, tvb, pinfo, tree);
-                       return;
+                       return tvb_length(tvb);
 
                case RTP0_INVALID:
                        if (!(tvb_memeql(tvb, 4, "ZRTP", 4)))
                        {
                                call_dissector(zrtp_handle,tvb,pinfo,tree);
-                               return;
+                               return tvb_length(tvb);
                        }
                default:
                        ; /* Unknown or unsupported version (let it fall through) */
@@ -1548,7 +1666,7 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                        proto_tree_add_uint( rtp_tree, hf_rtp_version, tvb,
                            offset, 1, octet1);
                }
-               return;
+               return offset;
        }
 
        padding_set = RTP_PADDING( octet1 );
@@ -1636,6 +1754,12 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
        }
 #endif
 
+       if (p_conv_data && p_conv_data->bta2dp_info && p_conv_data->bta2dp_info->codec_dissector) {
+               rtp_info->info_payload_type_str = (const char *) dissector_handle_get_short_name(p_conv_data->bta2dp_info->codec_dissector);
+       } else if (p_conv_data && p_conv_data->btvdp_info && p_conv_data->btvdp_info->codec_dissector) {
+               rtp_info->info_payload_type_str = (const char *) dissector_handle_get_short_name(p_conv_data->btvdp_info->codec_dissector);
+       }
+
        /* if it is dynamic payload, let use the conv data to see if it is defined */
        if ( (payload_type>95) && (payload_type<128) ) {
                if (p_conv_data && p_conv_data->rtp_dyn_payload){
@@ -1648,15 +1772,22 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                }
        }
 
+       if (p_conv_data && p_conv_data->bta2dp_info) {
+               pt = (p_conv_data->bta2dp_info->codec_dissector) ? dissector_handle_get_short_name(p_conv_data->bta2dp_info->codec_dissector) : "Unknown";
+       } else if (p_conv_data && p_conv_data->btvdp_info) {
+               pt = (p_conv_data->btvdp_info->codec_dissector) ? dissector_handle_get_short_name(p_conv_data->btvdp_info->codec_dissector) : "Unknown";
+       } else {
+               pt = (payload_type_str ? payload_type_str : val_to_str_ext(payload_type, &rtp_payload_type_vals_ext,"Unknown (%u)"));
+       }
+
        col_add_fstr( pinfo->cinfo, COL_INFO,
            "PT=%s, SSRC=0x%X, Seq=%u, Time=%u%s",
-               payload_type_str ? payload_type_str : val_to_str_ext( payload_type, &rtp_payload_type_vals_ext,"Unknown (%u)" ),
+               pt,
            sync_src,
            seq_num,
            timestamp,
            marker_set ? ", Mark" : "");
 
-
        if ( tree ) {
                proto_tree *item;
                /* Create RTP protocol tree */
@@ -1682,10 +1813,8 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                proto_tree_add_boolean( rtp_tree, hf_rtp_marker, tvb, offset,
                    1, octet2 );
 
-               proto_tree_add_uint_format_value( rtp_tree, hf_rtp_payload_type, tvb,
-                   offset, 1, octet2, "%s (%u)",
-                       payload_type_str ? payload_type_str : val_to_str_ext_const( payload_type, &rtp_payload_type_vals_ext,"Unknown"),
-                       payload_type);
+               proto_tree_add_uint_format( rtp_tree, hf_rtp_payload_type, tvb,
+                   offset, 1, octet2, "Payload type: %s (%u)", pt, payload_type);
 
                offset++;
 
@@ -1714,7 +1843,7 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                proto_item_append_text(ti, " (%u items)", csrc_count);
                rtp_csrc_tree = proto_item_add_subtree( ti, ett_csrc_list );
 
-        for (i = 0; i < csrc_count; i++ ) {
+               for (i = 0; i < csrc_count; i++ ) {
                        csrc_item = tvb_get_ntohl( tvb, offset );
                        proto_tree_add_uint_format( rtp_csrc_tree,
                            hf_rtp_csrc_item, tvb, offset, 4,
@@ -1788,7 +1917,7 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                        call_dissector(data_handle,
                            tvb_new_subset_remaining(tvb, offset),
                            pinfo, rtp_tree);
-                       return;
+                       return tvb_length(tvb);;
                }
 
                padding_count = tvb_get_guint8( tvb,
@@ -1800,6 +1929,24 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                rtp_info->info_payload_len = tvb_length_remaining(tvb, offset);
                rtp_info->info_padding_count = padding_count;
 
+               if (p_conv_data && p_conv_data->bta2dp_info) {
+                       if (p_conv_data->bta2dp_info->codec_dissector == sbc_handle) {
+                               rtp_info->info_payload_offset += 1;
+                               rtp_info->info_payload_len -= 1;
+                       }
+
+                       if (p_conv_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
+                               rtp_info->info_payload_offset += 1;
+                               rtp_info->info_payload_len -= 1;
+                       }
+               }
+
+               if (p_conv_data && p_conv_data->btvdp_info &&
+                               p_conv_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
+                       rtp_info->info_payload_offset += 1;
+                       rtp_info->info_payload_len -= 1;
+               }
+
                if (data_len > 0) {
                        /*
                         * There's data left over when you take out
@@ -1811,7 +1958,7 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                                    offset,
                                    data_len,
                                    data_len,
-                                   payload_type );
+                                   payload_type);
                        } CATCH_ALL {
                                if (!pinfo->flags.in_error_pkt)
                                        tap_queue_packet(rtp_tap, pinfo, rtp_info);
@@ -1852,13 +1999,34 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                /*
                 * No padding.
                 */
+               rtp_info->info_payload_offset = offset;
+               rtp_info->info_payload_len = tvb_length_remaining(tvb, offset);
+
+               if (p_conv_data && p_conv_data->bta2dp_info) {
+                       if (p_conv_data->bta2dp_info->codec_dissector == sbc_handle) {
+                               rtp_info->info_payload_offset += 1;
+                               rtp_info->info_payload_len -= 1;
+                       }
+
+                       if (p_conv_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
+                               rtp_info->info_payload_offset += 1;
+                               rtp_info->info_payload_len -= 1;
+                       }
+               }
+
+               if (p_conv_data && p_conv_data->btvdp_info &&
+                               p_conv_data->bta2dp_info->content_protection_type == BTAVDTP_CONTENT_PROTECTION_TYPE_SCMS_T) {
+                       rtp_info->info_payload_offset += 1;
+                       rtp_info->info_payload_len -= 1;
+               }
+
                if (tvb_reported_length_remaining(tvb, offset) > 0) {
                        /* Ensure that tap is called after packet dissection, even in case of exception */
                        TRY {
                                dissect_rtp_data( tvb, pinfo, tree, rtp_tree, offset,
                                                  tvb_length_remaining( tvb, offset ),
                                                  tvb_reported_length_remaining( tvb, offset ),
-                                                 payload_type );
+                                                 payload_type);
                        } CATCH_ALL {
                                if (!pinfo->flags.in_error_pkt)
                                        tap_queue_packet(rtp_tap, pinfo, rtp_info);
@@ -1866,11 +2034,11 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
                        }
                        ENDTRY;
                }
-               rtp_info->info_payload_offset = offset;
-               rtp_info->info_payload_len = tvb_length_remaining(tvb, offset);
        }
        if (!pinfo->flags.in_error_pkt)
                tap_queue_packet(rtp_tap, pinfo, rtp_info);
+
+       return offset;
 }
 
 static void
@@ -2079,6 +2247,8 @@ get_conv_info(packet_info *pinfo, struct _rtp_info *rtp_info)
                                p_conv_packet_data->rtp_dyn_payload = p_conv_data->rtp_dyn_payload;
                                p_conv_packet_data->rtp_conv_info = p_conv_data->rtp_conv_info;
                                p_conv_packet_data->srtp_info = p_conv_data->srtp_info;
+                               p_conv_packet_data->bta2dp_info = p_conv_data->bta2dp_info;
+                               p_conv_packet_data->btvdp_info = p_conv_data->btvdp_info;
                                p_add_proto_data(pinfo->fd, proto_rtp, 0, p_conv_packet_data);
 
                                /* calculate extended sequence number */
@@ -2129,8 +2299,8 @@ show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
 /* Dissect PacketCable CCC header */
 
-static void
-dissect_pkt_ccc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int
+dissect_pkt_ccc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
 {
        proto_item *ti            = NULL;
        proto_tree *pkt_ccc_tree      = NULL;
@@ -2144,7 +2314,7 @@ dissect_pkt_ccc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                                    ENC_TIME_NTP|ENC_BIG_ENDIAN);
        }
 
-       dissect_rtp(tvb, pinfo, tree);
+       return dissect_rtp(tvb, pinfo, tree, data);
 }
 
 
@@ -2194,7 +2364,7 @@ proto_register_pkt_ccc(void)
        proto_register_field_array(proto_pkt_ccc, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
-       register_dissector("pkt_ccc", dissect_pkt_ccc, proto_pkt_ccc);
+       new_register_dissector("pkt_ccc", dissect_pkt_ccc, proto_pkt_ccc);
 
        pkt_ccc_module = prefs_register_protocol(proto_pkt_ccc, proto_reg_handoff_pkt_ccc);
 
@@ -3041,7 +3211,7 @@ proto_register_rtp(void)
        proto_register_field_array(proto_rtp, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
-       register_dissector("rtp", dissect_rtp, proto_rtp);
+       new_register_dissector("rtp", dissect_rtp, proto_rtp);
        register_dissector("rtp.rfc2198", dissect_rtp_rfc2198, proto_rtp);
 
        rtp_tap = register_tap("rtp");
@@ -3128,8 +3298,16 @@ proto_reg_handoff_rtp(void)
                sprt_handle = find_dissector("sprt");
                v150fw_handle = find_dissector("v150fw");
 
+               bta2dp_content_protection_header_scms_t = find_dissector("bta2dp_content_protection_header_scms_t");
+               btvdp_content_protection_header_scms_t = find_dissector("btvdp_content_protection_header_scms_t");
+               bta2dp_handle = find_dissector("bta2dp");
+               btvdp_handle = find_dissector("btvdp");
+               sbc_handle = find_dissector("sbc");
+
                dissector_add_string("rtp_dyn_payload_type", "v150fw", v150fw_handle);
 
+               dissector_add_handle("btl2cap.cid", rtp_handle);
+
                rtp_prefs_initialized = TRUE;
        } else {
                dissector_delete_uint("rtp.pt", rtp_saved_rfc2198_pt, rtp_rfc2198_handle);
index ec95019dd922a8caa41560e5e020149373e121d6..7fb7b69c8a6628245a276048f1fae131100543ed 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include "epan/packet.h"
 #include "ws_symbol_export.h"
 
+#include "packet-btavdtp.h"
+
 struct _rtp_info {
        unsigned int  info_version;
        gboolean      info_padding_set;
        gboolean      info_marker_set;
-       gboolean          info_is_video;
+       gboolean      info_is_video;
        unsigned int  info_payload_type;
        unsigned int  info_padding_count;
        guint16       info_seq_num;
@@ -44,10 +47,10 @@ struct _rtp_info {
        guint         info_payload_offset; /* start of payload relative to info_data */
        guint         info_payload_len;    /* length of payload (incl padding) */
        gboolean      info_is_srtp;
-       guint32           info_setup_frame_num; /* the frame num of the packet that set this RTP connection */
+       guint32       info_setup_frame_num; /* the frame num of the packet that set this RTP connection */
        const guint8* info_data;           /* pointer to raw rtp data */
-       gchar             *info_payload_type_str;
-       gint              info_payload_rate;
+       const gchar   *info_payload_type_str;
+       gint          info_payload_rate;
        /*
        * info_data: pointer to raw rtp data = header + payload incl. padding.
        * That should be safe because the "epan_dissect_t" constructed for the packet
@@ -116,6 +119,8 @@ struct _rtp_conversation_info
                                                       * to the rtp dissector
                                                                                                   */
        struct srtp_info *srtp_info;    /* SRTP context */
+       bta2dp_codec_info_t *bta2dp_info;
+       btvdp_codec_info_t *btvdp_info;
 };
 
 typedef struct {
@@ -144,6 +149,12 @@ void srtp_add_address(packet_info *pinfo,
                      GHashTable *rtp_dyn_payload,
                      struct srtp_info *srtp_info);
 
+/* Add an Bluetooth conversation with the given details */
+void
+bluetooth_add_address(packet_info *pinfo, address *addr,
+         const gchar *setup_method, guint32 setup_frame_number,
+         gboolean is_video, void *data);
+
 /* Free and destroy the dyn_payload hash table */
 WS_DLL_PUBLIC
 void rtp_free_hash_dyn_payload(GHashTable *rtp_dyn_payload);
index 059444b96da7229cb38d0454fb74080c3329ecd0..14c484bbd9b2fc75951a22a24d5f6eeb96cd7ecb 100644 (file)
@@ -58,7 +58,7 @@ typedef struct _rtp_stream_info {
     guint32 dest_port;
     guint32 ssrc;
     guint8  pt;
-    gchar      *info_payload_type_str;
+    const gchar *info_payload_type_str;
     guint32 npackets;
 
     guint32 first_frame_num;           /**< frame number of first frame */
index 6785e5fd1dce2dbbbf714b4bd63673d8c64dcd1c..9f9c070f6c5d54a6d991cc3debbd7abeddac2920 100644 (file)
@@ -417,7 +417,7 @@ static const mimetype_and_clock mimetype_and_clock_map[] = {
 #define NUM_DYN_CLOCK_VALUES   (sizeof mimetype_and_clock_map / sizeof mimetype_and_clock_map[0])
 
 static guint32
-get_dyn_pt_clock_rate(gchar *payload_type_str)
+get_dyn_pt_clock_rate(const gchar *payload_type_str)
 {
        int i;