Bluetooth: A2DP: Add AVRCP song position indicator

"sbc.avrcp_song_position" can be used to determine time synchronization
between AVRCP and A2DP. It is updated on every
AVRCP PlaybackPositionChanged. Also provide version for aptx.

Change-Id: I48cd49f0fee54131a738290e2a70a24d33ba1d22
Reviewed-on: https://code.wireshark.org/review/5290
Reviewed-by: Michal Labedzki <michal.labedzki@tieto.com>
This commit is contained in:
Michal Labedzki 2014-11-12 11:57:12 +01:00
parent ad1977bc19
commit f1dee59d66
6 changed files with 131 additions and 6 deletions

View File

@ -1381,6 +1381,7 @@ DISSECTOR_INCLUDES = \
packet-bssgp.h \
packet-btavctp.h \
packet-btavdtp.h \
packet-btavrcp.h \
packet-bthci_acl.h \
packet-btl2cap.h \
packet-btle.h \

View File

@ -34,6 +34,7 @@
#include "packet-btsdp.h"
#include "packet-btavdtp.h"
#include "packet-rtp.h"
#include "packet-btavrcp.h"
#define AVDTP_MESSAGE_TYPE_MASK 0x03
#define AVDTP_PACKET_TYPE_MASK 0x0C
@ -354,6 +355,7 @@ static int proto_aptx = -1;
static int hf_aptx_data = -1;
static int hf_aptx_cummulative_frame_duration = -1;
static int hf_aptx_delta_time = -1;
static int hf_aptx_avrcp_song_position = -1;
static int hf_aptx_delta_time_from_the_beginning = -1;
static int hf_aptx_cummulative_duration = -1;
static int hf_aptx_diff = -1;
@ -1382,6 +1384,8 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
media_packet_info_t *current_media_packet_info;
nstime_t first_abs_ts;
gdouble cummulative_frame_duration;
gdouble avrcp_song_position = -1.0;
btavrcp_song_position_data_t *song_position_data;
sep_data.codec = channels_info->sep->codec;
sep_data.vendor_id = channels_info->sep->vendor_id;
@ -1410,19 +1414,41 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
key[5].length = 0;
key[5].key = NULL;
key[2].length = 0;
key[2].key = NULL;
subtree = (wmem_tree_t *) wmem_tree_lookup32_array(btavrcp_song_positions, key);
song_position_data = (subtree) ? (btavrcp_song_position_data_t *) wmem_tree_lookup32_le(subtree, frame_number) : NULL;
if (song_position_data && (song_position_data->used_in_frame == 0 ||
song_position_data->used_in_frame == frame_number)) {
avrcp_song_position = song_position_data->song_position;
if (!pinfo->fd->flags.visited)
song_position_data->used_in_frame = frame_number;
}
key[2].length = 1;
key[2].key = &chandle;
subtree = (wmem_tree_t *) wmem_tree_lookup32_array(media_packet_times, key);
previous_media_packet_info = (subtree) ? (media_packet_info_t *) wmem_tree_lookup32_le(subtree, frame_number - 1) : NULL;
if (previous_media_packet_info && previous_media_packet_info->stream_number == sep_data.stream_number ) {
sep_data.previous_media_packet_info = previous_media_packet_info;
first_abs_ts = previous_media_packet_info->first_abs_ts;
cummulative_frame_duration = previous_media_packet_info->cummulative_frame_duration;
if (avrcp_song_position == -1.0)
avrcp_song_position = previous_media_packet_info->avrcp_song_position;
else
previous_media_packet_info->avrcp_song_position = avrcp_song_position;
} else {
if (avrcp_song_position == -1.0)
avrcp_song_position = 0.0;
first_abs_ts = pinfo->fd->abs_ts;
cummulative_frame_duration = 0.0;
sep_data.previous_media_packet_info = (media_packet_info_t *) wmem_new(wmem_epan_scope(), media_packet_info_t);
sep_data.previous_media_packet_info->abs_ts = pinfo->fd->abs_ts;
sep_data.previous_media_packet_info->first_abs_ts = first_abs_ts;
sep_data.previous_media_packet_info->cummulative_frame_duration = cummulative_frame_duration;
sep_data.previous_media_packet_info->avrcp_song_position = avrcp_song_position;
sep_data.previous_media_packet_info->stream_number = sep_data.stream_number;
}
@ -1432,10 +1458,14 @@ dissect_btavdtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
key[6].length = 0;
key[6].key = NULL;
if (avrcp_song_position == -1.0)
avrcp_song_position = 0.0;
current_media_packet_info = wmem_new(wmem_file_scope(), media_packet_info_t);
current_media_packet_info->abs_ts = pinfo->fd->abs_ts;
current_media_packet_info->first_abs_ts = first_abs_ts;
current_media_packet_info->cummulative_frame_duration = cummulative_frame_duration;
current_media_packet_info->avrcp_song_position = avrcp_song_position;
current_media_packet_info->stream_number = sep_data.stream_number;
wmem_tree_insert32_array(media_packet_times, key, current_media_packet_info);
@ -2665,6 +2695,10 @@ dissect_aptx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
proto_item_append_text(pitem, " ms");
PROTO_ITEM_SET_GENERATED(pitem);
pitem = proto_tree_add_double(aptx_tree, hf_aptx_avrcp_song_position, tvb, 0, 0, info->previous_media_packet_info->avrcp_song_position);
proto_item_append_text(pitem, " ms");
PROTO_ITEM_SET_GENERATED(pitem);
nstime_delta(&delta, &pinfo->fd->abs_ts, &info->previous_media_packet_info->first_abs_ts);
pitem = proto_tree_add_double(aptx_tree, hf_aptx_delta_time_from_the_beginning, tvb, 0, 0, nstime_to_msec(&delta));
proto_item_append_text(pitem, " ms");
@ -2704,6 +2738,11 @@ proto_register_aptx(void)
FT_DOUBLE, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_aptx_avrcp_song_position,
{ "AVRCP Song Position", "aptx.avrcp_song_position",
FT_DOUBLE, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_aptx_delta_time_from_the_beginning,
{ "Delta time from the beginning", "aptx.delta_time_from_the_beginning",
FT_DOUBLE, BASE_NONE, NULL, 0x00,

View File

@ -31,6 +31,7 @@ typedef struct _media_packet_info_t {
nstime_t abs_ts;
nstime_t first_abs_ts;
gdouble cummulative_frame_duration;
gdouble avrcp_song_position;
guint32 stream_number;
} media_packet_info_t;

View File

@ -34,6 +34,7 @@
#include "packet-btl2cap.h"
#include "packet-btsdp.h"
#include "packet-btavctp.h"
#include "packet-btavrcp.h"
static int proto_btavrcp = -1;
@ -272,8 +273,9 @@ static dissector_handle_t btavrcp_handle;
#define STATUS_OK 0x04
static wmem_tree_t *reassembling = NULL;
static wmem_tree_t *timing = NULL;
static wmem_tree_t *reassembling = NULL;
static wmem_tree_t *timing = NULL;
wmem_tree_t *btavrcp_song_positions = NULL;
typedef struct _fragment {
guint start_frame_number;
@ -307,7 +309,7 @@ typedef struct _timing_info {
guint32 opcode;
guint32 op;
guint32 op_arg;
} timing_info_t;
} timing_info_t;
static const value_string packet_type_vals[] = {
{ PACKET_TYPE_SINGLE, "Single" },
@ -1592,6 +1594,27 @@ dissect_vendor_dependant(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
if (song_position == 0xFFFFFFFF) {
proto_item_append_text(pitem, " (NOT SELECTED)");
col_append_str(pinfo->cinfo, COL_INFO, " (NOT SELECTED)");
} else if (!pinfo->fd->flags.visited) {
btavrcp_song_position_data_t *song_position_data;
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_frame_number = pinfo->fd->num;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_frame_number;
key[3].length = 0;
key[3].key = NULL;
song_position_data = wmem_new(wmem_file_scope(), btavrcp_song_position_data_t);
song_position_data->song_position = song_position;
song_position_data->used_in_frame = 0;
wmem_tree_insert32_array(btavrcp_song_positions, key, song_position_data);
}
break;
case EVENT_BATTERY_STATUS_CHANGED:
@ -3162,8 +3185,9 @@ proto_register_btavrcp(void)
{ &ei_btavrcp_no_response, { "btavrcp.no_response", PI_PROTOCOL, PI_WARN, "No response", EXPFILL }},
};
reassembling = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
timing = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
reassembling = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
timing = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
btavrcp_song_positions = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
proto_btavrcp = proto_register_protocol("Bluetooth AVRCP Profile", "BT AVRCP", "btavrcp");
btavrcp_handle = new_register_dissector("btavrcp", dissect_btavrcp, proto_btavrcp);

View File

@ -0,0 +1,48 @@
/* packet-btavrcp.h
* Headers for AVRCP
*
* Copyright 2014, Michal Labedzki for Tieto Corporation
*
* 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.
*/
#ifndef __PACKET_BTAVRCP_H__
#define __PACKET_BTAVRCP_H__
wmem_tree_t *btavrcp_song_positions;
typedef struct _btavrcp_song_position_data_t {
guint32 song_position;
guint32 used_in_frame;
} btavrcp_song_position_data_t;
#endif
/*
* 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:
*/

View File

@ -62,6 +62,7 @@ static int hf_sbc_cummulative_frame_duration = -1;
static int hf_sbc_delta_time = -1;
static int hf_sbc_delta_time_from_the_beginning = -1;
static int hf_sbc_cummulative_duration = -1;
static int hf_sbc_avrcp_song_position = -1;
static int hf_sbc_diff = -1;
static int hf_sbc_data = -1;
@ -252,13 +253,19 @@ dissect_sbc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
proto_item_append_text(pitem, " ms");
PROTO_ITEM_SET_GENERATED(pitem);
pitem = proto_tree_add_double(sbc_tree, hf_sbc_avrcp_song_position, tvb, offset, 0, info->previous_media_packet_info->avrcp_song_position);
proto_item_append_text(pitem, " ms");
PROTO_ITEM_SET_GENERATED(pitem);
nstime_delta(&delta, &pinfo->fd->abs_ts, &info->previous_media_packet_info->first_abs_ts);
pitem = proto_tree_add_double(sbc_tree, hf_sbc_delta_time_from_the_beginning, tvb, offset, 0, nstime_to_msec(&delta));
proto_item_append_text(pitem, " ms");
PROTO_ITEM_SET_GENERATED(pitem);
if (!pinfo->fd->flags.visited)
if (!pinfo->fd->flags.visited) {
info->current_media_packet_info->cummulative_frame_duration += cummulative_frame_duration;
info->current_media_packet_info->avrcp_song_position += cummulative_frame_duration;
}
pitem = proto_tree_add_double(sbc_tree, hf_sbc_cummulative_duration, tvb, offset, 0, info->previous_media_packet_info->cummulative_frame_duration);
proto_item_append_text(pitem, " ms");
@ -378,6 +385,11 @@ proto_register_sbc(void)
FT_DOUBLE, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_sbc_avrcp_song_position,
{ "AVRCP Song Position", "sbc.avrcp_song_position",
FT_DOUBLE, BASE_NONE, NULL, 0x00,
NULL, HFILL }
},
{ &hf_sbc_diff,
{ "Diff", "sbc.diff",
FT_DOUBLE, BASE_NONE, NULL, 0x00,