MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-btavrcp.c
blob4a3c8ffad6b7d344f79cd39ab2b96573bb0dc559
1 /* packet-btavrcp.c
2 * Routines for Bluetooth AVRCP dissection
4 * Copyright 2012, Michal Labedzki for Tieto Corporation
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <epan/packet.h>
30 #include <epan/prefs.h>
31 #include <epan/expert.h>
32 #include <epan/oui.h>
33 #include <epan/wmem/wmem.h>
35 #include "packet-wap.h"
36 #include "packet-btl2cap.h"
37 #include "packet-btsdp.h"
38 #include "packet-btavctp.h"
40 static int proto_btavrcp = -1;
42 static int hf_btavrcp_rfa = -1;
43 static int hf_btavrcp_ctype = -1;
44 static int hf_btavrcp_subunit_type = -1;
45 static int hf_btavrcp_subunit_id = -1;
46 static int hf_btavrcp_opcode = -1;
47 static int hf_btavrcp_company_id = -1;
48 static int hf_btavrcp_length = -1;
49 static int hf_btavrcp_pdu_id = -1;
50 static int hf_btavrcp_bt_pdu_id = -1;
51 static int hf_btavrcp_bt_continuing_pdu_id = -1;
52 static int hf_btavrcp_browsing_pdu_id = -1;
53 static int hf_btavrcp_reserved = -1;
54 static int hf_btavrcp_packet_type = -1;
55 static int hf_btavrcp_passthrough_state = -1;
56 static int hf_btavrcp_passthrough_operation = -1;
57 static int hf_btavrcp_passthrough_data_length = -1;
58 static int hf_btavrcp_passthrough_company_id = -1;
59 static int hf_btavrcp_passthrough_vendor_unique_id = -1;
60 static int hf_btavrcp_unit_unknown = -1;
61 static int hf_btavrcp_unit_type = -1;
62 static int hf_btavrcp_unit_id = -1;
63 static int hf_btavrcp_subunit_page = -1;
64 static int hf_btavrcp_subunit_extention_code = -1;
65 static int hf_btavrcp_item = -1;
66 static int hf_btavrcp_folder = -1;
67 static int hf_btavrcp_player_id = -1;
68 static int hf_btavrcp_status = -1;
69 static int hf_btavrcp_uid_counter = -1;
70 static int hf_btavrcp_number_of_items = -1;
71 static int hf_btavrcp_number_of_items16 = -1;
72 static int hf_btavrcp_character_set = -1;
73 static int hf_btavrcp_folder_depth = -1;
74 static int hf_btavrcp_folder_name_length = -1;
75 static int hf_btavrcp_folder_name = -1;
76 static int hf_btavrcp_search = -1;
77 static int hf_btavrcp_search_length = -1;
78 static int hf_btavrcp_number_of_attributes = -1;
79 static int hf_btavrcp_uid = -1;
80 static int hf_btavrcp_scope = -1;
81 static int hf_btavrcp_start_item = -1;
82 static int hf_btavrcp_end_item = -1;
83 static int hf_btavrcp_direction = -1;
84 static int hf_btavrcp_identifier = -1;
85 static int hf_btavrcp_song_length = -1;
86 static int hf_btavrcp_song_position = -1;
87 static int hf_btavrcp_play_status = -1;
88 static int hf_btavrcp_notification_interval = -1;
89 static int hf_btavrcp_event_id = -1;
90 static int hf_btavrcp_battery_status = -1;
91 static int hf_btavrcp_number_of_character_set = -1;
92 static int hf_btavrcp_absolute_volume_rfa = -1;
93 static int hf_btavrcp_absolute_volume = -1;
94 static int hf_btavrcp_capability = -1;
95 static int hf_btavrcp_capability_count = -1;
96 static int hf_btavrcp_item_type = -1;
97 static int hf_btavrcp_item_length = -1;
98 static int hf_btavrcp_system_status = -1;
99 static int hf_btavrcp_number_of_settings = -1;
100 static int hf_btavrcp_settings_attribute = -1;
101 static int hf_btavrcp_settings_value = -1;
102 static int hf_btavrcp_displayable_name = -1;
103 static int hf_btavrcp_displayable_name_length = -1;
104 static int hf_btavrcp_media_type = -1;
105 static int hf_btavrcp_folder_type = -1;
106 static int hf_btavrcp_folder_playable = -1;
107 static int hf_btavrcp_major_player_type = -1;
108 static int hf_btavrcp_player_subtype = -1;
109 static int hf_btavrcp_player_item = -1;
110 static int hf_btavrcp_attribute = -1;
111 static int hf_btavrcp_attribute_count = -1;
112 static int hf_btavrcp_attribute_value = -1;
113 static int hf_btavrcp_attribute_value_length = -1;
114 static int hf_btavrcp_attribute_item = -1;
115 static int hf_btavrcp_attribute_list = -1;
116 static int hf_btavrcp_attribute_entries = -1;
117 static int hf_btavrcp_attribute_name_length = -1;
118 static int hf_btavrcp_attribute_name = -1;
119 static int hf_btavrcp_setting_value_length = -1;
120 static int hf_btavrcp_setting_value = -1;
121 static int hf_btavrcp_features = -1;
122 static int hf_btavrcp_not_used_features = -1;
123 static int hf_btavrcp_feature_reserved_0 = -1;
124 static int hf_btavrcp_feature_reserved_1 = -1;
125 static int hf_btavrcp_feature_reserved_2 = -1;
126 static int hf_btavrcp_feature_reserved_3 = -1;
127 static int hf_btavrcp_feature_reserved_4 = -1;
128 static int hf_btavrcp_feature_reserved_5 = -1;
129 static int hf_btavrcp_feature_reserved_6 = -1;
130 static int hf_btavrcp_feature_reserved_7 = -1;
131 static int hf_btavrcp_feature_passthrough_select = -1;
132 static int hf_btavrcp_feature_passthrough_up = -1;
133 static int hf_btavrcp_feature_passthrough_down = -1;
134 static int hf_btavrcp_feature_passthrough_left = -1;
135 static int hf_btavrcp_feature_passthrough_right = -1;
136 static int hf_btavrcp_feature_passthrough_right_up = -1;
137 static int hf_btavrcp_feature_passthrough_right_down = -1;
138 static int hf_btavrcp_feature_passthrough_left_up = -1;
139 static int hf_btavrcp_feature_passthrough_left_down = -1;
140 static int hf_btavrcp_feature_passthrough_root_menu = -1;
141 static int hf_btavrcp_feature_passthrough_setup_menu = -1;
142 static int hf_btavrcp_feature_passthrough_contents_menu = -1;
143 static int hf_btavrcp_feature_passthrough_favorite_menu = -1;
144 static int hf_btavrcp_feature_passthrough_exit = -1;
145 static int hf_btavrcp_feature_passthrough_0 = -1;
146 static int hf_btavrcp_feature_passthrough_1 = -1;
147 static int hf_btavrcp_feature_passthrough_2 = -1;
148 static int hf_btavrcp_feature_passthrough_3 = -1;
149 static int hf_btavrcp_feature_passthrough_4 = -1;
150 static int hf_btavrcp_feature_passthrough_5 = -1;
151 static int hf_btavrcp_feature_passthrough_6 = -1;
152 static int hf_btavrcp_feature_passthrough_7 = -1;
153 static int hf_btavrcp_feature_passthrough_8 = -1;
154 static int hf_btavrcp_feature_passthrough_9 = -1;
155 static int hf_btavrcp_feature_passthrough_dot = -1;
156 static int hf_btavrcp_feature_passthrough_enter = -1;
157 static int hf_btavrcp_feature_passthrough_clear = -1;
158 static int hf_btavrcp_feature_passthrough_channel_up = -1;
159 static int hf_btavrcp_feature_passthrough_channel_down = -1;
160 static int hf_btavrcp_feature_passthrough_previous_channel = -1;
161 static int hf_btavrcp_feature_passthrough_sound_select = -1;
162 static int hf_btavrcp_feature_passthrough_input_select = -1;
163 static int hf_btavrcp_feature_passthrough_display_information = -1;
164 static int hf_btavrcp_feature_passthrough_help = -1;
165 static int hf_btavrcp_feature_passthrough_page_up = -1;
166 static int hf_btavrcp_feature_passthrough_page_down = -1;
167 static int hf_btavrcp_feature_passthrough_power = -1;
168 static int hf_btavrcp_feature_passthrough_volume_up = -1;
169 static int hf_btavrcp_feature_passthrough_volume_down = -1;
170 static int hf_btavrcp_feature_passthrough_mute = -1;
171 static int hf_btavrcp_feature_passthrough_play = -1;
172 static int hf_btavrcp_feature_passthrough_stop = -1;
173 static int hf_btavrcp_feature_passthrough_pause = -1;
174 static int hf_btavrcp_feature_passthrough_record = -1;
175 static int hf_btavrcp_feature_passthrough_rewind = -1;
176 static int hf_btavrcp_feature_passthrough_fast_forward = -1;
177 static int hf_btavrcp_feature_passthrough_eject = -1;
178 static int hf_btavrcp_feature_passthrough_forward = -1;
179 static int hf_btavrcp_feature_passthrough_backward = -1;
180 static int hf_btavrcp_feature_passthrough_angle = -1;
181 static int hf_btavrcp_feature_passthrough_subpicture = -1;
182 static int hf_btavrcp_feature_passthrough_f1 = -1;
183 static int hf_btavrcp_feature_passthrough_f2 = -1;
184 static int hf_btavrcp_feature_passthrough_f3 = -1;
185 static int hf_btavrcp_feature_passthrough_f4 = -1;
186 static int hf_btavrcp_feature_passthrough_f5 = -1;
187 static int hf_btavrcp_feature_vendor_unique = -1;
188 static int hf_btavrcp_feature_basic_group_navigation = -1;
189 static int hf_btavrcp_feature_advanced_control_player = -1;
190 static int hf_btavrcp_feature_browsing = -1;
191 static int hf_btavrcp_feature_searching = -1;
192 static int hf_btavrcp_feature_addtonowplayer = -1;
193 static int hf_btavrcp_feature_uid_unique = -1;
194 static int hf_btavrcp_feature_only_browsable_when_addressed = -1;
195 static int hf_btavrcp_feature_only_searchable_when_addressed = -1;
196 static int hf_btavrcp_feature_nowplaying = -1;
197 static int hf_btavrcp_feature_uid_persistency = -1;
198 static int hf_btavrcp_reassembled = -1;
199 static int hf_btavrcp_currect_path = -1;
200 static int hf_btavrcp_response_time = -1;
201 static int hf_btavrcp_data = -1;
203 static gint ett_btavrcp = -1;
204 static gint ett_btavrcp_attribute_list = -1;
205 static gint ett_btavrcp_attribute_entry = -1;
206 static gint ett_btavrcp_attribute_entries = -1;
207 static gint ett_btavrcp_element = -1;
208 static gint ett_btavrcp_folder = -1;
209 static gint ett_btavrcp_player = -1;
210 static gint ett_btavrcp_features = -1;
211 static gint ett_btavrcp_features_not_used = -1;
212 static gint ett_btavrcp_path = -1;
214 static expert_field ei_btavrcp_item_length_bad = EI_INIT;
215 static expert_field ei_btavrcp_unexpected_data = EI_INIT;
217 #define OPCODE_VENDOR_DEPENDANT 0x00
218 #define OPCODE_UNIT 0x30
219 #define OPCODE_SUBUNIT 0x31
220 #define OPCODE_PASSTHROUGH 0x7C
222 #define ITEM_MEDIAPLAYER 0x01
223 #define ITEM_FOLDER 0x02
224 #define ITEM_MEDIA_ELEMENT 0x03
226 #define PACKET_TYPE_SINGLE 0x00
227 #define PACKET_TYPE_START 0x01
228 #define PACKET_TYPE_CONTINUE 0x02
229 #define PACKET_TYPE_END 0x03
231 #define EVENT_PLAYBACK_STATUS_CHANGED 0x01
232 #define EVENT_TRACK_CHANGED 0x02
233 #define EVENT_TRACK_REACHED_END 0x03
234 #define EVENT_TRACK_REACHED_START 0x04
235 #define EVENT_PLAYBACK_POSITION_CHANGED 0x05
236 #define EVENT_BATTERY_STATUS_CHANGED 0x06
237 #define EVENT_SYSTEM_STATUS_CHANGED 0x07
238 #define EVENT_PLAYER_APPLICATION_SETTING_CHANGED 0x08
239 #define EVENT_NOWPLAYING_CONTENT_CHANGED 0x09
240 #define EVENT_AVAILABLE_PLAYERS_CHANGED 0x0A
241 #define EVENT_ADDRESSEDPLAYER_CHANGED 0x0B
242 #define EVENT_UIDS_CHANGED 0x0C
243 #define EVENT_VOLUME_CHANGED 0x0D
245 #define PDU_GET_CAPABILITIES 0x10
246 #define PDU_LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES 0x11
247 #define PDU_LIST_PLAYER_APPLICATION_SETTING_VALUE 0x12
248 #define PDU_GET_CURRENT_PLAYER_APPLICATION_SETTING_VALUE 0x13
249 #define PDU_SET_PLAYER_APPLICATION_SETTING_VALUE 0x14
250 #define PDU_GET_PLAYER_APPLICATION_SETTING_ATTRIBUTE_TEXT 0x15
251 #define PDU_GET_PLAYER_APPLICATION_SETTING_VALUE_TEXT 0x16
252 #define PDU_INFORM_DISPLAYABLE_CHARACTER_SET 0x17
253 #define PDU_INFORM_BATTERY_STATUS_OF_CT 0x18
254 #define PDU_GET_ELEMENT_ATTRIBUTES 0x20
255 #define PDU_GET_PLAY_STATUS 0x30
256 #define PDU_REGISTER_NOTIFICATION 0x31
257 #define PDU_REQUEST_CONTINUING_RESPONSE 0x40
258 #define PDU_ABORT_CONTINUING_RESPONSE 0x41
259 #define PDU_SET_ABSOLUTE_VOLUME 0x50
260 #define PDU_SET_ADDRESSED_PLAYER 0x60
261 #define PDU_SET_BROWSED_PLAYER 0x70
262 #define PDU_GET_FOLDER_ITEMS 0x71
263 #define PDU_CHANGE_PATH 0x72
264 #define PDU_GET_ITEM_ATTRIBUTES 0x73
265 #define PDU_PLAY_ITEM 0x74
266 #define PDU_SEARCH 0x80
267 #define PDU_ADD_TO_NOW_PLAYING 0x90
268 #define PDU_GENERAL_REJECT 0xA0
270 #define STATUS_OK 0x04
272 static wmem_tree_t *reassembling = NULL;
273 static wmem_tree_t *timing = NULL;
275 typedef struct _fragment {
276 guint start_frame_number;
277 guint end_frame_number;
278 guint32 interface_id;
279 guint32 adapter_id;
280 guint32 chandle;
281 guint32 psm;
282 guint32 op;
283 guint state;
284 guint32 count;
285 wmem_tree_t *fragments;
286 } fragment_t;
288 typedef struct _data_fragment_t {
289 guint32 length;
290 guint8 *data;
291 } data_fragment_t;
293 typedef struct _timing_info {
294 guint command_frame_number;
295 nstime_t command_timestamp;
296 guint response_frame_number;
297 nstime_t response_timestamp;
298 guint max_response_time;
299 guint used;
300 guint32 interface_id;
301 guint32 adapter_id;
302 guint32 chandle;
303 guint32 psm;
304 guint32 opcode;
305 guint32 op;
306 guint32 op_arg;
307 } timing_info_t;
309 static const value_string packet_type_vals[] = {
310 { PACKET_TYPE_SINGLE, "Single" },
311 { PACKET_TYPE_START, "Start" },
312 { PACKET_TYPE_CONTINUE, "Continue" },
313 { PACKET_TYPE_END, "End" },
314 { 0, NULL }
317 static const value_string ctype_vals[] = {
318 { 0x00, "Control" },
319 { 0x01, "Status" },
320 { 0x02, "Specific Inquiry" },
321 { 0x03, "Notify" },
322 { 0x04, "General Inquiry" },
323 { 0x05, "reserved" },
324 { 0x06, "reserved" },
325 { 0x07, "reserved" },
326 { 0x08, "Not Implemented" },
327 { 0x09, "Accepted" },
328 { 0x0A, "Rejected" },
329 { 0x0B, "In Transition" },
330 { 0x0C, "Stable" },
331 { 0x0D, "Changed" },
332 { 0x0E, "reserved" },
333 { 0x0F, "Interim" },
334 { 0, NULL }
337 static const value_string opcode_vals[] = {
338 { OPCODE_VENDOR_DEPENDANT, "Vendor dependent" },
339 { OPCODE_UNIT, "Unit Info" },
340 { OPCODE_SUBUNIT, "Subunit Info" },
341 { OPCODE_PASSTHROUGH, "Pass Through" },
342 { 0, NULL }
345 static const value_string subunit_type_vals[] = {
346 { 0x00, "Monitor" },
347 { 0x01, "Audio" },
348 { 0x02, "Printer" },
349 { 0x03, "Disc" },
350 { 0x04, "Tape Recorder/Player" },
351 { 0x05, "Tuner" },
352 { 0x06, "CA" },
353 { 0x07, "Camera" },
355 { 0x08, "reserved" },
357 { 0x09, "Panel" },
358 { 0x0A, "Bulletin Board" },
359 { 0x0B, "Camera Storage" },
361 { 0x1C, "Vendor Unique" },
362 { 0x1D, "All subunit types" },
363 { 0x1E, "Subunit_type extended to next byte" },
364 { 0x1F, "Unit" },
365 { 0, NULL }
368 static const value_string passthrough_state_vals[] = {
369 { 0x00, "Pushed" },
370 { 0x01, "Released" },
371 { 0, NULL }
374 static const value_string passthrough_operation_vals[] = {
375 { 0x41, "VOLUME UP" },
376 { 0x42, "VOLUME DOWN" },
377 { 0x43, "MUTE" },
378 { 0x44, "PLAY" },
379 { 0x45, "STOP" },
380 { 0x46, "PAUSE" },
381 { 0x47, "RECORD" },
382 { 0x48, "REWIND" },
383 { 0x49, "FAST FORWARD" },
384 { 0x4A, "EJECT" },
385 { 0x4B, "FORWARD" },
386 { 0x4C, "BACKWARD" },
387 { 0, NULL }
390 static const value_string pdu_id_vals[] = {
391 { PDU_GET_CAPABILITIES, "GetCapabilities" },
392 { PDU_LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES, "ListPlayerApplicationSettingAttributes" },
393 { PDU_LIST_PLAYER_APPLICATION_SETTING_VALUE, "ListPlayerApplicationSettingValue" },
394 { PDU_GET_CURRENT_PLAYER_APPLICATION_SETTING_VALUE, "GetCurrentPlayerApplicationSettingValue" },
395 { PDU_SET_PLAYER_APPLICATION_SETTING_VALUE, "SetPlayerApplicationSettingValue" },
396 { PDU_GET_PLAYER_APPLICATION_SETTING_ATTRIBUTE_TEXT, "GetPlayerApplicationSettingAttributeText" },
397 { PDU_GET_PLAYER_APPLICATION_SETTING_VALUE_TEXT, "GetPlayerApplicationSettingValueText" },
398 { PDU_INFORM_DISPLAYABLE_CHARACTER_SET, "InformDisplayableCharacterSet" },
399 { PDU_INFORM_BATTERY_STATUS_OF_CT, "InformBatteryStatusOfCT" },
400 { PDU_GET_ELEMENT_ATTRIBUTES, "GetElementAttributes" },
401 { PDU_GET_PLAY_STATUS, "GetPlayStatus" },
402 { PDU_REGISTER_NOTIFICATION, "RegisterNotification" },
403 { PDU_REQUEST_CONTINUING_RESPONSE, "RequestContinuingResponse" },
404 { PDU_ABORT_CONTINUING_RESPONSE, "AbortContinuingResponse" },
405 { PDU_SET_ABSOLUTE_VOLUME, "SetAbsoluteVolume" },
406 { PDU_SET_ADDRESSED_PLAYER, "SetAddressedPlayer" },
407 { PDU_PLAY_ITEM, "PlayItem" },
408 { PDU_ADD_TO_NOW_PLAYING, "AddToNowPlaying" },
409 { 0, NULL }
412 static const value_string browsing_pdu_id_vals[] = {
413 { PDU_SET_BROWSED_PLAYER, "SetBrowsedPlayer" },
414 { PDU_GET_FOLDER_ITEMS, "GetFolderItems" },
415 { PDU_CHANGE_PATH, "ChangePath" },
416 { PDU_GET_ITEM_ATTRIBUTES, "GetItemAttributes" },
417 { PDU_SEARCH, "Search" },
418 { PDU_GENERAL_REJECT, "GeneralReject" },
419 { 0, NULL }
422 static const value_string status_vals[] = {
423 { 0x00, "Invalid Command" },
424 { 0x01, "Invalid Parameter" },
425 { 0x02, "Parameter Not Found" },
426 { 0x03, "Internal Error" },
427 { 0x04, "OK" },
428 { 0x05, "UID Changed" },
429 { 0x06, "Reserved" },
430 { 0x07, "Invalid Direction" },
431 { 0x08, "Not a Directory" },
432 { 0x09, "Does Not Exist" },
433 { 0x0A, "Invalid Scope" },
434 { 0x0B, "Range Out of Bounds" },
435 { 0x0C, "UID is a Directory" },
436 { 0x0D, "Media In Use" },
437 { 0x0E, "Now Player List Full" },
438 { 0x0F, "Search Not Supported" },
439 { 0x10, "Search in Progress" },
440 { 0x11, "Invalid Player Id" },
441 { 0x12, "Player Not Browsable" },
442 { 0x13, "Player Not Addressed" },
443 { 0x14, "No Valid Search Results" },
444 { 0x15, "No Available Players" },
445 { 0x16, "Addressed Player Changed" },
446 { 0, NULL }
449 static const value_string vendor_unique_id_vals[] = {
450 { 0x0000, "Next Group" },
451 { 0x0001, "Previous Group" },
452 { 0, NULL }
455 static const value_string direction_vals[] = {
456 { 0x00, "Folder Up" },
457 { 0x01, "Folder Down" },
458 { 0, NULL }
461 static const value_string attribute_count_vals[] = {
462 { 0x00, "All attributes are requested" },
463 { 0xFF, "No attributes are requested" },
464 { 0, NULL }
467 static const value_string scope_vals[] = {
468 { 0x00, "MediaPlayerList" },
469 { 0x01, "VFS" },
470 { 0x02, "Search" },
471 { 0x03, "NowPlaying" },
472 { 0, NULL }
475 static const value_string attribute_id_vals[] = {
476 { 0x00, "Invalid" },
477 { 0x01, "Title" },
478 { 0x02, "Artist" },
479 { 0x03, "Album" },
480 { 0x04, "Media Number" },
481 { 0x05, "Total Number of Media" },
482 { 0x06, "Genre" },
483 { 0x07, "Playing Time" },
484 { 0, NULL }
487 static const value_string settings_vals[] = {
488 { 0x00, "Illegal" },
489 { 0x01, "Equalizer" },
490 { 0x02, "Repeat mode" },
491 { 0x03, "Shuffle" },
492 { 0x04, "Scan" },
493 { 0, NULL }
496 static const value_string notification_vals[] = {
497 { EVENT_PLAYBACK_STATUS_CHANGED, "PlaybackStatusChanged" },
498 { EVENT_TRACK_CHANGED, "TrackChanged" },
499 { EVENT_TRACK_REACHED_END, "TrackReachedEnd" },
500 { EVENT_TRACK_REACHED_START, "TrackReachedStart" },
501 { EVENT_PLAYBACK_POSITION_CHANGED, "PlaybackPositionChanged" },
502 { EVENT_BATTERY_STATUS_CHANGED, "BatteryStatusChanged" },
503 { EVENT_SYSTEM_STATUS_CHANGED, "SystemStatusChanged" },
504 { EVENT_PLAYER_APPLICATION_SETTING_CHANGED, "PlayerApplicationSettingChanged" },
505 { EVENT_NOWPLAYING_CONTENT_CHANGED, "NowPlayingContentChanged" },
506 { EVENT_AVAILABLE_PLAYERS_CHANGED, "AvailablePlayersChanged" },
507 { EVENT_ADDRESSEDPLAYER_CHANGED, "AddressedPlayerChanged" },
508 { EVENT_UIDS_CHANGED, "UIDsChanged" },
509 { EVENT_VOLUME_CHANGED, "VolumeChanged" },
510 { 0, NULL }
513 static const value_string play_status_vals[] = {
514 { 0x00, "Stopped" },
515 { 0x01, "Playing" },
516 { 0x02, "Paused" },
517 { 0x03, "Forward Seek" },
518 { 0x04, "Revrse Seek" },
519 { 0xFF, "Error" },
520 { 0, NULL }
523 static const value_string battery_status_vals[] = {
524 { 0x00, "Normal" },
525 { 0x01, "Warning" },
526 { 0x02, "Critical" },
527 { 0x03, "External" },
528 { 0x04, "Full Charge" },
529 { 0, NULL }
532 static const value_string capability_vals[] = {
533 { 0x02, "Company ID" },
534 { 0x03, "Events Supported" },
535 { 0, NULL }
538 static const value_string item_type_vals[] = {
539 { 0x01, "Media Player Item" },
540 { 0x02, "Folder Item" },
541 { 0x03, "Media Element Item" },
542 { 0, NULL }
545 static const value_string system_status_vals[] = {
546 { 0x00, "Power On" },
547 { 0x01, "Power Off" },
548 { 0x02, "Unplugged" },
549 { 0, NULL }
552 static const value_string media_type_vals[] = {
553 { 0x00, "Audio" },
554 { 0x01, "Video" },
555 { 0, NULL }
558 static const value_string folder_type_vals[] = {
559 { 0x00, "Mixed" },
560 { 0x01, "Titles" },
561 { 0x02, "Albums" },
562 { 0x03, "Artists" },
563 { 0x04, "Genres" },
564 { 0x05, "Playlists" },
565 { 0x06, "Years" },
566 { 0, NULL }
569 static const value_string folder_playable_vals[] = {
570 { 0x00, "Not Playable" },
571 { 0x01, "Playable" },
572 { 0, NULL }
575 static const value_string major_player_type_vals[] = {
576 { 0x00, "Audio" },
577 { 0x02, "Video" },
578 { 0x04, "Broadcasting Audio" },
579 { 0x08, "Broadcasting Video" },
580 { 0, NULL }
583 static const value_string player_subtype_vals[] = {
584 { 0x00, "Audio Book" },
585 { 0x02, "Podcast" },
586 { 0, NULL }
589 void proto_register_btavrcp(void);
590 void proto_reg_handoff_btavrcp(void);
592 static gint
593 dissect_attribute_id_list(tvbuff_t *tvb, proto_tree *tree, gint offset,
594 guint count)
596 guint i_attribute;
597 proto_item *pitem;
598 proto_tree *ptree;
600 pitem = proto_tree_add_item(tree, hf_btavrcp_attribute_list, tvb, offset, count * 4, ENC_NA);
601 ptree = proto_item_add_subtree(pitem, ett_btavrcp_attribute_list);
603 for (i_attribute = 0; i_attribute < count; ++i_attribute) {
604 proto_tree_add_item(ptree, hf_btavrcp_attribute, tvb, offset, 4, ENC_BIG_ENDIAN);
605 offset += 4;
608 return offset;
612 static gint
613 dissect_attribute_entries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
614 gint offset, guint count)
616 guint i_entry;
617 guint attribute_id;
618 guint value_length;
619 guint length;
620 guint8 *value;
621 proto_item *pitem = NULL;
622 proto_tree *ptree = NULL;
623 proto_item *entry_item = NULL;
624 proto_tree *entry_tree = NULL;
626 length = 0;
627 for (i_entry = 0; i_entry < count; ++i_entry) {
628 length += 4 + 2 + 2 + tvb_get_ntohs(tvb, offset + length + 4 + 2);
631 pitem = proto_tree_add_item(tree, hf_btavrcp_attribute_entries, tvb, offset, length, ENC_NA);
632 ptree = proto_item_add_subtree(pitem, ett_btavrcp_attribute_entries);
634 for (i_entry = 0; i_entry < count; ++i_entry) {
635 attribute_id = tvb_get_ntohl(tvb, offset);
636 value_length = tvb_get_ntohs(tvb, offset + 4 + 2);
637 value = tvb_get_string(NULL, tvb, offset + 4 + 2 + 2, value_length);
639 if (attribute_id == 0x01) col_append_fstr(pinfo->cinfo, COL_INFO, " - Title: \"%s\"", value);
641 entry_item = proto_tree_add_none_format(ptree, hf_btavrcp_attribute_item, tvb, offset, 4 + 2 + 2 + value_length, "Attribute [%21s]: %s", val_to_str_const(attribute_id, attribute_id_vals, "Unknown"), value);
642 entry_tree = proto_item_add_subtree(entry_item, ett_btavrcp_attribute_entry);
644 proto_tree_add_item(entry_tree, hf_btavrcp_attribute, tvb, offset, 4, ENC_BIG_ENDIAN);
645 offset += 4;
646 proto_tree_add_item(entry_tree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
647 offset += 2;
648 proto_tree_add_item(entry_tree, hf_btavrcp_setting_value_length, tvb, offset, 2, ENC_BIG_ENDIAN);
649 offset += 2;
650 proto_tree_add_item(entry_tree, hf_btavrcp_setting_value, tvb, offset, value_length, ENC_UTF_8 | ENC_NA);
651 offset += value_length;
654 return offset;
658 static gint
659 dissect_item_mediaplayer(tvbuff_t *tvb, proto_tree *tree, gint offset)
661 guint displayable_name_length;
662 guint item_length;
663 guint feature_octet;
664 guint i_feature;
665 guint8 *displayable_name;
666 proto_item *pitem;
667 proto_tree *ptree;
668 proto_item *features_item;
669 proto_tree *features_tree;
670 proto_item *features_not_set_item;
671 proto_tree *features_not_set_tree;
673 item_length = tvb_get_ntohs(tvb, offset + 1);
674 displayable_name_length = tvb_get_ntohs(tvb, offset + 1 + 2 + 1 + 1 + 4 + 16 + 1 + 2);
675 displayable_name = tvb_get_string(NULL, tvb, offset + 1 + 2 + 1 + 1 + 4 + 16 + 1 + 2 + 2, displayable_name_length);
677 pitem = proto_tree_add_none_format(tree, hf_btavrcp_player_item, tvb, offset, 1 + 2 + item_length, "Player: %s", displayable_name);
678 ptree = proto_item_add_subtree(pitem, ett_btavrcp_player);
680 proto_tree_add_item(ptree, hf_btavrcp_item_type, tvb, offset, 1, ENC_BIG_ENDIAN);
681 offset += 1;
682 proto_tree_add_item(ptree, hf_btavrcp_item_length, tvb, offset, 2, ENC_BIG_ENDIAN);
683 offset += 2;
685 proto_tree_add_item(ptree, hf_btavrcp_player_id, tvb, offset, 1, ENC_BIG_ENDIAN);
686 offset += 1;
688 proto_tree_add_item(ptree, hf_btavrcp_major_player_type, tvb, offset, 1, ENC_BIG_ENDIAN);
689 offset += 1;
691 proto_tree_add_item(ptree, hf_btavrcp_player_subtype, tvb, offset, 4, ENC_BIG_ENDIAN);
692 offset += 4;
694 /* feature bit mask */
695 features_item = proto_tree_add_item(ptree, hf_btavrcp_features, tvb, offset, 16, ENC_NA);
696 features_tree = proto_item_add_subtree(features_item, ett_btavrcp_features);
698 features_not_set_item = proto_tree_add_item(features_tree, hf_btavrcp_not_used_features, tvb, offset, 16, ENC_NA);
699 features_not_set_tree = proto_item_add_subtree(features_not_set_item, ett_btavrcp_features_not_used);
701 feature_octet = tvb_get_guint8(tvb, offset + 0);
702 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_select, tvb, offset + 0, 1, ENC_BIG_ENDIAN);
703 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_up, tvb, offset + 0, 1, ENC_BIG_ENDIAN);
704 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_down, tvb, offset + 0, 1, ENC_BIG_ENDIAN);
705 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_left, tvb, offset + 0, 1, ENC_BIG_ENDIAN);
706 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_right, tvb, offset + 0, 1, ENC_BIG_ENDIAN);
707 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_right_up, tvb, offset + 0, 1, ENC_BIG_ENDIAN);
708 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_right_down, tvb, offset + 0, 1, ENC_BIG_ENDIAN);
709 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_left_up, tvb, offset + 0, 1, ENC_BIG_ENDIAN);
711 feature_octet = tvb_get_guint8(tvb, offset + 1);
712 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_left_down , tvb, offset + 1, 1, ENC_BIG_ENDIAN);
713 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_root_menu , tvb, offset + 1, 1, ENC_BIG_ENDIAN);
714 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_setup_menu, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
715 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_contents_menu, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
716 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_favorite_menu, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
717 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_exit, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
718 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_0, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
719 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_1, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
721 feature_octet = tvb_get_guint8(tvb, offset + 2);
722 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_2, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
723 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_3, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
724 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_4, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
725 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_5, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
726 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_6, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
727 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_7, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
728 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_8, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
729 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_9, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
731 feature_octet = tvb_get_guint8(tvb, offset + 3);
732 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_dot, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
733 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_enter, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
734 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_clear, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
735 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_channel_up, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
736 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_channel_down, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
737 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_previous_channel, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
738 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_sound_select, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
739 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_input_select, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
741 feature_octet = tvb_get_guint8(tvb, offset + 4);
742 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_display_information, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
743 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_help, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
744 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_page_up, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
745 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_page_down, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
746 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_power, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
747 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_volume_up, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
748 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_volume_down, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
749 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_mute, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
751 feature_octet = tvb_get_guint8(tvb, offset + 5);
752 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_play, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
753 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_stop, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
754 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_pause, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
755 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_record, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
756 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_rewind, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
757 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_fast_forward, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
758 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_eject, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
759 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_forward, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
761 feature_octet = tvb_get_guint8(tvb, offset + 6);
762 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_backward, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
763 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_angle, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
764 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_subpicture, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
765 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_f1, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
766 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_f2, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
767 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_f3, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
768 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_f4, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
769 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_passthrough_f5, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
771 feature_octet = tvb_get_guint8(tvb, offset + 7);
772 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_vendor_unique, tvb, offset + 7, 1, ENC_BIG_ENDIAN);
773 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_basic_group_navigation, tvb, offset + 7, 1, ENC_BIG_ENDIAN);
774 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_advanced_control_player, tvb, offset + 7, 1, ENC_BIG_ENDIAN);
775 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_browsing, tvb, offset + 7, 1, ENC_BIG_ENDIAN);
776 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_searching, tvb, offset + 7, 1, ENC_BIG_ENDIAN);
777 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_addtonowplayer, tvb, offset + 7, 1, ENC_BIG_ENDIAN);
778 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_uid_unique, tvb, offset + 7, 1, ENC_BIG_ENDIAN);
779 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_only_browsable_when_addressed, tvb, offset + 7, 1, ENC_BIG_ENDIAN);
781 feature_octet = tvb_get_guint8(tvb, offset + 8);
782 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_only_searchable_when_addressed, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
783 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_nowplaying, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
784 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_uid_persistency, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
786 /* reserved */
787 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_3, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
788 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_4, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
789 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_5, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
790 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_6, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
791 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_7, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
793 for (i_feature = 9; i_feature <= 16; ++i_feature) {
794 feature_octet = tvb_get_guint8(tvb, offset + i_feature);
795 proto_tree_add_item((feature_octet & (1 << 0)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_0, tvb, offset + i_feature, 1, ENC_BIG_ENDIAN);
796 proto_tree_add_item((feature_octet & (1 << 1)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_1, tvb, offset + i_feature, 1, ENC_BIG_ENDIAN);
797 proto_tree_add_item((feature_octet & (1 << 2)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_2, tvb, offset + i_feature, 1, ENC_BIG_ENDIAN);
798 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_3, tvb, offset + i_feature, 1, ENC_BIG_ENDIAN);
799 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_4, tvb, offset + i_feature, 1, ENC_BIG_ENDIAN);
800 proto_tree_add_item((feature_octet & (1 << 5)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_5, tvb, offset + i_feature, 1, ENC_BIG_ENDIAN);
801 proto_tree_add_item((feature_octet & (1 << 6)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_6, tvb, offset + i_feature, 1, ENC_BIG_ENDIAN);
802 proto_tree_add_item((feature_octet & (1 << 7)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_reserved_7, tvb, offset + i_feature, 1, ENC_BIG_ENDIAN);
804 offset += 16;
806 proto_tree_add_item(ptree, hf_btavrcp_play_status, tvb, offset, 1, ENC_BIG_ENDIAN);
807 offset += 1;
809 proto_tree_add_item(ptree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
810 offset += 2;
812 proto_tree_add_item(ptree, hf_btavrcp_displayable_name_length, tvb, offset, 2, ENC_BIG_ENDIAN);
813 displayable_name_length = tvb_get_ntohs(tvb, offset);
814 offset += 2;
816 proto_tree_add_item(ptree, hf_btavrcp_displayable_name, tvb, offset, displayable_name_length, ENC_UTF_8 | ENC_NA);
817 offset += displayable_name_length;
819 return offset;
823 static gint
824 dissect_item_media_element(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
825 gint offset)
827 guint number_of_attributes;
828 guint displayable_name_length;
829 guint item_length;
830 guint8 *displayable_name;
831 proto_item *pitem;
832 proto_tree *ptree;
833 gint offset_in;
835 item_length = tvb_get_ntohs(tvb, offset + 1);
836 displayable_name_length = tvb_get_ntohs(tvb, offset + 1 + 2 + 8 + 1 + 2);
837 displayable_name = tvb_get_string(NULL, tvb, offset + 1 + 2 + 8 + 1 + 2 + 2, displayable_name_length);
839 pitem = proto_tree_add_none_format(tree, hf_btavrcp_item , tvb, offset, 1 + 2 + item_length, "Element: %s", displayable_name);
840 ptree = proto_item_add_subtree(pitem, ett_btavrcp_element);
842 proto_tree_add_item(ptree, hf_btavrcp_item_type, tvb, offset, 1, ENC_BIG_ENDIAN);
843 offset += 1;
844 proto_tree_add_item(ptree, hf_btavrcp_item_length, tvb, offset, 2, ENC_BIG_ENDIAN);
845 offset += 2;
846 offset_in = offset;
848 proto_tree_add_item(ptree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
849 offset += 8;
851 proto_tree_add_item(ptree, hf_btavrcp_media_type, tvb, offset, 1, ENC_BIG_ENDIAN);
852 offset += 1;
854 proto_tree_add_item(ptree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
855 offset += 2;
857 proto_tree_add_item(ptree, hf_btavrcp_displayable_name_length, tvb, offset, 2, ENC_BIG_ENDIAN);
858 displayable_name_length = tvb_get_ntohs(tvb, offset);
859 offset += 2;
861 proto_tree_add_item(ptree, hf_btavrcp_displayable_name, tvb, offset, displayable_name_length, ENC_UTF_8 | ENC_NA);
862 offset += displayable_name_length;
864 proto_tree_add_item(ptree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
865 number_of_attributes = tvb_get_guint8(tvb, offset);
866 offset += 1;
868 offset = dissect_attribute_entries(tvb, pinfo, ptree, offset, number_of_attributes);
870 if ( item_length != (guint) offset - offset_in) {
871 expert_add_info(pinfo, pitem, &ei_btavrcp_item_length_bad);
874 return offset;
878 static gint
879 dissect_item_folder(tvbuff_t *tvb, proto_tree *tree, gint offset)
881 guint displayable_name_length;
882 guint item_length;
883 guint8 *displayable_name;
884 proto_item *pitem;
885 proto_tree *ptree;
887 item_length = tvb_get_ntohs(tvb, offset + 1);
888 displayable_name_length = tvb_get_ntohs(tvb, offset + 1 + 2 + 8 + 1 + 1 + 2);
889 displayable_name = tvb_get_string(NULL, tvb, offset + 1 + 2 + 8 + 1 + 1 + 2 + 2, displayable_name_length);
891 pitem = proto_tree_add_none_format(tree, hf_btavrcp_folder, tvb, offset, 1 + 2 + item_length, "Folder : %s", displayable_name);
892 ptree = proto_item_add_subtree(pitem, ett_btavrcp_folder);
894 proto_tree_add_item(ptree, hf_btavrcp_item_type, tvb, offset, 1, ENC_BIG_ENDIAN);
895 offset += 1;
896 proto_tree_add_item(ptree, hf_btavrcp_item_length, tvb, offset, 2, ENC_BIG_ENDIAN);
897 offset += 2;
899 proto_tree_add_item(ptree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
900 offset += 8;
902 proto_tree_add_item(ptree, hf_btavrcp_folder_type, tvb, offset, 1, ENC_BIG_ENDIAN);
903 offset += 1;
905 proto_tree_add_item(ptree, hf_btavrcp_folder_playable, tvb, offset, 1, ENC_BIG_ENDIAN);
906 offset += 1;
908 proto_tree_add_item(ptree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
909 offset += 2;
911 proto_tree_add_item(ptree, hf_btavrcp_displayable_name_length, tvb, offset, 2, ENC_BIG_ENDIAN);
912 displayable_name_length = tvb_get_ntohs(tvb, offset);
913 offset += 2;
915 proto_tree_add_item(ptree, hf_btavrcp_displayable_name, tvb, offset, displayable_name_length, ENC_UTF_8 | ENC_NA);
916 offset += displayable_name_length;
918 return offset;
922 static gint
923 dissect_passthrough(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
924 gint offset, gboolean is_command, guint32 *op)
926 guint operation;
927 guint state;
929 proto_tree_add_item(tree, hf_btavrcp_passthrough_state, tvb, offset, 1, ENC_BIG_ENDIAN);
930 proto_tree_add_item(tree, hf_btavrcp_passthrough_operation, tvb, offset, 1, ENC_BIG_ENDIAN);
931 *op = tvb_get_guint8(tvb, offset);
932 operation = tvb_get_guint8(tvb, offset) & 0x7F;
933 state = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
934 offset += 1;
935 proto_tree_add_item(tree, hf_btavrcp_passthrough_data_length, tvb, offset, 1, ENC_BIG_ENDIAN);
936 offset += 1;
938 if (!is_command) {
939 if (operation == 0x7E) {
940 proto_tree_add_item(tree, hf_btavrcp_passthrough_company_id, tvb, offset, 3, ENC_BIG_ENDIAN);
941 offset += 3;
942 proto_tree_add_item(tree, hf_btavrcp_passthrough_vendor_unique_id, tvb, offset, 2, ENC_BIG_ENDIAN);
943 offset += 2;
947 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (%s)",
948 val_to_str_const(operation, passthrough_operation_vals, "Unknown opcode"),
949 val_to_str_const(state, passthrough_state_vals, "unknown"));
950 return offset;
954 static gint
955 dissect_unit(tvbuff_t *tvb, proto_tree *tree, gint offset, gboolean is_command)
957 if (is_command) {
958 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, 5, ENC_NA);
959 offset += 5;
960 } else {
961 proto_tree_add_item(tree, hf_btavrcp_unit_unknown, tvb, offset, 1, ENC_BIG_ENDIAN);
962 offset += 1;
963 proto_tree_add_item(tree, hf_btavrcp_unit_type, tvb, offset, 1, ENC_BIG_ENDIAN);
964 proto_tree_add_item(tree, hf_btavrcp_unit_id, tvb, offset, 1, ENC_BIG_ENDIAN);
965 offset += 1;
966 proto_tree_add_item(tree, hf_btavrcp_passthrough_company_id, tvb, offset, 3, ENC_BIG_ENDIAN);
967 offset += 3;
970 return offset;
974 static gint
975 dissect_subunit(tvbuff_t *tvb, proto_tree *tree, gint offset, gboolean is_command)
977 proto_tree_add_item(tree, hf_btavrcp_subunit_page, tvb, offset, 1, ENC_BIG_ENDIAN);
978 proto_tree_add_item(tree, hf_btavrcp_subunit_extention_code, tvb, offset, 1, ENC_BIG_ENDIAN);
979 offset += 1;
981 if (!is_command) {
982 proto_tree_add_item(tree, hf_btavrcp_subunit_type, tvb, offset, 1, ENC_BIG_ENDIAN);
983 proto_tree_add_item(tree, hf_btavrcp_subunit_id, tvb, offset, 1, ENC_BIG_ENDIAN);
984 offset += 1;
985 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, 3, ENC_NA);
986 offset += 3;
987 } else {
988 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, 4, ENC_NA);
989 offset += 4;
992 return offset;
996 static gint
997 dissect_vendor_dependant(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
998 gint offset, guint ctype, guint32 *op, guint32 *op_arg,
999 gboolean is_command, btavctp_data_t *avctp_data)
1001 proto_item *pitem;
1002 guint pdu_id;
1003 guint company_id;
1004 guint event_id;
1005 guint packet_type;
1006 guint parameter_length;
1007 guint length;
1008 wmem_tree_key_t key[7];
1009 guint32 k_interface_id;
1010 guint32 k_adapter_id;
1011 guint32 k_chandle;
1012 guint32 k_psm;
1013 guint32 k_op;
1014 guint32 k_frame_number;
1015 guint32 interface_id;
1016 guint32 adapter_id;
1017 guint32 chandle;
1018 guint32 psm;
1019 guint volume;
1020 guint volume_percent;
1021 fragment_t *fragment;
1022 data_fragment_t *data_fragment;
1024 *op_arg = 0;
1026 interface_id = avctp_data->interface_id;
1027 adapter_id = avctp_data->adapter_id;
1028 chandle = avctp_data->chandle;
1029 psm = avctp_data->psm;
1031 proto_tree_add_item(tree, hf_btavrcp_company_id, tvb, offset, 3, ENC_BIG_ENDIAN);
1032 company_id = tvb_get_ntoh24(tvb, offset);
1033 offset += 3;
1035 if (company_id == OUI_BLUETOOTH) {
1036 proto_tree_add_item(tree, hf_btavrcp_bt_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1037 } else {
1039 if (tvb_length_remaining(tvb, offset) == 0) {
1040 col_append_str(pinfo->cinfo, COL_INFO, " - No PDU ID");
1041 return offset;
1044 proto_tree_add_item(tree, hf_btavrcp_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1046 pdu_id = tvb_get_guint8(tvb, offset);
1047 *op = pdu_id | (company_id << 8);
1048 offset += 1;
1050 if (company_id != OUI_BLUETOOTH) {
1051 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1052 val_to_str_const(pdu_id, NULL, "Unknown PDU ID"));
1055 proto_tree_add_item(tree, hf_btavrcp_rfa, tvb, offset, 1, ENC_BIG_ENDIAN);
1056 proto_tree_add_item(tree, hf_btavrcp_packet_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1057 packet_type = tvb_get_guint8(tvb, offset) & 0x03;
1058 offset += 1;
1060 proto_tree_add_item(tree, hf_btavrcp_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1061 parameter_length = tvb_get_ntohs(tvb, offset);
1062 offset += 2;
1064 if (company_id != OUI_BLUETOOTH)
1065 return offset;
1067 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1068 val_to_str_const(pdu_id, pdu_id_vals, "Unknown PDU ID"));
1070 if (parameter_length == 0) return offset;
1072 length = tvb_ensure_length_remaining(tvb, offset);
1073 if (packet_type == PACKET_TYPE_START) {
1074 if (pinfo->fd->flags.visited == 0) {
1075 k_interface_id = interface_id;
1076 k_adapter_id = adapter_id;
1077 k_chandle = chandle;
1078 k_psm = psm;
1079 k_op = pdu_id | (company_id << 8);
1080 k_frame_number = pinfo->fd->num;
1082 fragment = wmem_new(wmem_file_scope(), fragment_t);
1083 fragment->start_frame_number = pinfo->fd->num;
1084 fragment->end_frame_number = 0;
1085 fragment->state = 0;
1087 fragment->count = 1;
1088 fragment->fragments = wmem_tree_new(wmem_file_scope());
1090 data_fragment = wmem_new(wmem_file_scope(), data_fragment_t);
1091 data_fragment->length = length;
1092 data_fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), data_fragment->length);
1093 tvb_memcpy(tvb, data_fragment->data, offset, data_fragment->length);
1095 wmem_tree_insert32(fragment->fragments, fragment->count, data_fragment);
1097 key[0].length = 1;
1098 key[0].key = &k_interface_id;
1099 key[1].length = 1;
1100 key[1].key = &k_adapter_id;
1101 key[2].length = 1;
1102 key[2].key = &k_chandle;
1103 key[3].length = 1;
1104 key[3].key = &k_psm;
1105 key[4].length = 1;
1106 key[4].key = &k_op;
1107 key[5].length = 1;
1108 key[5].key = &k_frame_number;
1109 key[6].length = 0;
1110 key[6].key = NULL;
1112 fragment->interface_id = interface_id;
1113 fragment->adapter_id = adapter_id;
1114 fragment->chandle = chandle;
1115 fragment->psm = psm;
1116 fragment->op = pdu_id | (company_id << 8);
1118 wmem_tree_insert32_array(reassembling, key, fragment);
1121 col_append_str(pinfo->cinfo, COL_INFO, " [start]");
1122 return offset;
1123 } else if (packet_type == PACKET_TYPE_CONTINUE) {
1124 if (pinfo->fd->flags.visited == 0) {
1125 k_interface_id = interface_id;
1126 k_adapter_id = adapter_id;
1127 k_chandle = chandle;
1128 k_psm = psm;
1129 k_op = pdu_id | (company_id << 8);
1130 k_frame_number = pinfo->fd->num;
1132 key[0].length = 1;
1133 key[0].key = &k_interface_id;
1134 key[1].length = 1;
1135 key[1].key = &k_adapter_id;
1136 key[2].length = 1;
1137 key[2].key = &k_chandle;
1138 key[3].length = 1;
1139 key[3].key = &k_psm;
1140 key[4].length = 1;
1141 key[4].key = &k_op;
1142 key[5].length = 1;
1143 key[5].key = &k_frame_number;
1144 key[6].length = 0;
1145 key[6].key = NULL;
1147 fragment = (fragment_t *)wmem_tree_lookup32_array_le(reassembling, key);
1148 if (fragment && fragment->interface_id == interface_id &&
1149 fragment->adapter_id == adapter_id &&
1150 fragment->chandle == chandle &&
1151 fragment->psm == psm &&
1152 fragment->op == (pdu_id | (company_id << 8)) &&
1153 fragment->state == 1) {
1154 fragment->count += 1;
1155 fragment->state = 0;
1157 data_fragment = wmem_new(wmem_file_scope(), data_fragment_t);
1158 data_fragment->length = length;
1159 data_fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), data_fragment->length);
1160 tvb_memcpy(tvb, data_fragment->data, offset, data_fragment->length);
1161 wmem_tree_insert32(fragment->fragments, fragment->count, data_fragment);
1165 col_append_str(pinfo->cinfo, COL_INFO, " [continue]");
1166 return offset;
1167 } else if (packet_type == PACKET_TYPE_END) {
1168 guint i_frame;
1169 tvbuff_t *next_tvb;
1171 col_append_str(pinfo->cinfo, COL_INFO, " [end]");
1173 k_interface_id = interface_id;
1174 k_adapter_id = adapter_id;
1175 k_chandle = chandle;
1176 k_psm = psm;
1177 k_op = pdu_id | (company_id << 8);
1178 k_frame_number = pinfo->fd->num;
1180 key[0].length = 1;
1181 key[0].key = &k_interface_id;
1182 key[1].length = 1;
1183 key[1].key = &k_adapter_id;
1184 key[2].length = 1;
1185 key[2].key = &k_chandle;
1186 key[3].length = 1;
1187 key[3].key = &k_psm;
1188 key[4].length = 1;
1189 key[4].key = &k_op;
1190 key[5].length = 1;
1191 key[5].key = &k_frame_number;
1192 key[6].length = 0;
1193 key[6].key = NULL;
1195 fragment = (fragment_t *)wmem_tree_lookup32_array_le(reassembling, key);
1196 if (fragment && fragment->interface_id == interface_id &&
1197 fragment->adapter_id == adapter_id &&
1198 fragment->chandle == chandle &&
1199 fragment->psm == psm &&
1200 fragment->op == (pdu_id | (company_id << 8))) {
1203 if (fragment->state == 1 && pinfo->fd->flags.visited == 0) {
1204 fragment->end_frame_number = pinfo->fd->num;
1205 fragment->count += 1;
1206 fragment->state = 2;
1208 data_fragment = wmem_new(wmem_file_scope(), data_fragment_t);
1209 data_fragment->length = length;
1210 data_fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), data_fragment->length);
1211 tvb_memcpy(tvb, data_fragment->data, offset, data_fragment->length);
1212 wmem_tree_insert32(fragment->fragments, fragment->count, data_fragment);
1214 /* reassembling*/
1215 length = 0;
1216 if (fragment->state == 2) {
1217 guint i_length = 0;
1218 guint8 *reassembled;
1220 for (i_frame = 1; i_frame <= fragment->count; ++i_frame) {
1221 data_fragment = (data_fragment_t *)wmem_tree_lookup32_le(fragment->fragments, i_frame);
1222 length += data_fragment->length;
1225 reassembled = (guint8 *) wmem_alloc(wmem_file_scope(), length);
1227 for (i_frame = 1; i_frame <= fragment->count; ++i_frame) {
1228 data_fragment = (data_fragment_t *)wmem_tree_lookup32_le(fragment->fragments, i_frame);
1229 memcpy(reassembled + i_length,
1230 data_fragment->data,
1231 data_fragment->length);
1232 i_length += data_fragment->length;
1235 next_tvb = tvb_new_child_real_data(tvb, reassembled, length, length);
1236 add_new_data_source(pinfo, next_tvb, "Reassembled AVRCP");
1238 tvb = next_tvb;
1239 offset = 0;
1241 pitem = proto_tree_add_item(tree, hf_btavrcp_reassembled, tvb, offset, 0, ENC_NA);
1242 PROTO_ITEM_SET_GENERATED(pitem);
1247 if (ctype == 0x0a) { /* REJECT */
1248 guint status;
1249 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1250 status = tvb_get_guint8(tvb, offset);
1251 offset += 1;
1253 col_append_fstr(pinfo->cinfo, COL_INFO, " - Status: %s",
1254 val_to_str_const(status, status_vals, "Unknown status"));
1255 } else switch(pdu_id) {
1256 case PDU_GET_CAPABILITIES:
1257 if (is_command) {
1258 guint capability;
1260 proto_tree_add_item(tree, hf_btavrcp_capability, tvb, offset, 1, ENC_BIG_ENDIAN);
1261 capability = tvb_get_guint8(tvb, offset);
1262 *op_arg = capability;
1263 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s)",
1264 val_to_str_const(capability, capability_vals, "unknown"));
1265 offset += 1;
1266 } else {
1267 guint capability;
1268 guint capability_count;
1269 guint i_capability;
1271 proto_tree_add_item(tree, hf_btavrcp_capability, tvb, offset, 1, ENC_BIG_ENDIAN);
1272 capability = tvb_get_guint8(tvb, offset);
1273 *op_arg = capability;
1274 offset += 1;
1275 proto_tree_add_item(tree, hf_btavrcp_capability_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1276 capability_count = tvb_get_guint8(tvb, offset);
1277 offset += 1;
1279 for (i_capability = 0; i_capability < capability_count; ++i_capability) {
1280 if (capability == 0x02) {
1281 proto_tree_add_item(tree, hf_btavrcp_company_id, tvb, offset, 3, ENC_BIG_ENDIAN);
1282 offset += 3;
1283 } else if (capability == 0x03) {
1284 proto_tree_add_item(tree, hf_btavrcp_event_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1285 offset += 1;
1289 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) - Count: %u",
1290 val_to_str_const(capability, capability_vals, "unknown"), capability_count);
1292 break;
1293 case PDU_LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES:
1294 if (is_command) {
1295 /* non */
1296 } else {
1297 guint number_of_attributes;
1298 guint i_attribute;
1300 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1301 number_of_attributes = tvb_get_guint8(tvb, offset);
1302 offset += 1;
1304 for (i_attribute = 0; i_attribute < number_of_attributes; ++i_attribute) {
1305 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1306 offset += 1;
1309 break;
1310 case PDU_LIST_PLAYER_APPLICATION_SETTING_VALUE:
1311 if (is_command) {
1312 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1313 offset += 1;
1314 } else {
1315 guint number_of_values;
1316 guint i_value;
1318 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1319 number_of_values = tvb_get_guint8(tvb, offset);
1320 offset += 1;
1322 for (i_value = 0; i_value < number_of_values; ++i_value) {
1323 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1324 offset += 1;
1327 break;
1328 case PDU_GET_CURRENT_PLAYER_APPLICATION_SETTING_VALUE:
1329 if (is_command) {
1330 guint number_of_attributes;
1331 guint i_attribute;
1333 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1334 number_of_attributes = tvb_get_guint8(tvb, offset);
1335 offset += 1;
1337 for (i_attribute = 0; i_attribute < number_of_attributes; ++i_attribute) {
1338 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1339 offset += 1;
1341 } else {
1342 guint number_of_settings;
1343 guint i_setting;
1345 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1346 number_of_settings = tvb_get_guint8(tvb, offset);
1347 offset += 1;
1349 for (i_setting = 0; i_setting < number_of_settings; ++i_setting) {
1350 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1351 offset += 1;
1352 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1353 offset += 1;
1356 break;
1357 case PDU_SET_PLAYER_APPLICATION_SETTING_VALUE:
1358 if (is_command) {
1359 guint number_of_settings;
1360 guint i_setting;
1362 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1363 number_of_settings = tvb_get_guint8(tvb, offset);
1364 offset += 1;
1366 for (i_setting = 0; i_setting < number_of_settings; ++i_setting) {
1367 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1368 offset += 1;
1369 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1370 offset += 1;
1372 } else {
1373 /* non */
1375 break;
1376 case PDU_GET_PLAYER_APPLICATION_SETTING_ATTRIBUTE_TEXT:
1377 if (is_command) {
1378 guint number_of_attributes;
1379 guint i_attribute;
1381 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1382 number_of_attributes = tvb_get_guint8(tvb, offset);
1383 offset += 1;
1385 for (i_attribute = 0; i_attribute < number_of_attributes; ++i_attribute) {
1386 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1387 offset += 1;
1389 } else {
1390 guint number_of_attributes;
1391 guint i_attribute;
1392 guint attribute_name_length;
1394 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1395 number_of_attributes = tvb_get_guint8(tvb, offset);
1396 offset += 1;
1398 for (i_attribute = 0; i_attribute < number_of_attributes; ++i_attribute) {
1399 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1400 offset += 1;
1402 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 1, ENC_BIG_ENDIAN);
1403 offset += 2;
1405 proto_tree_add_item(tree, hf_btavrcp_attribute_name_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1406 attribute_name_length = tvb_get_ntohs(tvb, offset);
1407 offset += 1;
1409 proto_tree_add_item(tree, hf_btavrcp_attribute_name, tvb, offset, attribute_name_length, ENC_UTF_8 | ENC_NA);
1410 offset += attribute_name_length;
1413 break;
1414 case PDU_GET_PLAYER_APPLICATION_SETTING_VALUE_TEXT:
1415 if (is_command) {
1416 guint number_of_values;
1417 guint i_value;
1419 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1420 offset += 1;
1421 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1422 number_of_values = tvb_get_guint8(tvb, offset);
1423 offset += 1;
1425 for (i_value = 0; i_value < number_of_values; ++i_value) {
1426 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1427 offset += 1;
1429 } else {
1430 guint number_of_values;
1431 guint i_attribute;
1432 guint attribute_value_length;
1434 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1435 number_of_values = tvb_get_guint8(tvb, offset);
1436 offset += 1;
1438 for (i_attribute = 0; i_attribute < number_of_values; ++i_attribute) {
1439 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1440 offset += 1;
1442 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 1, ENC_BIG_ENDIAN);
1443 offset += 2;
1445 proto_tree_add_item(tree, hf_btavrcp_attribute_value_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1446 attribute_value_length = tvb_get_ntohs(tvb, offset);
1447 offset += 1;
1449 proto_tree_add_item(tree, hf_btavrcp_attribute_value, tvb, offset, attribute_value_length, ENC_UTF_8 | ENC_NA);
1450 offset += attribute_value_length;
1453 break;
1454 case PDU_INFORM_DISPLAYABLE_CHARACTER_SET:
1455 if (is_command) {
1456 guint number_of_character_set;
1457 guint i_character_set;
1459 proto_tree_add_item(tree, hf_btavrcp_number_of_character_set, tvb, offset, 1, ENC_BIG_ENDIAN);
1460 number_of_character_set = tvb_get_guint8(tvb, offset);
1461 offset += 1;
1463 for (i_character_set = 0; i_character_set < number_of_character_set; ++i_character_set) {
1464 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
1465 offset += 2;
1467 } else {
1468 /* non */
1470 break;
1471 case PDU_INFORM_BATTERY_STATUS_OF_CT:
1472 if (is_command) {
1473 guint battery_status;
1475 proto_tree_add_item(tree, hf_btavrcp_battery_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1476 battery_status = tvb_get_guint8(tvb, offset);
1477 offset += 1;
1478 col_append_fstr(pinfo->cinfo, COL_INFO, " - Battery: %s", val_to_str_const(battery_status, battery_status_vals, "unknown"));
1479 } else {
1480 /* non */
1482 break;
1483 case PDU_GET_ELEMENT_ATTRIBUTES:
1484 if (is_command) {
1485 guint number_of_attributes;
1486 guint64 identifier;
1488 proto_tree_add_item(tree, hf_btavrcp_identifier, tvb, offset, 8, ENC_BIG_ENDIAN);
1489 identifier = tvb_get_ntoh64(tvb, offset);
1490 offset += 8;
1492 col_append_fstr(pinfo->cinfo, COL_INFO, " - 0x%08X%08X", (guint) (identifier >> 32), (guint) (identifier & 0xFFFFFFFF));
1493 if (identifier == 0x00) col_append_str(pinfo->cinfo, COL_INFO, " (PLAYING)");
1495 pitem = proto_tree_add_item(tree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
1496 number_of_attributes = tvb_get_guint8(tvb, offset);
1497 if (number_of_attributes == 0) proto_item_append_text(pitem, " (All Supported Attributes)");
1498 offset += 1;
1499 offset = dissect_attribute_id_list(tvb, tree, offset, number_of_attributes);
1500 } else {
1501 guint number_of_attributes;
1503 proto_tree_add_item(tree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
1504 number_of_attributes = tvb_get_guint8(tvb, offset);
1505 offset += 1;
1506 offset = dissect_attribute_entries(tvb, pinfo, tree, offset, number_of_attributes);
1508 break;
1509 case PDU_GET_PLAY_STATUS:
1510 if (is_command) {
1511 /* non */
1512 } else {
1513 guint song_length;
1514 guint song_position;
1515 guint play_status;
1517 proto_tree_add_item(tree, hf_btavrcp_song_length, tvb, offset, 4, ENC_BIG_ENDIAN);
1518 song_length = tvb_get_ntohl(tvb, offset);
1519 offset += 4;
1520 proto_tree_add_item(tree, hf_btavrcp_song_position, tvb, offset, 4, ENC_BIG_ENDIAN);
1521 song_position = tvb_get_ntohl(tvb, offset);
1522 offset += 4;
1523 proto_tree_add_item(tree, hf_btavrcp_play_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1524 play_status = tvb_get_guint8(tvb, offset);
1525 offset += 1;
1527 col_append_fstr(pinfo->cinfo, COL_INFO, " PlayStatus: %s, SongPosition: %ums, SongLength: %ums",
1528 val_to_str_const(play_status, play_status_vals, "unknown"), song_length, song_position);
1530 break;
1531 case PDU_REGISTER_NOTIFICATION:
1532 event_id = tvb_get_guint8(tvb, offset);
1533 *op_arg = event_id;
1534 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1535 val_to_str_const(event_id, notification_vals, "Unknown Event ID"));
1537 if (is_command) {
1538 proto_tree_add_item(tree, hf_btavrcp_event_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1539 offset += 1;
1540 proto_tree_add_item(tree, hf_btavrcp_notification_interval, tvb, offset, 4, ENC_BIG_ENDIAN);
1541 offset += 4;
1542 } else {
1543 guint number_of_settings;
1544 guint i_setting;
1545 guint64 identifier;
1546 guint play_status;
1547 guint song_position;
1548 guint battery_status;
1549 guint uid_counter;
1550 guint player_id;
1551 guint system_status;
1553 proto_tree_add_item(tree, hf_btavrcp_event_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1554 offset += 1;
1556 if (ctype == 0x0D || ctype == 0x0F) switch(event_id) {
1557 case EVENT_PLAYBACK_STATUS_CHANGED:
1558 proto_tree_add_item(tree, hf_btavrcp_play_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1559 play_status = tvb_get_guint8(tvb, offset);
1560 offset += 1;
1561 col_append_fstr(pinfo->cinfo, COL_INFO, " - PlayStatus: %s", val_to_str_const(play_status, play_status_vals, "unknown"));
1562 break;
1563 case EVENT_TRACK_CHANGED:
1564 pitem = proto_tree_add_item(tree, hf_btavrcp_identifier, tvb, offset, 8, ENC_BIG_ENDIAN);
1565 identifier = tvb_get_ntoh64(tvb, offset);
1566 offset += 8;
1568 col_append_fstr(pinfo->cinfo, COL_INFO, " - 0x%08X%08X", (guint) (identifier >> 32), (guint) (identifier & 0xFFFFFFFF));
1569 if (identifier == G_GINT64_CONSTANT(0x0000000000000000)) {
1570 col_append_str(pinfo->cinfo, COL_INFO, " (SELECTED)");
1571 proto_item_append_text(pitem, " (SELECTED)");
1572 } else if (identifier == G_GINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
1573 col_append_str(pinfo->cinfo, COL_INFO, " (NOT SELECTED)");
1574 proto_item_append_text(pitem, " (NOT SELECTED)");
1577 break;
1578 case EVENT_TRACK_REACHED_END:
1579 /* non */
1580 break;
1581 case EVENT_TRACK_REACHED_START:
1582 /* non */
1583 break;
1584 case EVENT_PLAYBACK_POSITION_CHANGED:
1585 pitem = proto_tree_add_item(tree, hf_btavrcp_song_position, tvb, offset, 4, ENC_BIG_ENDIAN);
1586 song_position = tvb_get_ntohl(tvb, offset);
1587 offset += 4;
1588 col_append_fstr(pinfo->cinfo, COL_INFO, " - SongPosition: %ums", song_position);
1589 if (song_position == 0xFFFFFFFF) {
1590 proto_item_append_text(pitem, " (NOT SELECTED)");
1591 col_append_str(pinfo->cinfo, COL_INFO, " (NOT SELECTED)");
1593 break;
1594 case EVENT_BATTERY_STATUS_CHANGED:
1595 proto_tree_add_item(tree, hf_btavrcp_battery_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1596 battery_status = tvb_get_guint8(tvb, offset);
1597 offset += 1;
1598 col_append_fstr(pinfo->cinfo, COL_INFO, " - Battery: %s", val_to_str_const(battery_status, battery_status_vals, "unknown"));
1599 break;
1600 case EVENT_SYSTEM_STATUS_CHANGED:
1601 proto_tree_add_item(tree, hf_btavrcp_system_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1602 system_status = tvb_get_guint8(tvb, offset);
1603 offset += 1;
1604 col_append_fstr(pinfo->cinfo, COL_INFO, " - SystemStatus: %s", val_to_str_const(system_status, system_status_vals, "unknown"));
1605 break;
1606 case EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
1607 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1608 number_of_settings = tvb_get_guint8(tvb, offset);
1609 offset += 1;
1611 for (i_setting = 0; i_setting < number_of_settings; ++i_setting) {
1612 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1613 offset += 1;
1614 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1615 offset += 1;
1617 break;
1618 case EVENT_NOWPLAYING_CONTENT_CHANGED:
1619 /* non */
1620 break;
1621 case EVENT_AVAILABLE_PLAYERS_CHANGED:
1622 /* non */
1623 break;
1624 case EVENT_ADDRESSEDPLAYER_CHANGED:
1625 proto_tree_add_item(tree, hf_btavrcp_player_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1626 player_id = tvb_get_ntohs(tvb, offset);
1627 offset += 2;
1628 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1629 uid_counter = tvb_get_ntohs(tvb, offset);
1630 offset += 2;
1631 col_append_fstr(pinfo->cinfo, COL_INFO, " - PlayerID: %u, UidCounter: 0x%04x", player_id, uid_counter);
1632 break;
1633 case EVENT_UIDS_CHANGED:
1634 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1635 uid_counter = tvb_get_ntohs(tvb, offset);
1636 offset += 2;
1637 col_append_fstr(pinfo->cinfo, COL_INFO, " - UidCounter: 0x%04x", uid_counter);
1638 break;
1639 case EVENT_VOLUME_CHANGED:
1640 proto_tree_add_item(tree, hf_btavrcp_absolute_volume_rfa, tvb, offset, 1, ENC_BIG_ENDIAN);
1641 pitem = proto_tree_add_item(tree, hf_btavrcp_absolute_volume, tvb, offset, 1, ENC_BIG_ENDIAN);
1643 volume = tvb_get_guint8(tvb, offset) & 0x7F;
1644 volume_percent = (guint) ((double) volume * 100 / (double) 0x7F);
1645 offset += 1;
1647 proto_item_append_text(pitem, " (%u%%)", volume_percent);
1648 col_append_fstr(pinfo->cinfo, COL_INFO, " - Volume: %u%%", volume_percent);
1649 break;
1650 default:
1651 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, -1, ENC_NA);
1652 offset = tvb_reported_length(tvb);
1653 break;
1657 break;
1658 case PDU_REQUEST_CONTINUING_RESPONSE:
1659 if (is_command) {
1660 guint continuing_op;
1662 proto_tree_add_item(tree, hf_btavrcp_bt_continuing_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1663 continuing_op = tvb_get_guint8(tvb, offset) | (company_id << 8);
1664 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1665 val_to_str_const(tvb_get_guint8(tvb, offset), pdu_id_vals, "Unknown opcode"));
1666 offset += 1;
1668 if (pinfo->fd->flags.visited == 0) {
1669 k_interface_id = interface_id;
1670 k_adapter_id = adapter_id;
1671 k_chandle = chandle;
1672 k_psm = psm;
1673 k_op = continuing_op;
1674 k_frame_number = pinfo->fd->num;
1676 key[0].length = 1;
1677 key[0].key = &k_interface_id;
1678 key[1].length = 1;
1679 key[1].key = &k_adapter_id;
1680 key[2].length = 1;
1681 key[2].key = &k_chandle;
1682 key[3].length = 1;
1683 key[3].key = &k_psm;
1684 key[4].length = 1;
1685 key[4].key = &k_op;
1686 key[5].length = 1;
1687 key[5].key = &k_frame_number;
1688 key[6].length = 0;
1689 key[6].key = NULL;
1691 fragment = (fragment_t *)wmem_tree_lookup32_array_le(reassembling, key);
1692 if (fragment && fragment->interface_id == interface_id &&
1693 fragment->adapter_id == adapter_id &&
1694 fragment->chandle == chandle &&
1695 fragment->psm == psm &&
1696 fragment->op == continuing_op &&
1697 fragment->state == 0) {
1698 fragment->state = 1;
1702 *op = continuing_op;
1703 } else {
1704 /* non */
1706 break;
1707 case PDU_ABORT_CONTINUING_RESPONSE:
1708 if (is_command) {
1709 guint continuing_op;
1711 proto_tree_add_item(tree, hf_btavrcp_bt_continuing_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1712 continuing_op = tvb_get_guint8(tvb, offset) | (company_id << 8);
1713 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1714 val_to_str_const(tvb_get_guint8(tvb, offset), pdu_id_vals, "Unknown opcode"));
1715 offset += 1;
1717 if (pinfo->fd->flags.visited == 0) {
1718 k_interface_id = interface_id;
1719 k_adapter_id = adapter_id;
1720 k_chandle = chandle;
1721 k_psm = psm;
1722 k_op = continuing_op;
1723 k_frame_number = pinfo->fd->num;
1725 key[0].length = 1;
1726 key[0].key = &k_interface_id;
1727 key[1].length = 1;
1728 key[1].key = &k_adapter_id;
1729 key[2].length = 1;
1730 key[2].key = &k_chandle;
1731 key[3].length = 1;
1732 key[3].key = &k_psm;
1733 key[4].length = 1;
1734 key[4].key = &k_op;
1735 key[5].length = 1;
1736 key[5].key = &k_frame_number;
1737 key[6].length = 0;
1738 key[6].key = NULL;
1740 fragment = (fragment_t *)wmem_tree_lookup32_array_le(reassembling, key);
1741 if (fragment && fragment->interface_id == interface_id &&
1742 fragment->adapter_id == adapter_id &&
1743 fragment->chandle == chandle &&
1744 fragment->psm == psm &&
1745 fragment->op == continuing_op &&
1746 fragment->state == 0) {
1747 fragment->state = 3;
1750 } else {
1751 /* non */
1753 break;
1754 case PDU_SET_ABSOLUTE_VOLUME:
1755 proto_tree_add_item(tree, hf_btavrcp_absolute_volume_rfa, tvb, offset, 1, ENC_BIG_ENDIAN);
1756 pitem = proto_tree_add_item(tree, hf_btavrcp_absolute_volume, tvb, offset, 1, ENC_BIG_ENDIAN);
1757 volume = tvb_get_guint8(tvb, offset) & 0x7F;
1758 volume_percent = (guint) ((double) volume * 100 / (double) 0x7F);
1759 offset += 1;
1761 proto_item_append_text(pitem, " (%u%%)", volume_percent);
1762 col_append_fstr(pinfo->cinfo, COL_INFO, " - Volume: %u%%", volume_percent);
1763 break;
1764 case PDU_SET_ADDRESSED_PLAYER:
1765 if (is_command) {
1766 guint player_id;
1768 proto_tree_add_item(tree, hf_btavrcp_player_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1769 player_id = tvb_get_ntohs(tvb, offset);
1770 offset += 2;
1772 col_append_fstr(pinfo->cinfo, COL_INFO, " - Player ID: %u", player_id);
1773 } else {
1774 guint status;
1776 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1777 status = tvb_get_guint8(tvb, offset);
1778 offset += 1;
1780 col_append_fstr(pinfo->cinfo, COL_INFO, " - Status: %s",
1781 val_to_str_const(status, status_vals, "Unknown status"));
1783 break;
1784 case PDU_PLAY_ITEM:
1785 if (is_command) {
1786 guint scope;
1787 guint64 uid;
1788 guint uid_counter;
1790 proto_tree_add_item(tree, hf_btavrcp_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
1791 scope = tvb_get_guint8(tvb, offset);
1792 offset += 1;
1793 proto_tree_add_item(tree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
1794 uid = tvb_get_ntoh64(tvb, offset);
1795 offset += 8;
1796 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1797 uid_counter = tvb_get_ntohs(tvb, offset);
1798 offset += 2;
1800 col_append_fstr(pinfo->cinfo, COL_INFO, " - Scope: %s, Uid: 0x%016" G_GINT64_MODIFIER "x, UidCounter: 0x%04x",
1801 val_to_str_const(scope, scope_vals, "unknown"), uid, uid_counter);
1802 } else {
1803 guint status;
1805 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1806 status = tvb_get_guint8(tvb, offset);
1807 offset += 1;
1808 col_append_fstr(pinfo->cinfo, COL_INFO, " - Status: %s",
1809 val_to_str_const(status, status_vals, "Unknown status"));
1811 break;
1812 case PDU_ADD_TO_NOW_PLAYING:
1813 if (is_command) {
1814 guint scope;
1815 guint64 uid;
1816 guint uid_counter;
1818 proto_tree_add_item(tree, hf_btavrcp_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
1819 scope = tvb_get_guint8(tvb, offset);
1820 offset += 1;
1821 proto_tree_add_item(tree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
1822 uid = tvb_get_ntoh64(tvb, offset);
1823 offset += 8;
1824 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1825 uid_counter = tvb_get_ntohs(tvb, offset);
1826 offset += 2;
1828 col_append_fstr(pinfo->cinfo, COL_INFO, " - Scope: %s, Uid: 0x%016" G_GINT64_MODIFIER "x, UidCounter: 0x%04x",
1829 val_to_str_const(scope, scope_vals, "unknown"), uid, uid_counter);
1830 } else {
1831 guint status;
1833 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1834 status = tvb_get_guint8(tvb, offset);
1835 offset += 1;
1836 col_append_fstr(pinfo->cinfo, COL_INFO, " - Status: %s",
1837 val_to_str_const(status, status_vals, "Unknown status"));
1839 break;
1842 return offset;
1846 static gint
1847 dissect_browsing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1848 gint offset, gboolean is_command)
1850 guint pdu_id;
1851 guint status = 0x00;
1853 proto_tree_add_item(tree, hf_btavrcp_browsing_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1854 pdu_id = tvb_get_guint8(tvb, offset);
1855 offset += 1;
1857 proto_tree_add_item(tree, hf_btavrcp_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1858 offset += 2;
1860 if (is_command) {
1861 col_append_str(pinfo->cinfo, COL_INFO, ": Command");
1862 } else {
1863 /* common code "status" in response */
1864 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1865 status = tvb_get_guint8(tvb, offset);
1866 offset += 1;
1868 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
1869 val_to_str_const(status, status_vals, "Unknown status"));
1872 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1873 val_to_str_const(pdu_id, browsing_pdu_id_vals, "Unknown opcode"));
1875 if (is_command || status == STATUS_OK) switch(pdu_id) {
1876 case PDU_SET_BROWSED_PLAYER:
1877 if (is_command) {
1878 guint player_id;
1880 proto_tree_add_item(tree, hf_btavrcp_player_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1881 player_id = tvb_get_ntohs(tvb, offset);
1882 offset += 2;
1884 col_append_fstr(pinfo->cinfo, COL_INFO, " - Player ID: %u", player_id);
1885 } else {
1886 guint i_folder;
1887 guint folder_depth;
1888 guint folder_name_length;
1889 proto_item *pitem;
1890 proto_tree *ptree;
1891 guint8 *folder_name;
1893 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1894 offset += 2;
1895 proto_tree_add_item(tree, hf_btavrcp_number_of_items, tvb, offset, 4, ENC_BIG_ENDIAN);
1896 offset += 4;
1897 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
1898 offset += 2;
1899 proto_tree_add_item(tree, hf_btavrcp_folder_depth, tvb, offset, 1, ENC_BIG_ENDIAN);
1900 folder_depth = tvb_get_guint8(tvb, offset);
1901 offset += 1;
1903 pitem = proto_tree_add_none_format(tree, hf_btavrcp_currect_path, tvb, offset, -1, "Current Path: /");
1904 col_append_str(pinfo->cinfo, COL_INFO, "Current Path: /");
1905 ptree = proto_item_add_subtree(pitem, ett_btavrcp_path);
1907 for (i_folder = 0; i_folder < folder_depth; ++i_folder) {
1908 proto_tree_add_item(ptree, hf_btavrcp_folder_name_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1909 folder_name_length = tvb_get_ntohs(tvb, offset);
1910 offset += 2;
1911 proto_tree_add_item(ptree, hf_btavrcp_folder_name, tvb, offset, folder_name_length, ENC_NA);
1912 folder_name = tvb_get_string(NULL, tvb, offset, folder_name_length);
1913 offset += folder_name_length;
1914 proto_item_append_text(pitem, "%s/", folder_name);
1915 col_append_fstr(pinfo->cinfo, COL_INFO, "%s/", folder_name);
1918 break;
1919 case PDU_GET_FOLDER_ITEMS:
1920 if (is_command) {
1921 guint attribute_count;
1922 guint scope;
1923 guint start_item;
1924 guint end_item;
1926 proto_tree_add_item(tree, hf_btavrcp_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
1927 scope = tvb_get_guint8(tvb, offset);
1928 offset += 1;
1929 proto_tree_add_item(tree, hf_btavrcp_start_item, tvb, offset, 4, ENC_BIG_ENDIAN);
1930 start_item = tvb_get_ntohl(tvb, offset);
1931 offset += 4;
1932 proto_tree_add_item(tree, hf_btavrcp_end_item, tvb, offset, 4, ENC_BIG_ENDIAN);
1933 end_item = tvb_get_ntohl(tvb, offset);
1934 offset += 4;
1935 proto_tree_add_item(tree, hf_btavrcp_attribute_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1936 attribute_count = tvb_get_guint8(tvb, offset);
1937 offset += 1;
1938 offset = dissect_attribute_id_list(tvb, tree, offset, attribute_count);
1940 col_append_fstr(pinfo->cinfo, COL_INFO, " - Scope: %s, StartItem: 0x%04x, EndItem: 0x%04x",
1941 val_to_str_const(scope, scope_vals, "unknown"), start_item, end_item);
1942 } else {
1943 guint number_of_items;
1944 guint uid_counter;
1945 guint i_item;
1946 guint item_type;
1947 guint item_length;
1949 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1950 uid_counter = tvb_get_ntohs(tvb, offset);
1951 offset += 2;
1952 proto_tree_add_item(tree, hf_btavrcp_number_of_items16, tvb, offset, 2, ENC_BIG_ENDIAN);
1953 number_of_items = tvb_get_ntohs(tvb, offset);
1954 offset += 2;
1956 col_append_fstr(pinfo->cinfo, COL_INFO, " - UidCounter: 0x%04x, NumberOfItems: %u",
1957 uid_counter, number_of_items);
1959 for (i_item = 0; i_item < number_of_items; ++i_item) {
1960 item_type = tvb_get_guint8(tvb, offset);
1961 item_length = tvb_get_ntohs(tvb, offset + 1);
1963 if (item_type == ITEM_MEDIAPLAYER) {
1964 dissect_item_mediaplayer(tvb, tree, offset);
1965 offset += 1 + 2 + item_length;
1966 } else if (item_type == ITEM_MEDIA_ELEMENT) {
1967 dissect_item_media_element(tvb, pinfo, tree, offset);
1968 offset += 1 + 2 + item_length;
1969 } else if (item_type == ITEM_FOLDER) {
1970 dissect_item_folder(tvb, tree, offset);
1971 offset += 1 + 2 + item_length;
1972 } else {
1973 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, item_length, ENC_NA);
1974 offset += 1 + 2 + item_length;
1978 break;
1979 case PDU_CHANGE_PATH:
1980 if (is_command) {
1981 guint64 uid;
1982 guint uid_counter;
1983 guint direction;
1985 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1986 uid_counter = tvb_get_ntohs(tvb, offset);
1987 offset += 2;
1988 proto_tree_add_item(tree, hf_btavrcp_direction, tvb, offset, 1, ENC_BIG_ENDIAN);
1989 direction = tvb_get_guint8(tvb, offset);
1990 offset += 1;
1991 proto_tree_add_item(tree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
1992 uid = tvb_get_ntoh64(tvb, offset);
1993 offset += 8;
1995 col_append_fstr(pinfo->cinfo, COL_INFO, " - Direction: %s, Uid: 0x%016" G_GINT64_MODIFIER "x, UidCounter: 0x%04x",
1996 val_to_str_const(direction, direction_vals, "unknown"), uid, uid_counter);
1997 } else {
1998 guint number_of_items;
2000 proto_tree_add_item(tree, hf_btavrcp_number_of_items, tvb, offset, 4, ENC_BIG_ENDIAN);
2001 number_of_items = tvb_get_ntohl(tvb, offset);
2002 offset += 4;
2003 col_append_fstr(pinfo->cinfo, COL_INFO, " - NumberOfItems: %u", number_of_items);
2005 break;
2006 case PDU_GET_ITEM_ATTRIBUTES:
2007 if (is_command) {
2008 guint number_of_attributes;
2009 guint64 uid;
2010 guint uid_counter;
2011 guint scope;
2012 proto_item *pitem = NULL;
2014 proto_tree_add_item(tree, hf_btavrcp_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
2015 scope = tvb_get_guint8(tvb, offset);
2016 offset += 1;
2017 proto_tree_add_item(tree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
2018 uid = tvb_get_ntoh64(tvb, offset);
2019 offset += 8;
2020 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
2021 uid_counter = tvb_get_ntohs(tvb, offset);
2022 offset += 2;
2023 pitem = proto_tree_add_item(tree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
2024 number_of_attributes = tvb_get_guint8(tvb, offset);
2026 col_append_fstr(pinfo->cinfo, COL_INFO, " - Scope: %s, Uid: 0x%016" G_GINT64_MODIFIER "x, UidCounter: 0x%04x",
2027 val_to_str_const(scope, scope_vals, "unknown"), uid, uid_counter);
2029 if (number_of_attributes == 0) proto_item_append_text(pitem, " (All Supported Attributes)");
2030 offset += 1;
2031 offset = dissect_attribute_id_list(tvb, tree, offset, number_of_attributes);
2032 } else {
2033 guint number_of_attributes;
2035 proto_tree_add_item(tree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
2036 number_of_attributes = tvb_get_guint8(tvb, offset);
2037 offset += 1;
2038 offset = dissect_attribute_entries(tvb, pinfo, tree, offset, number_of_attributes);
2040 break;
2041 case PDU_SEARCH:
2042 if (is_command) {
2043 guint search_length;
2045 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
2046 offset += 2;
2047 proto_tree_add_item(tree, hf_btavrcp_search_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2048 search_length = tvb_get_ntohs(tvb, offset);
2049 offset += 2;
2050 proto_tree_add_item(tree, hf_btavrcp_search, tvb, offset, search_length, ENC_NA);
2051 offset += search_length;
2052 } else {
2053 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
2054 offset += 2;
2055 proto_tree_add_item(tree, hf_btavrcp_number_of_items, tvb, offset, 4, ENC_BIG_ENDIAN);
2056 offset += 4;
2058 break;
2059 case PDU_GENERAL_REJECT:
2060 /* implemented in common code before switch() */
2061 break;
2065 return offset;
2068 static gint
2069 dissect_btavrcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2071 proto_item *ti;
2072 proto_tree *btavrcp_tree;
2073 proto_item *pitem = NULL;
2074 gint offset = 0;
2075 guint32 opcode;
2076 guint32 op = 0;
2077 guint32 op_arg = 0;
2078 guint ctype;
2079 guint response_time;
2080 guint max_response_time;
2081 guint is_command;
2082 timing_info_t *timing_info;
2083 wmem_tree_key_t key[9];
2084 guint32 k_interface_id;
2085 guint32 k_adapter_id;
2086 guint32 k_chandle;
2087 guint32 k_psm;
2088 guint32 k_opcode;
2089 guint32 k_op;
2090 guint32 k_op_arg;
2091 guint32 k_frame_number;
2092 guint32 interface_id;
2093 guint32 adapter_id;
2094 guint32 chandle;
2095 guint32 psm;
2096 btavctp_data_t *avctp_data;
2098 ti = proto_tree_add_item(tree, proto_btavrcp, tvb, offset, -1, ENC_NA);
2099 btavrcp_tree = proto_item_add_subtree(ti, ett_btavrcp);
2101 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AVRCP");
2103 switch (pinfo->p2p_dir) {
2104 case P2P_DIR_SENT:
2105 col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
2106 break;
2107 case P2P_DIR_RECV:
2108 col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
2109 break;
2110 default:
2111 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
2112 pinfo->p2p_dir);
2113 break;
2116 avctp_data = (btavctp_data_t *) data;
2117 DISSECTOR_ASSERT(avctp_data);
2119 is_command = !avctp_data->cr;
2121 interface_id = avctp_data->interface_id;
2122 adapter_id = avctp_data->adapter_id;
2123 chandle = avctp_data->chandle;
2124 psm = avctp_data->psm;
2126 if (avctp_data->psm == BTL2CAP_PSM_AVCTP_BRWS) {
2127 col_append_str(pinfo->cinfo, COL_INFO, "Browsing");
2128 offset = dissect_browsing(tvb, pinfo, btavrcp_tree, offset, is_command);
2129 } else {
2130 proto_tree_add_item(btavrcp_tree, hf_btavrcp_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2131 proto_tree_add_item(btavrcp_tree, hf_btavrcp_ctype, tvb, offset, 1, ENC_BIG_ENDIAN);
2132 ctype = tvb_get_guint8(tvb, offset) & 0x0F;
2133 offset += 1;
2134 proto_tree_add_item(btavrcp_tree, hf_btavrcp_subunit_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2135 proto_tree_add_item(btavrcp_tree, hf_btavrcp_subunit_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2136 offset += 1;
2137 proto_tree_add_item(btavrcp_tree, hf_btavrcp_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
2138 opcode = tvb_get_guint8(tvb, offset);
2139 offset += 1;
2141 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
2142 val_to_str_const(opcode, opcode_vals, "Unknown opcode"),
2143 val_to_str_const(ctype, ctype_vals, "Unknown ctype"));
2145 switch(opcode) {
2146 case OPCODE_PASSTHROUGH:
2147 offset = dissect_passthrough(tvb, pinfo, btavrcp_tree, offset,
2148 is_command, &op);
2149 break;
2150 case OPCODE_UNIT:
2151 offset = dissect_unit(tvb, btavrcp_tree, offset, is_command);
2152 break;
2153 case OPCODE_SUBUNIT:
2154 offset = dissect_subunit(tvb, btavrcp_tree, offset, is_command);
2155 break;
2156 case OPCODE_VENDOR_DEPENDANT:
2157 offset = dissect_vendor_dependant(tvb, pinfo, btavrcp_tree,
2158 offset, ctype, &op, &op_arg, is_command, avctp_data);
2159 break;
2162 k_interface_id = interface_id;
2163 k_adapter_id = adapter_id;
2164 k_chandle = chandle;
2165 k_psm = psm;
2166 k_opcode = opcode;
2167 k_op = op;
2168 k_op_arg = (ctype == 0x0a) ? G_MAXUINT32 : op_arg;
2169 k_frame_number = pinfo->fd->num;
2171 key[0].length = 1;
2172 key[0].key = &k_interface_id;
2173 key[1].length = 1;
2174 key[1].key = &k_adapter_id;
2175 key[2].length = 1;
2176 key[2].key = &k_chandle;
2177 key[3].length = 1;
2178 key[3].key = &k_psm;
2179 key[4].length = 1;
2180 key[4].key = &k_opcode;
2181 key[5].length = 1;
2182 key[5].key = &k_op;
2183 key[6].length = 1;
2184 key[6].key = &k_op_arg;
2185 key[7].length = 1;
2186 key[7].key = &k_frame_number;
2187 key[8].length = 0;
2188 key[8].key = NULL;
2190 if (pinfo->fd->flags.visited == 0) {
2191 if (is_command) {
2192 if (ctype == 0x00) { /* MTC is for CONTROL */
2193 max_response_time = 200;
2194 } else if (ctype == 0x01 || ctype == 0x03) {
2195 /* MTP is for STATUS, NOTIFY */
2196 max_response_time = 1000;
2197 } else { /* RCP */
2198 max_response_time = 100;
2201 timing_info = wmem_new(wmem_file_scope(), timing_info_t);
2202 timing_info->command_frame_number = pinfo->fd->num;
2203 timing_info->command_timestamp = pinfo->fd->abs_ts;
2204 timing_info->response_frame_number = 0;
2205 timing_info->response_timestamp.secs = 0;
2206 timing_info->response_timestamp.nsecs = 0;
2207 timing_info->max_response_time = max_response_time;
2209 timing_info->interface_id = interface_id;
2210 timing_info->adapter_id = adapter_id;
2211 timing_info->chandle = chandle;
2212 timing_info->psm = psm;
2213 timing_info->opcode = opcode;
2214 timing_info->op = op;
2215 timing_info->op_arg = op_arg;
2216 timing_info->used = 0;
2218 wmem_tree_insert32_array(timing, key, timing_info);
2219 } else {
2220 timing_info = (timing_info_t *)wmem_tree_lookup32_array_le(timing, key);
2221 if (timing_info && timing_info->interface_id == interface_id &&
2222 timing_info->adapter_id == adapter_id &&
2223 timing_info->chandle == chandle &&
2224 timing_info->psm == psm &&
2225 timing_info->opcode == opcode &&
2226 timing_info->op == op &&
2227 ((ctype == 0x0a) ? 1 : (timing_info->op_arg == op_arg)) &&
2228 timing_info->used == 0) {
2229 timing_info->response_frame_number = pinfo->fd->num;
2230 timing_info->response_timestamp = pinfo->fd->abs_ts;
2231 timing_info->used = 1;
2235 k_interface_id = interface_id;
2236 k_adapter_id = adapter_id;
2237 k_chandle = chandle;
2238 k_psm = psm;
2239 k_opcode = opcode;
2240 k_op = op;
2241 k_op_arg = (ctype == 0x0a) ? G_MAXUINT32 : op_arg;
2242 k_frame_number = pinfo->fd->num;
2244 key[0].length = 1;
2245 key[0].key = &k_interface_id;
2246 key[1].length = 1;
2247 key[1].key = &k_adapter_id;
2248 key[2].length = 1;
2249 key[2].key = &k_chandle;
2250 key[3].length = 1;
2251 key[3].key = &k_psm;
2252 key[4].length = 1;
2253 key[4].key = &k_opcode;
2254 key[5].length = 1;
2255 key[5].key = &k_op;
2256 key[6].length = 1;
2257 key[6].key = &k_op_arg;
2258 key[7].length = 1;
2259 key[7].key = &k_frame_number;
2260 key[8].length = 0;
2261 key[8].key = NULL;
2265 timing_info = (timing_info_t *)wmem_tree_lookup32_array_le(timing, key);
2266 if (timing_info && timing_info->interface_id == interface_id &&
2267 timing_info->adapter_id == adapter_id &&
2268 timing_info->chandle == chandle &&
2269 timing_info->psm == psm &&
2270 timing_info->opcode == opcode &&
2271 timing_info->op == op &&
2272 ((ctype == 0x0a) ? 1 : (timing_info->op_arg == op_arg))) {
2274 if (timing_info->command_timestamp.nsecs > timing_info->response_timestamp.nsecs) {
2275 response_time = timing_info->response_timestamp.nsecs + (1000000000 - timing_info->command_timestamp.nsecs);
2276 response_time /= 1000000;
2277 response_time += ((guint)timing_info->response_timestamp.secs - 1 - (guint)timing_info->command_timestamp.secs) / 1000;
2278 } else {
2279 response_time = timing_info->response_timestamp.nsecs - timing_info->command_timestamp.nsecs;
2280 response_time /= 1000000;
2281 response_time += ((guint)timing_info->response_timestamp.secs - (guint)timing_info->command_timestamp.secs) / 1000;
2284 if (timing_info->response_frame_number == 0) {
2285 response_time = UINT_MAX;
2288 pitem = proto_tree_add_uint(btavrcp_tree, hf_btavrcp_response_time, tvb, 0, 0, response_time);
2289 proto_item_append_text(pitem, "/%ums", timing_info->max_response_time);
2290 if (response_time > timing_info->max_response_time) {
2291 proto_item_append_text(pitem, "; TIME EXCEEDED");
2294 if (timing_info->response_frame_number == 0) {
2295 proto_item_append_text(pitem, "; There is no response");
2296 } else {
2297 if (is_command) {
2298 proto_item_append_text(pitem, "; Response is at frame: %u", timing_info->response_frame_number);
2299 } else {
2300 proto_item_append_text(pitem, "; Command is at frame: %u", timing_info->command_frame_number);
2303 PROTO_ITEM_SET_GENERATED(pitem);
2309 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2310 pitem = proto_tree_add_item(btavrcp_tree, hf_btavrcp_data, tvb, offset, -1, ENC_NA);
2311 expert_add_info(pinfo, pitem, &ei_btavrcp_unexpected_data);
2314 return offset;
2318 void
2319 proto_register_btavrcp(void)
2321 module_t *module;
2322 expert_module_t* expert_btavrcp;
2324 static hf_register_info hf[] = {
2325 { &hf_btavrcp_reserved,
2326 { "Reserved", "btavrcp.reserved",
2327 FT_UINT8, BASE_HEX, NULL, 0xF0,
2328 NULL, HFILL }
2330 { &hf_btavrcp_ctype,
2331 { "Ctype", "btavrcp.ctype",
2332 FT_UINT8, BASE_HEX, VALS(ctype_vals), 0x0F,
2333 NULL, HFILL }
2335 { &hf_btavrcp_subunit_type,
2336 { "Subunit Type", "btavrcp.subunit_type",
2337 FT_UINT8, BASE_HEX, VALS(subunit_type_vals), 0xF8,
2338 NULL, HFILL }
2340 { &hf_btavrcp_subunit_id,
2341 { "Subunit ID", "btavrcp.subunit_id",
2342 FT_UINT8, BASE_HEX, NULL, 0x07,
2343 NULL, HFILL }
2345 { &hf_btavrcp_opcode,
2346 { "Opcode", "btavrcp.opcode",
2347 FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x00,
2348 NULL, HFILL }
2350 { &hf_btavrcp_company_id,
2351 { "Company ID", "btavrcp.company_id",
2352 FT_UINT24, BASE_HEX, VALS(oui_vals), 0x00,
2353 NULL, HFILL }
2355 { &hf_btavrcp_passthrough_state,
2356 { "State", "btavrcp.passthrough.state",
2357 FT_UINT8, BASE_HEX, VALS(passthrough_state_vals), 0x80,
2358 NULL, HFILL }
2360 { &hf_btavrcp_passthrough_operation,
2361 { "Operation ID", "btavrcp.passthrough.operation",
2362 FT_UINT8, BASE_HEX, VALS(passthrough_operation_vals), 0x7F,
2363 NULL, HFILL }
2365 { &hf_btavrcp_passthrough_data_length,
2366 { "Data Length", "btavrcp.passthrough.length",
2367 FT_UINT8, BASE_HEX, NULL, 0x00,
2368 NULL, HFILL }
2370 { &hf_btavrcp_passthrough_vendor_unique_id,
2371 { "Vendor Unique ID", "btavrcp.passthrough.vendor_unique_id",
2372 FT_UINT16, BASE_HEX, VALS(vendor_unique_id_vals), 0x00,
2373 NULL, HFILL }
2375 { &hf_btavrcp_passthrough_company_id,
2376 { "Company ID", "btavrcp.passthrough.company_id",
2377 FT_UINT24, BASE_HEX, VALS(oui_vals), 0x00,
2378 NULL, HFILL }
2380 { &hf_btavrcp_unit_unknown,
2381 { "Unknown", "btavrcp.unit.unknown",
2382 FT_UINT8, BASE_HEX, NULL, 0xFF,
2383 NULL, HFILL }
2385 { &hf_btavrcp_unit_type,
2386 { "Unit Type", "btavrcp.unit.type",
2387 FT_UINT8, BASE_HEX, VALS(subunit_type_vals), 0xF8,
2388 NULL, HFILL }
2390 { &hf_btavrcp_unit_id,
2391 { "Subunit ID", "btavrcp.unit.id",
2392 FT_UINT8, BASE_HEX, NULL, 0x07,
2393 NULL, HFILL }
2395 { &hf_btavrcp_subunit_page,
2396 { "Page", "btavrcp.subunit.page",
2397 FT_UINT8, BASE_HEX, VALS(subunit_type_vals), 0xF8,
2398 NULL, HFILL }
2400 { &hf_btavrcp_subunit_extention_code,
2401 { "Extention Code", "btavrcp.subunit.extention_code",
2402 FT_UINT8, BASE_HEX, NULL, 0x07,
2403 NULL, HFILL }
2405 { &hf_btavrcp_bt_pdu_id,
2406 { "PDU ID", "btavrcp.pdu_id",
2407 FT_UINT8, BASE_HEX, VALS(pdu_id_vals), 0x00,
2408 NULL, HFILL }
2410 { &hf_btavrcp_pdu_id,
2411 { "PDU ID", "btavrcp.pdu_id",
2412 FT_UINT8, BASE_HEX, NULL, 0x00,
2413 NULL, HFILL }
2415 { &hf_btavrcp_bt_continuing_pdu_id,
2416 { "Continuing PDU ID", "btavrcp.pdu_id",
2417 FT_UINT8, BASE_HEX, VALS(pdu_id_vals), 0x00,
2418 NULL, HFILL }
2420 { &hf_btavrcp_browsing_pdu_id,
2421 { "PDU ID", "btavrcp.pdu_id",
2422 FT_UINT8, BASE_HEX, VALS(browsing_pdu_id_vals), 0x00,
2423 NULL, HFILL }
2425 { &hf_btavrcp_rfa,
2426 { "RFA", "btavrcp.rfa",
2427 FT_UINT8, BASE_HEX, NULL, 0xFC,
2428 NULL, HFILL }
2430 { &hf_btavrcp_packet_type,
2431 { "Packet Type", "btavrcp.packet_type",
2432 FT_UINT8, BASE_HEX, VALS(packet_type_vals), 0x03,
2433 NULL, HFILL }
2435 { &hf_btavrcp_length,
2436 { "Parameter Length", "btavrcp.length",
2437 FT_UINT16, BASE_DEC, NULL, 0x00,
2438 NULL, HFILL }
2440 { &hf_btavrcp_player_id,
2441 { "Player ID", "btavrcp.player_id",
2442 FT_UINT16, BASE_DEC, NULL, 0x00,
2443 NULL, HFILL }
2445 { &hf_btavrcp_status,
2446 { "Status", "btavrcp.status",
2447 FT_UINT8, BASE_HEX, VALS(status_vals), 0x00,
2448 NULL, HFILL }
2450 { &hf_btavrcp_uid_counter,
2451 { "UID Counter", "btavrcp.uid_counter",
2452 FT_UINT16, BASE_HEX, NULL, 0x00,
2453 NULL, HFILL }
2455 { &hf_btavrcp_character_set,
2456 { "Character Set", "btavrcp.character_set",
2457 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &wap_mib_enum_vals_character_sets_ext, 0x00,
2458 NULL, HFILL }
2460 { &hf_btavrcp_number_of_items,
2461 { "Number Of Items", "btavrcp.number_of_items",
2462 FT_UINT32, BASE_DEC, NULL, 0x00,
2463 "32bit number of items", HFILL }
2465 { &hf_btavrcp_number_of_items16,
2466 { "Number Of Items", "btavrcp.number_of_items",
2467 FT_UINT16, BASE_DEC, NULL, 0x00,
2468 "16bit number of items", HFILL }
2470 { &hf_btavrcp_folder_depth,
2471 { "Folder Depth", "btavrcp.folder_depth",
2472 FT_UINT8, BASE_DEC, NULL, 0x00,
2473 NULL, HFILL }
2475 { &hf_btavrcp_folder_name_length,
2476 { "Folder Name Length", "btavrcp.folder_name_length",
2477 FT_UINT16, BASE_DEC, NULL, 0x00,
2478 NULL, HFILL }
2480 { &hf_btavrcp_folder_name,
2481 { "Folder Name", "btavrcp.folder_name",
2482 FT_NONE, BASE_NONE, NULL, 0x00,
2483 NULL, HFILL }
2485 { &hf_btavrcp_search_length,
2486 { "Search String Length", "btavrcp.search_length",
2487 FT_UINT16, BASE_DEC, NULL, 0x00,
2488 NULL, HFILL }
2490 { &hf_btavrcp_search,
2491 { "Search String", "btavrcp.search",
2492 FT_NONE, BASE_NONE, NULL, 0x00,
2493 NULL, HFILL }
2495 { &hf_btavrcp_number_of_attributes,
2496 { "Number of Attributes", "btavrcp.number_of_attributes",
2497 FT_UINT8, BASE_DEC, NULL, 0x00,
2498 NULL, HFILL }
2500 { &hf_btavrcp_attribute_count,
2501 { "Attribute Count", "btavrcp.attribute_count",
2502 FT_UINT8, BASE_DEC, VALS(attribute_count_vals), 0x00,
2503 NULL, HFILL }
2505 { &hf_btavrcp_direction,
2506 { "Direction", "btavrcp.direction",
2507 FT_UINT8, BASE_HEX, VALS(direction_vals), 0x00,
2508 NULL, HFILL }
2510 { &hf_btavrcp_scope,
2511 { "Scope", "btavrcp.scope",
2512 FT_UINT8, BASE_HEX, VALS(scope_vals), 0x00,
2513 NULL, HFILL }
2515 { &hf_btavrcp_start_item,
2516 { "StartItem", "btavrcp.start_item",
2517 FT_UINT32, BASE_DEC, NULL, 0x00,
2518 NULL, HFILL }
2520 { &hf_btavrcp_end_item,
2521 { "EndItem", "btavrcp.end_item",
2522 FT_UINT32, BASE_DEC, NULL, 0x00,
2523 NULL, HFILL }
2525 { &hf_btavrcp_uid,
2526 { "UID", "btavrcp.uid",
2527 FT_UINT64, BASE_HEX, NULL, 0x00,
2528 NULL, HFILL }
2530 { &hf_btavrcp_identifier,
2531 { "Identifier", "btavrcp.identifier",
2532 FT_UINT64, BASE_HEX, NULL, 0x00,
2533 NULL, HFILL }
2535 { &hf_btavrcp_play_status,
2536 { "Play Status", "btavrcp.play_status",
2537 FT_UINT8, BASE_HEX, VALS(play_status_vals), 0x00,
2538 NULL, HFILL }
2540 { &hf_btavrcp_song_length,
2541 { "Song Length", "btavrcp.song_length",
2542 FT_UINT32, BASE_DEC, NULL, 0x00,
2543 NULL, HFILL }
2545 { &hf_btavrcp_song_position,
2546 { "Song Position", "btavrcp.song_position",
2547 FT_UINT32, BASE_DEC, NULL, 0x00,
2548 NULL, HFILL }
2550 { &hf_btavrcp_notification_interval,
2551 { "Interval", "btavrcp.notification.interval",
2552 FT_UINT32, BASE_DEC, NULL, 0x00,
2553 NULL, HFILL }
2555 { &hf_btavrcp_event_id,
2556 { "Event ID", "btavrcp.notification.event_id",
2557 FT_UINT8, BASE_HEX, VALS(notification_vals), 0x00,
2558 NULL, HFILL }
2560 { &hf_btavrcp_battery_status,
2561 { "Battery Status", "btavrcp.battery_status",
2562 FT_UINT8, BASE_HEX, VALS(battery_status_vals), 0x00,
2563 NULL, HFILL }
2565 { &hf_btavrcp_number_of_character_set,
2566 { "Number of Character Set", "btavrcp.number_of_character_set",
2567 FT_UINT8, BASE_DEC, NULL, 0x00,
2568 NULL, HFILL }
2570 { &hf_btavrcp_absolute_volume_rfa,
2571 { "RFA", "btavrcp.absoluter_volume_rfa",
2572 FT_UINT8, BASE_HEX, NULL, 0x80,
2573 NULL, HFILL }
2575 { &hf_btavrcp_absolute_volume,
2576 { "Volume", "btavrcp.volume",
2577 FT_UINT8, BASE_HEX, NULL, 0x7F,
2578 NULL, HFILL }
2580 { &hf_btavrcp_capability,
2581 { "Capability", "btavrcp.capability",
2582 FT_UINT8, BASE_HEX, VALS(capability_vals), 0x00,
2583 NULL, HFILL }
2585 { &hf_btavrcp_capability_count,
2586 { "Capability Count", "btavrcp.capability.count",
2587 FT_UINT8, BASE_HEX, NULL, 0x00,
2588 NULL, HFILL }
2590 { &hf_btavrcp_item_type,
2591 { "Item Type", "btavrcp.item.type",
2592 FT_UINT8, BASE_HEX, VALS(item_type_vals), 0x00,
2593 NULL, HFILL }
2595 { &hf_btavrcp_item_length,
2596 { "Item Length", "btavrcp.item.length",
2597 FT_UINT16, BASE_DEC, NULL, 0x00,
2598 NULL, HFILL }
2601 { &hf_btavrcp_number_of_settings,
2602 { "Number of Settings", "btavrcp.number_of_settings",
2603 FT_UINT8, BASE_DEC, NULL, 0x00,
2604 NULL, HFILL }
2606 { &hf_btavrcp_settings_attribute,
2607 { "Setting Attribute", "btavrcp.settings.attribute",
2608 FT_UINT8, BASE_HEX, VALS(settings_vals), 0x00,
2609 NULL, HFILL }
2611 { &hf_btavrcp_settings_value,
2612 { "Setting Value", "btavrcp.settings.value",
2613 FT_UINT8, BASE_HEX, NULL, 0x00,
2614 NULL, HFILL }
2616 { &hf_btavrcp_system_status,
2617 { "System Status", "btavrcp.system_status",
2618 FT_UINT8, BASE_HEX, VALS(system_status_vals), 0x00,
2619 NULL, HFILL }
2621 { &hf_btavrcp_player_item,
2622 { "Player", "btavrcp.player_item",
2623 FT_NONE, BASE_NONE, NULL, 0x00,
2624 NULL, HFILL }
2626 { &hf_btavrcp_folder,
2627 { "Folder", "btavrcp.folder",
2628 FT_NONE, BASE_NONE, NULL, 0x00,
2629 NULL, HFILL }
2631 { &hf_btavrcp_item,
2632 { "Item", "btavrcp.item",
2633 FT_NONE, BASE_NONE, NULL, 0x00,
2634 NULL, HFILL }
2636 { &hf_btavrcp_features,
2637 { "Features", "btavrcp.features",
2638 FT_NONE, BASE_NONE, NULL, 0x00,
2639 NULL, HFILL }
2641 { &hf_btavrcp_not_used_features,
2642 { "Not Used Features", "btavrcp.not_used_features",
2643 FT_NONE, BASE_NONE, NULL, 0x00,
2644 NULL, HFILL }
2646 { &hf_btavrcp_attribute_list,
2647 { "Attribute List", "btavrcp.attribute_list",
2648 FT_NONE, BASE_NONE, NULL, 0x00,
2649 NULL, HFILL }
2651 { &hf_btavrcp_attribute_item,
2652 { "Attribute", "btavrcp.attribute_item",
2653 FT_NONE, BASE_NONE, NULL, 0x00,
2654 NULL, HFILL }
2656 { &hf_btavrcp_attribute_entries,
2657 { "Attribute Entries", "btavrcp.attribute_entries",
2658 FT_NONE, BASE_NONE, NULL, 0x00,
2659 NULL, HFILL }
2661 { &hf_btavrcp_attribute,
2662 { "Attribute ID", "btavrcp.attribute",
2663 FT_UINT32, BASE_HEX, VALS(attribute_id_vals), 0x00,
2664 NULL, HFILL }
2666 { &hf_btavrcp_attribute_value_length,
2667 { "Value Length", "btavrcp.value.length",
2668 FT_UINT16, BASE_DEC, NULL, 0x00,
2669 NULL, HFILL }
2671 { &hf_btavrcp_attribute_value,
2672 { "Value", "btavrcp.value",
2673 FT_STRING, BASE_NONE, NULL, 0x00,
2674 NULL, HFILL }
2676 { &hf_btavrcp_displayable_name_length,
2677 { "Displayable Name Length", "btavrcp.displayable_name_length",
2678 FT_UINT16, BASE_DEC, NULL, 0x00,
2679 NULL, HFILL }
2681 { &hf_btavrcp_displayable_name,
2682 { "Displayable Name", "btavrcp.displayable_name",
2683 FT_STRING, BASE_NONE, NULL, 0x00,
2684 NULL, HFILL }
2686 { &hf_btavrcp_media_type,
2687 { "Media Type", "btavrcp.media_type",
2688 FT_UINT8, BASE_HEX, VALS(media_type_vals), 0x00,
2689 NULL, HFILL }
2691 { &hf_btavrcp_folder_type,
2692 { "Folder Type", "btavrcp.folder_type",
2693 FT_UINT8, BASE_HEX, VALS(folder_type_vals), 0x00,
2694 NULL, HFILL }
2696 { &hf_btavrcp_folder_playable,
2697 { "Folder Playable", "btavrcp.folder_playable",
2698 FT_UINT8, BASE_HEX, VALS(folder_playable_vals), 0x00,
2699 NULL, HFILL }
2701 { &hf_btavrcp_major_player_type,
2702 { "Major Player Type", "btavrcp.major_player_type",
2703 FT_UINT8, BASE_HEX, VALS(major_player_type_vals), 0x00,
2704 NULL, HFILL }
2706 { &hf_btavrcp_player_subtype,
2707 { "Player SubType", "btavrcp.player_subtype",
2708 FT_UINT8, BASE_HEX, VALS(player_subtype_vals), 0x00,
2709 NULL, HFILL }
2711 { &hf_btavrcp_setting_value_length,
2712 { "Value Length", "btavrcp.setting_value.length",
2713 FT_UINT8, BASE_DEC, NULL, 0x00,
2714 NULL, HFILL }
2716 { &hf_btavrcp_setting_value,
2717 { "Value", "btavrcp.setting_value",
2718 FT_STRING, BASE_NONE, NULL, 0x00,
2719 NULL, HFILL }
2721 { &hf_btavrcp_attribute_name_length,
2722 { "Value Length", "btavrcp.attribute_name.length",
2723 FT_UINT8, BASE_DEC, NULL, 0x00,
2724 NULL, HFILL }
2726 { &hf_btavrcp_attribute_name,
2727 { "Value", "btavrcp.attribute_name",
2728 FT_STRING, BASE_NONE, NULL, 0x00,
2729 NULL, HFILL }
2731 /* features */
2732 { &hf_btavrcp_feature_reserved_0,
2733 { "Feature Reserved", "btavrcp.feature.reserved",
2734 FT_UINT8, BASE_HEX, NULL, 0x01,
2735 NULL, HFILL }
2737 { &hf_btavrcp_feature_reserved_1,
2738 { "Feature Reserved", "btavrcp.feature.reserved",
2739 FT_UINT8, BASE_HEX, NULL, 0x02,
2740 NULL, HFILL }
2742 { &hf_btavrcp_feature_reserved_2,
2743 { "Feature Reserved", "btavrcp.feature.reserved",
2744 FT_UINT8, BASE_HEX, NULL, 0x04,
2745 NULL, HFILL }
2747 { &hf_btavrcp_feature_reserved_3,
2748 { "Feature Reserved", "btavrcp.feature.reserved",
2749 FT_UINT8, BASE_HEX, NULL, 0x08,
2750 NULL, HFILL }
2752 { &hf_btavrcp_feature_reserved_4,
2753 { "Feature Reserved", "btavrcp.feature.reserved",
2754 FT_UINT8, BASE_HEX, NULL, 0x10,
2755 NULL, HFILL }
2757 { &hf_btavrcp_feature_reserved_5,
2758 { "Feature Reserved", "btavrcp.feature.reserved",
2759 FT_UINT8, BASE_HEX, NULL, 0x20,
2760 NULL, HFILL }
2762 { &hf_btavrcp_feature_reserved_6,
2763 { "Feature Reserved", "btavrcp.feature.reserved",
2764 FT_UINT8, BASE_HEX, NULL, 0x40,
2765 NULL, HFILL }
2767 { &hf_btavrcp_feature_reserved_7,
2768 { "Feature Reserved", "btavrcp.feature.reserved",
2769 FT_UINT8, BASE_HEX, NULL, 0x80,
2770 NULL, HFILL }
2772 { &hf_btavrcp_feature_passthrough_select,
2773 { "PASSTHROUGH Select", "btavrcp.feature.passthrough.select",
2774 FT_UINT8, BASE_HEX, NULL, 0x01,
2775 NULL, HFILL }
2777 { &hf_btavrcp_feature_passthrough_up,
2778 { "PASSTHROUGH Up", "btavrcp.feature.passthrough.up",
2779 FT_UINT8, BASE_HEX, NULL, 0x02,
2780 NULL, HFILL }
2782 { &hf_btavrcp_feature_passthrough_down,
2783 { "PASSTHROUGH Down", "btavrcp.feature.passthrough.down",
2784 FT_UINT8, BASE_HEX, NULL, 0x04,
2785 NULL, HFILL }
2787 { &hf_btavrcp_feature_passthrough_left,
2788 { "PASSTHROUGH Left", "btavrcp.feature.passthrough.left",
2789 FT_UINT8, BASE_HEX, NULL, 0x08,
2790 NULL, HFILL }
2792 { &hf_btavrcp_feature_passthrough_right,
2793 { "PASSTHROUGH Right", "btavrcp.feature.passthrough.right",
2794 FT_UINT8, BASE_HEX, NULL, 0x10,
2795 NULL, HFILL }
2797 { &hf_btavrcp_feature_passthrough_right_up,
2798 { "PASSTHROUGH Right Up", "btavrcp.feature.passthrough.right_up",
2799 FT_UINT8, BASE_HEX, NULL, 0x20,
2800 NULL, HFILL }
2802 { &hf_btavrcp_feature_passthrough_right_down,
2803 { "PASSTHROUGH Right Down", "btavrcp.feature.passthrough.right_down",
2804 FT_UINT8, BASE_HEX, NULL, 0x40,
2805 NULL, HFILL }
2807 { &hf_btavrcp_feature_passthrough_left_up,
2808 { "PASSTHROUGH Left Up", "btavrcp.feature.passthrough.left_up",
2809 FT_UINT8, BASE_HEX, NULL, 0x80,
2810 NULL, HFILL }
2812 { &hf_btavrcp_feature_passthrough_left_down,
2813 { "PASSTHROUGH Left Down", "btavrcp.feature.passthrough.left_down",
2814 FT_UINT8, BASE_HEX, NULL, 0x01,
2815 NULL, HFILL }
2817 { &hf_btavrcp_feature_passthrough_root_menu,
2818 { "PASSTHROUGH Root Menu", "btavrcp.feature.passthrough.root_menu",
2819 FT_UINT8, BASE_HEX, NULL, 0x02,
2820 NULL, HFILL }
2822 { &hf_btavrcp_feature_passthrough_setup_menu,
2823 { "PASSTHROUGH Setup Menu", "btavrcp.feature.passthrough.setup_menu",
2824 FT_UINT8, BASE_HEX, NULL, 0x04,
2825 NULL, HFILL }
2827 { &hf_btavrcp_feature_passthrough_contents_menu,
2828 { "PASSTHROUGH Contents Menu", "btavrcp.feature.passthrough.contents_menu",
2829 FT_UINT8, BASE_HEX, NULL, 0x08,
2830 NULL, HFILL }
2832 { &hf_btavrcp_feature_passthrough_favorite_menu,
2833 { "PASSTHROUGH Favorite Menu", "btavrcp.feature.passthrough.favorite_menu",
2834 FT_UINT8, BASE_HEX, NULL, 0x10,
2835 NULL, HFILL }
2837 { &hf_btavrcp_feature_passthrough_exit,
2838 { "PASSTHROUGH Exit", "btavrcp.feature.passthrough.exit",
2839 FT_UINT8, BASE_HEX, NULL, 0x20,
2840 NULL, HFILL }
2842 { &hf_btavrcp_feature_passthrough_0,
2843 { "PASSTHROUGH 0", "btavrcp.feature.passthrough.0",
2844 FT_UINT8, BASE_HEX, NULL, 0x40,
2845 NULL, HFILL }
2847 { &hf_btavrcp_feature_passthrough_1,
2848 { "PASSTHROUGH 1", "btavrcp.feature.passthrough.1",
2849 FT_UINT8, BASE_HEX, NULL, 0x80,
2850 NULL, HFILL }
2852 { &hf_btavrcp_feature_passthrough_2,
2853 { "PASSTHROUGH 2", "btavrcp.feature.passthrough.2",
2854 FT_UINT8, BASE_HEX, NULL, 0x01,
2855 NULL, HFILL }
2857 { &hf_btavrcp_feature_passthrough_3,
2858 { "PASSTHROUGH 3", "btavrcp.feature.passthrough.3",
2859 FT_UINT8, BASE_HEX, NULL, 0x02,
2860 NULL, HFILL }
2862 { &hf_btavrcp_feature_passthrough_4,
2863 { "PASSTHROUGH 4", "btavrcp.feature.passthrough.4",
2864 FT_UINT8, BASE_HEX, NULL, 0x04,
2865 NULL, HFILL }
2867 { &hf_btavrcp_feature_passthrough_5,
2868 { "PASSTHROUGH 5", "btavrcp.feature.passthrough.5",
2869 FT_UINT8, BASE_HEX, NULL, 0x08,
2870 NULL, HFILL }
2872 { &hf_btavrcp_feature_passthrough_6,
2873 { "PASSTHROUGH 6", "btavrcp.feature.passthrough.6",
2874 FT_UINT8, BASE_HEX, NULL, 0x10,
2875 NULL, HFILL }
2877 { &hf_btavrcp_feature_passthrough_7,
2878 { "PASSTHROUGH 7", "btavrcp.feature.passthrough.7",
2879 FT_UINT8, BASE_HEX, NULL, 0x20,
2880 NULL, HFILL }
2882 { &hf_btavrcp_feature_passthrough_8,
2883 { "PASSTHROUGH 8", "btavrcp.feature.passthrough.8",
2884 FT_UINT8, BASE_HEX, NULL, 0x40,
2885 NULL, HFILL }
2887 { &hf_btavrcp_feature_passthrough_9,
2888 { "PASSTHROUGH 9", "btavrcp.feature.passthrough.9",
2889 FT_UINT8, BASE_HEX, NULL, 0x80,
2890 NULL, HFILL }
2892 { &hf_btavrcp_feature_passthrough_dot,
2893 { "PASSTHROUGH Dot", "btavrcp.feature.passthrough.dot",
2894 FT_UINT8, BASE_HEX, NULL, 0x01,
2895 NULL, HFILL }
2897 { &hf_btavrcp_feature_passthrough_enter,
2898 { "PASSTHROUGH Enter", "btavrcp.feature.passthrough.enter",
2899 FT_UINT8, BASE_HEX, NULL, 0x02,
2900 NULL, HFILL }
2902 { &hf_btavrcp_feature_passthrough_clear,
2903 { "PASSTHROUGH Clear", "btavrcp.feature.passthrough.clear",
2904 FT_UINT8, BASE_HEX, NULL, 0x04,
2905 NULL, HFILL }
2907 { &hf_btavrcp_feature_passthrough_channel_up,
2908 { "PASSTHROUGH Channel Up", "btavrcp.feature.passthrough.channel_up",
2909 FT_UINT8, BASE_HEX, NULL, 0x08,
2910 NULL, HFILL }
2912 { &hf_btavrcp_feature_passthrough_channel_down,
2913 { "PASSTHROUGH Channel Down", "btavrcp.feature.passthrough.channel_down",
2914 FT_UINT8, BASE_HEX, NULL, 0x10,
2915 NULL, HFILL }
2917 { &hf_btavrcp_feature_passthrough_previous_channel,
2918 { "PASSTHROUGH Previous Channel", "btavrcp.feature.passthrough.previous_channel",
2919 FT_UINT8, BASE_HEX, NULL, 0x20,
2920 NULL, HFILL }
2922 { &hf_btavrcp_feature_passthrough_sound_select,
2923 { "PASSTHROUGH Sound Select", "btavrcp.feature.passthrough.sound_select",
2924 FT_UINT8, BASE_HEX, NULL, 0x40,
2925 NULL, HFILL }
2927 { &hf_btavrcp_feature_passthrough_input_select,
2928 { "PASSTHROUGH Input Select", "btavrcp.feature.passthrough.input_select",
2929 FT_UINT8, BASE_HEX, NULL, 0x80,
2930 NULL, HFILL }
2932 { &hf_btavrcp_feature_passthrough_display_information,
2933 { "PASSTHROUGH Display Information", "btavrcp.feature.passthrough.display_information",
2934 FT_UINT8, BASE_HEX, NULL, 0x01,
2935 NULL, HFILL }
2937 { &hf_btavrcp_feature_passthrough_help,
2938 { "PASSTHROUGH Help", "btavrcp.feature.passthrough.help",
2939 FT_UINT8, BASE_HEX, NULL, 0x02,
2940 NULL, HFILL }
2942 { &hf_btavrcp_feature_passthrough_page_up,
2943 { "PASSTHROUGH Page Up", "btavrcp.feature.passthrough.page_up",
2944 FT_UINT8, BASE_HEX, NULL, 0x04,
2945 NULL, HFILL }
2947 { &hf_btavrcp_feature_passthrough_page_down,
2948 { "PASSTHROUGH Page Down", "btavrcp.feature.passthrough.page_down",
2949 FT_UINT8, BASE_HEX, NULL, 0x08,
2950 NULL, HFILL }
2952 { &hf_btavrcp_feature_passthrough_power,
2953 { "PASSTHROUGH Power", "btavrcp.feature.passthrough.power",
2954 FT_UINT8, BASE_HEX, NULL, 0x10,
2955 NULL, HFILL }
2957 { &hf_btavrcp_feature_passthrough_volume_up,
2958 { "PASSTHROUGH Volume Up", "btavrcp.feature.passthrough.volume_up",
2959 FT_UINT8, BASE_HEX, NULL, 0x20,
2960 NULL, HFILL }
2962 { &hf_btavrcp_feature_passthrough_volume_down,
2963 { "PASSTHROUGH Volume Down", "btavrcp.feature.passthrough.volume_down",
2964 FT_UINT8, BASE_HEX, NULL, 0x40,
2965 NULL, HFILL }
2967 { &hf_btavrcp_feature_passthrough_mute,
2968 { "PASSTHROUGH Mute", "btavrcp.feature.passthrough.mute",
2969 FT_UINT8, BASE_HEX, NULL, 0x80,
2970 NULL, HFILL }
2972 { &hf_btavrcp_feature_passthrough_play,
2973 { "PASSTHROUGH Play", "btavrcp.feature.passthrough.play",
2974 FT_UINT8, BASE_HEX, NULL, 0x01,
2975 NULL, HFILL }
2977 { &hf_btavrcp_feature_passthrough_stop,
2978 { "PASSTHROUGH Stop", "btavrcp.feature.passthrough.stop",
2979 FT_UINT8, BASE_HEX, NULL, 0x02,
2980 NULL, HFILL }
2982 { &hf_btavrcp_feature_passthrough_pause,
2983 { "PASSTHROUGH Pause", "btavrcp.feature.passthrough.pause",
2984 FT_UINT8, BASE_HEX, NULL, 0x04,
2985 NULL, HFILL }
2987 { &hf_btavrcp_feature_passthrough_record,
2988 { "PASSTHROUGH Record", "btavrcp.feature.passthrough.record",
2989 FT_UINT8, BASE_HEX, NULL, 0x08,
2990 NULL, HFILL }
2992 { &hf_btavrcp_feature_passthrough_rewind,
2993 { "PASSTHROUGH Rewind", "btavrcp.feature.passthrough.rewind",
2994 FT_UINT8, BASE_HEX, NULL, 0x10,
2995 NULL, HFILL }
2997 { &hf_btavrcp_feature_passthrough_fast_forward,
2998 { "PASSTHROUGH FastForward", "btavrcp.feature.passthrough.fast_forward",
2999 FT_UINT8, BASE_HEX, NULL, 0x20,
3000 NULL, HFILL }
3002 { &hf_btavrcp_feature_passthrough_eject,
3003 { "PASSTHROUGH Eject", "btavrcp.feature.passthrough.eject",
3004 FT_UINT8, BASE_HEX, NULL, 0x40,
3005 NULL, HFILL }
3007 { &hf_btavrcp_feature_passthrough_forward,
3008 { "PASSTHROUGH Forward", "btavrcp.feature.passthrough.forward",
3009 FT_UINT8, BASE_HEX, NULL, 0x80,
3010 NULL, HFILL }
3012 { &hf_btavrcp_feature_passthrough_backward,
3013 { "PASSTHROUGH Backward", "btavrcp.feature.passthrough.backward",
3014 FT_UINT8, BASE_HEX, NULL, 0x01,
3015 NULL, HFILL }
3017 { &hf_btavrcp_feature_passthrough_angle,
3018 { "PASSTHROUGH Angle", "btavrcp.feature.passthrough.angle",
3019 FT_UINT8, BASE_HEX, NULL, 0x02,
3020 NULL, HFILL }
3022 { &hf_btavrcp_feature_passthrough_subpicture,
3023 { "PASSTHROUGH SubPicture", "btavrcp.feature.passthrough.subpicture",
3024 FT_UINT8, BASE_HEX, NULL, 0x04,
3025 NULL, HFILL }
3027 { &hf_btavrcp_feature_passthrough_f1,
3028 { "PASSTHROUGH F1", "btavrcp.feature.passthrough.f1",
3029 FT_UINT8, BASE_HEX, NULL, 0x08,
3030 NULL, HFILL }
3032 { &hf_btavrcp_feature_passthrough_f2,
3033 { "PASSTHROUGH F2", "btavrcp.feature.passthrough.f2",
3034 FT_UINT8, BASE_HEX, NULL, 0x10,
3035 NULL, HFILL }
3037 { &hf_btavrcp_feature_passthrough_f3,
3038 { "PASSTHROUGH F3", "btavrcp.feature.passthrough.f3",
3039 FT_UINT8, BASE_HEX, NULL, 0x20,
3040 NULL, HFILL }
3042 { &hf_btavrcp_feature_passthrough_f4,
3043 { "PASSTHROUGH F4", "btavrcp.feature.passthrough.f4",
3044 FT_UINT8, BASE_HEX, NULL, 0x40,
3045 NULL, HFILL }
3047 { &hf_btavrcp_feature_passthrough_f5,
3048 { "PASSTHROUGH F5", "btavrcp.feature.passthrough.f5",
3049 FT_UINT8, BASE_HEX, NULL, 0x80,
3050 NULL, HFILL }
3052 { &hf_btavrcp_feature_vendor_unique,
3053 { "Vendor Unique", "btavrcp.feature.vendor_unique",
3054 FT_UINT8, BASE_HEX, NULL, 0x01,
3055 NULL, HFILL }
3057 { &hf_btavrcp_feature_basic_group_navigation,
3058 { "Basic Group Navigation", "btavrcp.feature.basic_group_navigation",
3059 FT_UINT8, BASE_HEX, NULL, 0x02,
3060 NULL, HFILL }
3062 { &hf_btavrcp_feature_advanced_control_player,
3063 { "Advanced Control Player", "btavrcp.feature.advanced_control_player",
3064 FT_UINT8, BASE_HEX, NULL, 0x04,
3065 NULL, HFILL }
3067 { &hf_btavrcp_feature_browsing,
3068 { "Browsing", "btavrcp.feature.browsing",
3069 FT_UINT8, BASE_HEX, NULL, 0x08,
3070 NULL, HFILL }
3072 { &hf_btavrcp_feature_searching,
3073 { "Searching", "btavrcp.feature.searching",
3074 FT_UINT8, BASE_HEX, NULL, 0x10,
3075 NULL, HFILL }
3077 { &hf_btavrcp_feature_addtonowplayer,
3078 { "AddToNowPlaying", "btavrcp.feature.addtonowplaying",
3079 FT_UINT8, BASE_HEX, NULL, 0x20,
3080 NULL, HFILL }
3082 { &hf_btavrcp_feature_uid_unique,
3083 { "UID Unique", "btavrcp.feature.uid_unique",
3084 FT_UINT8, BASE_HEX, NULL, 0x40,
3085 NULL, HFILL }
3087 { &hf_btavrcp_feature_only_browsable_when_addressed,
3088 { "Only Browsable When Addressed", "btavrcp.feature.only_browsable_when_addressed",
3089 FT_UINT8, BASE_HEX, NULL, 0x80,
3090 NULL, HFILL }
3092 { &hf_btavrcp_feature_only_searchable_when_addressed,
3093 { "Only Searchable When Addressed", "btavrcp.feature.only_searchable_when_addressed",
3094 FT_UINT8, BASE_HEX, NULL, 0x01,
3095 NULL, HFILL }
3097 { &hf_btavrcp_feature_nowplaying,
3098 { "Nowplaying", "btavrcp.feature.nowplaying",
3099 FT_UINT8, BASE_HEX, NULL, 0x02,
3100 NULL, HFILL }
3102 { &hf_btavrcp_feature_uid_persistency,
3103 { "UID Persistency", "btavrcp.feature.uid_persistency",
3104 FT_UINT8, BASE_HEX, NULL, 0x04,
3105 NULL, HFILL }
3107 /* end of features */
3108 { &hf_btavrcp_currect_path,
3109 { "Currect Path", "btavrcp.currect_path",
3110 FT_NONE, BASE_NONE, NULL, 0x00,
3111 NULL, HFILL }
3113 { &hf_btavrcp_reassembled,
3114 { "Reassembled", "btavrcp.reassembled",
3115 FT_NONE, BASE_NONE, NULL, 0x00,
3116 NULL, HFILL }
3118 { &hf_btavrcp_response_time,
3119 { "Response Time", "btavrcp.response_time",
3120 FT_UINT32, BASE_DEC, NULL, 0x00,
3121 NULL, HFILL }
3123 { &hf_btavrcp_data,
3124 { "Data", "btavrcp.data",
3125 FT_NONE, BASE_NONE, NULL, 0x0,
3126 NULL, HFILL }
3130 static gint *ett[] = {
3131 &ett_btavrcp,
3132 &ett_btavrcp_attribute_list,
3133 &ett_btavrcp_attribute_entry,
3134 &ett_btavrcp_attribute_entries,
3135 &ett_btavrcp_element,
3136 &ett_btavrcp_player,
3137 &ett_btavrcp_folder,
3138 &ett_btavrcp_path,
3141 static ei_register_info ei[] = {
3142 { &ei_btavrcp_item_length_bad, { "btavrcp.item.length.bad", PI_PROTOCOL, PI_WARN, "Item length does not correspond to sum of length of attributes", EXPFILL }},
3143 { &ei_btavrcp_unexpected_data, { "btavrcp.unexpected_data", PI_PROTOCOL, PI_WARN, "Unexpected data", EXPFILL }},
3146 reassembling = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3147 timing = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3149 proto_btavrcp = proto_register_protocol("Bluetooth AVRCP Profile", "BT AVRCP", "btavrcp");
3150 new_register_dissector("btavrcp", dissect_btavrcp, proto_btavrcp);
3152 proto_register_field_array(proto_btavrcp, hf, array_length(hf));
3153 proto_register_subtree_array(ett, array_length(ett));
3154 expert_btavrcp = expert_register_protocol(proto_btavrcp);
3155 expert_register_field_array(expert_btavrcp, ei, array_length(ei));
3157 module = prefs_register_protocol(proto_btavrcp, NULL);
3158 prefs_register_static_text_preference(module, "avrcp.version",
3159 "Bluetooth Profile AVRCP version: 1.5",
3160 "Version of profile supported by this dissector.");
3163 void
3164 proto_reg_handoff_btavrcp(void)
3166 dissector_handle_t btavrcp_handle;
3168 btavrcp_handle = find_dissector("btavrcp");
3170 dissector_add_uint("btavctp.service", BTSDP_AVRCP_TG_SERVICE_UUID, btavrcp_handle);
3171 dissector_add_uint("btavctp.service", BTSDP_AVRCP_CT_SERVICE_UUID, btavrcp_handle);
3172 dissector_add_uint("btavctp.service", BTSDP_AVRCP_SERVICE_UUID, btavrcp_handle);
3177 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3179 * Local variables:
3180 * c-basic-offset: 4
3181 * tab-width: 8
3182 * indent-tabs-mode: nil
3183 * End:
3185 * vi: set shiftwidth=4 tabstop=8 expandtab:
3186 * :indentSize=4:tabSize=8:noTabs=true: