Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-btavrcp.c
blob77bfdf66b65997eef40b5d05c55c982ef1aa1b33
1 /* packet-btavrcp.c
2 * Routines for Bluetooth AVRCP dissection
4 * Copyright 2012, Michal Labedzki for Tieto Corporation
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <epan/oui.h>
19 #include <epan/iana_charsets.h>
20 #include "packet-btl2cap.h"
21 #include "packet-btsdp.h"
22 #include "packet-btavctp.h"
23 #include "packet-btavrcp.h"
25 static int proto_btavrcp;
27 static int hf_btavrcp_rfa;
28 static int hf_btavrcp_ctype;
29 static int hf_btavrcp_subunit_type;
30 static int hf_btavrcp_subunit_id;
31 static int hf_btavrcp_opcode;
32 static int hf_btavrcp_company_id;
33 static int hf_btavrcp_length;
34 static int hf_btavrcp_pdu_id;
35 static int hf_btavrcp_bt_pdu_id;
36 static int hf_btavrcp_bt_continuing_pdu_id;
37 static int hf_btavrcp_browsing_pdu_id;
38 static int hf_btavrcp_reserved;
39 static int hf_btavrcp_packet_type;
40 static int hf_btavrcp_passthrough_state;
41 static int hf_btavrcp_passthrough_operation;
42 static int hf_btavrcp_passthrough_data_length;
43 static int hf_btavrcp_passthrough_company_id;
44 static int hf_btavrcp_passthrough_vendor_unique_id;
45 static int hf_btavrcp_unit_unknown;
46 static int hf_btavrcp_unit_type;
47 static int hf_btavrcp_unit_id;
48 static int hf_btavrcp_subunit_page;
49 static int hf_btavrcp_subunit_extension_code;
50 static int hf_btavrcp_item;
51 static int hf_btavrcp_folder;
52 static int hf_btavrcp_player_id;
53 static int hf_btavrcp_status;
54 static int hf_btavrcp_uid_counter;
55 static int hf_btavrcp_number_of_items;
56 static int hf_btavrcp_number_of_items16;
57 static int hf_btavrcp_character_set;
58 static int hf_btavrcp_folder_depth;
59 static int hf_btavrcp_folder_name_length;
60 static int hf_btavrcp_folder_name;
61 static int hf_btavrcp_search;
62 static int hf_btavrcp_search_length;
63 static int hf_btavrcp_number_of_attributes;
64 static int hf_btavrcp_uid;
65 static int hf_btavrcp_scope;
66 static int hf_btavrcp_start_item;
67 static int hf_btavrcp_end_item;
68 static int hf_btavrcp_direction;
69 static int hf_btavrcp_identifier;
70 static int hf_btavrcp_song_length;
71 static int hf_btavrcp_song_position;
72 static int hf_btavrcp_play_status;
73 static int hf_btavrcp_notification_interval;
74 static int hf_btavrcp_event_id;
75 static int hf_btavrcp_battery_status;
76 static int hf_btavrcp_number_of_character_set;
77 static int hf_btavrcp_absolute_volume_rfa;
78 static int hf_btavrcp_absolute_volume;
79 static int hf_btavrcp_capability;
80 static int hf_btavrcp_capability_count;
81 static int hf_btavrcp_item_type;
82 static int hf_btavrcp_item_length;
83 static int hf_btavrcp_system_status;
84 static int hf_btavrcp_number_of_settings;
85 static int hf_btavrcp_settings_attribute;
86 static int hf_btavrcp_settings_value;
87 static int hf_btavrcp_displayable_name;
88 static int hf_btavrcp_displayable_name_length;
89 static int hf_btavrcp_media_type;
90 static int hf_btavrcp_folder_type;
91 static int hf_btavrcp_folder_playable;
92 static int hf_btavrcp_major_player_type;
93 static int hf_btavrcp_player_subtype;
94 static int hf_btavrcp_player_item;
95 static int hf_btavrcp_attribute;
96 static int hf_btavrcp_attribute_count;
97 static int hf_btavrcp_attribute_value;
98 static int hf_btavrcp_attribute_value_length;
99 static int hf_btavrcp_attribute_item;
100 static int hf_btavrcp_attribute_list;
101 static int hf_btavrcp_attribute_entries;
102 static int hf_btavrcp_attribute_name_length;
103 static int hf_btavrcp_attribute_name;
104 static int hf_btavrcp_setting_value_length;
105 static int hf_btavrcp_setting_value;
106 static int hf_btavrcp_features;
107 static int hf_btavrcp_not_used_features;
108 static int hf_btavrcp_feature_reserved_0;
109 static int hf_btavrcp_feature_reserved_1;
110 static int hf_btavrcp_feature_reserved_2;
111 static int hf_btavrcp_feature_reserved_3;
112 static int hf_btavrcp_feature_reserved_4;
113 static int hf_btavrcp_feature_reserved_5;
114 static int hf_btavrcp_feature_reserved_6;
115 static int hf_btavrcp_feature_reserved_7;
116 static int hf_btavrcp_feature_passthrough_select;
117 static int hf_btavrcp_feature_passthrough_up;
118 static int hf_btavrcp_feature_passthrough_down;
119 static int hf_btavrcp_feature_passthrough_left;
120 static int hf_btavrcp_feature_passthrough_right;
121 static int hf_btavrcp_feature_passthrough_right_up;
122 static int hf_btavrcp_feature_passthrough_right_down;
123 static int hf_btavrcp_feature_passthrough_left_up;
124 static int hf_btavrcp_feature_passthrough_left_down;
125 static int hf_btavrcp_feature_passthrough_root_menu;
126 static int hf_btavrcp_feature_passthrough_setup_menu;
127 static int hf_btavrcp_feature_passthrough_contents_menu;
128 static int hf_btavrcp_feature_passthrough_favorite_menu;
129 static int hf_btavrcp_feature_passthrough_exit;
130 static int hf_btavrcp_feature_passthrough_0;
131 static int hf_btavrcp_feature_passthrough_1;
132 static int hf_btavrcp_feature_passthrough_2;
133 static int hf_btavrcp_feature_passthrough_3;
134 static int hf_btavrcp_feature_passthrough_4;
135 static int hf_btavrcp_feature_passthrough_5;
136 static int hf_btavrcp_feature_passthrough_6;
137 static int hf_btavrcp_feature_passthrough_7;
138 static int hf_btavrcp_feature_passthrough_8;
139 static int hf_btavrcp_feature_passthrough_9;
140 static int hf_btavrcp_feature_passthrough_dot;
141 static int hf_btavrcp_feature_passthrough_enter;
142 static int hf_btavrcp_feature_passthrough_clear;
143 static int hf_btavrcp_feature_passthrough_channel_up;
144 static int hf_btavrcp_feature_passthrough_channel_down;
145 static int hf_btavrcp_feature_passthrough_previous_channel;
146 static int hf_btavrcp_feature_passthrough_sound_select;
147 static int hf_btavrcp_feature_passthrough_input_select;
148 static int hf_btavrcp_feature_passthrough_display_information;
149 static int hf_btavrcp_feature_passthrough_help;
150 static int hf_btavrcp_feature_passthrough_page_up;
151 static int hf_btavrcp_feature_passthrough_page_down;
152 static int hf_btavrcp_feature_passthrough_power;
153 static int hf_btavrcp_feature_passthrough_volume_up;
154 static int hf_btavrcp_feature_passthrough_volume_down;
155 static int hf_btavrcp_feature_passthrough_mute;
156 static int hf_btavrcp_feature_passthrough_play;
157 static int hf_btavrcp_feature_passthrough_stop;
158 static int hf_btavrcp_feature_passthrough_pause;
159 static int hf_btavrcp_feature_passthrough_record;
160 static int hf_btavrcp_feature_passthrough_rewind;
161 static int hf_btavrcp_feature_passthrough_fast_forward;
162 static int hf_btavrcp_feature_passthrough_eject;
163 static int hf_btavrcp_feature_passthrough_forward;
164 static int hf_btavrcp_feature_passthrough_backward;
165 static int hf_btavrcp_feature_passthrough_angle;
166 static int hf_btavrcp_feature_passthrough_subpicture;
167 static int hf_btavrcp_feature_passthrough_f1;
168 static int hf_btavrcp_feature_passthrough_f2;
169 static int hf_btavrcp_feature_passthrough_f3;
170 static int hf_btavrcp_feature_passthrough_f4;
171 static int hf_btavrcp_feature_passthrough_f5;
172 static int hf_btavrcp_feature_vendor_unique;
173 static int hf_btavrcp_feature_basic_group_navigation;
174 static int hf_btavrcp_feature_advanced_control_player;
175 static int hf_btavrcp_feature_browsing;
176 static int hf_btavrcp_feature_searching;
177 static int hf_btavrcp_feature_addtonowplayer;
178 static int hf_btavrcp_feature_uid_unique;
179 static int hf_btavrcp_feature_only_browsable_when_addressed;
180 static int hf_btavrcp_feature_only_searchable_when_addressed;
181 static int hf_btavrcp_feature_nowplaying;
182 static int hf_btavrcp_feature_uid_persistency;
183 static int hf_btavrcp_feature_number_of_items;
184 static int hf_btavrcp_feature_cover_art;
185 static int hf_btavrcp_reassembled;
186 static int hf_btavrcp_current_path;
187 static int hf_btavrcp_response_time;
188 static int hf_btavrcp_command_in_frame;
189 static int hf_btavrcp_response_in_frame;
190 static int hf_btavrcp_data;
192 static int ett_btavrcp;
193 static int ett_btavrcp_attribute_list;
194 static int ett_btavrcp_attribute_entry;
195 static int ett_btavrcp_attribute_entries;
196 static int ett_btavrcp_element;
197 static int ett_btavrcp_folder;
198 static int ett_btavrcp_player;
199 static int ett_btavrcp_features;
200 static int ett_btavrcp_features_not_used;
201 static int ett_btavrcp_path;
203 static expert_field ei_btavrcp_no_response;
204 static expert_field ei_btavrcp_item_length_bad;
205 static expert_field ei_btavrcp_unexpected_data;
207 static dissector_handle_t btavrcp_handle;
209 #define OPCODE_VENDOR_DEPENDENT 0x00
210 #define OPCODE_UNIT 0x30
211 #define OPCODE_SUBUNIT 0x31
212 #define OPCODE_PASSTHROUGH 0x7C
214 #define ITEM_MEDIAPLAYER 0x01
215 #define ITEM_FOLDER 0x02
216 #define ITEM_MEDIA_ELEMENT 0x03
218 #define PACKET_TYPE_SINGLE 0x00
219 #define PACKET_TYPE_START 0x01
220 #define PACKET_TYPE_CONTINUE 0x02
221 #define PACKET_TYPE_END 0x03
223 #define EVENT_PLAYBACK_STATUS_CHANGED 0x01
224 #define EVENT_TRACK_CHANGED 0x02
225 #define EVENT_TRACK_REACHED_END 0x03
226 #define EVENT_TRACK_REACHED_START 0x04
227 #define EVENT_PLAYBACK_POSITION_CHANGED 0x05
228 #define EVENT_BATTERY_STATUS_CHANGED 0x06
229 #define EVENT_SYSTEM_STATUS_CHANGED 0x07
230 #define EVENT_PLAYER_APPLICATION_SETTING_CHANGED 0x08
231 #define EVENT_NOWPLAYING_CONTENT_CHANGED 0x09
232 #define EVENT_AVAILABLE_PLAYERS_CHANGED 0x0A
233 #define EVENT_ADDRESSEDPLAYER_CHANGED 0x0B
234 #define EVENT_UIDS_CHANGED 0x0C
235 #define EVENT_VOLUME_CHANGED 0x0D
237 #define PDU_GET_CAPABILITIES 0x10
238 #define PDU_LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES 0x11
239 #define PDU_LIST_PLAYER_APPLICATION_SETTING_VALUE 0x12
240 #define PDU_GET_CURRENT_PLAYER_APPLICATION_SETTING_VALUE 0x13
241 #define PDU_SET_PLAYER_APPLICATION_SETTING_VALUE 0x14
242 #define PDU_GET_PLAYER_APPLICATION_SETTING_ATTRIBUTE_TEXT 0x15
243 #define PDU_GET_PLAYER_APPLICATION_SETTING_VALUE_TEXT 0x16
244 #define PDU_INFORM_DISPLAYABLE_CHARACTER_SET 0x17
245 #define PDU_INFORM_BATTERY_STATUS_OF_CT 0x18
246 #define PDU_GET_ELEMENT_ATTRIBUTES 0x20
247 #define PDU_GET_PLAY_STATUS 0x30
248 #define PDU_REGISTER_NOTIFICATION 0x31
249 #define PDU_REQUEST_CONTINUING_RESPONSE 0x40
250 #define PDU_ABORT_CONTINUING_RESPONSE 0x41
251 #define PDU_SET_ABSOLUTE_VOLUME 0x50
252 #define PDU_SET_ADDRESSED_PLAYER 0x60
253 #define PDU_SET_BROWSED_PLAYER 0x70
254 #define PDU_GET_FOLDER_ITEMS 0x71
255 #define PDU_CHANGE_PATH 0x72
256 #define PDU_GET_ITEM_ATTRIBUTES 0x73
257 #define PDU_PLAY_ITEM 0x74
258 #define PDU_SEARCH 0x80
259 #define PDU_ADD_TO_NOW_PLAYING 0x90
260 #define PDU_GENERAL_REJECT 0xA0
262 #define STATUS_OK 0x04
264 static wmem_tree_t *reassembling;
265 static wmem_tree_t *timing;
266 wmem_tree_t *btavrcp_song_positions = NULL;
268 typedef struct _avrcp_proto_data_t {
269 uint32_t interface_id;
270 uint32_t adapter_id;
271 uint32_t chandle;
272 uint32_t channel;
273 } avrcp_proto_data_t;
275 typedef struct _fragment {
276 unsigned start_frame_number;
277 unsigned end_frame_number;
278 uint32_t interface_id;
279 uint32_t adapter_id;
280 uint32_t chandle;
281 uint32_t psm;
282 uint32_t op;
283 unsigned state;
284 uint32_t count;
285 wmem_tree_t *fragments;
286 } fragment_t;
288 typedef struct _data_fragment_t {
289 uint32_t length;
290 uint8_t *data;
291 } data_fragment_t;
293 typedef struct _timing_info {
294 unsigned command_frame_number;
295 nstime_t command_timestamp;
296 unsigned response_frame_number;
297 nstime_t response_timestamp;
298 unsigned max_response_time;
299 unsigned used;
300 uint32_t interface_id;
301 uint32_t adapter_id;
302 uint32_t chandle;
303 uint32_t psm;
304 uint32_t opcode;
305 uint32_t op;
306 uint32_t 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_DEPENDENT, "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, "Reverse 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 { 0x01, "Audio Book" },
585 { 0x02, "Podcast" },
586 { 0, NULL }
589 static const value_string unique_all_supported_attributes[] = {
590 { 0x00, "All Supported Attributes" },
591 { 0, NULL }
594 void proto_register_btavrcp(void);
595 void proto_reg_handoff_btavrcp(void);
597 static int
598 dissect_attribute_id_list(tvbuff_t *tvb, proto_tree *tree, int offset,
599 unsigned count)
601 unsigned i_attribute;
602 proto_item *pitem;
603 proto_tree *ptree;
605 pitem = proto_tree_add_item(tree, hf_btavrcp_attribute_list, tvb, offset, count * 4, ENC_NA);
606 ptree = proto_item_add_subtree(pitem, ett_btavrcp_attribute_list);
608 for (i_attribute = 0; i_attribute < count; ++i_attribute) {
609 proto_tree_add_item(ptree, hf_btavrcp_attribute, tvb, offset, 4, ENC_BIG_ENDIAN);
610 offset += 4;
613 return offset;
617 static int
618 dissect_attribute_entries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
619 int offset, unsigned count)
621 unsigned i_entry;
622 unsigned attribute_id;
623 unsigned value_length;
624 unsigned length;
625 uint8_t *value;
626 proto_item *pitem = NULL;
627 proto_tree *ptree = NULL;
628 proto_item *entry_item = NULL;
629 proto_tree *entry_tree = NULL;
631 length = 0;
632 for (i_entry = 0; i_entry < count; ++i_entry) {
633 length += 4 + 2 + 2 + tvb_get_ntohs(tvb, offset + length + 4 + 2);
636 pitem = proto_tree_add_item(tree, hf_btavrcp_attribute_entries, tvb, offset, length, ENC_NA);
637 ptree = proto_item_add_subtree(pitem, ett_btavrcp_attribute_entries);
639 for (i_entry = 0; i_entry < count; ++i_entry) {
640 attribute_id = tvb_get_ntohl(tvb, offset);
641 value_length = tvb_get_ntohs(tvb, offset + 4 + 2);
642 value = tvb_get_string_enc(pinfo->pool, tvb, offset + 4 + 2 + 2, value_length, ENC_ASCII);
644 if (attribute_id == 0x01) col_append_fstr(pinfo->cinfo, COL_INFO, " - Title: \"%s\"", value);
646 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);
647 entry_tree = proto_item_add_subtree(entry_item, ett_btavrcp_attribute_entry);
649 proto_tree_add_item(entry_tree, hf_btavrcp_attribute, tvb, offset, 4, ENC_BIG_ENDIAN);
650 offset += 4;
651 proto_tree_add_item(entry_tree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
652 offset += 2;
653 proto_tree_add_item(entry_tree, hf_btavrcp_setting_value_length, tvb, offset, 2, ENC_BIG_ENDIAN);
654 offset += 2;
655 proto_tree_add_item(entry_tree, hf_btavrcp_setting_value, tvb, offset, value_length, ENC_UTF_8 | ENC_NA);
656 offset += value_length;
659 return offset;
663 static int
664 dissect_item_mediaplayer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
666 unsigned displayable_name_length;
667 unsigned item_length;
668 unsigned feature_octet;
669 unsigned i_feature;
670 uint8_t *displayable_name;
671 proto_item *pitem;
672 proto_tree *ptree;
673 proto_item *features_item;
674 proto_tree *features_tree;
675 proto_item *features_not_set_item;
676 proto_tree *features_not_set_tree;
678 item_length = tvb_get_ntohs(tvb, offset + 1);
679 displayable_name_length = tvb_get_ntohs(tvb, offset + 1 + 2 + 2 + 1 + 4 + 16 + 1 + 2);
680 displayable_name = tvb_get_string_enc(pinfo->pool, tvb, offset + 1 + 2 + 2 + 1 + 4 + 16 + 1 + 2 + 2, displayable_name_length, ENC_ASCII);
682 pitem = proto_tree_add_none_format(tree, hf_btavrcp_player_item, tvb, offset, 1 + 2 + item_length, "Player: %s", displayable_name);
683 ptree = proto_item_add_subtree(pitem, ett_btavrcp_player);
685 proto_tree_add_item(ptree, hf_btavrcp_item_type, tvb, offset, 1, ENC_BIG_ENDIAN);
686 offset += 1;
687 proto_tree_add_item(ptree, hf_btavrcp_item_length, tvb, offset, 2, ENC_BIG_ENDIAN);
688 offset += 2;
690 proto_tree_add_item(ptree, hf_btavrcp_player_id, tvb, offset, 2, ENC_BIG_ENDIAN);
691 offset += 2;
693 proto_tree_add_item(ptree, hf_btavrcp_major_player_type, tvb, offset, 1, ENC_BIG_ENDIAN);
694 offset += 1;
696 proto_tree_add_item(ptree, hf_btavrcp_player_subtype, tvb, offset, 4, ENC_BIG_ENDIAN);
697 offset += 4;
699 proto_tree_add_item(ptree, hf_btavrcp_play_status, tvb, offset, 1, ENC_BIG_ENDIAN);
700 offset += 1;
702 /* feature bit mask */
703 features_item = proto_tree_add_item(ptree, hf_btavrcp_features, tvb, offset, 16, ENC_NA);
704 features_tree = proto_item_add_subtree(features_item, ett_btavrcp_features);
706 features_not_set_item = proto_tree_add_item(features_tree, hf_btavrcp_not_used_features, tvb, offset, 16, ENC_NA);
707 features_not_set_tree = proto_item_add_subtree(features_not_set_item, ett_btavrcp_features_not_used);
709 feature_octet = tvb_get_uint8(tvb, offset + 0);
710 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);
711 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);
712 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);
713 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);
714 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);
715 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);
716 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);
717 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);
719 feature_octet = tvb_get_uint8(tvb, offset + 1);
720 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);
721 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);
722 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);
723 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);
724 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);
725 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);
726 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);
727 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);
729 feature_octet = tvb_get_uint8(tvb, offset + 2);
730 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);
731 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);
732 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);
733 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);
734 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);
735 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);
736 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);
737 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);
739 feature_octet = tvb_get_uint8(tvb, offset + 3);
740 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);
741 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);
742 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);
743 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);
744 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);
745 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);
746 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);
747 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);
749 feature_octet = tvb_get_uint8(tvb, offset + 4);
750 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);
751 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);
752 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);
753 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);
754 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);
755 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);
756 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);
757 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);
759 feature_octet = tvb_get_uint8(tvb, offset + 5);
760 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);
761 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);
762 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);
763 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);
764 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);
765 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);
766 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);
767 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);
769 feature_octet = tvb_get_uint8(tvb, offset + 6);
770 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);
771 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);
772 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);
773 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);
774 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);
775 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);
776 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);
777 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);
779 feature_octet = tvb_get_uint8(tvb, offset + 7);
780 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);
781 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);
782 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);
783 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);
784 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);
785 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);
786 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);
787 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);
789 feature_octet = tvb_get_uint8(tvb, offset + 8);
790 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);
791 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);
792 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);
793 proto_tree_add_item((feature_octet & (1 << 3)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_number_of_items, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
794 proto_tree_add_item((feature_octet & (1 << 4)) ? features_tree : features_not_set_tree, hf_btavrcp_feature_cover_art, tvb, offset + 8, 1, ENC_BIG_ENDIAN);
796 /* reserved */
797 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);
798 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);
799 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);
801 for (i_feature = 9; i_feature <= 16; ++i_feature) {
802 feature_octet = tvb_get_uint8(tvb, offset + i_feature);
803 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);
804 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);
805 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);
806 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);
807 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);
808 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);
809 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);
810 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);
812 offset += 16;
814 proto_tree_add_item(ptree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
815 offset += 2;
817 proto_tree_add_item(ptree, hf_btavrcp_displayable_name_length, tvb, offset, 2, ENC_BIG_ENDIAN);
818 displayable_name_length = tvb_get_ntohs(tvb, offset);
819 offset += 2;
821 proto_tree_add_item(ptree, hf_btavrcp_displayable_name, tvb, offset, displayable_name_length, ENC_UTF_8 | ENC_NA);
822 offset += displayable_name_length;
824 return offset;
828 static int
829 dissect_item_media_element(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
830 int offset)
832 unsigned number_of_attributes;
833 unsigned displayable_name_length;
834 unsigned item_length;
835 uint8_t *displayable_name;
836 proto_item *pitem;
837 proto_tree *ptree;
838 int offset_in;
840 item_length = tvb_get_ntohs(tvb, offset + 1);
841 displayable_name_length = tvb_get_ntohs(tvb, offset + 1 + 2 + 8 + 1 + 2);
842 displayable_name = tvb_get_string_enc(pinfo->pool, tvb, offset + 1 + 2 + 8 + 1 + 2 + 2, displayable_name_length, ENC_ASCII);
844 pitem = proto_tree_add_none_format(tree, hf_btavrcp_item , tvb, offset, 1 + 2 + item_length, "Element: %s", displayable_name);
845 ptree = proto_item_add_subtree(pitem, ett_btavrcp_element);
847 proto_tree_add_item(ptree, hf_btavrcp_item_type, tvb, offset, 1, ENC_BIG_ENDIAN);
848 offset += 1;
849 proto_tree_add_item(ptree, hf_btavrcp_item_length, tvb, offset, 2, ENC_BIG_ENDIAN);
850 offset += 2;
851 offset_in = offset;
853 proto_tree_add_item(ptree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
854 offset += 8;
856 proto_tree_add_item(ptree, hf_btavrcp_media_type, tvb, offset, 1, ENC_BIG_ENDIAN);
857 offset += 1;
859 proto_tree_add_item(ptree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
860 offset += 2;
862 proto_tree_add_item(ptree, hf_btavrcp_displayable_name_length, tvb, offset, 2, ENC_BIG_ENDIAN);
863 displayable_name_length = tvb_get_ntohs(tvb, offset);
864 offset += 2;
866 proto_tree_add_item(ptree, hf_btavrcp_displayable_name, tvb, offset, displayable_name_length, ENC_UTF_8 | ENC_NA);
867 offset += displayable_name_length;
869 proto_tree_add_item(ptree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
870 number_of_attributes = tvb_get_uint8(tvb, offset);
871 offset += 1;
873 offset = dissect_attribute_entries(tvb, pinfo, ptree, offset, number_of_attributes);
875 if ( item_length != (unsigned) offset - offset_in) {
876 expert_add_info(pinfo, pitem, &ei_btavrcp_item_length_bad);
879 return offset;
883 static int
884 dissect_item_folder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
886 unsigned displayable_name_length;
887 unsigned item_length;
888 uint8_t *displayable_name;
889 proto_item *pitem;
890 proto_tree *ptree;
892 item_length = tvb_get_ntohs(tvb, offset + 1);
893 displayable_name_length = tvb_get_ntohs(tvb, offset + 1 + 2 + 8 + 1 + 1 + 2);
894 displayable_name = tvb_get_string_enc(pinfo->pool, tvb, offset + 1 + 2 + 8 + 1 + 1 + 2 + 2, displayable_name_length, ENC_ASCII);
896 pitem = proto_tree_add_none_format(tree, hf_btavrcp_folder, tvb, offset, 1 + 2 + item_length, "Folder : %s", displayable_name);
897 ptree = proto_item_add_subtree(pitem, ett_btavrcp_folder);
899 proto_tree_add_item(ptree, hf_btavrcp_item_type, tvb, offset, 1, ENC_BIG_ENDIAN);
900 offset += 1;
901 proto_tree_add_item(ptree, hf_btavrcp_item_length, tvb, offset, 2, ENC_BIG_ENDIAN);
902 offset += 2;
904 proto_tree_add_item(ptree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
905 offset += 8;
907 proto_tree_add_item(ptree, hf_btavrcp_folder_type, tvb, offset, 1, ENC_BIG_ENDIAN);
908 offset += 1;
910 proto_tree_add_item(ptree, hf_btavrcp_folder_playable, tvb, offset, 1, ENC_BIG_ENDIAN);
911 offset += 1;
913 proto_tree_add_item(ptree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
914 offset += 2;
916 proto_tree_add_item(ptree, hf_btavrcp_displayable_name_length, tvb, offset, 2, ENC_BIG_ENDIAN);
917 displayable_name_length = tvb_get_ntohs(tvb, offset);
918 offset += 2;
920 proto_tree_add_item(ptree, hf_btavrcp_displayable_name, tvb, offset, displayable_name_length, ENC_UTF_8 | ENC_NA);
921 offset += displayable_name_length;
923 return offset;
927 static int
928 dissect_passthrough(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
929 int offset, bool is_command, uint32_t *op)
931 unsigned operation;
932 unsigned state;
934 proto_tree_add_item(tree, hf_btavrcp_passthrough_state, tvb, offset, 1, ENC_BIG_ENDIAN);
935 proto_tree_add_item(tree, hf_btavrcp_passthrough_operation, tvb, offset, 1, ENC_BIG_ENDIAN);
936 *op = tvb_get_uint8(tvb, offset);
937 operation = tvb_get_uint8(tvb, offset) & 0x7F;
938 state = (tvb_get_uint8(tvb, offset) & 0x80) >> 7;
939 offset += 1;
940 proto_tree_add_item(tree, hf_btavrcp_passthrough_data_length, tvb, offset, 1, ENC_BIG_ENDIAN);
941 offset += 1;
943 if (!is_command) {
944 if (operation == 0x7E) {
945 proto_tree_add_item(tree, hf_btavrcp_passthrough_company_id, tvb, offset, 3, ENC_BIG_ENDIAN);
946 offset += 3;
947 proto_tree_add_item(tree, hf_btavrcp_passthrough_vendor_unique_id, tvb, offset, 2, ENC_BIG_ENDIAN);
948 offset += 2;
952 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (%s)",
953 val_to_str_const(operation, passthrough_operation_vals, "Unknown opcode"),
954 val_to_str_const(state, passthrough_state_vals, "unknown"));
955 return offset;
959 static int
960 dissect_unit(tvbuff_t *tvb, proto_tree *tree, int offset, bool is_command)
962 if (is_command) {
963 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, 5, ENC_NA);
964 offset += 5;
965 } else {
966 proto_tree_add_item(tree, hf_btavrcp_unit_unknown, tvb, offset, 1, ENC_BIG_ENDIAN);
967 offset += 1;
968 proto_tree_add_item(tree, hf_btavrcp_unit_type, tvb, offset, 1, ENC_BIG_ENDIAN);
969 proto_tree_add_item(tree, hf_btavrcp_unit_id, tvb, offset, 1, ENC_BIG_ENDIAN);
970 offset += 1;
971 proto_tree_add_item(tree, hf_btavrcp_passthrough_company_id, tvb, offset, 3, ENC_BIG_ENDIAN);
972 offset += 3;
975 return offset;
979 static int
980 dissect_subunit(tvbuff_t *tvb, proto_tree *tree, int offset, bool is_command)
982 proto_tree_add_item(tree, hf_btavrcp_subunit_page, tvb, offset, 1, ENC_BIG_ENDIAN);
983 proto_tree_add_item(tree, hf_btavrcp_subunit_extension_code, tvb, offset, 1, ENC_BIG_ENDIAN);
984 offset += 1;
986 if (!is_command) {
987 proto_tree_add_item(tree, hf_btavrcp_subunit_type, tvb, offset, 1, ENC_BIG_ENDIAN);
988 proto_tree_add_item(tree, hf_btavrcp_subunit_id, tvb, offset, 1, ENC_BIG_ENDIAN);
989 offset += 1;
990 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, 3, ENC_NA);
991 offset += 3;
992 } else {
993 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, 4, ENC_NA);
994 offset += 4;
997 return offset;
1001 static int
1002 dissect_vendor_dependent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1003 int offset, unsigned ctype, uint32_t *op, uint32_t *op_arg,
1004 bool is_command, avrcp_proto_data_t *avrcp_proto_data)
1006 proto_item *pitem;
1007 unsigned pdu_id;
1008 unsigned company_id;
1009 unsigned event_id;
1010 unsigned packet_type;
1011 unsigned parameter_length;
1012 int length;
1013 wmem_tree_key_t key[7];
1014 uint32_t k_op;
1015 uint32_t frame_number;
1016 unsigned volume;
1017 unsigned volume_percent;
1018 fragment_t *fragment;
1019 data_fragment_t *data_fragment;
1021 *op_arg = 0;
1023 proto_tree_add_item(tree, hf_btavrcp_company_id, tvb, offset, 3, ENC_BIG_ENDIAN);
1024 company_id = tvb_get_ntoh24(tvb, offset);
1025 offset += 3;
1027 if (company_id == OUI_BLUETOOTH) {
1028 proto_tree_add_item(tree, hf_btavrcp_bt_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1029 } else {
1031 if (tvb_reported_length_remaining(tvb, offset) == 0) {
1032 col_append_str(pinfo->cinfo, COL_INFO, " - No PDU ID");
1033 return offset;
1036 proto_tree_add_item(tree, hf_btavrcp_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1038 pdu_id = tvb_get_uint8(tvb, offset);
1039 *op = pdu_id | (company_id << 8);
1040 offset += 1;
1042 if (company_id != OUI_BLUETOOTH) {
1043 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1044 val_to_str_const(pdu_id, NULL, "Unknown PDU ID"));
1047 proto_tree_add_item(tree, hf_btavrcp_rfa, tvb, offset, 1, ENC_BIG_ENDIAN);
1048 proto_tree_add_item(tree, hf_btavrcp_packet_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1049 packet_type = tvb_get_uint8(tvb, offset) & 0x03;
1050 offset += 1;
1052 proto_tree_add_item(tree, hf_btavrcp_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1053 parameter_length = tvb_get_ntohs(tvb, offset);
1054 offset += 2;
1056 if (company_id != OUI_BLUETOOTH)
1057 return offset;
1059 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1060 val_to_str_const(pdu_id, pdu_id_vals, "Unknown PDU ID"));
1062 if (parameter_length == 0) return offset;
1064 length = tvb_reported_length_remaining(tvb, offset);
1065 if (packet_type == PACKET_TYPE_START) {
1066 if (pinfo->fd->visited == 0 && tvb_captured_length_remaining(tvb, offset) == length) {
1067 k_op = pdu_id | (company_id << 8);
1068 frame_number = pinfo->num;
1070 fragment = wmem_new(wmem_file_scope(), fragment_t);
1071 fragment->start_frame_number = pinfo->num;
1072 fragment->end_frame_number = 0;
1073 fragment->state = 0;
1075 fragment->count = 1;
1076 fragment->fragments = wmem_tree_new(wmem_file_scope());
1078 data_fragment = wmem_new(wmem_file_scope(), data_fragment_t);
1079 data_fragment->length = length;
1080 data_fragment->data = (uint8_t *) wmem_alloc(wmem_file_scope(), data_fragment->length);
1081 tvb_memcpy(tvb, data_fragment->data, offset, data_fragment->length);
1083 wmem_tree_insert32(fragment->fragments, fragment->count, data_fragment);
1085 key[0].length = 1;
1086 key[0].key = &avrcp_proto_data->interface_id;
1087 key[1].length = 1;
1088 key[1].key = &avrcp_proto_data->adapter_id;
1089 key[2].length = 1;
1090 key[2].key = &avrcp_proto_data->chandle;
1091 key[3].length = 1;
1092 key[3].key = &avrcp_proto_data->channel;
1093 key[4].length = 1;
1094 key[4].key = &k_op;
1095 key[5].length = 1;
1096 key[5].key = &frame_number;
1097 key[6].length = 0;
1098 key[6].key = NULL;
1100 fragment->interface_id = avrcp_proto_data->interface_id;
1101 fragment->adapter_id = avrcp_proto_data->adapter_id;
1102 fragment->chandle = avrcp_proto_data->chandle;
1103 fragment->psm = avrcp_proto_data->channel;
1104 fragment->op = pdu_id | (company_id << 8);
1106 wmem_tree_insert32_array(reassembling, key, fragment);
1109 col_append_str(pinfo->cinfo, COL_INFO, " [start]");
1110 return offset;
1111 } else if (packet_type == PACKET_TYPE_CONTINUE) {
1112 if (pinfo->fd->visited == 0 && tvb_captured_length_remaining(tvb, offset) == length) {
1113 k_op = pdu_id | (company_id << 8);
1114 frame_number = pinfo->num;
1116 key[0].length = 1;
1117 key[0].key = &avrcp_proto_data->interface_id;
1118 key[1].length = 1;
1119 key[1].key = &avrcp_proto_data->adapter_id;
1120 key[2].length = 1;
1121 key[2].key = &avrcp_proto_data->chandle;
1122 key[3].length = 1;
1123 key[3].key = &avrcp_proto_data->channel;
1124 key[4].length = 1;
1125 key[4].key = &k_op;
1126 key[5].length = 1;
1127 key[5].key = &frame_number;
1128 key[6].length = 0;
1129 key[6].key = NULL;
1131 fragment = (fragment_t *)wmem_tree_lookup32_array_le(reassembling, key);
1132 if (fragment && fragment->interface_id == avrcp_proto_data->interface_id &&
1133 fragment->adapter_id == avrcp_proto_data->adapter_id &&
1134 fragment->chandle == avrcp_proto_data->chandle &&
1135 fragment->psm == avrcp_proto_data->channel &&
1136 fragment->op == (pdu_id | (company_id << 8)) &&
1137 fragment->state == 1) {
1138 fragment->count += 1;
1139 fragment->state = 0;
1141 data_fragment = wmem_new(wmem_file_scope(), data_fragment_t);
1142 data_fragment->length = length;
1143 data_fragment->data = (uint8_t *) wmem_alloc(wmem_file_scope(), data_fragment->length);
1144 tvb_memcpy(tvb, data_fragment->data, offset, data_fragment->length);
1145 wmem_tree_insert32(fragment->fragments, fragment->count, data_fragment);
1149 col_append_str(pinfo->cinfo, COL_INFO, " [continue]");
1150 return offset;
1151 } else if (packet_type == PACKET_TYPE_END) {
1152 unsigned i_frame;
1153 tvbuff_t *next_tvb;
1155 col_append_str(pinfo->cinfo, COL_INFO, " [end]");
1157 k_op = pdu_id | (company_id << 8);
1158 frame_number = pinfo->num;
1160 key[0].length = 1;
1161 key[0].key = &avrcp_proto_data->interface_id;
1162 key[1].length = 1;
1163 key[1].key = &avrcp_proto_data->adapter_id;
1164 key[2].length = 1;
1165 key[2].key = &avrcp_proto_data->chandle;
1166 key[3].length = 1;
1167 key[3].key = &avrcp_proto_data->channel;
1168 key[4].length = 1;
1169 key[4].key = &k_op;
1170 key[5].length = 1;
1171 key[5].key = &frame_number;
1172 key[6].length = 0;
1173 key[6].key = NULL;
1175 fragment = (fragment_t *)wmem_tree_lookup32_array_le(reassembling, key);
1176 if (fragment && fragment->interface_id == avrcp_proto_data->interface_id &&
1177 fragment->adapter_id == avrcp_proto_data->adapter_id &&
1178 fragment->chandle == avrcp_proto_data->chandle &&
1179 fragment->psm == avrcp_proto_data->channel &&
1180 fragment->op == (pdu_id | (company_id << 8))) {
1183 if (fragment->state == 1 && pinfo->fd->visited == 0) {
1184 fragment->end_frame_number = pinfo->num;
1185 fragment->count += 1;
1186 fragment->state = 2;
1188 data_fragment = wmem_new(wmem_file_scope(), data_fragment_t);
1189 data_fragment->length = length;
1190 data_fragment->data = (uint8_t *) wmem_alloc(wmem_file_scope(), data_fragment->length);
1191 tvb_memcpy(tvb, data_fragment->data, offset, data_fragment->length);
1192 wmem_tree_insert32(fragment->fragments, fragment->count, data_fragment);
1194 /* reassembling*/
1195 length = 0;
1196 if (fragment->state == 2) {
1197 unsigned i_length = 0;
1198 uint8_t *reassembled;
1200 for (i_frame = 1; i_frame <= fragment->count; ++i_frame) {
1201 data_fragment = (data_fragment_t *)wmem_tree_lookup32_le(fragment->fragments, i_frame);
1202 length += data_fragment->length;
1205 reassembled = (uint8_t *) wmem_alloc(pinfo->pool, length);
1207 for (i_frame = 1; i_frame <= fragment->count; ++i_frame) {
1208 data_fragment = (data_fragment_t *)wmem_tree_lookup32_le(fragment->fragments, i_frame);
1209 memcpy(reassembled + i_length,
1210 data_fragment->data,
1211 data_fragment->length);
1212 i_length += data_fragment->length;
1215 next_tvb = tvb_new_child_real_data(tvb, reassembled, length, length);
1216 add_new_data_source(pinfo, next_tvb, "Reassembled AVRCP");
1218 tvb = next_tvb;
1219 offset = 0;
1221 pitem = proto_tree_add_item(tree, hf_btavrcp_reassembled, tvb, offset, 0, ENC_NA);
1222 proto_item_set_generated(pitem);
1227 if (ctype == 0x0a) { /* REJECT */
1228 unsigned status;
1229 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1230 status = tvb_get_uint8(tvb, offset);
1231 offset += 1;
1233 col_append_fstr(pinfo->cinfo, COL_INFO, " - Status: %s",
1234 val_to_str_const(status, status_vals, "Unknown status"));
1235 } else switch(pdu_id) {
1236 case PDU_GET_CAPABILITIES:
1237 if (is_command) {
1238 unsigned capability;
1240 proto_tree_add_item(tree, hf_btavrcp_capability, tvb, offset, 1, ENC_BIG_ENDIAN);
1241 capability = tvb_get_uint8(tvb, offset);
1242 *op_arg = capability;
1243 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s)",
1244 val_to_str_const(capability, capability_vals, "unknown"));
1245 offset += 1;
1246 } else {
1247 unsigned capability;
1248 unsigned capability_count;
1249 unsigned i_capability;
1251 proto_tree_add_item(tree, hf_btavrcp_capability, tvb, offset, 1, ENC_BIG_ENDIAN);
1252 capability = tvb_get_uint8(tvb, offset);
1253 *op_arg = capability;
1254 offset += 1;
1255 proto_tree_add_item(tree, hf_btavrcp_capability_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1256 capability_count = tvb_get_uint8(tvb, offset);
1257 offset += 1;
1259 for (i_capability = 0; i_capability < capability_count; ++i_capability) {
1260 if (capability == 0x02) {
1261 proto_tree_add_item(tree, hf_btavrcp_company_id, tvb, offset, 3, ENC_BIG_ENDIAN);
1262 offset += 3;
1263 } else if (capability == 0x03) {
1264 proto_tree_add_item(tree, hf_btavrcp_event_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1265 offset += 1;
1269 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) - Count: %u",
1270 val_to_str_const(capability, capability_vals, "unknown"), capability_count);
1272 break;
1273 case PDU_LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES:
1274 if (is_command) {
1275 /* non */
1276 } else {
1277 unsigned number_of_attributes;
1278 unsigned i_attribute;
1280 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1281 number_of_attributes = tvb_get_uint8(tvb, offset);
1282 offset += 1;
1284 for (i_attribute = 0; i_attribute < number_of_attributes; ++i_attribute) {
1285 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1286 offset += 1;
1289 break;
1290 case PDU_LIST_PLAYER_APPLICATION_SETTING_VALUE:
1291 if (is_command) {
1292 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1293 offset += 1;
1294 } else {
1295 unsigned number_of_values;
1296 unsigned i_value;
1298 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1299 number_of_values = tvb_get_uint8(tvb, offset);
1300 offset += 1;
1302 for (i_value = 0; i_value < number_of_values; ++i_value) {
1303 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1304 offset += 1;
1307 break;
1308 case PDU_GET_CURRENT_PLAYER_APPLICATION_SETTING_VALUE:
1309 if (is_command) {
1310 unsigned number_of_attributes;
1311 unsigned i_attribute;
1313 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1314 number_of_attributes = tvb_get_uint8(tvb, offset);
1315 offset += 1;
1317 for (i_attribute = 0; i_attribute < number_of_attributes; ++i_attribute) {
1318 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1319 offset += 1;
1321 } else {
1322 unsigned number_of_settings;
1323 unsigned i_setting;
1325 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1326 number_of_settings = tvb_get_uint8(tvb, offset);
1327 offset += 1;
1329 for (i_setting = 0; i_setting < number_of_settings; ++i_setting) {
1330 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1331 offset += 1;
1332 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1333 offset += 1;
1336 break;
1337 case PDU_SET_PLAYER_APPLICATION_SETTING_VALUE:
1338 if (is_command) {
1339 unsigned number_of_settings;
1340 unsigned i_setting;
1342 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1343 number_of_settings = tvb_get_uint8(tvb, offset);
1344 offset += 1;
1346 for (i_setting = 0; i_setting < number_of_settings; ++i_setting) {
1347 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1348 offset += 1;
1349 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1350 offset += 1;
1352 } else {
1353 /* non */
1355 break;
1356 case PDU_GET_PLAYER_APPLICATION_SETTING_ATTRIBUTE_TEXT:
1357 if (is_command) {
1358 unsigned number_of_attributes;
1359 unsigned i_attribute;
1361 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1362 number_of_attributes = tvb_get_uint8(tvb, offset);
1363 offset += 1;
1365 for (i_attribute = 0; i_attribute < number_of_attributes; ++i_attribute) {
1366 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1367 offset += 1;
1369 } else {
1370 unsigned number_of_attributes;
1371 unsigned i_attribute;
1372 unsigned attribute_name_length;
1374 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1375 number_of_attributes = tvb_get_uint8(tvb, offset);
1376 offset += 1;
1378 for (i_attribute = 0; i_attribute < number_of_attributes; ++i_attribute) {
1379 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1380 offset += 1;
1382 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 1, ENC_BIG_ENDIAN);
1383 offset += 2;
1385 proto_tree_add_item(tree, hf_btavrcp_attribute_name_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1386 attribute_name_length = tvb_get_ntohs(tvb, offset);
1387 offset += 1;
1389 proto_tree_add_item(tree, hf_btavrcp_attribute_name, tvb, offset, attribute_name_length, ENC_UTF_8 | ENC_NA);
1390 offset += attribute_name_length;
1393 break;
1394 case PDU_GET_PLAYER_APPLICATION_SETTING_VALUE_TEXT:
1395 if (is_command) {
1396 unsigned number_of_values;
1397 unsigned i_value;
1399 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1400 offset += 1;
1401 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1402 number_of_values = tvb_get_uint8(tvb, offset);
1403 offset += 1;
1405 for (i_value = 0; i_value < number_of_values; ++i_value) {
1406 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1407 offset += 1;
1409 } else {
1410 unsigned number_of_values;
1411 unsigned i_attribute;
1412 unsigned attribute_value_length;
1414 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1415 number_of_values = tvb_get_uint8(tvb, offset);
1416 offset += 1;
1418 for (i_attribute = 0; i_attribute < number_of_values; ++i_attribute) {
1419 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1420 offset += 1;
1422 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 1, ENC_BIG_ENDIAN);
1423 offset += 2;
1425 proto_tree_add_item(tree, hf_btavrcp_attribute_value_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1426 attribute_value_length = tvb_get_ntohs(tvb, offset);
1427 offset += 1;
1429 proto_tree_add_item(tree, hf_btavrcp_attribute_value, tvb, offset, attribute_value_length, ENC_UTF_8 | ENC_NA);
1430 offset += attribute_value_length;
1433 break;
1434 case PDU_INFORM_DISPLAYABLE_CHARACTER_SET:
1435 if (is_command) {
1436 unsigned number_of_character_set;
1437 unsigned i_character_set;
1439 proto_tree_add_item(tree, hf_btavrcp_number_of_character_set, tvb, offset, 1, ENC_BIG_ENDIAN);
1440 number_of_character_set = tvb_get_uint8(tvb, offset);
1441 offset += 1;
1443 for (i_character_set = 0; i_character_set < number_of_character_set; ++i_character_set) {
1444 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
1445 offset += 2;
1447 } else {
1448 /* non */
1450 break;
1451 case PDU_INFORM_BATTERY_STATUS_OF_CT:
1452 if (is_command) {
1453 unsigned battery_status;
1455 proto_tree_add_item(tree, hf_btavrcp_battery_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1456 battery_status = tvb_get_uint8(tvb, offset);
1457 offset += 1;
1458 col_append_fstr(pinfo->cinfo, COL_INFO, " - Battery: %s", val_to_str_const(battery_status, battery_status_vals, "unknown"));
1459 } else {
1460 /* non */
1462 break;
1463 case PDU_GET_ELEMENT_ATTRIBUTES:
1464 if (is_command) {
1465 unsigned number_of_attributes;
1466 uint64_t identifier;
1468 proto_tree_add_item(tree, hf_btavrcp_identifier, tvb, offset, 8, ENC_BIG_ENDIAN);
1469 identifier = tvb_get_ntoh64(tvb, offset);
1470 offset += 8;
1472 col_append_fstr(pinfo->cinfo, COL_INFO, " - 0x%08X%08X", (unsigned) (identifier >> 32), (unsigned) (identifier & 0xFFFFFFFF));
1473 if (identifier == 0x00) col_append_str(pinfo->cinfo, COL_INFO, " (PLAYING)");
1475 proto_tree_add_item(tree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
1476 number_of_attributes = tvb_get_uint8(tvb, offset);
1477 offset += 1;
1478 offset = dissect_attribute_id_list(tvb, tree, offset, number_of_attributes);
1479 } else {
1480 unsigned number_of_attributes;
1482 proto_tree_add_item(tree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
1483 number_of_attributes = tvb_get_uint8(tvb, offset);
1484 offset += 1;
1485 offset = dissect_attribute_entries(tvb, pinfo, tree, offset, number_of_attributes);
1487 break;
1488 case PDU_GET_PLAY_STATUS:
1489 if (is_command) {
1490 /* non */
1491 } else {
1492 unsigned song_length;
1493 unsigned song_position;
1494 unsigned play_status;
1496 proto_tree_add_item(tree, hf_btavrcp_song_length, tvb, offset, 4, ENC_BIG_ENDIAN);
1497 song_length = tvb_get_ntohl(tvb, offset);
1498 offset += 4;
1499 proto_tree_add_item(tree, hf_btavrcp_song_position, tvb, offset, 4, ENC_BIG_ENDIAN);
1500 song_position = tvb_get_ntohl(tvb, offset);
1501 offset += 4;
1502 proto_tree_add_item(tree, hf_btavrcp_play_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1503 play_status = tvb_get_uint8(tvb, offset);
1504 offset += 1;
1506 col_append_fstr(pinfo->cinfo, COL_INFO, " PlayStatus: %s, SongPosition: %ums, SongLength: %ums",
1507 val_to_str_const(play_status, play_status_vals, "unknown"), song_position, song_length);
1509 break;
1510 case PDU_REGISTER_NOTIFICATION:
1511 event_id = tvb_get_uint8(tvb, offset);
1512 *op_arg = event_id;
1513 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1514 val_to_str_const(event_id, notification_vals, "Unknown Event ID"));
1516 if (is_command) {
1517 proto_tree_add_item(tree, hf_btavrcp_event_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1518 offset += 1;
1519 proto_tree_add_item(tree, hf_btavrcp_notification_interval, tvb, offset, 4, ENC_BIG_ENDIAN);
1520 offset += 4;
1521 } else {
1522 unsigned number_of_settings;
1523 unsigned i_setting;
1524 uint64_t identifier;
1525 unsigned play_status;
1526 unsigned song_position;
1527 unsigned battery_status;
1528 unsigned uid_counter;
1529 unsigned player_id;
1530 unsigned system_status;
1532 proto_tree_add_item(tree, hf_btavrcp_event_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1533 offset += 1;
1535 if (ctype == 0x0D || ctype == 0x0F) switch(event_id) {
1536 case EVENT_PLAYBACK_STATUS_CHANGED:
1537 proto_tree_add_item(tree, hf_btavrcp_play_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1538 play_status = tvb_get_uint8(tvb, offset);
1539 offset += 1;
1540 col_append_fstr(pinfo->cinfo, COL_INFO, " - PlayStatus: %s", val_to_str_const(play_status, play_status_vals, "unknown"));
1541 break;
1542 case EVENT_TRACK_CHANGED:
1543 pitem = proto_tree_add_item(tree, hf_btavrcp_identifier, tvb, offset, 8, ENC_BIG_ENDIAN);
1544 identifier = tvb_get_ntoh64(tvb, offset);
1545 offset += 8;
1547 col_append_fstr(pinfo->cinfo, COL_INFO, " - 0x%08X%08X", (unsigned) (identifier >> 32), (unsigned) (identifier & 0xFFFFFFFF));
1548 if (identifier == UINT64_C(0x0000000000000000)) {
1549 col_append_str(pinfo->cinfo, COL_INFO, " (SELECTED)");
1550 proto_item_append_text(pitem, " (SELECTED)");
1551 } else if (identifier == UINT64_C(0xFFFFFFFFFFFFFFFF)) {
1552 col_append_str(pinfo->cinfo, COL_INFO, " (NOT SELECTED)");
1553 proto_item_append_text(pitem, " (NOT SELECTED)");
1556 break;
1557 case EVENT_TRACK_REACHED_END:
1558 /* non */
1559 break;
1560 case EVENT_TRACK_REACHED_START:
1561 /* non */
1562 break;
1563 case EVENT_PLAYBACK_POSITION_CHANGED:
1564 pitem = proto_tree_add_item(tree, hf_btavrcp_song_position, tvb, offset, 4, ENC_BIG_ENDIAN);
1565 song_position = tvb_get_ntohl(tvb, offset);
1566 offset += 4;
1567 col_append_fstr(pinfo->cinfo, COL_INFO, " - SongPosition: %ums", song_position);
1568 if (song_position == 0xFFFFFFFF) {
1569 proto_item_append_text(pitem, " (NOT SELECTED)");
1570 col_append_str(pinfo->cinfo, COL_INFO, " (NOT SELECTED)");
1571 } else if (!pinfo->fd->visited) {
1572 btavrcp_song_position_data_t *song_position_data;
1574 frame_number = pinfo->num;
1576 key[0].length = 1;
1577 key[0].key = &avrcp_proto_data->interface_id;
1578 key[1].length = 1;
1579 key[1].key = &avrcp_proto_data->adapter_id;
1580 key[2].length = 1;
1581 key[2].key = &frame_number;
1582 key[3].length = 0;
1583 key[3].key = NULL;
1585 song_position_data = wmem_new(wmem_file_scope(), btavrcp_song_position_data_t);
1586 song_position_data->song_position = song_position;
1587 song_position_data->used_in_frame = 0;
1589 wmem_tree_insert32_array(btavrcp_song_positions, key, song_position_data);
1591 break;
1592 case EVENT_BATTERY_STATUS_CHANGED:
1593 proto_tree_add_item(tree, hf_btavrcp_battery_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1594 battery_status = tvb_get_uint8(tvb, offset);
1595 offset += 1;
1596 col_append_fstr(pinfo->cinfo, COL_INFO, " - Battery: %s", val_to_str_const(battery_status, battery_status_vals, "unknown"));
1597 break;
1598 case EVENT_SYSTEM_STATUS_CHANGED:
1599 proto_tree_add_item(tree, hf_btavrcp_system_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1600 system_status = tvb_get_uint8(tvb, offset);
1601 offset += 1;
1602 col_append_fstr(pinfo->cinfo, COL_INFO, " - SystemStatus: %s", val_to_str_const(system_status, system_status_vals, "unknown"));
1603 break;
1604 case EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
1605 proto_tree_add_item(tree, hf_btavrcp_number_of_settings, tvb, offset, 1, ENC_BIG_ENDIAN);
1606 number_of_settings = tvb_get_uint8(tvb, offset);
1607 offset += 1;
1609 for (i_setting = 0; i_setting < number_of_settings; ++i_setting) {
1610 proto_tree_add_item(tree, hf_btavrcp_settings_attribute, tvb, offset, 1, ENC_BIG_ENDIAN);
1611 offset += 1;
1612 proto_tree_add_item(tree, hf_btavrcp_settings_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1613 offset += 1;
1615 break;
1616 case EVENT_NOWPLAYING_CONTENT_CHANGED:
1617 /* non */
1618 break;
1619 case EVENT_AVAILABLE_PLAYERS_CHANGED:
1620 /* non */
1621 break;
1622 case EVENT_ADDRESSEDPLAYER_CHANGED:
1623 proto_tree_add_item(tree, hf_btavrcp_player_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1624 player_id = tvb_get_ntohs(tvb, offset);
1625 offset += 2;
1626 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1627 uid_counter = tvb_get_ntohs(tvb, offset);
1628 offset += 2;
1629 col_append_fstr(pinfo->cinfo, COL_INFO, " - PlayerID: %u, UidCounter: 0x%04x", player_id, uid_counter);
1630 break;
1631 case EVENT_UIDS_CHANGED:
1632 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1633 uid_counter = tvb_get_ntohs(tvb, offset);
1634 offset += 2;
1635 col_append_fstr(pinfo->cinfo, COL_INFO, " - UidCounter: 0x%04x", uid_counter);
1636 break;
1637 case EVENT_VOLUME_CHANGED:
1638 proto_tree_add_item(tree, hf_btavrcp_absolute_volume_rfa, tvb, offset, 1, ENC_BIG_ENDIAN);
1639 pitem = proto_tree_add_item(tree, hf_btavrcp_absolute_volume, tvb, offset, 1, ENC_BIG_ENDIAN);
1641 volume = tvb_get_uint8(tvb, offset) & 0x7F;
1642 volume_percent = (unsigned) ((double) volume * 100 / (double) 0x7F);
1643 offset += 1;
1645 proto_item_append_text(pitem, " (%u%%)", volume_percent);
1646 col_append_fstr(pinfo->cinfo, COL_INFO, " - Volume: %u%%", volume_percent);
1647 break;
1648 default:
1649 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
1650 offset = tvb_reported_length(tvb);
1651 break;
1655 break;
1656 case PDU_REQUEST_CONTINUING_RESPONSE:
1657 if (is_command) {
1658 unsigned continuing_op;
1660 proto_tree_add_item(tree, hf_btavrcp_bt_continuing_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1661 continuing_op = tvb_get_uint8(tvb, offset) | (company_id << 8);
1662 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1663 val_to_str_const(tvb_get_uint8(tvb, offset), pdu_id_vals, "Unknown opcode"));
1664 offset += 1;
1666 if (pinfo->fd->visited == 0) {
1667 k_op = continuing_op;
1668 frame_number = pinfo->num;
1670 key[0].length = 1;
1671 key[0].key = &avrcp_proto_data->interface_id;
1672 key[1].length = 1;
1673 key[1].key = &avrcp_proto_data->adapter_id;
1674 key[2].length = 1;
1675 key[2].key = &avrcp_proto_data->chandle;
1676 key[3].length = 1;
1677 key[3].key = &avrcp_proto_data->channel;
1678 key[4].length = 1;
1679 key[4].key = &k_op;
1680 key[5].length = 1;
1681 key[5].key = &frame_number;
1682 key[6].length = 0;
1683 key[6].key = NULL;
1685 fragment = (fragment_t *)wmem_tree_lookup32_array_le(reassembling, key);
1686 if (fragment && fragment->interface_id == avrcp_proto_data->interface_id &&
1687 fragment->adapter_id == avrcp_proto_data->adapter_id &&
1688 fragment->chandle == avrcp_proto_data->chandle &&
1689 fragment->psm == avrcp_proto_data->channel &&
1690 fragment->op == continuing_op &&
1691 fragment->state == 0) {
1692 fragment->state = 1;
1696 *op = continuing_op;
1697 } else {
1698 /* non */
1700 break;
1701 case PDU_ABORT_CONTINUING_RESPONSE:
1702 if (is_command) {
1703 unsigned continuing_op;
1705 proto_tree_add_item(tree, hf_btavrcp_bt_continuing_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1706 continuing_op = tvb_get_uint8(tvb, offset) | (company_id << 8);
1707 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1708 val_to_str_const(tvb_get_uint8(tvb, offset), pdu_id_vals, "Unknown opcode"));
1709 offset += 1;
1711 if (pinfo->fd->visited == 0) {
1712 k_op = continuing_op;
1713 frame_number = pinfo->num;
1715 key[0].length = 1;
1716 key[0].key = &avrcp_proto_data->interface_id;
1717 key[1].length = 1;
1718 key[1].key = &avrcp_proto_data->adapter_id;
1719 key[2].length = 1;
1720 key[2].key = &avrcp_proto_data->chandle;
1721 key[3].length = 1;
1722 key[3].key = &avrcp_proto_data->channel;
1723 key[4].length = 1;
1724 key[4].key = &k_op;
1725 key[5].length = 1;
1726 key[5].key = &frame_number;
1727 key[6].length = 0;
1728 key[6].key = NULL;
1730 fragment = (fragment_t *)wmem_tree_lookup32_array_le(reassembling, key);
1731 if (fragment && fragment->interface_id == avrcp_proto_data->interface_id &&
1732 fragment->adapter_id == avrcp_proto_data->adapter_id &&
1733 fragment->chandle == avrcp_proto_data->chandle &&
1734 fragment->psm == avrcp_proto_data->channel &&
1735 fragment->op == continuing_op &&
1736 fragment->state == 0) {
1737 fragment->state = 3;
1740 } else {
1741 /* non */
1743 break;
1744 case PDU_SET_ABSOLUTE_VOLUME:
1745 proto_tree_add_item(tree, hf_btavrcp_absolute_volume_rfa, tvb, offset, 1, ENC_BIG_ENDIAN);
1746 pitem = proto_tree_add_item(tree, hf_btavrcp_absolute_volume, tvb, offset, 1, ENC_BIG_ENDIAN);
1747 volume = tvb_get_uint8(tvb, offset) & 0x7F;
1748 volume_percent = (unsigned) ((double) volume * 100 / (double) 0x7F);
1749 offset += 1;
1751 proto_item_append_text(pitem, " (%u%%)", volume_percent);
1752 col_append_fstr(pinfo->cinfo, COL_INFO, " - Volume: %u%%", volume_percent);
1753 break;
1754 case PDU_SET_ADDRESSED_PLAYER:
1755 if (is_command) {
1756 unsigned player_id;
1758 proto_tree_add_item(tree, hf_btavrcp_player_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1759 player_id = tvb_get_ntohs(tvb, offset);
1760 offset += 2;
1762 col_append_fstr(pinfo->cinfo, COL_INFO, " - Player ID: %u", player_id);
1763 } else {
1764 unsigned status;
1766 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1767 status = tvb_get_uint8(tvb, offset);
1768 offset += 1;
1770 col_append_fstr(pinfo->cinfo, COL_INFO, " - Status: %s",
1771 val_to_str_const(status, status_vals, "Unknown status"));
1773 break;
1774 case PDU_PLAY_ITEM:
1775 if (is_command) {
1776 unsigned scope;
1777 uint64_t uid;
1778 unsigned uid_counter;
1780 proto_tree_add_item(tree, hf_btavrcp_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
1781 scope = tvb_get_uint8(tvb, offset);
1782 offset += 1;
1783 proto_tree_add_item(tree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
1784 uid = tvb_get_ntoh64(tvb, offset);
1785 offset += 8;
1786 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1787 uid_counter = tvb_get_ntohs(tvb, offset);
1788 offset += 2;
1790 col_append_fstr(pinfo->cinfo, COL_INFO, " - Scope: %s, Uid: 0x%016" PRIx64 ", UidCounter: 0x%04x",
1791 val_to_str_const(scope, scope_vals, "unknown"), uid, uid_counter);
1792 } else {
1793 unsigned status;
1795 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1796 status = tvb_get_uint8(tvb, offset);
1797 offset += 1;
1798 col_append_fstr(pinfo->cinfo, COL_INFO, " - Status: %s",
1799 val_to_str_const(status, status_vals, "Unknown status"));
1801 break;
1802 case PDU_ADD_TO_NOW_PLAYING:
1803 if (is_command) {
1804 unsigned scope;
1805 uint64_t uid;
1806 unsigned uid_counter;
1808 proto_tree_add_item(tree, hf_btavrcp_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
1809 scope = tvb_get_uint8(tvb, offset);
1810 offset += 1;
1811 proto_tree_add_item(tree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
1812 uid = tvb_get_ntoh64(tvb, offset);
1813 offset += 8;
1814 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1815 uid_counter = tvb_get_ntohs(tvb, offset);
1816 offset += 2;
1818 col_append_fstr(pinfo->cinfo, COL_INFO, " - Scope: %s, Uid: 0x%016" PRIx64 ", UidCounter: 0x%04x",
1819 val_to_str_const(scope, scope_vals, "unknown"), uid, uid_counter);
1820 } else {
1821 unsigned status;
1823 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1824 status = tvb_get_uint8(tvb, offset);
1825 offset += 1;
1826 col_append_fstr(pinfo->cinfo, COL_INFO, " - Status: %s",
1827 val_to_str_const(status, status_vals, "Unknown status"));
1829 break;
1832 return offset;
1836 static int
1837 dissect_browsing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1838 int offset, bool is_command)
1840 unsigned pdu_id;
1841 unsigned status = 0x00;
1843 proto_tree_add_item(tree, hf_btavrcp_browsing_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1844 pdu_id = tvb_get_uint8(tvb, offset);
1845 offset += 1;
1847 proto_tree_add_item(tree, hf_btavrcp_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1848 offset += 2;
1850 if (is_command) {
1851 col_append_str(pinfo->cinfo, COL_INFO, ": Command");
1852 } else {
1853 /* common code "status" in response */
1854 proto_tree_add_item(tree, hf_btavrcp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
1855 status = tvb_get_uint8(tvb, offset);
1856 offset += 1;
1858 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
1859 val_to_str_const(status, status_vals, "Unknown status"));
1862 col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
1863 val_to_str_const(pdu_id, browsing_pdu_id_vals, "Unknown opcode"));
1865 if (is_command || status == STATUS_OK) switch(pdu_id) {
1866 case PDU_SET_BROWSED_PLAYER:
1867 if (is_command) {
1868 unsigned player_id;
1870 proto_tree_add_item(tree, hf_btavrcp_player_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1871 player_id = tvb_get_ntohs(tvb, offset);
1872 offset += 2;
1874 col_append_fstr(pinfo->cinfo, COL_INFO, " - Player ID: %u", player_id);
1875 } else {
1876 unsigned i_folder;
1877 unsigned folder_depth;
1878 unsigned folder_name_length;
1879 proto_item *pitem;
1880 proto_tree *ptree;
1881 const uint8_t *folder_name;
1883 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1884 offset += 2;
1885 proto_tree_add_item(tree, hf_btavrcp_number_of_items, tvb, offset, 4, ENC_BIG_ENDIAN);
1886 offset += 4;
1887 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
1888 offset += 2;
1889 proto_tree_add_item(tree, hf_btavrcp_folder_depth, tvb, offset, 1, ENC_BIG_ENDIAN);
1890 folder_depth = tvb_get_uint8(tvb, offset);
1891 offset += 1;
1893 pitem = proto_tree_add_none_format(tree, hf_btavrcp_current_path, tvb, offset, tvb_reported_length_remaining(tvb, offset), "Current Path: /");
1894 col_append_str(pinfo->cinfo, COL_INFO, "Current Path: /");
1895 ptree = proto_item_add_subtree(pitem, ett_btavrcp_path);
1897 for (i_folder = 0; i_folder < folder_depth; ++i_folder) {
1898 proto_tree_add_item(ptree, hf_btavrcp_folder_name_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1899 folder_name_length = tvb_get_ntohs(tvb, offset);
1900 offset += 2;
1901 proto_tree_add_item_ret_string(ptree, hf_btavrcp_folder_name, tvb, offset, folder_name_length, ENC_ASCII|ENC_NA, pinfo->pool, &folder_name);
1902 offset += folder_name_length;
1903 proto_item_append_text(pitem, "%s/", folder_name);
1904 col_append_fstr(pinfo->cinfo, COL_INFO, "%s/", folder_name);
1907 break;
1908 case PDU_GET_FOLDER_ITEMS:
1909 if (is_command) {
1910 unsigned attribute_count;
1911 unsigned scope;
1912 unsigned start_item;
1913 unsigned end_item;
1915 proto_tree_add_item(tree, hf_btavrcp_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
1916 scope = tvb_get_uint8(tvb, offset);
1917 offset += 1;
1918 proto_tree_add_item(tree, hf_btavrcp_start_item, tvb, offset, 4, ENC_BIG_ENDIAN);
1919 start_item = tvb_get_ntohl(tvb, offset);
1920 offset += 4;
1921 proto_tree_add_item(tree, hf_btavrcp_end_item, tvb, offset, 4, ENC_BIG_ENDIAN);
1922 end_item = tvb_get_ntohl(tvb, offset);
1923 offset += 4;
1924 proto_tree_add_item(tree, hf_btavrcp_attribute_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1925 attribute_count = tvb_get_uint8(tvb, offset);
1926 offset += 1;
1927 offset = dissect_attribute_id_list(tvb, tree, offset, attribute_count);
1929 col_append_fstr(pinfo->cinfo, COL_INFO, " - Scope: %s, StartItem: 0x%04x, EndItem: 0x%04x",
1930 val_to_str_const(scope, scope_vals, "unknown"), start_item, end_item);
1931 } else {
1932 unsigned number_of_items;
1933 unsigned uid_counter;
1934 unsigned i_item;
1935 unsigned item_type;
1936 unsigned item_length;
1938 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1939 uid_counter = tvb_get_ntohs(tvb, offset);
1940 offset += 2;
1941 proto_tree_add_item(tree, hf_btavrcp_number_of_items16, tvb, offset, 2, ENC_BIG_ENDIAN);
1942 number_of_items = tvb_get_ntohs(tvb, offset);
1943 offset += 2;
1945 col_append_fstr(pinfo->cinfo, COL_INFO, " - UidCounter: 0x%04x, NumberOfItems: %u",
1946 uid_counter, number_of_items);
1948 for (i_item = 0; i_item < number_of_items; ++i_item) {
1949 item_type = tvb_get_uint8(tvb, offset);
1950 item_length = tvb_get_ntohs(tvb, offset + 1);
1952 if (item_type == ITEM_MEDIAPLAYER) {
1953 dissect_item_mediaplayer(tvb, pinfo, tree, offset);
1954 offset += 1 + 2 + item_length;
1955 } else if (item_type == ITEM_MEDIA_ELEMENT) {
1956 dissect_item_media_element(tvb, pinfo, tree, offset);
1957 offset += 1 + 2 + item_length;
1958 } else if (item_type == ITEM_FOLDER) {
1959 dissect_item_folder(tvb, pinfo, tree, offset);
1960 offset += 1 + 2 + item_length;
1961 } else {
1962 proto_tree_add_item(tree, hf_btavrcp_data, tvb, offset, item_length, ENC_NA);
1963 offset += 1 + 2 + item_length;
1967 break;
1968 case PDU_CHANGE_PATH:
1969 if (is_command) {
1970 uint64_t uid;
1971 unsigned uid_counter;
1972 unsigned direction;
1974 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
1975 uid_counter = tvb_get_ntohs(tvb, offset);
1976 offset += 2;
1977 proto_tree_add_item(tree, hf_btavrcp_direction, tvb, offset, 1, ENC_BIG_ENDIAN);
1978 direction = tvb_get_uint8(tvb, offset);
1979 offset += 1;
1980 proto_tree_add_item(tree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
1981 uid = tvb_get_ntoh64(tvb, offset);
1982 offset += 8;
1984 col_append_fstr(pinfo->cinfo, COL_INFO, " - Direction: %s, Uid: 0x%016" PRIx64 ", UidCounter: 0x%04x",
1985 val_to_str_const(direction, direction_vals, "unknown"), uid, uid_counter);
1986 } else {
1987 unsigned number_of_items;
1989 proto_tree_add_item(tree, hf_btavrcp_number_of_items, tvb, offset, 4, ENC_BIG_ENDIAN);
1990 number_of_items = tvb_get_ntohl(tvb, offset);
1991 offset += 4;
1992 col_append_fstr(pinfo->cinfo, COL_INFO, " - NumberOfItems: %u", number_of_items);
1994 break;
1995 case PDU_GET_ITEM_ATTRIBUTES:
1996 if (is_command) {
1997 unsigned number_of_attributes;
1998 uint64_t uid;
1999 unsigned uid_counter;
2000 unsigned scope;
2002 proto_tree_add_item(tree, hf_btavrcp_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
2003 scope = tvb_get_uint8(tvb, offset);
2004 offset += 1;
2005 proto_tree_add_item(tree, hf_btavrcp_uid, tvb, offset, 8, ENC_BIG_ENDIAN);
2006 uid = tvb_get_ntoh64(tvb, offset);
2007 offset += 8;
2008 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
2009 uid_counter = tvb_get_ntohs(tvb, offset);
2010 offset += 2;
2011 proto_tree_add_item(tree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
2012 number_of_attributes = tvb_get_uint8(tvb, offset);
2014 col_append_fstr(pinfo->cinfo, COL_INFO, " - Scope: %s, Uid: 0x%016" PRIx64 ", UidCounter: 0x%04x",
2015 val_to_str_const(scope, scope_vals, "unknown"), uid, uid_counter);
2017 offset += 1;
2018 offset = dissect_attribute_id_list(tvb, tree, offset, number_of_attributes);
2019 } else {
2020 unsigned number_of_attributes;
2022 proto_tree_add_item(tree, hf_btavrcp_number_of_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
2023 number_of_attributes = tvb_get_uint8(tvb, offset);
2024 offset += 1;
2025 offset = dissect_attribute_entries(tvb, pinfo, tree, offset, number_of_attributes);
2027 break;
2028 case PDU_SEARCH:
2029 if (is_command) {
2030 unsigned search_length;
2032 proto_tree_add_item(tree, hf_btavrcp_character_set, tvb, offset, 2, ENC_BIG_ENDIAN);
2033 offset += 2;
2034 proto_tree_add_item(tree, hf_btavrcp_search_length, tvb, offset, 2, ENC_BIG_ENDIAN);
2035 search_length = tvb_get_ntohs(tvb, offset);
2036 offset += 2;
2037 proto_tree_add_item(tree, hf_btavrcp_search, tvb, offset, search_length, ENC_NA);
2038 offset += search_length;
2039 } else {
2040 proto_tree_add_item(tree, hf_btavrcp_uid_counter, tvb, offset, 2, ENC_BIG_ENDIAN);
2041 offset += 2;
2042 proto_tree_add_item(tree, hf_btavrcp_number_of_items, tvb, offset, 4, ENC_BIG_ENDIAN);
2043 offset += 4;
2045 break;
2046 case PDU_GENERAL_REJECT:
2047 /* implemented in common code before switch() */
2048 break;
2052 return offset;
2055 static int
2056 dissect_btavrcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2058 proto_item *ti;
2059 proto_tree *btavrcp_tree;
2060 proto_item *pitem = NULL;
2061 int offset = 0;
2062 uint32_t opcode;
2063 uint32_t op = 0;
2064 uint32_t op_arg = 0;
2065 unsigned ctype;
2066 unsigned response_time;
2067 unsigned max_response_time;
2068 unsigned is_command;
2069 timing_info_t *timing_info;
2070 wmem_tree_key_t key[9];
2071 uint32_t k_op_arg;
2072 uint32_t frame_number;
2073 int previous_proto;
2074 avrcp_proto_data_t avrcp_proto_data;
2076 previous_proto = (GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers)))));
2077 if (previous_proto == proto_btavctp) {
2078 btavctp_data_t *avctp_data;
2080 avctp_data = (btavctp_data_t *) data;
2082 avrcp_proto_data.interface_id = avctp_data->interface_id;
2083 avrcp_proto_data.adapter_id = avctp_data->adapter_id;
2084 avrcp_proto_data.chandle = avctp_data->chandle;
2085 avrcp_proto_data.channel = avctp_data->psm;
2087 is_command = !avctp_data->cr;
2088 } else {
2089 avrcp_proto_data.interface_id = HCI_INTERFACE_DEFAULT;
2090 avrcp_proto_data.adapter_id = HCI_ADAPTER_DEFAULT;
2091 avrcp_proto_data.chandle = 0;
2092 avrcp_proto_data.channel = 0;
2094 /* NOTE: There is need to allow user specify that */
2095 is_command = (pinfo->p2p_dir == P2P_DIR_SENT);
2098 ti = proto_tree_add_item(tree, proto_btavrcp, tvb, offset, tvb_captured_length_remaining(tvb, offset), 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_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
2112 break;
2115 if (avrcp_proto_data.channel == BTL2CAP_PSM_AVCTP_BRWS) {
2116 col_append_str(pinfo->cinfo, COL_INFO, "Browsing");
2117 offset = dissect_browsing(tvb, pinfo, btavrcp_tree, offset, is_command);
2118 } else {
2119 proto_tree_add_item(btavrcp_tree, hf_btavrcp_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2120 proto_tree_add_item(btavrcp_tree, hf_btavrcp_ctype, tvb, offset, 1, ENC_BIG_ENDIAN);
2121 ctype = tvb_get_uint8(tvb, offset) & 0x0F;
2122 offset += 1;
2123 proto_tree_add_item(btavrcp_tree, hf_btavrcp_subunit_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2124 proto_tree_add_item(btavrcp_tree, hf_btavrcp_subunit_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2125 offset += 1;
2126 proto_tree_add_item(btavrcp_tree, hf_btavrcp_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
2127 opcode = tvb_get_uint8(tvb, offset);
2128 offset += 1;
2130 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
2131 val_to_str_const(opcode, opcode_vals, "Unknown opcode"),
2132 val_to_str_const(ctype, ctype_vals, "Unknown ctype"));
2134 switch(opcode) {
2135 case OPCODE_PASSTHROUGH:
2136 offset = dissect_passthrough(tvb, pinfo, btavrcp_tree, offset,
2137 is_command, &op);
2138 break;
2139 case OPCODE_UNIT:
2140 offset = dissect_unit(tvb, btavrcp_tree, offset, is_command);
2141 break;
2142 case OPCODE_SUBUNIT:
2143 offset = dissect_subunit(tvb, btavrcp_tree, offset, is_command);
2144 break;
2145 case OPCODE_VENDOR_DEPENDENT:
2146 offset = dissect_vendor_dependent(tvb, pinfo, btavrcp_tree,
2147 offset, ctype, &op, &op_arg, is_command, &avrcp_proto_data);
2148 break;
2151 k_op_arg = (ctype == 0x0a) ? UINT32_MAX : op_arg;
2152 frame_number = pinfo->num;
2154 key[0].length = 1;
2155 key[0].key = &avrcp_proto_data.interface_id;
2156 key[1].length = 1;
2157 key[1].key = &avrcp_proto_data.adapter_id;
2158 key[2].length = 1;
2159 key[2].key = &avrcp_proto_data.chandle;
2160 key[3].length = 1;
2161 key[3].key = &avrcp_proto_data.channel;
2162 key[4].length = 1;
2163 key[4].key = &opcode;
2164 key[5].length = 1;
2165 key[5].key = &op;
2166 key[6].length = 1;
2167 key[6].key = &k_op_arg;
2168 key[7].length = 1;
2169 key[7].key = &frame_number;
2170 key[8].length = 0;
2171 key[8].key = NULL;
2173 if (pinfo->fd->visited == 0) {
2174 if (is_command) {
2175 if (ctype == 0x00) { /* MTC is for CONTROL */
2176 max_response_time = 200;
2177 } else if (ctype == 0x01 || ctype == 0x03) {
2178 /* MTP is for STATUS, NOTIFY */
2179 max_response_time = 1000;
2180 } else { /* RCP */
2181 max_response_time = 100;
2184 timing_info = wmem_new(wmem_file_scope(), timing_info_t);
2185 timing_info->command_frame_number = pinfo->num;
2186 timing_info->command_timestamp = pinfo->abs_ts;
2187 timing_info->response_frame_number = 0;
2188 timing_info->response_timestamp.secs = 0;
2189 timing_info->response_timestamp.nsecs = 0;
2190 timing_info->max_response_time = max_response_time;
2192 timing_info->interface_id = avrcp_proto_data.interface_id;
2193 timing_info->adapter_id = avrcp_proto_data.adapter_id;
2194 timing_info->chandle = avrcp_proto_data.chandle;
2195 timing_info->psm = avrcp_proto_data.channel;
2196 timing_info->opcode = opcode;
2197 timing_info->op = op;
2198 timing_info->op_arg = op_arg;
2199 timing_info->used = 0;
2201 wmem_tree_insert32_array(timing, key, timing_info);
2202 } else {
2203 timing_info = (timing_info_t *)wmem_tree_lookup32_array_le(timing, key);
2204 if (timing_info && timing_info->interface_id == avrcp_proto_data.interface_id &&
2205 timing_info->adapter_id == avrcp_proto_data.adapter_id &&
2206 timing_info->chandle == avrcp_proto_data.chandle &&
2207 timing_info->psm == avrcp_proto_data.channel &&
2208 timing_info->opcode == opcode &&
2209 timing_info->op == op &&
2210 ((ctype == 0x0a) ? 1 : (timing_info->op_arg == op_arg)) &&
2211 timing_info->used == 0) {
2212 timing_info->response_frame_number = pinfo->num;
2213 timing_info->response_timestamp = pinfo->abs_ts;
2214 timing_info->used = 1;
2218 k_op_arg = (ctype == 0x0a) ? UINT32_MAX : op_arg;
2219 frame_number = pinfo->num;
2221 key[0].length = 1;
2222 key[0].key = &avrcp_proto_data.interface_id;
2223 key[1].length = 1;
2224 key[1].key = &avrcp_proto_data.adapter_id;
2225 key[2].length = 1;
2226 key[2].key = &avrcp_proto_data.chandle;
2227 key[3].length = 1;
2228 key[3].key = &avrcp_proto_data.channel;
2229 key[4].length = 1;
2230 key[4].key = &opcode;
2231 key[5].length = 1;
2232 key[5].key = &op;
2233 key[6].length = 1;
2234 key[6].key = &k_op_arg;
2235 key[7].length = 1;
2236 key[7].key = &frame_number;
2237 key[8].length = 0;
2238 key[8].key = NULL;
2242 timing_info = (timing_info_t *)wmem_tree_lookup32_array_le(timing, key);
2243 if (timing_info && timing_info->interface_id == avrcp_proto_data.interface_id &&
2244 timing_info->adapter_id == avrcp_proto_data.adapter_id &&
2245 timing_info->chandle == avrcp_proto_data.chandle &&
2246 timing_info->psm == avrcp_proto_data.channel &&
2247 timing_info->opcode == opcode &&
2248 timing_info->op == op &&
2249 ((ctype == 0x0a) ? 1 : (timing_info->op_arg == op_arg))) {
2251 if (timing_info->command_timestamp.nsecs > timing_info->response_timestamp.nsecs) {
2252 response_time = timing_info->response_timestamp.nsecs + (1000000000 - timing_info->command_timestamp.nsecs);
2253 response_time /= 1000000;
2254 response_time += ((unsigned)timing_info->response_timestamp.secs - 1 - (unsigned)timing_info->command_timestamp.secs) / 1000;
2255 } else {
2256 response_time = timing_info->response_timestamp.nsecs - timing_info->command_timestamp.nsecs;
2257 response_time /= 1000000;
2258 response_time += ((unsigned)timing_info->response_timestamp.secs - (unsigned)timing_info->command_timestamp.secs) / 1000;
2261 if (timing_info->response_frame_number == 0) {
2262 response_time = UINT_MAX;
2265 pitem = proto_tree_add_uint(btavrcp_tree, hf_btavrcp_response_time, tvb, 0, 0, response_time);
2266 proto_item_append_text(pitem, "/%ums", timing_info->max_response_time);
2267 if (response_time > timing_info->max_response_time) {
2268 proto_item_append_text(pitem, "; TIME EXCEEDED");
2270 proto_item_set_generated(pitem);
2272 if (timing_info->response_frame_number == 0) {
2273 pitem = proto_tree_add_expert(btavrcp_tree, pinfo, &ei_btavrcp_no_response, tvb, 0, 0);
2274 proto_item_set_generated(pitem);
2275 } else {
2276 if (is_command) {
2277 pitem = proto_tree_add_uint(btavrcp_tree, hf_btavrcp_response_in_frame, tvb, 0, 0, timing_info->response_frame_number);
2278 proto_item_set_generated(pitem);
2279 } else {
2280 pitem = proto_tree_add_uint(btavrcp_tree, hf_btavrcp_command_in_frame, tvb, 0, 0, timing_info->command_frame_number);
2281 proto_item_set_generated(pitem);
2289 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2290 pitem = proto_tree_add_item(btavrcp_tree, hf_btavrcp_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
2291 expert_add_info(pinfo, pitem, &ei_btavrcp_unexpected_data);
2294 return offset;
2298 void
2299 proto_register_btavrcp(void)
2301 module_t *module;
2302 expert_module_t* expert_btavrcp;
2304 static hf_register_info hf[] = {
2305 { &hf_btavrcp_reserved,
2306 { "Reserved", "btavrcp.reserved",
2307 FT_UINT8, BASE_HEX, NULL, 0xF0,
2308 NULL, HFILL }
2310 { &hf_btavrcp_ctype,
2311 { "Ctype", "btavrcp.ctype",
2312 FT_UINT8, BASE_HEX, VALS(ctype_vals), 0x0F,
2313 NULL, HFILL }
2315 { &hf_btavrcp_subunit_type,
2316 { "Subunit Type", "btavrcp.subunit_type",
2317 FT_UINT8, BASE_HEX, VALS(subunit_type_vals), 0xF8,
2318 NULL, HFILL }
2320 { &hf_btavrcp_subunit_id,
2321 { "Subunit ID", "btavrcp.subunit_id",
2322 FT_UINT8, BASE_HEX, NULL, 0x07,
2323 NULL, HFILL }
2325 { &hf_btavrcp_opcode,
2326 { "Opcode", "btavrcp.opcode",
2327 FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x00,
2328 NULL, HFILL }
2330 { &hf_btavrcp_company_id,
2331 { "Company ID", "btavrcp.company_id",
2332 FT_UINT24, BASE_OUI, NULL, 0x00,
2333 NULL, HFILL }
2335 { &hf_btavrcp_passthrough_state,
2336 { "State", "btavrcp.passthrough.state",
2337 FT_UINT8, BASE_HEX, VALS(passthrough_state_vals), 0x80,
2338 NULL, HFILL }
2340 { &hf_btavrcp_passthrough_operation,
2341 { "Operation ID", "btavrcp.passthrough.operation",
2342 FT_UINT8, BASE_HEX, VALS(passthrough_operation_vals), 0x7F,
2343 NULL, HFILL }
2345 { &hf_btavrcp_passthrough_data_length,
2346 { "Data Length", "btavrcp.passthrough.length",
2347 FT_UINT8, BASE_HEX, NULL, 0x00,
2348 NULL, HFILL }
2350 { &hf_btavrcp_passthrough_vendor_unique_id,
2351 { "Vendor Unique ID", "btavrcp.passthrough.vendor_unique_id",
2352 FT_UINT16, BASE_HEX, VALS(vendor_unique_id_vals), 0x00,
2353 NULL, HFILL }
2355 { &hf_btavrcp_passthrough_company_id,
2356 { "Company ID", "btavrcp.passthrough.company_id",
2357 FT_UINT24, BASE_OUI, NULL, 0x00,
2358 NULL, HFILL }
2360 { &hf_btavrcp_unit_unknown,
2361 { "Unknown", "btavrcp.unit.unknown",
2362 FT_UINT8, BASE_HEX, NULL, 0x0,
2363 NULL, HFILL }
2365 { &hf_btavrcp_unit_type,
2366 { "Unit Type", "btavrcp.unit.type",
2367 FT_UINT8, BASE_HEX, VALS(subunit_type_vals), 0xF8,
2368 NULL, HFILL }
2370 { &hf_btavrcp_unit_id,
2371 { "Subunit ID", "btavrcp.unit.id",
2372 FT_UINT8, BASE_HEX, NULL, 0x07,
2373 NULL, HFILL }
2375 { &hf_btavrcp_subunit_page,
2376 { "Page", "btavrcp.subunit.page",
2377 FT_UINT8, BASE_HEX, VALS(subunit_type_vals), 0xF8,
2378 NULL, HFILL }
2380 { &hf_btavrcp_subunit_extension_code,
2381 { "Extension Code", "btavrcp.subunit.extension_code",
2382 FT_UINT8, BASE_HEX, NULL, 0x07,
2383 NULL, HFILL }
2385 { &hf_btavrcp_bt_pdu_id,
2386 { "PDU ID", "btavrcp.pdu_id",
2387 FT_UINT8, BASE_HEX, VALS(pdu_id_vals), 0x00,
2388 NULL, HFILL }
2390 { &hf_btavrcp_pdu_id,
2391 { "PDU ID", "btavrcp.pdu_id",
2392 FT_UINT8, BASE_HEX, NULL, 0x00,
2393 NULL, HFILL }
2395 { &hf_btavrcp_bt_continuing_pdu_id,
2396 { "Continuing PDU ID", "btavrcp.pdu_id",
2397 FT_UINT8, BASE_HEX, VALS(pdu_id_vals), 0x00,
2398 NULL, HFILL }
2400 { &hf_btavrcp_browsing_pdu_id,
2401 { "PDU ID", "btavrcp.pdu_id",
2402 FT_UINT8, BASE_HEX, VALS(browsing_pdu_id_vals), 0x00,
2403 NULL, HFILL }
2405 { &hf_btavrcp_rfa,
2406 { "RFA", "btavrcp.rfa",
2407 FT_UINT8, BASE_HEX, NULL, 0xFC,
2408 NULL, HFILL }
2410 { &hf_btavrcp_packet_type,
2411 { "Packet Type", "btavrcp.packet_type",
2412 FT_UINT8, BASE_HEX, VALS(packet_type_vals), 0x03,
2413 NULL, HFILL }
2415 { &hf_btavrcp_length,
2416 { "Parameter Length", "btavrcp.length",
2417 FT_UINT16, BASE_DEC, NULL, 0x00,
2418 NULL, HFILL }
2420 { &hf_btavrcp_player_id,
2421 { "Player ID", "btavrcp.player_id",
2422 FT_UINT16, BASE_DEC, NULL, 0x00,
2423 NULL, HFILL }
2425 { &hf_btavrcp_status,
2426 { "Status", "btavrcp.status",
2427 FT_UINT8, BASE_HEX, VALS(status_vals), 0x00,
2428 NULL, HFILL }
2430 { &hf_btavrcp_uid_counter,
2431 { "UID Counter", "btavrcp.uid_counter",
2432 FT_UINT16, BASE_HEX, NULL, 0x00,
2433 NULL, HFILL }
2435 { &hf_btavrcp_character_set,
2436 { "Character Set", "btavrcp.character_set",
2437 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &mibenum_vals_character_sets_ext, 0x00,
2438 NULL, HFILL }
2440 { &hf_btavrcp_number_of_items,
2441 { "Number Of Items", "btavrcp.number_of_items",
2442 FT_UINT32, BASE_DEC, NULL, 0x00,
2443 "32bit number of items", HFILL }
2445 { &hf_btavrcp_number_of_items16,
2446 { "Number Of Items", "btavrcp.number_of_items",
2447 FT_UINT16, BASE_DEC, NULL, 0x00,
2448 "16bit number of items", HFILL }
2450 { &hf_btavrcp_folder_depth,
2451 { "Folder Depth", "btavrcp.folder_depth",
2452 FT_UINT8, BASE_DEC, NULL, 0x00,
2453 NULL, HFILL }
2455 { &hf_btavrcp_folder_name_length,
2456 { "Folder Name Length", "btavrcp.folder_name_length",
2457 FT_UINT16, BASE_DEC, NULL, 0x00,
2458 NULL, HFILL }
2460 { &hf_btavrcp_folder_name,
2461 { "Folder Name", "btavrcp.folder_name",
2462 FT_STRING, BASE_NONE, NULL, 0x00,
2463 NULL, HFILL }
2465 { &hf_btavrcp_search_length,
2466 { "Search String Length", "btavrcp.search_length",
2467 FT_UINT16, BASE_DEC, NULL, 0x00,
2468 NULL, HFILL }
2470 { &hf_btavrcp_search,
2471 { "Search String", "btavrcp.search",
2472 FT_NONE, BASE_NONE, NULL, 0x00,
2473 NULL, HFILL }
2475 { &hf_btavrcp_number_of_attributes,
2476 { "Number of Attributes", "btavrcp.number_of_attributes",
2477 FT_UINT8, BASE_DEC|BASE_SPECIAL_VALS, VALS(unique_all_supported_attributes), 0x00,
2478 NULL, HFILL }
2480 { &hf_btavrcp_attribute_count,
2481 { "Attribute Count", "btavrcp.attribute_count",
2482 FT_UINT8, BASE_DEC, VALS(attribute_count_vals), 0x00,
2483 NULL, HFILL }
2485 { &hf_btavrcp_direction,
2486 { "Direction", "btavrcp.direction",
2487 FT_UINT8, BASE_HEX, VALS(direction_vals), 0x00,
2488 NULL, HFILL }
2490 { &hf_btavrcp_scope,
2491 { "Scope", "btavrcp.scope",
2492 FT_UINT8, BASE_HEX, VALS(scope_vals), 0x00,
2493 NULL, HFILL }
2495 { &hf_btavrcp_start_item,
2496 { "StartItem", "btavrcp.start_item",
2497 FT_UINT32, BASE_DEC, NULL, 0x00,
2498 NULL, HFILL }
2500 { &hf_btavrcp_end_item,
2501 { "EndItem", "btavrcp.end_item",
2502 FT_UINT32, BASE_DEC, NULL, 0x00,
2503 NULL, HFILL }
2505 { &hf_btavrcp_uid,
2506 { "UID", "btavrcp.uid",
2507 FT_UINT64, BASE_HEX, NULL, 0x00,
2508 NULL, HFILL }
2510 { &hf_btavrcp_identifier,
2511 { "Identifier", "btavrcp.identifier",
2512 FT_UINT64, BASE_HEX, NULL, 0x00,
2513 NULL, HFILL }
2515 { &hf_btavrcp_play_status,
2516 { "Play Status", "btavrcp.play_status",
2517 FT_UINT8, BASE_HEX, VALS(play_status_vals), 0x00,
2518 NULL, HFILL }
2520 { &hf_btavrcp_song_length,
2521 { "Song Length", "btavrcp.song_length",
2522 FT_UINT32, BASE_DEC, NULL, 0x00,
2523 NULL, HFILL }
2525 { &hf_btavrcp_song_position,
2526 { "Song Position", "btavrcp.song_position",
2527 FT_UINT32, BASE_DEC, NULL, 0x00,
2528 NULL, HFILL }
2530 { &hf_btavrcp_notification_interval,
2531 { "Interval", "btavrcp.notification.interval",
2532 FT_UINT32, BASE_DEC, NULL, 0x00,
2533 NULL, HFILL }
2535 { &hf_btavrcp_event_id,
2536 { "Event ID", "btavrcp.notification.event_id",
2537 FT_UINT8, BASE_HEX, VALS(notification_vals), 0x00,
2538 NULL, HFILL }
2540 { &hf_btavrcp_battery_status,
2541 { "Battery Status", "btavrcp.battery_status",
2542 FT_UINT8, BASE_HEX, VALS(battery_status_vals), 0x00,
2543 NULL, HFILL }
2545 { &hf_btavrcp_number_of_character_set,
2546 { "Number of Character Set", "btavrcp.number_of_character_set",
2547 FT_UINT8, BASE_DEC, NULL, 0x00,
2548 NULL, HFILL }
2550 { &hf_btavrcp_absolute_volume_rfa,
2551 { "RFA", "btavrcp.absoluter_volume_rfa",
2552 FT_UINT8, BASE_HEX, NULL, 0x80,
2553 NULL, HFILL }
2555 { &hf_btavrcp_absolute_volume,
2556 { "Volume", "btavrcp.volume",
2557 FT_UINT8, BASE_HEX, NULL, 0x7F,
2558 NULL, HFILL }
2560 { &hf_btavrcp_capability,
2561 { "Capability", "btavrcp.capability",
2562 FT_UINT8, BASE_HEX, VALS(capability_vals), 0x00,
2563 NULL, HFILL }
2565 { &hf_btavrcp_capability_count,
2566 { "Capability Count", "btavrcp.capability.count",
2567 FT_UINT8, BASE_HEX, NULL, 0x00,
2568 NULL, HFILL }
2570 { &hf_btavrcp_item_type,
2571 { "Item Type", "btavrcp.item.type",
2572 FT_UINT8, BASE_HEX, VALS(item_type_vals), 0x00,
2573 NULL, HFILL }
2575 { &hf_btavrcp_item_length,
2576 { "Item Length", "btavrcp.item.length",
2577 FT_UINT16, BASE_DEC, NULL, 0x00,
2578 NULL, HFILL }
2581 { &hf_btavrcp_number_of_settings,
2582 { "Number of Settings", "btavrcp.number_of_settings",
2583 FT_UINT8, BASE_DEC, NULL, 0x00,
2584 NULL, HFILL }
2586 { &hf_btavrcp_settings_attribute,
2587 { "Setting Attribute", "btavrcp.settings.attribute",
2588 FT_UINT8, BASE_HEX, VALS(settings_vals), 0x00,
2589 NULL, HFILL }
2591 { &hf_btavrcp_settings_value,
2592 { "Setting Value", "btavrcp.settings.value",
2593 FT_UINT8, BASE_HEX, NULL, 0x00,
2594 NULL, HFILL }
2596 { &hf_btavrcp_system_status,
2597 { "System Status", "btavrcp.system_status",
2598 FT_UINT8, BASE_HEX, VALS(system_status_vals), 0x00,
2599 NULL, HFILL }
2601 { &hf_btavrcp_player_item,
2602 { "Player", "btavrcp.player_item",
2603 FT_NONE, BASE_NONE, NULL, 0x00,
2604 NULL, HFILL }
2606 { &hf_btavrcp_folder,
2607 { "Folder", "btavrcp.folder",
2608 FT_NONE, BASE_NONE, NULL, 0x00,
2609 NULL, HFILL }
2611 { &hf_btavrcp_item,
2612 { "Item", "btavrcp.item",
2613 FT_NONE, BASE_NONE, NULL, 0x00,
2614 NULL, HFILL }
2616 { &hf_btavrcp_features,
2617 { "Features", "btavrcp.features",
2618 FT_NONE, BASE_NONE, NULL, 0x00,
2619 NULL, HFILL }
2621 { &hf_btavrcp_not_used_features,
2622 { "Not Used Features", "btavrcp.not_used_features",
2623 FT_NONE, BASE_NONE, NULL, 0x00,
2624 NULL, HFILL }
2626 { &hf_btavrcp_attribute_list,
2627 { "Attribute List", "btavrcp.attribute_list",
2628 FT_NONE, BASE_NONE, NULL, 0x00,
2629 NULL, HFILL }
2631 { &hf_btavrcp_attribute_item,
2632 { "Attribute", "btavrcp.attribute_item",
2633 FT_NONE, BASE_NONE, NULL, 0x00,
2634 NULL, HFILL }
2636 { &hf_btavrcp_attribute_entries,
2637 { "Attribute Entries", "btavrcp.attribute_entries",
2638 FT_NONE, BASE_NONE, NULL, 0x00,
2639 NULL, HFILL }
2641 { &hf_btavrcp_attribute,
2642 { "Attribute ID", "btavrcp.attribute",
2643 FT_UINT32, BASE_HEX, VALS(attribute_id_vals), 0x00,
2644 NULL, HFILL }
2646 { &hf_btavrcp_attribute_value_length,
2647 { "Value Length", "btavrcp.value.length",
2648 FT_UINT16, BASE_DEC, NULL, 0x00,
2649 NULL, HFILL }
2651 { &hf_btavrcp_attribute_value,
2652 { "Value", "btavrcp.value",
2653 FT_STRING, BASE_NONE, NULL, 0x00,
2654 NULL, HFILL }
2656 { &hf_btavrcp_displayable_name_length,
2657 { "Displayable Name Length", "btavrcp.displayable_name_length",
2658 FT_UINT16, BASE_DEC, NULL, 0x00,
2659 NULL, HFILL }
2661 { &hf_btavrcp_displayable_name,
2662 { "Displayable Name", "btavrcp.displayable_name",
2663 FT_STRING, BASE_NONE, NULL, 0x00,
2664 NULL, HFILL }
2666 { &hf_btavrcp_media_type,
2667 { "Media Type", "btavrcp.media_type",
2668 FT_UINT8, BASE_HEX, VALS(media_type_vals), 0x00,
2669 NULL, HFILL }
2671 { &hf_btavrcp_folder_type,
2672 { "Folder Type", "btavrcp.folder_type",
2673 FT_UINT8, BASE_HEX, VALS(folder_type_vals), 0x00,
2674 NULL, HFILL }
2676 { &hf_btavrcp_folder_playable,
2677 { "Folder Playable", "btavrcp.folder_playable",
2678 FT_UINT8, BASE_HEX, VALS(folder_playable_vals), 0x00,
2679 NULL, HFILL }
2681 { &hf_btavrcp_major_player_type,
2682 { "Major Player Type", "btavrcp.major_player_type",
2683 FT_UINT8, BASE_HEX, VALS(major_player_type_vals), 0x00,
2684 NULL, HFILL }
2686 { &hf_btavrcp_player_subtype,
2687 { "Player SubType", "btavrcp.player_subtype",
2688 FT_UINT32, BASE_HEX, VALS(player_subtype_vals), 0x00,
2689 NULL, HFILL }
2691 { &hf_btavrcp_setting_value_length,
2692 { "Value Length", "btavrcp.setting_value.length",
2693 FT_UINT16, BASE_DEC, NULL, 0x00,
2694 NULL, HFILL }
2696 { &hf_btavrcp_setting_value,
2697 { "Value", "btavrcp.setting_value",
2698 FT_STRING, BASE_NONE, NULL, 0x00,
2699 NULL, HFILL }
2701 { &hf_btavrcp_attribute_name_length,
2702 { "Name Length", "btavrcp.attribute_name.length",
2703 FT_UINT8, BASE_DEC, NULL, 0x00,
2704 NULL, HFILL }
2706 { &hf_btavrcp_attribute_name,
2707 { "Name", "btavrcp.attribute_name",
2708 FT_STRING, BASE_NONE, NULL, 0x00,
2709 NULL, HFILL }
2711 /* features */
2712 { &hf_btavrcp_feature_reserved_0,
2713 { "Feature Reserved", "btavrcp.feature.reserved",
2714 FT_UINT8, BASE_HEX, NULL, 0x01,
2715 NULL, HFILL }
2717 { &hf_btavrcp_feature_reserved_1,
2718 { "Feature Reserved", "btavrcp.feature.reserved",
2719 FT_UINT8, BASE_HEX, NULL, 0x02,
2720 NULL, HFILL }
2722 { &hf_btavrcp_feature_reserved_2,
2723 { "Feature Reserved", "btavrcp.feature.reserved",
2724 FT_UINT8, BASE_HEX, NULL, 0x04,
2725 NULL, HFILL }
2727 { &hf_btavrcp_feature_reserved_3,
2728 { "Feature Reserved", "btavrcp.feature.reserved",
2729 FT_UINT8, BASE_HEX, NULL, 0x08,
2730 NULL, HFILL }
2732 { &hf_btavrcp_feature_reserved_4,
2733 { "Feature Reserved", "btavrcp.feature.reserved",
2734 FT_UINT8, BASE_HEX, NULL, 0x10,
2735 NULL, HFILL }
2737 { &hf_btavrcp_feature_reserved_5,
2738 { "Feature Reserved", "btavrcp.feature.reserved",
2739 FT_UINT8, BASE_HEX, NULL, 0x20,
2740 NULL, HFILL }
2742 { &hf_btavrcp_feature_reserved_6,
2743 { "Feature Reserved", "btavrcp.feature.reserved",
2744 FT_UINT8, BASE_HEX, NULL, 0x40,
2745 NULL, HFILL }
2747 { &hf_btavrcp_feature_reserved_7,
2748 { "Feature Reserved", "btavrcp.feature.reserved",
2749 FT_UINT8, BASE_HEX, NULL, 0x80,
2750 NULL, HFILL }
2752 { &hf_btavrcp_feature_passthrough_select,
2753 { "PASSTHROUGH Select", "btavrcp.feature.passthrough.select",
2754 FT_UINT8, BASE_HEX, NULL, 0x01,
2755 NULL, HFILL }
2757 { &hf_btavrcp_feature_passthrough_up,
2758 { "PASSTHROUGH Up", "btavrcp.feature.passthrough.up",
2759 FT_UINT8, BASE_HEX, NULL, 0x02,
2760 NULL, HFILL }
2762 { &hf_btavrcp_feature_passthrough_down,
2763 { "PASSTHROUGH Down", "btavrcp.feature.passthrough.down",
2764 FT_UINT8, BASE_HEX, NULL, 0x04,
2765 NULL, HFILL }
2767 { &hf_btavrcp_feature_passthrough_left,
2768 { "PASSTHROUGH Left", "btavrcp.feature.passthrough.left",
2769 FT_UINT8, BASE_HEX, NULL, 0x08,
2770 NULL, HFILL }
2772 { &hf_btavrcp_feature_passthrough_right,
2773 { "PASSTHROUGH Right", "btavrcp.feature.passthrough.right",
2774 FT_UINT8, BASE_HEX, NULL, 0x10,
2775 NULL, HFILL }
2777 { &hf_btavrcp_feature_passthrough_right_up,
2778 { "PASSTHROUGH Right Up", "btavrcp.feature.passthrough.right_up",
2779 FT_UINT8, BASE_HEX, NULL, 0x20,
2780 NULL, HFILL }
2782 { &hf_btavrcp_feature_passthrough_right_down,
2783 { "PASSTHROUGH Right Down", "btavrcp.feature.passthrough.right_down",
2784 FT_UINT8, BASE_HEX, NULL, 0x40,
2785 NULL, HFILL }
2787 { &hf_btavrcp_feature_passthrough_left_up,
2788 { "PASSTHROUGH Left Up", "btavrcp.feature.passthrough.left_up",
2789 FT_UINT8, BASE_HEX, NULL, 0x80,
2790 NULL, HFILL }
2792 { &hf_btavrcp_feature_passthrough_left_down,
2793 { "PASSTHROUGH Left Down", "btavrcp.feature.passthrough.left_down",
2794 FT_UINT8, BASE_HEX, NULL, 0x01,
2795 NULL, HFILL }
2797 { &hf_btavrcp_feature_passthrough_root_menu,
2798 { "PASSTHROUGH Root Menu", "btavrcp.feature.passthrough.root_menu",
2799 FT_UINT8, BASE_HEX, NULL, 0x02,
2800 NULL, HFILL }
2802 { &hf_btavrcp_feature_passthrough_setup_menu,
2803 { "PASSTHROUGH Setup Menu", "btavrcp.feature.passthrough.setup_menu",
2804 FT_UINT8, BASE_HEX, NULL, 0x04,
2805 NULL, HFILL }
2807 { &hf_btavrcp_feature_passthrough_contents_menu,
2808 { "PASSTHROUGH Contents Menu", "btavrcp.feature.passthrough.contents_menu",
2809 FT_UINT8, BASE_HEX, NULL, 0x08,
2810 NULL, HFILL }
2812 { &hf_btavrcp_feature_passthrough_favorite_menu,
2813 { "PASSTHROUGH Favorite Menu", "btavrcp.feature.passthrough.favorite_menu",
2814 FT_UINT8, BASE_HEX, NULL, 0x10,
2815 NULL, HFILL }
2817 { &hf_btavrcp_feature_passthrough_exit,
2818 { "PASSTHROUGH Exit", "btavrcp.feature.passthrough.exit",
2819 FT_UINT8, BASE_HEX, NULL, 0x20,
2820 NULL, HFILL }
2822 { &hf_btavrcp_feature_passthrough_0,
2823 { "PASSTHROUGH 0", "btavrcp.feature.passthrough.0",
2824 FT_UINT8, BASE_HEX, NULL, 0x40,
2825 NULL, HFILL }
2827 { &hf_btavrcp_feature_passthrough_1,
2828 { "PASSTHROUGH 1", "btavrcp.feature.passthrough.1",
2829 FT_UINT8, BASE_HEX, NULL, 0x80,
2830 NULL, HFILL }
2832 { &hf_btavrcp_feature_passthrough_2,
2833 { "PASSTHROUGH 2", "btavrcp.feature.passthrough.2",
2834 FT_UINT8, BASE_HEX, NULL, 0x01,
2835 NULL, HFILL }
2837 { &hf_btavrcp_feature_passthrough_3,
2838 { "PASSTHROUGH 3", "btavrcp.feature.passthrough.3",
2839 FT_UINT8, BASE_HEX, NULL, 0x02,
2840 NULL, HFILL }
2842 { &hf_btavrcp_feature_passthrough_4,
2843 { "PASSTHROUGH 4", "btavrcp.feature.passthrough.4",
2844 FT_UINT8, BASE_HEX, NULL, 0x04,
2845 NULL, HFILL }
2847 { &hf_btavrcp_feature_passthrough_5,
2848 { "PASSTHROUGH 5", "btavrcp.feature.passthrough.5",
2849 FT_UINT8, BASE_HEX, NULL, 0x08,
2850 NULL, HFILL }
2852 { &hf_btavrcp_feature_passthrough_6,
2853 { "PASSTHROUGH 6", "btavrcp.feature.passthrough.6",
2854 FT_UINT8, BASE_HEX, NULL, 0x10,
2855 NULL, HFILL }
2857 { &hf_btavrcp_feature_passthrough_7,
2858 { "PASSTHROUGH 7", "btavrcp.feature.passthrough.7",
2859 FT_UINT8, BASE_HEX, NULL, 0x20,
2860 NULL, HFILL }
2862 { &hf_btavrcp_feature_passthrough_8,
2863 { "PASSTHROUGH 8", "btavrcp.feature.passthrough.8",
2864 FT_UINT8, BASE_HEX, NULL, 0x40,
2865 NULL, HFILL }
2867 { &hf_btavrcp_feature_passthrough_9,
2868 { "PASSTHROUGH 9", "btavrcp.feature.passthrough.9",
2869 FT_UINT8, BASE_HEX, NULL, 0x80,
2870 NULL, HFILL }
2872 { &hf_btavrcp_feature_passthrough_dot,
2873 { "PASSTHROUGH Dot", "btavrcp.feature.passthrough.dot",
2874 FT_UINT8, BASE_HEX, NULL, 0x01,
2875 NULL, HFILL }
2877 { &hf_btavrcp_feature_passthrough_enter,
2878 { "PASSTHROUGH Enter", "btavrcp.feature.passthrough.enter",
2879 FT_UINT8, BASE_HEX, NULL, 0x02,
2880 NULL, HFILL }
2882 { &hf_btavrcp_feature_passthrough_clear,
2883 { "PASSTHROUGH Clear", "btavrcp.feature.passthrough.clear",
2884 FT_UINT8, BASE_HEX, NULL, 0x04,
2885 NULL, HFILL }
2887 { &hf_btavrcp_feature_passthrough_channel_up,
2888 { "PASSTHROUGH Channel Up", "btavrcp.feature.passthrough.channel_up",
2889 FT_UINT8, BASE_HEX, NULL, 0x08,
2890 NULL, HFILL }
2892 { &hf_btavrcp_feature_passthrough_channel_down,
2893 { "PASSTHROUGH Channel Down", "btavrcp.feature.passthrough.channel_down",
2894 FT_UINT8, BASE_HEX, NULL, 0x10,
2895 NULL, HFILL }
2897 { &hf_btavrcp_feature_passthrough_previous_channel,
2898 { "PASSTHROUGH Previous Channel", "btavrcp.feature.passthrough.previous_channel",
2899 FT_UINT8, BASE_HEX, NULL, 0x20,
2900 NULL, HFILL }
2902 { &hf_btavrcp_feature_passthrough_sound_select,
2903 { "PASSTHROUGH Sound Select", "btavrcp.feature.passthrough.sound_select",
2904 FT_UINT8, BASE_HEX, NULL, 0x40,
2905 NULL, HFILL }
2907 { &hf_btavrcp_feature_passthrough_input_select,
2908 { "PASSTHROUGH Input Select", "btavrcp.feature.passthrough.input_select",
2909 FT_UINT8, BASE_HEX, NULL, 0x80,
2910 NULL, HFILL }
2912 { &hf_btavrcp_feature_passthrough_display_information,
2913 { "PASSTHROUGH Display Information", "btavrcp.feature.passthrough.display_information",
2914 FT_UINT8, BASE_HEX, NULL, 0x01,
2915 NULL, HFILL }
2917 { &hf_btavrcp_feature_passthrough_help,
2918 { "PASSTHROUGH Help", "btavrcp.feature.passthrough.help",
2919 FT_UINT8, BASE_HEX, NULL, 0x02,
2920 NULL, HFILL }
2922 { &hf_btavrcp_feature_passthrough_page_up,
2923 { "PASSTHROUGH Page Up", "btavrcp.feature.passthrough.page_up",
2924 FT_UINT8, BASE_HEX, NULL, 0x04,
2925 NULL, HFILL }
2927 { &hf_btavrcp_feature_passthrough_page_down,
2928 { "PASSTHROUGH Page Down", "btavrcp.feature.passthrough.page_down",
2929 FT_UINT8, BASE_HEX, NULL, 0x08,
2930 NULL, HFILL }
2932 { &hf_btavrcp_feature_passthrough_power,
2933 { "PASSTHROUGH Power", "btavrcp.feature.passthrough.power",
2934 FT_UINT8, BASE_HEX, NULL, 0x10,
2935 NULL, HFILL }
2937 { &hf_btavrcp_feature_passthrough_volume_up,
2938 { "PASSTHROUGH Volume Up", "btavrcp.feature.passthrough.volume_up",
2939 FT_UINT8, BASE_HEX, NULL, 0x20,
2940 NULL, HFILL }
2942 { &hf_btavrcp_feature_passthrough_volume_down,
2943 { "PASSTHROUGH Volume Down", "btavrcp.feature.passthrough.volume_down",
2944 FT_UINT8, BASE_HEX, NULL, 0x40,
2945 NULL, HFILL }
2947 { &hf_btavrcp_feature_passthrough_mute,
2948 { "PASSTHROUGH Mute", "btavrcp.feature.passthrough.mute",
2949 FT_UINT8, BASE_HEX, NULL, 0x80,
2950 NULL, HFILL }
2952 { &hf_btavrcp_feature_passthrough_play,
2953 { "PASSTHROUGH Play", "btavrcp.feature.passthrough.play",
2954 FT_UINT8, BASE_HEX, NULL, 0x01,
2955 NULL, HFILL }
2957 { &hf_btavrcp_feature_passthrough_stop,
2958 { "PASSTHROUGH Stop", "btavrcp.feature.passthrough.stop",
2959 FT_UINT8, BASE_HEX, NULL, 0x02,
2960 NULL, HFILL }
2962 { &hf_btavrcp_feature_passthrough_pause,
2963 { "PASSTHROUGH Pause", "btavrcp.feature.passthrough.pause",
2964 FT_UINT8, BASE_HEX, NULL, 0x04,
2965 NULL, HFILL }
2967 { &hf_btavrcp_feature_passthrough_record,
2968 { "PASSTHROUGH Record", "btavrcp.feature.passthrough.record",
2969 FT_UINT8, BASE_HEX, NULL, 0x08,
2970 NULL, HFILL }
2972 { &hf_btavrcp_feature_passthrough_rewind,
2973 { "PASSTHROUGH Rewind", "btavrcp.feature.passthrough.rewind",
2974 FT_UINT8, BASE_HEX, NULL, 0x10,
2975 NULL, HFILL }
2977 { &hf_btavrcp_feature_passthrough_fast_forward,
2978 { "PASSTHROUGH FastForward", "btavrcp.feature.passthrough.fast_forward",
2979 FT_UINT8, BASE_HEX, NULL, 0x20,
2980 NULL, HFILL }
2982 { &hf_btavrcp_feature_passthrough_eject,
2983 { "PASSTHROUGH Eject", "btavrcp.feature.passthrough.eject",
2984 FT_UINT8, BASE_HEX, NULL, 0x40,
2985 NULL, HFILL }
2987 { &hf_btavrcp_feature_passthrough_forward,
2988 { "PASSTHROUGH Forward", "btavrcp.feature.passthrough.forward",
2989 FT_UINT8, BASE_HEX, NULL, 0x80,
2990 NULL, HFILL }
2992 { &hf_btavrcp_feature_passthrough_backward,
2993 { "PASSTHROUGH Backward", "btavrcp.feature.passthrough.backward",
2994 FT_UINT8, BASE_HEX, NULL, 0x01,
2995 NULL, HFILL }
2997 { &hf_btavrcp_feature_passthrough_angle,
2998 { "PASSTHROUGH Angle", "btavrcp.feature.passthrough.angle",
2999 FT_UINT8, BASE_HEX, NULL, 0x02,
3000 NULL, HFILL }
3002 { &hf_btavrcp_feature_passthrough_subpicture,
3003 { "PASSTHROUGH SubPicture", "btavrcp.feature.passthrough.subpicture",
3004 FT_UINT8, BASE_HEX, NULL, 0x04,
3005 NULL, HFILL }
3007 { &hf_btavrcp_feature_passthrough_f1,
3008 { "PASSTHROUGH F1", "btavrcp.feature.passthrough.f1",
3009 FT_UINT8, BASE_HEX, NULL, 0x08,
3010 NULL, HFILL }
3012 { &hf_btavrcp_feature_passthrough_f2,
3013 { "PASSTHROUGH F2", "btavrcp.feature.passthrough.f2",
3014 FT_UINT8, BASE_HEX, NULL, 0x10,
3015 NULL, HFILL }
3017 { &hf_btavrcp_feature_passthrough_f3,
3018 { "PASSTHROUGH F3", "btavrcp.feature.passthrough.f3",
3019 FT_UINT8, BASE_HEX, NULL, 0x20,
3020 NULL, HFILL }
3022 { &hf_btavrcp_feature_passthrough_f4,
3023 { "PASSTHROUGH F4", "btavrcp.feature.passthrough.f4",
3024 FT_UINT8, BASE_HEX, NULL, 0x40,
3025 NULL, HFILL }
3027 { &hf_btavrcp_feature_passthrough_f5,
3028 { "PASSTHROUGH F5", "btavrcp.feature.passthrough.f5",
3029 FT_UINT8, BASE_HEX, NULL, 0x80,
3030 NULL, HFILL }
3032 { &hf_btavrcp_feature_vendor_unique,
3033 { "Vendor Unique", "btavrcp.feature.vendor_unique",
3034 FT_UINT8, BASE_HEX, NULL, 0x01,
3035 NULL, HFILL }
3037 { &hf_btavrcp_feature_basic_group_navigation,
3038 { "Basic Group Navigation", "btavrcp.feature.basic_group_navigation",
3039 FT_UINT8, BASE_HEX, NULL, 0x02,
3040 NULL, HFILL }
3042 { &hf_btavrcp_feature_advanced_control_player,
3043 { "Advanced Control Player", "btavrcp.feature.advanced_control_player",
3044 FT_UINT8, BASE_HEX, NULL, 0x04,
3045 NULL, HFILL }
3047 { &hf_btavrcp_feature_browsing,
3048 { "Browsing", "btavrcp.feature.browsing",
3049 FT_UINT8, BASE_HEX, NULL, 0x08,
3050 NULL, HFILL }
3052 { &hf_btavrcp_feature_searching,
3053 { "Searching", "btavrcp.feature.searching",
3054 FT_UINT8, BASE_HEX, NULL, 0x10,
3055 NULL, HFILL }
3057 { &hf_btavrcp_feature_addtonowplayer,
3058 { "AddToNowPlaying", "btavrcp.feature.addtonowplaying",
3059 FT_UINT8, BASE_HEX, NULL, 0x20,
3060 NULL, HFILL }
3062 { &hf_btavrcp_feature_uid_unique,
3063 { "UID Unique", "btavrcp.feature.uid_unique",
3064 FT_UINT8, BASE_HEX, NULL, 0x40,
3065 NULL, HFILL }
3067 { &hf_btavrcp_feature_only_browsable_when_addressed,
3068 { "Only Browsable When Addressed", "btavrcp.feature.only_browsable_when_addressed",
3069 FT_UINT8, BASE_HEX, NULL, 0x80,
3070 NULL, HFILL }
3072 { &hf_btavrcp_feature_only_searchable_when_addressed,
3073 { "Only Searchable When Addressed", "btavrcp.feature.only_searchable_when_addressed",
3074 FT_UINT8, BASE_HEX, NULL, 0x01,
3075 NULL, HFILL }
3077 { &hf_btavrcp_feature_nowplaying,
3078 { "Nowplaying", "btavrcp.feature.nowplaying",
3079 FT_UINT8, BASE_HEX, NULL, 0x02,
3080 NULL, HFILL }
3082 { &hf_btavrcp_feature_uid_persistency,
3083 { "UID Persistency", "btavrcp.feature.uid_persistency",
3084 FT_UINT8, BASE_HEX, NULL, 0x04,
3085 NULL, HFILL }
3087 { &hf_btavrcp_feature_number_of_items,
3088 { "Number of Items", "btavrcp.feature.number_of_items",
3089 FT_UINT8, BASE_HEX, NULL, 0x08,
3090 NULL, HFILL }
3092 { &hf_btavrcp_feature_cover_art,
3093 { "Cover Art", "btavrcp.feature.cover_art",
3094 FT_UINT8, BASE_HEX, NULL, 0x10,
3095 NULL, HFILL }
3097 /* end of features */
3098 { &hf_btavrcp_current_path,
3099 { "Current Path", "btavrcp.current_path",
3100 FT_NONE, BASE_NONE, NULL, 0x00,
3101 NULL, HFILL }
3103 { &hf_btavrcp_reassembled,
3104 { "Reassembled", "btavrcp.reassembled",
3105 FT_NONE, BASE_NONE, NULL, 0x00,
3106 NULL, HFILL }
3108 { &hf_btavrcp_response_time,
3109 { "Response Time", "btavrcp.response_time",
3110 FT_UINT32, BASE_DEC, NULL, 0x00,
3111 NULL, HFILL }
3113 { &hf_btavrcp_command_in_frame,
3114 { "Command in frame", "btavrcp.command_in_frame",
3115 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x00,
3116 NULL, HFILL }
3118 { &hf_btavrcp_response_in_frame,
3119 { "Response in frame", "btavrcp.response_in_frame",
3120 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x00,
3121 NULL, HFILL }
3123 { &hf_btavrcp_data,
3124 { "Data", "btavrcp.data",
3125 FT_NONE, BASE_NONE, NULL, 0x0,
3126 NULL, HFILL }
3130 static int *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_features,
3138 &ett_btavrcp_features_not_used,
3139 &ett_btavrcp_folder,
3140 &ett_btavrcp_path,
3143 static ei_register_info ei[] = {
3144 { &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 }},
3145 { &ei_btavrcp_unexpected_data, { "btavrcp.unexpected_data", PI_PROTOCOL, PI_WARN, "Unexpected data", EXPFILL }},
3146 { &ei_btavrcp_no_response, { "btavrcp.no_response", PI_PROTOCOL, PI_WARN, "No response", EXPFILL }},
3149 reassembling = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3150 timing = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3151 btavrcp_song_positions = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3153 proto_btavrcp = proto_register_protocol("Bluetooth AVRCP Profile", "BT AVRCP", "btavrcp");
3154 btavrcp_handle = register_dissector("btavrcp", dissect_btavrcp, proto_btavrcp);
3156 proto_register_field_array(proto_btavrcp, hf, array_length(hf));
3157 proto_register_subtree_array(ett, array_length(ett));
3158 expert_btavrcp = expert_register_protocol(proto_btavrcp);
3159 expert_register_field_array(expert_btavrcp, ei, array_length(ei));
3161 module = prefs_register_protocol_subtree("Bluetooth", proto_btavrcp, NULL);
3162 prefs_register_static_text_preference(module, "avrcp.version",
3163 "Bluetooth Profile AVRCP version: 1.5",
3164 "Version of profile supported by this dissector.");
3167 void
3168 proto_reg_handoff_btavrcp(void)
3170 dissector_add_string("bluetooth.uuid", "110c", btavrcp_handle);
3171 dissector_add_string("bluetooth.uuid", "110e", btavrcp_handle);
3172 dissector_add_string("bluetooth.uuid", "110f", btavrcp_handle);
3177 * Editor modelines - https://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: