1 // SPDX-License-Identifier: LGPL-2.1-or-later
4 * BlueZ - Bluetooth protocol stack for Linux
6 * Copyright (C) 2011-2014 Intel Corporation
7 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
22 #include "lib/bluetooth.h"
25 #include "src/shared/util.h"
36 #define AVC_CTYPE_CONTROL 0x0
37 #define AVC_CTYPE_STATUS 0x1
38 #define AVC_CTYPE_SPECIFIC_INQUIRY 0x2
39 #define AVC_CTYPE_NOTIFY 0x3
40 #define AVC_CTYPE_GENERAL_INQUIRY 0x4
41 #define AVC_CTYPE_NOT_IMPLEMENTED 0x8
42 #define AVC_CTYPE_ACCEPTED 0x9
43 #define AVC_CTYPE_REJECTED 0xA
44 #define AVC_CTYPE_IN_TRANSITION 0xB
45 #define AVC_CTYPE_STABLE 0xC
46 #define AVC_CTYPE_CHANGED 0xD
47 #define AVC_CTYPE_INTERIM 0xF
50 #define AVC_SUBUNIT_MONITOR 0x00
51 #define AVC_SUBUNIT_AUDIO 0x01
52 #define AVC_SUBUNIT_PRINTER 0x02
53 #define AVC_SUBUNIT_DISC 0x03
54 #define AVC_SUBUNIT_TAPE 0x04
55 #define AVC_SUBUNIT_TUNER 0x05
56 #define AVC_SUBUNIT_CA 0x06
57 #define AVC_SUBUNIT_CAMERA 0x07
58 #define AVC_SUBUNIT_PANEL 0x09
59 #define AVC_SUBUNIT_BULLETIN_BOARD 0x0a
60 #define AVC_SUBUNIT_CAMERA_STORAGE 0x0b
61 #define AVC_SUBUNIT_VENDOR_UNIQUE 0x0c
62 #define AVC_SUBUNIT_EXTENDED 0x1e
63 #define AVC_SUBUNIT_UNIT 0x1f
66 #define AVC_OP_VENDORDEP 0x00
67 #define AVC_OP_UNITINFO 0x30
68 #define AVC_OP_SUBUNITINFO 0x31
69 #define AVC_OP_PASSTHROUGH 0x7c
71 /* notification events */
72 #define AVRCP_EVENT_PLAYBACK_STATUS_CHANGED 0x01
73 #define AVRCP_EVENT_TRACK_CHANGED 0x02
74 #define AVRCP_EVENT_TRACK_REACHED_END 0x03
75 #define AVRCP_EVENT_TRACK_REACHED_START 0x04
76 #define AVRCP_EVENT_PLAYBACK_POS_CHANGED 0x05
77 #define AVRCP_EVENT_BATT_STATUS_CHANGED 0x06
78 #define AVRCP_EVENT_SYSTEM_STATUS_CHANGED 0x07
79 #define AVRCP_EVENT_PLAYER_APPLICATION_SETTING_CHANGED 0x08
80 #define AVRCP_EVENT_NOW_PLAYING_CONTENT_CHANGED 0x09
81 #define AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED 0x0a
82 #define AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED 0x0b
83 #define AVRCP_EVENT_UIDS_CHANGED 0x0c
84 #define AVRCP_EVENT_VOLUME_CHANGED 0x0d
87 #define AVRCP_STATUS_INVALID_COMMAND 0x00
88 #define AVRCP_STATUS_INVALID_PARAMETER 0x01
89 #define AVRCP_STATUS_NOT_FOUND 0x02
90 #define AVRCP_STATUS_INTERNAL_ERROR 0x03
91 #define AVRCP_STATUS_SUCCESS 0x04
92 #define AVRCP_STATUS_UID_CHANGED 0x05
93 #define AVRCP_STATUS_INVALID_DIRECTION 0x07
94 #define AVRCP_STATUS_NOT_DIRECTORY 0x08
95 #define AVRCP_STATUS_DOES_NOT_EXIST 0x09
96 #define AVRCP_STATUS_INVALID_SCOPE 0x0a
97 #define AVRCP_STATUS_OUT_OF_BOUNDS 0x0b
98 #define AVRCP_STATUS_IS_DIRECTORY 0x0c
99 #define AVRCP_STATUS_MEDIA_IN_USE 0x0d
100 #define AVRCP_STATUS_NOW_PLAYING_LIST_FULL 0x0e
101 #define AVRCP_STATUS_SEARCH_NOT_SUPPORTED 0x0f
102 #define AVRCP_STATUS_SEARCH_IN_PROGRESS 0x10
103 #define AVRCP_STATUS_INVALID_PLAYER_ID 0x11
104 #define AVRCP_STATUS_PLAYER_NOT_BROWSABLE 0x12
105 #define AVRCP_STATUS_PLAYER_NOT_ADDRESSED 0x13
106 #define AVRCP_STATUS_NO_VALID_SEARCH_RESULTS 0x14
107 #define AVRCP_STATUS_NO_AVAILABLE_PLAYERS 0x15
108 #define AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED 0x16
111 #define AVRCP_GET_CAPABILITIES 0x10
112 #define AVRCP_LIST_PLAYER_ATTRIBUTES 0x11
113 #define AVRCP_LIST_PLAYER_VALUES 0x12
114 #define AVRCP_GET_CURRENT_PLAYER_VALUE 0x13
115 #define AVRCP_SET_PLAYER_VALUE 0x14
116 #define AVRCP_GET_PLAYER_ATTRIBUTE_TEXT 0x15
117 #define AVRCP_GET_PLAYER_VALUE_TEXT 0x16
118 #define AVRCP_DISPLAYABLE_CHARSET 0x17
119 #define AVRCP_CT_BATTERY_STATUS 0x18
120 #define AVRCP_GET_ELEMENT_ATTRIBUTES 0x20
121 #define AVRCP_GET_PLAY_STATUS 0x30
122 #define AVRCP_REGISTER_NOTIFICATION 0x31
123 #define AVRCP_REQUEST_CONTINUING 0x40
124 #define AVRCP_ABORT_CONTINUING 0x41
125 #define AVRCP_SET_ABSOLUTE_VOLUME 0x50
126 #define AVRCP_SET_ADDRESSED_PLAYER 0x60
127 #define AVRCP_SET_BROWSED_PLAYER 0x70
128 #define AVRCP_GET_FOLDER_ITEMS 0x71
129 #define AVRCP_CHANGE_PATH 0x72
130 #define AVRCP_GET_ITEM_ATTRIBUTES 0x73
131 #define AVRCP_PLAY_ITEM 0x74
132 #define AVRCP_GET_TOTAL_NUMBER_OF_ITEMS 0x75
133 #define AVRCP_SEARCH 0x80
134 #define AVRCP_ADD_TO_NOW_PLAYING 0x90
135 #define AVRCP_GENERAL_REJECT 0xA0
138 #define AVRCP_PACKET_TYPE_SINGLE 0x00
139 #define AVRCP_PACKET_TYPE_START 0x01
140 #define AVRCP_PACKET_TYPE_CONTINUING 0x02
141 #define AVRCP_PACKET_TYPE_END 0x03
143 /* player attributes */
144 #define AVRCP_ATTRIBUTE_ILEGAL 0x00
145 #define AVRCP_ATTRIBUTE_EQUALIZER 0x01
146 #define AVRCP_ATTRIBUTE_REPEAT_MODE 0x02
147 #define AVRCP_ATTRIBUTE_SHUFFLE 0x03
148 #define AVRCP_ATTRIBUTE_SCAN 0x04
150 /* media attributes */
151 #define AVRCP_MEDIA_ATTRIBUTE_ILLEGAL 0x00
152 #define AVRCP_MEDIA_ATTRIBUTE_TITLE 0x01
153 #define AVRCP_MEDIA_ATTRIBUTE_ARTIST 0x02
154 #define AVRCP_MEDIA_ATTRIBUTE_ALBUM 0x03
155 #define AVRCP_MEDIA_ATTRIBUTE_TRACK 0x04
156 #define AVRCP_MEDIA_ATTRIBUTE_TOTAL 0x05
157 #define AVRCP_MEDIA_ATTRIBUTE_GENRE 0x06
158 #define AVRCP_MEDIA_ATTRIBUTE_DURATION 0x07
161 #define AVRCP_PLAY_STATUS_STOPPED 0x00
162 #define AVRCP_PLAY_STATUS_PLAYING 0x01
163 #define AVRCP_PLAY_STATUS_PAUSED 0x02
164 #define AVRCP_PLAY_STATUS_FWD_SEEK 0x03
165 #define AVRCP_PLAY_STATUS_REV_SEEK 0x04
166 #define AVRCP_PLAY_STATUS_ERROR 0xFF
169 #define AVRCP_MEDIA_PLAYER_LIST 0x00
170 #define AVRCP_MEDIA_PLAYER_VFS 0x01
171 #define AVRCP_MEDIA_SEARCH 0x02
172 #define AVRCP_MEDIA_NOW_PLAYING 0x03
174 /* Media Item Type */
175 #define AVRCP_MEDIA_PLAYER_ITEM_TYPE 0x01
176 #define AVRCP_FOLDER_ITEM_TYPE 0x02
177 #define AVRCP_MEDIA_ELEMENT_ITEM_TYPE 0x03
179 /* operands in passthrough commands */
180 #define AVC_PANEL_VOLUME_UP 0x41
181 #define AVC_PANEL_VOLUME_DOWN 0x42
182 #define AVC_PANEL_MUTE 0x43
183 #define AVC_PANEL_PLAY 0x44
184 #define AVC_PANEL_STOP 0x45
185 #define AVC_PANEL_PAUSE 0x46
186 #define AVC_PANEL_RECORD 0x47
187 #define AVC_PANEL_REWIND 0x48
188 #define AVC_PANEL_FAST_FORWARD 0x49
189 #define AVC_PANEL_EJECT 0x4a
190 #define AVC_PANEL_FORWARD 0x4b
191 #define AVC_PANEL_BACKWARD 0x4c
197 struct l2cap_frame l2cap_frame;
200 static struct avrcp_continuing {
205 static const char *ctype2str(uint8_t ctype)
207 switch (ctype & 0x0f) {
208 case AVC_CTYPE_CONTROL:
210 case AVC_CTYPE_STATUS:
212 case AVC_CTYPE_SPECIFIC_INQUIRY:
213 return "Specific Inquiry";
214 case AVC_CTYPE_NOTIFY:
216 case AVC_CTYPE_GENERAL_INQUIRY:
217 return "General Inquiry";
218 case AVC_CTYPE_NOT_IMPLEMENTED:
219 return "Not Implemented";
220 case AVC_CTYPE_ACCEPTED:
222 case AVC_CTYPE_REJECTED:
224 case AVC_CTYPE_IN_TRANSITION:
225 return "In Transition";
226 case AVC_CTYPE_STABLE:
228 case AVC_CTYPE_CHANGED:
230 case AVC_CTYPE_INTERIM:
237 static const char *subunit2str(uint8_t subunit)
240 case AVC_SUBUNIT_MONITOR:
242 case AVC_SUBUNIT_AUDIO:
244 case AVC_SUBUNIT_PRINTER:
246 case AVC_SUBUNIT_DISC:
248 case AVC_SUBUNIT_TAPE:
250 case AVC_SUBUNIT_TUNER:
254 case AVC_SUBUNIT_CAMERA:
256 case AVC_SUBUNIT_PANEL:
258 case AVC_SUBUNIT_BULLETIN_BOARD:
259 return "Bulletin Board";
260 case AVC_SUBUNIT_CAMERA_STORAGE:
261 return "Camera Storage";
262 case AVC_SUBUNIT_VENDOR_UNIQUE:
263 return "Vendor Unique";
264 case AVC_SUBUNIT_EXTENDED:
265 return "Extended to next byte";
266 case AVC_SUBUNIT_UNIT:
273 static const char *opcode2str(uint8_t opcode)
276 case AVC_OP_VENDORDEP:
277 return "Vendor Dependent";
278 case AVC_OP_UNITINFO:
280 case AVC_OP_SUBUNITINFO:
281 return "Subunit Info";
282 case AVC_OP_PASSTHROUGH:
283 return "Passthrough";
289 static char *cap2str(uint8_t cap)
301 static char *event2str(uint8_t event)
304 case AVRCP_EVENT_PLAYBACK_STATUS_CHANGED:
305 return "EVENT_PLAYBACK_STATUS_CHANGED";
306 case AVRCP_EVENT_TRACK_CHANGED:
307 return "EVENT_TRACK_CHANGED";
308 case AVRCP_EVENT_TRACK_REACHED_END:
309 return "EVENT_TRACK_REACHED_END";
310 case AVRCP_EVENT_TRACK_REACHED_START:
311 return "EVENT_TRACK_REACHED_START";
312 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
313 return "EVENT_PLAYBACK_POS_CHANGED";
314 case AVRCP_EVENT_BATT_STATUS_CHANGED:
315 return "EVENT_BATT_STATUS_CHANGED";
316 case AVRCP_EVENT_SYSTEM_STATUS_CHANGED:
317 return "EVENT_SYSTEM_STATUS_CHANGED";
318 case AVRCP_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
319 return "EVENT_PLAYER_APPLICATION_SETTING_CHANGED";
320 case AVRCP_EVENT_NOW_PLAYING_CONTENT_CHANGED:
321 return "EVENT_NOW_PLAYING_CONTENT_CHANGED";
322 case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
323 return "EVENT_AVAILABLE_PLAYERS_CHANGED";
324 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
325 return "EVENT_ADDRESSED_PLAYER_CHANGED";
326 case AVRCP_EVENT_UIDS_CHANGED:
327 return "EVENT_UIDS_CHANGED";
328 case AVRCP_EVENT_VOLUME_CHANGED:
329 return "EVENT_VOLUME_CHANGED";
335 static const char *error2str(uint8_t status)
338 case AVRCP_STATUS_INVALID_COMMAND:
339 return "Invalid Command";
340 case AVRCP_STATUS_INVALID_PARAMETER:
341 return "Invalid Parameter";
342 case AVRCP_STATUS_NOT_FOUND:
344 case AVRCP_STATUS_INTERNAL_ERROR:
345 return "Internal Error";
346 case AVRCP_STATUS_SUCCESS:
348 case AVRCP_STATUS_UID_CHANGED:
349 return "UID Changed";
350 case AVRCP_STATUS_INVALID_DIRECTION:
351 return "Invalid Direction";
352 case AVRCP_STATUS_NOT_DIRECTORY:
353 return "Not a Directory";
354 case AVRCP_STATUS_DOES_NOT_EXIST:
355 return "Does Not Exist";
356 case AVRCP_STATUS_INVALID_SCOPE:
357 return "Invalid Scope";
358 case AVRCP_STATUS_OUT_OF_BOUNDS:
359 return "Range Out of Bounds";
360 case AVRCP_STATUS_MEDIA_IN_USE:
361 return "Media in Use";
362 case AVRCP_STATUS_IS_DIRECTORY:
363 return "UID is a Directory";
364 case AVRCP_STATUS_NOW_PLAYING_LIST_FULL:
365 return "Now Playing List Full";
366 case AVRCP_STATUS_SEARCH_NOT_SUPPORTED:
367 return "Search Not Supported";
368 case AVRCP_STATUS_SEARCH_IN_PROGRESS:
369 return "Search in Progress";
370 case AVRCP_STATUS_INVALID_PLAYER_ID:
371 return "Invalid Player ID";
372 case AVRCP_STATUS_PLAYER_NOT_BROWSABLE:
373 return "Player Not Browsable";
374 case AVRCP_STATUS_PLAYER_NOT_ADDRESSED:
375 return "Player Not Addressed";
376 case AVRCP_STATUS_NO_VALID_SEARCH_RESULTS:
377 return "No Valid Search Result";
378 case AVRCP_STATUS_NO_AVAILABLE_PLAYERS:
379 return "No Available Players";
380 case AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED:
381 return "Addressed Player Changed";
387 static const char *pdu2str(uint8_t pduid)
390 case AVRCP_GET_CAPABILITIES:
391 return "GetCapabilities";
392 case AVRCP_LIST_PLAYER_ATTRIBUTES:
393 return "ListPlayerApplicationSettingAttributes";
394 case AVRCP_LIST_PLAYER_VALUES:
395 return "ListPlayerApplicationSettingValues";
396 case AVRCP_GET_CURRENT_PLAYER_VALUE:
397 return "GetCurrentPlayerApplicationSettingValue";
398 case AVRCP_SET_PLAYER_VALUE:
399 return "SetPlayerApplicationSettingValue";
400 case AVRCP_GET_PLAYER_ATTRIBUTE_TEXT:
401 return "GetPlayerApplicationSettingAttributeText";
402 case AVRCP_GET_PLAYER_VALUE_TEXT:
403 return "GetPlayerApplicationSettingValueText";
404 case AVRCP_DISPLAYABLE_CHARSET:
405 return "InformDisplayableCharacterSet";
406 case AVRCP_CT_BATTERY_STATUS:
407 return "InformBatteryStatusOfCT";
408 case AVRCP_GET_ELEMENT_ATTRIBUTES:
409 return "GetElementAttributes";
410 case AVRCP_GET_PLAY_STATUS:
411 return "GetPlayStatus";
412 case AVRCP_REGISTER_NOTIFICATION:
413 return "RegisterNotification";
414 case AVRCP_REQUEST_CONTINUING:
415 return "RequestContinuingResponse";
416 case AVRCP_ABORT_CONTINUING:
417 return "AbortContinuingResponse";
418 case AVRCP_SET_ABSOLUTE_VOLUME:
419 return "SetAbsoluteVolume";
420 case AVRCP_SET_ADDRESSED_PLAYER:
421 return "SetAddressedPlayer";
422 case AVRCP_SET_BROWSED_PLAYER:
423 return "SetBrowsedPlayer";
424 case AVRCP_GET_FOLDER_ITEMS:
425 return "GetFolderItems";
426 case AVRCP_CHANGE_PATH:
428 case AVRCP_GET_ITEM_ATTRIBUTES:
429 return "GetItemAttributes";
430 case AVRCP_PLAY_ITEM:
432 case AVRCP_GET_TOTAL_NUMBER_OF_ITEMS:
433 return "GetTotalNumOfItems";
436 case AVRCP_ADD_TO_NOW_PLAYING:
437 return "AddToNowPlaying";
438 case AVRCP_GENERAL_REJECT:
439 return "GeneralReject";
445 static const char *pt2str(uint8_t pt)
448 case AVRCP_PACKET_TYPE_SINGLE:
450 case AVRCP_PACKET_TYPE_START:
452 case AVRCP_PACKET_TYPE_CONTINUING:
454 case AVRCP_PACKET_TYPE_END:
461 static const char *attr2str(uint8_t attr)
464 case AVRCP_ATTRIBUTE_ILEGAL:
466 case AVRCP_ATTRIBUTE_EQUALIZER:
467 return "Equalizer ON/OFF Status";
468 case AVRCP_ATTRIBUTE_REPEAT_MODE:
469 return "Repeat Mode Status";
470 case AVRCP_ATTRIBUTE_SHUFFLE:
471 return "Shuffle ON/OFF Status";
472 case AVRCP_ATTRIBUTE_SCAN:
473 return "Scan ON/OFF Status";
479 static const char *value2str(uint8_t attr, uint8_t value)
482 case AVRCP_ATTRIBUTE_ILEGAL:
484 case AVRCP_ATTRIBUTE_EQUALIZER:
493 case AVRCP_ATTRIBUTE_REPEAT_MODE:
498 return "Single Track Repeat";
500 return "All Track Repeat";
502 return "Group Repeat";
506 case AVRCP_ATTRIBUTE_SHUFFLE:
511 return "All Track Shuffle";
513 return "Group Shuffle";
517 case AVRCP_ATTRIBUTE_SCAN:
522 return "All Track Scan";
533 static const char *charset2str(uint16_t charset)
566 static const char *mediattr2str(uint32_t attr)
569 case AVRCP_MEDIA_ATTRIBUTE_ILLEGAL:
571 case AVRCP_MEDIA_ATTRIBUTE_TITLE:
573 case AVRCP_MEDIA_ATTRIBUTE_ARTIST:
575 case AVRCP_MEDIA_ATTRIBUTE_ALBUM:
577 case AVRCP_MEDIA_ATTRIBUTE_TRACK:
579 case AVRCP_MEDIA_ATTRIBUTE_TOTAL:
580 return "Track Total";
581 case AVRCP_MEDIA_ATTRIBUTE_GENRE:
583 case AVRCP_MEDIA_ATTRIBUTE_DURATION:
584 return "Track duration";
590 static const char *playstatus2str(uint8_t status)
593 case AVRCP_PLAY_STATUS_STOPPED:
595 case AVRCP_PLAY_STATUS_PLAYING:
597 case AVRCP_PLAY_STATUS_PAUSED:
599 case AVRCP_PLAY_STATUS_FWD_SEEK:
601 case AVRCP_PLAY_STATUS_REV_SEEK:
603 case AVRCP_PLAY_STATUS_ERROR:
610 static const char *status2str(uint8_t status)
622 return "FULL_CHARGE";
628 static const char *scope2str(uint8_t scope)
631 case AVRCP_MEDIA_PLAYER_LIST:
632 return "Media Player List";
633 case AVRCP_MEDIA_PLAYER_VFS:
634 return "Media Player Virtual Filesystem";
635 case AVRCP_MEDIA_SEARCH:
637 case AVRCP_MEDIA_NOW_PLAYING:
638 return "Now Playing";
644 static char *op2str(uint8_t op)
647 case AVC_PANEL_VOLUME_UP:
649 case AVC_PANEL_VOLUME_DOWN:
650 return "VOLUME DOWN";
657 case AVC_PANEL_PAUSE:
659 case AVC_PANEL_RECORD:
661 case AVC_PANEL_REWIND:
663 case AVC_PANEL_FAST_FORWARD:
664 return "FAST FORWARD";
665 case AVC_PANEL_EJECT:
667 case AVC_PANEL_FORWARD:
669 case AVC_PANEL_BACKWARD:
676 static const char *type2str(uint8_t type)
679 case AVRCP_MEDIA_PLAYER_ITEM_TYPE:
680 return "Media Player";
681 case AVRCP_FOLDER_ITEM_TYPE:
683 case AVRCP_MEDIA_ELEMENT_ITEM_TYPE:
684 return "Media Element";
690 static const char *playertype2str(uint8_t type)
692 switch (type & 0x0F) {
698 return "Audio, Video";
700 return "Audio Broadcasting";
702 return "Audio, Audio Broadcasting";
704 return "Video, Audio Broadcasting";
706 return "Audio, Video, Audio Broadcasting";
708 return "Video Broadcasting";
710 return "Audio, Video Broadcasting";
712 return "Video, Video Broadcasting";
714 return "Audio, Video, Video Broadcasting";
716 return "Audio Broadcasting, Video Broadcasting";
718 return "Audio, Audio Broadcasting, Video Broadcasting";
720 return "Video, Audio Broadcasting, Video Broadcasting";
722 return "Audio, Video, Audio Broadcasting, Video Broadcasting";
728 static const char *playersubtype2str(uint32_t subtype)
730 switch (subtype & 0x03) {
736 return "Audio Book, Podcast";
742 static const char *foldertype2str(uint8_t type)
764 static const char *elementtype2str(uint8_t type)
776 static bool avrcp_passthrough_packet(struct avctp_frame *avctp_frame,
779 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
782 if (!l2cap_frame_get_u8(frame, &op))
785 print_field("%*cOperation: 0x%02x (%s %s)", (indent - 8), ' ', op,
786 op2str(op), op & 0x80 ? "Released" : "Pressed");
788 if (!l2cap_frame_get_u8(frame, &len))
791 print_field("%*cLength: 0x%02x", (indent - 8), ' ', len);
793 packet_hexdump(frame->data, frame->size);
797 static bool avrcp_get_capabilities(struct avctp_frame *avctp_frame,
798 uint8_t ctype, uint8_t len,
801 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
805 if (!l2cap_frame_get_u8(frame, &cap))
808 print_field("%*cCapabilityID: 0x%02x (%s)", (indent - 8), ' ', cap,
814 if (!l2cap_frame_get_u8(frame, &count))
817 print_field("%*cCapabilityCount: 0x%02x", (indent - 8), ' ', count);
821 for (; count > 0; count--) {
824 if (!l2cap_frame_get_u8(frame, &company[0]) ||
825 !l2cap_frame_get_u8(frame, &company[1]) ||
826 !l2cap_frame_get_u8(frame, &company[2]))
829 print_field("%*c%s: 0x%02x%02x%02x", (indent - 8), ' ',
830 cap2str(cap), company[0], company[1],
835 for (i = 0; count > 0; count--, i++) {
838 if (!l2cap_frame_get_u8(frame, &event))
841 print_field("%*c%s: 0x%02x (%s)", (indent - 8), ' ',
842 cap2str(cap), event, event2str(event));
846 packet_hexdump(frame->data, frame->size);
852 static bool avrcp_list_player_attributes(struct avctp_frame *avctp_frame,
853 uint8_t ctype, uint8_t len,
856 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
863 if (!l2cap_frame_get_u8(frame, &num))
866 print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num);
868 for (i = 0; num > 0; num--, i++) {
871 if (!l2cap_frame_get_u8(frame, &attr))
874 print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8), ' ',
875 attr, attr2str(attr));
881 static bool avrcp_list_player_values(struct avctp_frame *avctp_frame,
882 uint8_t ctype, uint8_t len,
885 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
886 static uint8_t attr = 0;
889 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
892 if (!l2cap_frame_get_u8(frame, &attr))
895 print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8), ' ',
896 attr, attr2str(attr));
901 if (!l2cap_frame_get_u8(frame, &num))
904 print_field("%*cValueCount: 0x%02x", (indent - 8), ' ', num);
906 for (; num > 0; num--) {
909 if (!l2cap_frame_get_u8(frame, &value))
912 print_field("%*cValueID: 0x%02x (%s)", (indent - 8),
913 ' ', value, value2str(attr, value));
919 static bool avrcp_get_current_player_value(struct avctp_frame *avctp_frame,
920 uint8_t ctype, uint8_t len,
923 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
926 if (!l2cap_frame_get_u8(frame, &num))
929 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
932 print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num);
934 for (; num > 0; num--) {
937 if (!l2cap_frame_get_u8(frame, &attr))
940 print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8),
941 ' ', attr, attr2str(attr));
947 print_field("%*cValueCount: 0x%02x", (indent - 8), ' ', num);
949 for (; num > 0; num--) {
952 if (!l2cap_frame_get_u8(frame, &attr))
955 print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8),
956 ' ', attr, attr2str(attr));
958 if (!l2cap_frame_get_u8(frame, &value))
961 print_field("%*cValueID: 0x%02x (%s)", (indent - 8),
962 ' ', value, value2str(attr, value));
968 static bool avrcp_set_player_value(struct avctp_frame *avctp_frame,
969 uint8_t ctype, uint8_t len,
972 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
975 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
978 if (!l2cap_frame_get_u8(frame, &num))
981 print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num);
983 for (; num > 0; num--) {
986 if (!l2cap_frame_get_u8(frame, &attr))
989 print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8), ' ',
990 attr, attr2str(attr));
992 if (!l2cap_frame_get_u8(frame, &value))
995 print_field("%*cValueID: 0x%02x (%s)", (indent - 8), ' ',
996 value, value2str(attr, value));
1002 static bool avrcp_get_player_attribute_text(struct avctp_frame *avctp_frame,
1003 uint8_t ctype, uint8_t len,
1006 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1009 if (!l2cap_frame_get_u8(frame, &num))
1012 print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num);
1014 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
1017 for (; num > 0; num--) {
1020 if (!l2cap_frame_get_u8(frame, &attr))
1023 print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8),
1024 ' ', attr, attr2str(attr));
1030 for (; num > 0; num--) {
1034 if (!l2cap_frame_get_u8(frame, &attr))
1037 print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8),
1038 ' ', attr, attr2str(attr));
1040 if (!l2cap_frame_get_be16(frame, &charset))
1043 print_field("%*cCharsetID: 0x%04x (%s)", (indent - 8),
1044 ' ', charset, charset2str(charset));
1046 if (!l2cap_frame_get_u8(frame, &len))
1049 print_field("%*cStringLength: 0x%02x", (indent - 8), ' ', len);
1052 for (; len > 0; len--) {
1055 if (!l2cap_frame_get_u8(frame, &c))
1058 printf("%1c", isprint(c) ? c : '.');
1066 static bool avrcp_get_player_value_text(struct avctp_frame *avctp_frame,
1067 uint8_t ctype, uint8_t len,
1070 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1071 static uint8_t attr = 0;
1074 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
1077 if (!l2cap_frame_get_u8(frame, &attr))
1080 print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8), ' ',
1081 attr, attr2str(attr));
1083 if (!l2cap_frame_get_u8(frame, &num))
1086 print_field("%*cValueCount: 0x%02x", (indent - 8), ' ', num);
1088 for (; num > 0; num--) {
1091 if (!l2cap_frame_get_u8(frame, &value))
1094 print_field("%*cValueID: 0x%02x (%s)", (indent - 8),
1095 ' ', value, value2str(attr, value));
1101 if (!l2cap_frame_get_u8(frame, &num))
1104 print_field("%*cValueCount: 0x%02x", (indent - 8), ' ', num);
1106 for (; num > 0; num--) {
1110 if (!l2cap_frame_get_u8(frame, &value))
1113 print_field("%*cValueID: 0x%02x (%s)", (indent - 8), ' ',
1114 value, value2str(attr, value));
1116 if (!l2cap_frame_get_be16(frame, &charset))
1119 print_field("%*cCharsetIDID: 0x%02x (%s)", (indent - 8), ' ',
1120 charset, charset2str(charset));
1122 if (!l2cap_frame_get_u8(frame, &len))
1125 print_field("%*cStringLength: 0x%02x", (indent - 8), ' ', len);
1128 for (; len > 0; len--) {
1131 if (!l2cap_frame_get_u8(frame, &c))
1134 printf("%1c", isprint(c) ? c : '.');
1142 static bool avrcp_displayable_charset(struct avctp_frame *avctp_frame,
1143 uint8_t ctype, uint8_t len,
1146 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1149 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
1152 if (!l2cap_frame_get_u8(frame, &num))
1155 print_field("%*cCharsetCount: 0x%02x", (indent - 8), ' ', num);
1157 for (; num > 0; num--) {
1160 if (!l2cap_frame_get_be16(frame, &charset))
1163 print_field("%*cCharsetID: 0x%04x (%s)", (indent - 8),
1164 ' ', charset, charset2str(charset));
1170 static bool avrcp_get_element_attributes(struct avctp_frame *avctp_frame,
1171 uint8_t ctype, uint8_t len,
1174 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1178 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
1181 if (!l2cap_frame_get_be64(frame, &id))
1184 print_field("%*cIdentifier: 0x%jx (%s)", (indent - 8), ' ',
1185 id, id ? "Reserved" : "PLAYING");
1187 if (!l2cap_frame_get_u8(frame, &num))
1190 print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num);
1192 for (; num > 0; num--) {
1195 if (!l2cap_frame_get_be32(frame, &attr))
1198 print_field("%*cAttributeID: 0x%08x (%s)", (indent - 8),
1199 ' ', attr, mediattr2str(attr));
1205 switch (avctp_frame->pt) {
1206 case AVRCP_PACKET_TYPE_SINGLE:
1207 case AVRCP_PACKET_TYPE_START:
1208 if (!l2cap_frame_get_u8(frame, &num))
1211 avrcp_continuing.num = num;
1212 print_field("%*cAttributeCount: 0x%02x", (indent - 8),
1216 case AVRCP_PACKET_TYPE_CONTINUING:
1217 case AVRCP_PACKET_TYPE_END:
1218 num = avrcp_continuing.num;
1220 if (avrcp_continuing.size > 0) {
1221 char attrval[UINT8_MAX] = {0};
1225 if (avrcp_continuing.size > len) {
1227 avrcp_continuing.size -= len;
1229 size = avrcp_continuing.size;
1230 avrcp_continuing.size = 0;
1233 for (idx = 0; size > 0; idx++, size--) {
1236 if (!l2cap_frame_get_u8(frame, &c))
1239 sprintf(&attrval[idx], "%1c",
1240 isprint(c) ? c : '.');
1242 print_field("%*cContinuingAttributeValue: %s",
1243 (indent - 8), ' ', attrval);
1252 while (num > 0 && len > 0) {
1254 uint16_t charset, attrlen;
1256 char attrval[UINT8_MAX] = {0};
1258 if (!l2cap_frame_get_be32(frame, &attr))
1261 print_field("%*cAttribute: 0x%08x (%s)", (indent - 8),
1262 ' ', attr, mediattr2str(attr));
1264 if (!l2cap_frame_get_be16(frame, &charset))
1267 print_field("%*cCharsetID: 0x%04x (%s)", (indent - 8),
1268 ' ', charset, charset2str(charset));
1270 if (!l2cap_frame_get_be16(frame, &attrlen))
1273 print_field("%*cAttributeValueLength: 0x%04x",
1274 (indent - 8), ' ', attrlen);
1276 len -= sizeof(attr) + sizeof(charset) + sizeof(attrlen);
1279 for (idx = 0; attrlen > 0 && len > 0; idx++, attrlen--, len--) {
1282 if (!l2cap_frame_get_u8(frame, &c))
1285 sprintf(&attrval[idx], "%1c", isprint(c) ? c : '.');
1287 print_field("%*cAttributeValue: %s", (indent - 8),
1291 avrcp_continuing.size = attrlen;
1294 avrcp_continuing.num = num;
1298 avrcp_continuing.num = 0;
1299 avrcp_continuing.size = 0;
1303 static bool avrcp_get_play_status(struct avctp_frame *avctp_frame,
1304 uint8_t ctype, uint8_t len,
1307 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1311 if (ctype <= AVC_CTYPE_GENERAL_INQUIRY)
1314 if (!l2cap_frame_get_be32(frame, &interval))
1317 print_field("%*cSongLength: 0x%08x (%u miliseconds)",
1318 (indent - 8), ' ', interval, interval);
1320 if (!l2cap_frame_get_be32(frame, &interval))
1323 print_field("%*cSongPosition: 0x%08x (%u miliseconds)",
1324 (indent - 8), ' ', interval, interval);
1326 if (!l2cap_frame_get_u8(frame, &status))
1329 print_field("%*cPlayStatus: 0x%02x (%s)", (indent - 8),
1330 ' ', status, playstatus2str(status));
1335 static bool avrcp_register_notification(struct avctp_frame *avctp_frame,
1336 uint8_t ctype, uint8_t len,
1339 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1340 uint8_t event, status;
1345 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
1348 if (!l2cap_frame_get_u8(frame, &event))
1351 print_field("%*cEventID: 0x%02x (%s)", (indent - 8),
1352 ' ', event, event2str(event));
1354 if (!l2cap_frame_get_be32(frame, &interval))
1357 print_field("%*cInterval: 0x%08x (%u seconds)",
1358 (indent - 8), ' ', interval, interval);
1363 if (!l2cap_frame_get_u8(frame, &event))
1366 print_field("%*cEventID: 0x%02x (%s)", (indent - 8),
1367 ' ', event, event2str(event));
1370 case AVRCP_EVENT_PLAYBACK_STATUS_CHANGED:
1371 if (!l2cap_frame_get_u8(frame, &status))
1374 print_field("%*cPlayStatus: 0x%02x (%s)", (indent - 8),
1375 ' ', status, playstatus2str(status));
1377 case AVRCP_EVENT_TRACK_CHANGED:
1378 if (!l2cap_frame_get_be64(frame, &id))
1381 print_field("%*cIdentifier: 0x%16" PRIx64 " (%" PRIu64 ")",
1382 (indent - 8), ' ', id, id);
1384 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
1385 if (!l2cap_frame_get_be32(frame, &interval))
1388 print_field("%*cPosition: 0x%08x (%u miliseconds)",
1389 (indent - 8), ' ', interval, interval);
1391 case AVRCP_EVENT_BATT_STATUS_CHANGED:
1392 if (!l2cap_frame_get_u8(frame, &status))
1395 print_field("%*cBatteryStatus: 0x%02x (%s)", (indent - 8),
1396 ' ', status, status2str(status));
1399 case AVRCP_EVENT_SYSTEM_STATUS_CHANGED:
1400 if (!l2cap_frame_get_u8(frame, &status))
1403 print_field("%*cSystemStatus: 0x%02x ", (indent - 8),
1407 printf("(POWER_ON)\n");
1410 printf("(POWER_OFF)\n");
1413 printf("(UNPLUGGED)\n");
1416 printf("(UNKNOWN)\n");
1420 case AVRCP_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
1421 if (!l2cap_frame_get_u8(frame, &status))
1424 print_field("%*cAttributeCount: 0x%02x", (indent - 8),
1427 for (; status > 0; status--) {
1428 uint8_t attr, value;
1430 if (!l2cap_frame_get_u8(frame, &attr))
1433 print_field("%*cAttributeID: 0x%02x (%s)",
1434 (indent - 8), ' ', attr, attr2str(attr));
1436 if (!l2cap_frame_get_u8(frame, &value))
1439 print_field("%*cValueID: 0x%02x (%s)", (indent - 8),
1440 ' ', value, value2str(attr, value));
1443 case AVRCP_EVENT_VOLUME_CHANGED:
1444 if (!l2cap_frame_get_u8(frame, &status))
1449 print_field("%*cVolume: %.2f%% (%d/127)", (indent - 8),
1450 ' ', status/1.27, status);
1452 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
1453 if (!l2cap_frame_get_be16(frame, &uid))
1456 print_field("%*cPlayerID: 0x%04x (%u)", (indent - 8),
1459 if (!l2cap_frame_get_be16(frame, &uid))
1462 print_field("%*cUIDCounter: 0x%04x (%u)", (indent - 8),
1465 case AVRCP_EVENT_UIDS_CHANGED:
1466 if (!l2cap_frame_get_be16(frame, &uid))
1469 print_field("%*cUIDCounter: 0x%04x (%u)", (indent - 8),
1477 static bool avrcp_set_absolute_volume(struct avctp_frame *avctp_frame,
1478 uint8_t ctype, uint8_t len,
1481 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1484 if (!l2cap_frame_get_u8(frame, &value))
1488 print_field("%*cVolume: %.2f%% (%d/127)", (indent - 8),
1489 ' ', value/1.27, value);
1494 static bool avrcp_set_addressed_player(struct avctp_frame *avctp_frame,
1495 uint8_t ctype, uint8_t len,
1498 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1502 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
1505 if (!l2cap_frame_get_be16(frame, &id))
1508 print_field("%*cPlayerID: 0x%04x (%u)", (indent - 8), ' ', id, id);
1513 if (!l2cap_frame_get_u8(frame, &status))
1516 print_field("%*cStatus: 0x%02x (%s)", (indent - 8), ' ',
1517 status, error2str(status));
1522 static bool avrcp_play_item(struct avctp_frame *avctp_frame, uint8_t ctype,
1523 uint8_t len, uint8_t indent)
1525 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1527 uint16_t uidcounter;
1528 uint8_t scope, status;
1530 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
1533 if (!l2cap_frame_get_u8(frame, &scope))
1536 print_field("%*cScope: 0x%02x (%s)", (indent - 8), ' ',
1537 scope, scope2str(scope));
1539 if (!l2cap_frame_get_be64(frame, &uid))
1542 print_field("%*cUID: 0x%16" PRIx64 " (%" PRIu64 ")", (indent - 8),
1545 if (!l2cap_frame_get_be16(frame, &uidcounter))
1548 print_field("%*cUIDCounter: 0x%04x (%u)", (indent - 8), ' ',
1549 uidcounter, uidcounter);
1554 if (!l2cap_frame_get_u8(frame, &status))
1557 print_field("%*cStatus: 0x%02x (%s)", (indent - 8), ' ', status,
1563 static bool avrcp_add_to_now_playing(struct avctp_frame *avctp_frame,
1564 uint8_t ctype, uint8_t len,
1567 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1569 uint16_t uidcounter;
1570 uint8_t scope, status;
1572 if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
1575 if (!l2cap_frame_get_u8(frame, &scope))
1578 print_field("%*cScope: 0x%02x (%s)", (indent - 8), ' ',
1579 scope, scope2str(scope));
1581 if (!l2cap_frame_get_be64(frame, &uid))
1584 print_field("%*cUID: 0x%16" PRIx64 " (%" PRIu64 ")", (indent - 8),
1587 if (!l2cap_frame_get_be16(frame, &uidcounter))
1590 print_field("%*cUIDCounter: 0x%04x (%u)", (indent - 8), ' ',
1591 uidcounter, uidcounter);
1596 if (!l2cap_frame_get_u8(frame, &status))
1599 print_field("%*cStatus: 0x%02x (%s)", (indent - 8), ' ', status,
1605 struct avrcp_ctrl_pdu_data {
1607 bool (*func) (struct avctp_frame *avctp_frame, uint8_t ctype,
1608 uint8_t len, uint8_t indent);
1611 static const struct avrcp_ctrl_pdu_data avrcp_ctrl_pdu_table[] = {
1612 { 0x10, avrcp_get_capabilities },
1613 { 0x11, avrcp_list_player_attributes },
1614 { 0x12, avrcp_list_player_values },
1615 { 0x13, avrcp_get_current_player_value },
1616 { 0x14, avrcp_set_player_value },
1617 { 0x15, avrcp_get_player_attribute_text },
1618 { 0x16, avrcp_get_player_value_text },
1619 { 0x17, avrcp_displayable_charset },
1620 { 0x20, avrcp_get_element_attributes },
1621 { 0x30, avrcp_get_play_status },
1622 { 0x31, avrcp_register_notification },
1623 { 0x50, avrcp_set_absolute_volume },
1624 { 0x60, avrcp_set_addressed_player },
1625 { 0x74, avrcp_play_item },
1626 { 0x90, avrcp_add_to_now_playing },
1630 static bool avrcp_rejected_packet(struct l2cap_frame *frame, uint8_t indent)
1634 if (!l2cap_frame_get_u8(frame, &status))
1637 print_field("%*cError: 0x%02x (%s)", (indent - 8), ' ', status,
1643 static bool avrcp_pdu_packet(struct avctp_frame *avctp_frame, uint8_t ctype,
1646 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1650 const struct avrcp_ctrl_pdu_data *ctrl_pdu_data = NULL;
1652 if (!l2cap_frame_get_u8(frame, &pduid))
1655 if (!l2cap_frame_get_u8(frame, &avctp_frame->pt))
1658 if (!l2cap_frame_get_be16(frame, &len))
1661 print_indent(indent, COLOR_OFF, "AVRCP: ", pdu2str(pduid), COLOR_OFF,
1662 " pt %s len 0x%04x", pt2str(avctp_frame->pt), len);
1664 if (frame->size != len)
1668 return avrcp_rejected_packet(frame, indent + 2);
1670 for (i = 0; avrcp_ctrl_pdu_table[i].func; i++) {
1671 if (avrcp_ctrl_pdu_table[i].pduid == pduid) {
1672 ctrl_pdu_data = &avrcp_ctrl_pdu_table[i];
1677 if (!ctrl_pdu_data || !ctrl_pdu_data->func) {
1678 packet_hexdump(frame->data, frame->size);
1682 return ctrl_pdu_data->func(avctp_frame, ctype, len, indent + 2);
1685 static bool avrcp_control_packet(struct avctp_frame *avctp_frame)
1687 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1689 uint8_t ctype, address, subunit, opcode, company[3], indent = 2;
1691 if (!l2cap_frame_get_u8(frame, &ctype) ||
1692 !l2cap_frame_get_u8(frame, &address) ||
1693 !l2cap_frame_get_u8(frame, &opcode))
1696 print_field("AV/C: %s: address 0x%02x opcode 0x%02x",
1697 ctype2str(ctype), address, opcode);
1699 subunit = address >> 3;
1701 print_field("%*cSubunit: %s", indent, ' ', subunit2str(subunit));
1703 print_field("%*cOpcode: %s", indent, ' ', opcode2str(opcode));
1705 /* Skip non-panel subunit packets */
1706 if (subunit != 0x09) {
1707 packet_hexdump(frame->data, frame->size);
1711 /* Not implemented should not contain any operand */
1713 packet_hexdump(frame->data, frame->size);
1719 return avrcp_passthrough_packet(avctp_frame, 10);
1721 if (!l2cap_frame_get_u8(frame, &company[0]) ||
1722 !l2cap_frame_get_u8(frame, &company[1]) ||
1723 !l2cap_frame_get_u8(frame, &company[2]))
1726 print_field("%*cCompany ID: 0x%02x%02x%02x", indent, ' ',
1727 company[0], company[1], company[2]);
1729 return avrcp_pdu_packet(avctp_frame, ctype, 10);
1731 packet_hexdump(frame->data, frame->size);
1736 static const char *dir2str(uint8_t dir)
1742 return "Folder Down";
1748 static bool avrcp_change_path(struct avctp_frame *avctp_frame)
1750 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1753 uint16_t uidcounter;
1754 uint8_t dir, status, indent = 2;
1756 if (avctp_frame->hdr & 0x02)
1759 if (frame->size < 11) {
1760 print_field("%*cPDU Malformed", indent, ' ');
1761 packet_hexdump(frame->data, frame->size);
1765 if (!l2cap_frame_get_be16(frame, &uidcounter))
1768 print_field("%*cUIDCounter: 0x%04x (%u)", indent, ' ',
1769 uidcounter, uidcounter);
1771 if (!l2cap_frame_get_u8(frame, &dir))
1774 print_field("%*cDirection: 0x%02x (%s)", indent, ' ',
1777 if (!l2cap_frame_get_be64(frame, &uid))
1780 print_field("%*cFolderUID: 0x%16" PRIx64 " (%" PRIu64 ")", indent, ' ',
1786 if (!l2cap_frame_get_u8(frame, &status))
1789 print_field("%*cStatus: 0x%02x (%s)", indent, ' ',
1790 status, error2str(status));
1792 if (frame->size == 1)
1795 if (!l2cap_frame_get_be32(frame, &items))
1798 print_field("%*cNumber of Items: 0x%04x (%u)", indent, ' ',
1808 } features_table[] = {
1809 /* Ignore passthrough bits */
1810 [58] = { "Advanced Control Player" },
1811 [59] = { "Browsing" },
1812 [60] = { "Searching" },
1813 [61] = { "AddToNowPlaying" },
1814 [62] = { "Unique UIDs" },
1815 [63] = { "OnlyBrowsableWhenAddressed" },
1816 [64] = { "OnlySearchableWhenAddressed" },
1817 [65] = { "NowPlaying" },
1818 [66] = { "UIDPersistency" },
1819 /* 67-127 reserved */
1820 [67 ... 127] = { .reserved = true },
1823 static void print_features(uint8_t features[16], uint8_t indent)
1827 for (i = 0; i < 127; i++) {
1828 if (!(features[i / 8] & (1 << (i % 8))))
1831 if (features_table[i].reserved) {
1832 print_text(COLOR_WHITE_BG, "Unknown bit %u", i);
1836 if (!features_table[i].str)
1839 print_field("%*c%s", indent, ' ', features_table[i].str);
1843 static bool avrcp_media_player_item(struct avctp_frame *avctp_frame,
1846 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1847 uint16_t id, charset, namelen;
1848 uint8_t type, status, i;
1850 uint8_t features[16];
1852 if (!l2cap_frame_get_be16(frame, &id))
1855 print_field("%*cPlayerID: 0x%04x (%u)", indent, ' ', id, id);
1857 if (!l2cap_frame_get_u8(frame, &type))
1860 print_field("%*cPlayerType: 0x%04x (%s)", indent, ' ',
1861 type, playertype2str(type));
1863 if (!l2cap_frame_get_be32(frame, &subtype))
1866 print_field("%*cPlayerSubType: 0x%08x (%s)", indent, ' ',
1867 subtype, playersubtype2str(subtype));
1869 if (!l2cap_frame_get_u8(frame, &status))
1872 print_field("%*cPlayStatus: 0x%02x (%s)", indent, ' ',
1873 status, playstatus2str(status));
1875 printf("%*cFeatures: 0x", indent+8, ' ');
1877 for (i = 0; i < 16; i++) {
1878 if (!l2cap_frame_get_u8(frame, &features[i]))
1881 printf("%02x", features[i]);
1886 print_features(features, indent + 2);
1888 if (!l2cap_frame_get_be16(frame, &charset))
1891 print_field("%*cCharsetID: 0x%04x (%s)", indent, ' ',
1892 charset, charset2str(charset));
1894 if (!l2cap_frame_get_be16(frame, &namelen))
1897 print_field("%*cNameLength: 0x%04x (%u)", indent, ' ',
1900 printf("%*cName: ", indent+8, ' ');
1901 for (; namelen > 0; namelen--) {
1904 if (!l2cap_frame_get_u8(frame, &c))
1906 printf("%1c", isprint(c) ? c : '.');
1913 static bool avrcp_folder_item(struct avctp_frame *avctp_frame,
1916 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1917 uint8_t type, playable;
1918 uint16_t charset, namelen;
1921 if (frame->size < 14) {
1922 printf("PDU Malformed\n");
1926 if (!l2cap_frame_get_be64(frame, &uid))
1929 print_field("%*cFolderUID: 0x%16" PRIx64 " (%" PRIu64 ")", indent, ' ',
1932 if (!l2cap_frame_get_u8(frame, &type))
1935 print_field("%*cFolderType: 0x%02x (%s)", indent, ' ',
1936 type, foldertype2str(type));
1938 if (!l2cap_frame_get_u8(frame, &playable))
1941 print_field("%*cIsPlayable: 0x%02x (%s)", indent, ' ', playable,
1942 playable & 0x01 ? "True" : "False");
1944 if (!l2cap_frame_get_be16(frame, &charset))
1947 print_field("%*cCharsetID: 0x%04x (%s)", indent, ' ',
1948 charset, charset2str(charset));
1950 if (!l2cap_frame_get_be16(frame, &namelen))
1953 print_field("%*cNameLength: 0x%04x (%u)", indent, ' ',
1956 printf("%*cName: ", indent+8, ' ');
1957 for (; namelen > 0; namelen--) {
1959 if (!l2cap_frame_get_u8(frame, &c))
1962 printf("%1c", isprint(c) ? c : '.');
1969 static bool avrcp_attribute_entry_list(struct avctp_frame *avctp_frame,
1970 uint8_t indent, uint8_t count)
1972 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
1974 for (; count > 0; count--) {
1976 uint16_t charset, len;
1978 if (!l2cap_frame_get_be32(frame, &attr))
1981 print_field("%*cAttributeID: 0x%08x (%s)", indent, ' ',
1982 attr, mediattr2str(attr));
1984 if (!l2cap_frame_get_be16(frame, &charset))
1987 print_field("%*cCharsetID: 0x%04x (%s)", indent, ' ',
1988 charset, charset2str(charset));
1990 if (!l2cap_frame_get_be16(frame, &len))
1993 print_field("%*cAttributeLength: 0x%04x (%u)", indent, ' ',
1996 printf("%*cAttributeValue: ", indent+8, ' ');
1997 for (; len > 0; len--) {
2000 if (!l2cap_frame_get_u8(frame, &c))
2003 printf("%1c", isprint(c) ? c : '.');
2011 static bool avrcp_media_element_item(struct avctp_frame *avctp_frame,
2014 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2016 uint16_t charset, namelen;
2017 uint8_t type, count;
2019 if (!l2cap_frame_get_be64(frame, &uid))
2022 print_field("%*cElementUID: 0x%16" PRIx64 " (%" PRIu64 ")",
2023 indent, ' ', uid, uid);
2025 if (!l2cap_frame_get_u8(frame, &type))
2028 print_field("%*cElementType: 0x%02x (%s)", indent, ' ',
2029 type, elementtype2str(type));
2031 if (!l2cap_frame_get_be16(frame, &charset))
2034 print_field("%*cCharsetID: 0x%04x (%s)", indent, ' ',
2035 charset, charset2str(charset));
2037 if (!l2cap_frame_get_be16(frame, &namelen))
2040 print_field("%*cNameLength: 0x%04x (%u)", indent, ' ',
2043 printf("%*cName: ", indent+8, ' ');
2044 for (; namelen > 0; namelen--) {
2046 if (!l2cap_frame_get_u8(frame, &c))
2049 printf("%1c", isprint(c) ? c : '.');
2053 if (!l2cap_frame_get_u8(frame, &count))
2056 print_field("%*cAttributeCount: 0x%02x (%u)", indent, ' ',
2059 if (!avrcp_attribute_entry_list(avctp_frame, indent, count))
2065 static bool avrcp_general_reject(struct avctp_frame *avctp_frame)
2067 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2068 uint8_t status, indent = 2;
2070 if (avctp_frame->hdr & 0x02)
2073 print_field("%*cPDU Malformed", indent, ' ');
2074 packet_hexdump(frame->data, frame->size);
2079 if (!l2cap_frame_get_u8(frame, &status))
2082 print_field("%*cStatus: 0x%02x (%s)", indent, ' ',
2083 status, error2str(status));
2088 static bool avrcp_get_total_number_of_items(struct avctp_frame *avctp_frame)
2090 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2091 uint32_t num_of_items;
2092 uint16_t uidcounter;
2093 uint8_t scope, status, indent = 2;
2095 if (avctp_frame->hdr & 0x02)
2098 if (frame->size < 4) {
2099 printf("PDU Malformed\n");
2100 packet_hexdump(frame->data, frame->size);
2104 if (!l2cap_frame_get_u8(frame, &scope))
2107 print_field("%*cScope: 0x%02x (%s)", (indent - 8), ' ',
2108 scope, scope2str(scope));
2113 if (!l2cap_frame_get_u8(frame, &status))
2116 print_field("%*cStatus: 0x%02x (%s)", indent, ' ',
2117 status, error2str(status));
2119 if (frame->size == 1)
2122 if (!l2cap_frame_get_be16(frame, &uidcounter))
2125 print_field("%*cUIDCounter: 0x%04x (%u)", indent, ' ',
2126 uidcounter, uidcounter);
2128 if (!l2cap_frame_get_be32(frame, &num_of_items))
2131 print_field("%*cNumber of Items: 0x%04x (%u)", indent, ' ',
2132 num_of_items, num_of_items);
2137 static bool avrcp_search_item(struct avctp_frame *avctp_frame)
2139 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2141 uint16_t charset, namelen, uidcounter;
2142 uint8_t status, indent = 2;
2144 if (avctp_frame->hdr & 0x02)
2147 if (frame->size < 4) {
2148 printf("PDU Malformed\n");
2149 packet_hexdump(frame->data, frame->size);
2153 if (!l2cap_frame_get_be16(frame, &charset))
2156 print_field("%*cCharsetID: 0x%04x (%s)", indent, ' ',
2157 charset, charset2str(charset));
2159 if (!l2cap_frame_get_be16(frame, &namelen))
2162 print_field("%*cLength: 0x%04x (%u)", indent, ' ', namelen, namelen);
2164 printf("%*cString: ", indent+8, ' ');
2165 for (; namelen > 0; namelen--) {
2168 if (!l2cap_frame_get_u8(frame, &c))
2171 printf("%1c", isprint(c) ? c : '.');
2179 if (!l2cap_frame_get_u8(frame, &status))
2182 print_field("%*cStatus: 0x%02x (%s)", indent, ' ',
2183 status, error2str(status));
2185 if (frame->size == 1)
2188 if (!l2cap_frame_get_be16(frame, &uidcounter))
2191 print_field("%*cUIDCounter: 0x%04x (%u)", indent, ' ',
2192 uidcounter, uidcounter);
2194 if (!l2cap_frame_get_be32(frame, &items))
2197 print_field("%*cNumber of Items: 0x%04x (%u)", indent, ' ',
2203 static bool avrcp_get_item_attributes(struct avctp_frame *avctp_frame)
2205 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2207 uint16_t uidcounter;
2208 uint8_t scope, count, status, indent = 2;
2210 if (avctp_frame->hdr & 0x02)
2213 if (frame->size < 12) {
2214 print_field("%*cPDU Malformed", indent, ' ');
2215 packet_hexdump(frame->data, frame->size);
2219 if (!l2cap_frame_get_u8(frame, &scope))
2222 print_field("%*cScope: 0x%02x (%s)", indent, ' ',
2223 scope, scope2str(scope));
2225 if (!l2cap_frame_get_be64(frame, &uid))
2228 print_field("%*cUID: 0x%016" PRIx64 " (%" PRIu64 ")", indent,
2231 if (!l2cap_frame_get_be16(frame, &uidcounter))
2234 print_field("%*cUIDCounter: 0x%04x (%u)", indent, ' ',
2235 uidcounter, uidcounter);
2237 if (!l2cap_frame_get_u8(frame, &count))
2240 print_field("%*cAttributeCount: 0x%02x (%u)", indent, ' ',
2243 for (; count > 0; count--) {
2246 if (!l2cap_frame_get_be32(frame, &attr))
2249 print_field("%*cAttributeID: 0x%08x (%s)", indent, ' ',
2250 attr, mediattr2str(attr));
2256 if (!l2cap_frame_get_u8(frame, &status))
2259 print_field("%*cStatus: 0x%02x (%s)", indent, ' ',
2260 status, error2str(status));
2262 if (frame->size == 1)
2265 if (!l2cap_frame_get_u8(frame, &count))
2268 print_field("%*cAttributeCount: 0x%02x (%u)", indent, ' ',
2271 if (!avrcp_attribute_entry_list(avctp_frame, indent, count))
2277 static bool avrcp_get_folder_items(struct avctp_frame *avctp_frame)
2279 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2280 uint8_t scope, count, status, indent = 2;
2281 uint32_t start, end;
2284 if (avctp_frame->hdr & 0x02)
2287 if (!l2cap_frame_get_u8(frame, &scope))
2290 print_field("%*cScope: 0x%02x (%s)", indent, ' ',
2291 scope, scope2str(scope));
2293 if (!l2cap_frame_get_be32(frame, &start))
2296 print_field("%*cStartItem: 0x%08x (%u)", indent, ' ', start, start);
2298 if (!l2cap_frame_get_be32(frame, &end))
2301 print_field("%*cEndItem: 0x%08x (%u)", indent, ' ', end, end);
2303 if (!l2cap_frame_get_u8(frame, &count))
2306 print_field("%*cAttributeCount: 0x%02x (%u)", indent, ' ',
2309 for (; count > 0; count--) {
2312 if (!l2cap_frame_get_be32(frame, &attr))
2315 print_field("%*cAttributeID: 0x%08x (%s)", indent, ' ',
2316 attr, mediattr2str(attr));
2322 if (!l2cap_frame_get_u8(frame, &status))
2325 print_field("%*cStatus: 0x%02x (%s)", indent, ' ',
2326 status, error2str(status));
2328 if (!l2cap_frame_get_be16(frame, &uid))
2331 print_field("%*cUIDCounter: 0x%04x (%u)", indent, ' ', uid, uid);
2333 if (!l2cap_frame_get_be16(frame, &num))
2336 print_field("%*cNumOfItems: 0x%04x (%u)", indent, ' ', num, num);
2338 for (; num > 0; num--) {
2342 if (!l2cap_frame_get_u8(frame, &type))
2345 if (!l2cap_frame_get_be16(frame, &len))
2348 print_field("%*cItem: 0x%02x (%s) ", indent, ' ',
2349 type, type2str(type));
2350 print_field("%*cLength: 0x%04x (%u)", indent, ' ', len, len);
2353 case AVRCP_MEDIA_PLAYER_ITEM_TYPE:
2354 avrcp_media_player_item(avctp_frame, indent);
2356 case AVRCP_FOLDER_ITEM_TYPE:
2357 avrcp_folder_item(avctp_frame, indent);
2359 case AVRCP_MEDIA_ELEMENT_ITEM_TYPE:
2360 avrcp_media_element_item(avctp_frame, indent);
2363 print_field("%*cUnknown Media Item type", indent, ' ');
2364 packet_hexdump(frame->data, frame->size);
2371 static bool avrcp_set_browsed_player(struct avctp_frame *avctp_frame)
2373 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2375 uint16_t id, uids, charset;
2376 uint8_t status, folders, indent = 2;
2378 if (avctp_frame->hdr & 0x02)
2381 if (!l2cap_frame_get_be16(frame, &id))
2384 print_field("%*cPlayerID: 0x%04x (%u)", indent, ' ', id, id);
2388 if (!l2cap_frame_get_u8(frame, &status))
2391 print_field("%*cStatus: 0x%02x (%s)", indent, ' ', status,
2394 if (!l2cap_frame_get_be16(frame, &uids))
2397 print_field("%*cUIDCounter: 0x%04x (%u)", indent, ' ', uids, uids);
2399 if (!l2cap_frame_get_be32(frame, &items))
2402 print_field("%*cNumber of Items: 0x%08x (%u)", indent, ' ',
2405 if (!l2cap_frame_get_be16(frame, &charset))
2408 print_field("%*cCharsetID: 0x%04x (%s)", indent, ' ', charset,
2409 charset2str(charset));
2411 if (!l2cap_frame_get_u8(frame, &folders))
2414 print_field("%*cFolder Depth: 0x%02x (%u)", indent, ' ', folders,
2417 for (; folders > 0; folders--) {
2420 if (!l2cap_frame_get_u8(frame, &len))
2424 print_field("%*cFolder: <empty>", indent, ' ');
2428 printf("%*cFolder: ", indent+8, ' ');
2429 for (; len > 0; len--) {
2432 if (!l2cap_frame_get_u8(frame, &c))
2435 printf("%1c", isprint(c) ? c : '.');
2443 static bool avrcp_browsing_packet(struct avctp_frame *avctp_frame)
2445 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2449 if (!l2cap_frame_get_u8(frame, &pduid))
2452 if (!l2cap_frame_get_be16(frame, &len))
2455 print_field("AVRCP: %s: len 0x%04x", pdu2str(pduid), len);
2458 case AVRCP_SET_BROWSED_PLAYER:
2459 avrcp_set_browsed_player(avctp_frame);
2461 case AVRCP_GET_FOLDER_ITEMS:
2462 avrcp_get_folder_items(avctp_frame);
2464 case AVRCP_CHANGE_PATH:
2465 avrcp_change_path(avctp_frame);
2467 case AVRCP_GET_ITEM_ATTRIBUTES:
2468 avrcp_get_item_attributes(avctp_frame);
2470 case AVRCP_GET_TOTAL_NUMBER_OF_ITEMS:
2471 avrcp_get_total_number_of_items(avctp_frame);
2474 avrcp_search_item(avctp_frame);
2476 case AVRCP_GENERAL_REJECT:
2477 avrcp_general_reject(avctp_frame);
2480 packet_hexdump(frame->data, frame->size);
2486 static void avrcp_packet(struct avctp_frame *avctp_frame)
2488 struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
2491 switch (frame->psm) {
2493 ret = avrcp_control_packet(avctp_frame);
2496 ret = avrcp_browsing_packet(avctp_frame);
2499 packet_hexdump(frame->data, frame->size);
2504 print_text(COLOR_ERROR, "PDU malformed");
2505 packet_hexdump(frame->data, frame->size);
2509 void avctp_packet(const struct l2cap_frame *frame)
2511 struct l2cap_frame *l2cap_frame;
2512 struct avctp_frame avctp_frame;
2513 const char *pdu_color;
2515 l2cap_frame_pull(&avctp_frame.l2cap_frame, frame, 0);
2517 l2cap_frame = &avctp_frame.l2cap_frame;
2519 if (!l2cap_frame_get_u8(l2cap_frame, &avctp_frame.hdr) ||
2520 !l2cap_frame_get_be16(l2cap_frame, &avctp_frame.pid)) {
2521 print_text(COLOR_ERROR, "frame too short");
2522 packet_hexdump(frame->data, frame->size);
2527 pdu_color = COLOR_MAGENTA;
2529 pdu_color = COLOR_BLUE;
2531 print_indent(6, pdu_color, "AVCTP", "", COLOR_OFF,
2532 " %s: %s: type 0x%02x label %d PID 0x%04x",
2533 frame->psm == 23 ? "Control" : "Browsing",
2534 avctp_frame.hdr & 0x02 ? "Response" : "Command",
2535 avctp_frame.hdr & 0x0c, avctp_frame.hdr >> 4,
2538 if (avctp_frame.pid == 0x110e || avctp_frame.pid == 0x110c)
2539 avrcp_packet(&avctp_frame);
2541 packet_hexdump(frame->data, frame->size);