3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2006-2010 Nokia Corporation
6 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
7 * Copyright (C) 2011 Texas Instruments, Inc.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
38 #include <sys/types.h>
43 #include <dbus/dbus.h>
45 #include "bluetooth/bluetooth.h"
46 #include "bluetooth/sdp.h"
47 #include "bluetooth/sdp_lib.h"
50 #include "gdbus/gdbus.h"
52 #include "src/plugin.h"
53 #include "src/adapter.h"
54 #include "src/device.h"
55 #include "src/profile.h"
56 #include "src/service.h"
58 #include "src/error.h"
60 #include "src/dbus-common.h"
61 #include "src/shared/util.h"
68 #include "transport.h"
70 /* Company IDs for vendor dependent commands */
71 #define IEEEID_BTSIG 0x001958
74 #define AVRCP_STATUS_INVALID_COMMAND 0x00
75 #define AVRCP_STATUS_INVALID_PARAM 0x01
76 #define AVRCP_STATUS_PARAM_NOT_FOUND 0x02
77 #define AVRCP_STATUS_INTERNAL_ERROR 0x03
78 #define AVRCP_STATUS_SUCCESS 0x04
79 #define AVRCP_STATUS_UID_CHANGED 0x05
80 #define AVRCP_STATUS_DOES_NOT_EXIST 0x09
81 #define AVRCP_STATUS_OUT_OF_BOUNDS 0x0b
82 #define AVRCP_STATUS_INVALID_PLAYER_ID 0x11
83 #define AVRCP_STATUS_PLAYER_NOT_BROWSABLE 0x12
84 #define AVRCP_STATUS_NO_AVAILABLE_PLAYERS 0x15
85 #define AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED 0x16
88 #define AVRCP_PACKET_TYPE_SINGLE 0x00
89 #define AVRCP_PACKET_TYPE_START 0x01
90 #define AVRCP_PACKET_TYPE_CONTINUING 0x02
91 #define AVRCP_PACKET_TYPE_END 0x03
93 /* PDU types for metadata transfer */
94 #define AVRCP_GET_CAPABILITIES 0x10
95 #define AVRCP_LIST_PLAYER_ATTRIBUTES 0X11
96 #define AVRCP_LIST_PLAYER_VALUES 0x12
97 #define AVRCP_GET_CURRENT_PLAYER_VALUE 0x13
98 #define AVRCP_SET_PLAYER_VALUE 0x14
99 #define AVRCP_GET_PLAYER_ATTRIBUTE_TEXT 0x15
100 #define AVRCP_GET_PLAYER_VALUE_TEXT 0x16
101 #define AVRCP_DISPLAYABLE_CHARSET 0x17
102 #define AVRCP_CT_BATTERY_STATUS 0x18
103 #define AVRCP_GET_ELEMENT_ATTRIBUTES 0x20
104 #define AVRCP_GET_PLAY_STATUS 0x30
105 #define AVRCP_REGISTER_NOTIFICATION 0x31
106 #define AVRCP_REQUEST_CONTINUING 0x40
107 #define AVRCP_ABORT_CONTINUING 0x41
108 #define AVRCP_SET_ABSOLUTE_VOLUME 0x50
109 #define AVRCP_SET_ADDRESSED_PLAYER 0x60
110 #define AVRCP_SET_BROWSED_PLAYER 0x70
111 #define AVRCP_GET_FOLDER_ITEMS 0x71
112 #define AVRCP_CHANGE_PATH 0x72
113 #define AVRCP_GET_ITEM_ATTRIBUTES 0x73
114 #define AVRCP_PLAY_ITEM 0x74
115 #define AVRCP_GET_TOTAL_NUMBER_OF_ITEMS 0x75
116 #define AVRCP_SEARCH 0x80
117 #define AVRCP_ADD_TO_NOW_PLAYING 0x90
118 #define AVRCP_GENERAL_REJECT 0xA0
120 /* Capabilities for AVRCP_GET_CAPABILITIES pdu */
121 #define CAP_COMPANY_ID 0x02
122 #define CAP_EVENTS_SUPPORTED 0x03
124 #define AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH 5
125 #define AVRCP_GET_CAPABILITIES_PARAM_LENGTH 1
127 #define AVRCP_FEATURE_CATEGORY_1 0x0001
128 #define AVRCP_FEATURE_CATEGORY_2 0x0002
129 #define AVRCP_FEATURE_CATEGORY_3 0x0004
130 #define AVRCP_FEATURE_CATEGORY_4 0x0008
131 #define AVRCP_FEATURE_PLAYER_SETTINGS 0x0010
132 #define AVRCP_FEATURE_BROWSING 0x0040
134 #define AVRCP_BATTERY_STATUS_NORMAL 0
135 #define AVRCP_BATTERY_STATUS_WARNING 1
136 #define AVRCP_BATTERY_STATUS_CRITICAL 2
137 #define AVRCP_BATTERY_STATUS_EXTERNAL 3
138 #define AVRCP_BATTERY_STATUS_FULL_CHARGE 4
140 #define AVRCP_CHARSET_UTF8 106
142 #define AVRCP_BROWSING_TIMEOUT 1
143 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
144 #define AVRCP_CT_VERSION 0x0104
145 #define AVRCP_TG_VERSION 0x0103
147 #define AVRCP_CT_VERSION 0x0106
148 #define AVRCP_TG_VERSION 0x0105
150 #define AVRCP_SCOPE_MEDIA_PLAYER_LIST 0x00
151 #define AVRCP_SCOPE_MEDIA_PLAYER_VFS 0x01
152 #define AVRCP_SCOPE_SEARCH 0x02
153 #define AVRCP_SCOPE_NOW_PLAYING 0x03
155 #if __BYTE_ORDER == __LITTLE_ENDIAN
157 struct avrcp_header {
158 uint8_t company_id[3];
160 uint8_t packet_type:2;
164 } __attribute__ ((packed));
165 #define AVRCP_HEADER_LENGTH 7
167 #elif __BYTE_ORDER == __BIG_ENDIAN
169 struct avrcp_header {
170 uint8_t company_id[3];
173 uint8_t packet_type:2;
176 } __attribute__ ((packed));
177 #define AVRCP_HEADER_LENGTH 7
180 #error "Unknown byte order"
183 #define AVRCP_MTU (AVC_MTU - AVC_HEADER_LENGTH)
184 #define AVRCP_PDU_MTU (AVRCP_MTU - AVRCP_HEADER_LENGTH)
186 struct avrcp_browsing_header {
190 } __attribute__ ((packed));
191 #define AVRCP_BROWSING_HEADER_LENGTH 3
193 struct get_folder_items_rsp {
195 uint16_t uid_counter;
198 } __attribute__ ((packed));
204 } __attribute__ ((packed));
211 uint8_t features[16];
215 } __attribute__ ((packed));
217 struct avrcp_server {
218 struct btd_adapter *adapter;
219 uint32_t tg_record_id;
220 uint32_t ct_record_id;
231 struct pending_list_items {
238 struct avrcp_player {
239 struct avrcp_server *server;
244 uint16_t uid_counter;
251 struct pending_list_items *p;
255 struct avrcp_player_cb *cb;
257 GDestroyNotify destroy;
261 struct avrcp_player *player;
268 struct avrcp_server *server;
270 struct btd_device *dev;
271 struct avrcp_data *target;
272 struct avrcp_data *controller;
274 const struct passthrough_handler *passthrough_handlers;
275 const struct control_pdu_handler *control_handlers;
277 unsigned int passthrough_id;
278 unsigned int control_id;
279 unsigned int browsing_id;
280 unsigned int browsing_timer;
281 uint16_t supported_events;
282 uint16_t registered_events;
284 uint8_t transaction_events[AVRCP_EVENT_LAST + 1];
285 struct pending_pdu *pending_pdu;
286 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
287 uint16_t remote_supported_events;
288 uint32_t playback_status_id;
292 struct passthrough_handler {
294 bool (*func) (struct avrcp *session);
297 struct control_pdu_handler {
300 uint8_t (*func) (struct avrcp *session, struct avrcp_header *pdu,
301 uint8_t transaction);
307 } passthrough_map[] = {
314 { 6, AVC_RIGHT_DOWN },
316 { 8, AVC_LEFT_DOWN },
317 { 9, AVC_ROOT_MENU },
318 { 10, AVC_SETUP_MENU },
319 { 11, AVC_CONTENTS_MENU },
320 { 12, AVC_FAVORITE_MENU },
335 { 27, AVC_CHANNEL_UP },
336 { 28, AVC_CHANNEL_DOWN },
337 { 29, AVC_CHANNEL_PREVIOUS },
338 { 30, AVC_SOUND_SELECT },
339 { 31, AVC_INPUT_SELECT },
343 { 35, AVC_PAGE_DOWN },
345 { 37, AVC_VOLUME_UP },
346 { 38, AVC_VOLUME_DOWN },
353 { 45, AVC_FAST_FORWARD },
356 { 48, AVC_BACKWARD },
358 { 50, AVC_SUBPICTURE },
364 { 56, AVC_VENDOR_UNIQUE },
368 static GSList *servers = NULL;
369 static unsigned int avctp_id = 0;
371 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
372 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_TARGET
373 static uint16_t adapter_avrcp_tg_ver = 0;
375 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_CONTROL
376 static uint16_t adapter_avrcp_ct_ver = 0;
380 /* Default feature bit mask for media player */
381 static uint8_t default_features[16];
383 /* Company IDs supported by this device */
384 static uint32_t company_ids[] = {
388 static void avrcp_register_notification(struct avrcp *session, uint8_t event);
389 static GList *player_list_settings(struct avrcp_player *player);
391 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
392 void avrcp_stop_position_timer(void);
393 unsigned int pos_timer_id = 0;
396 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_CONTROL
397 static sdp_record_t *avrcp_ct_record(void)
399 sdp_list_t *svclass_id, *pfseq, *apseq, *apseq1, *root;
400 uuid_t root_uuid, l2cap, avctp, avrct, avrctr;
401 sdp_profile_desc_t profile[1];
402 sdp_list_t *aproto, *aproto1, *proto[2], *proto1[2];
403 sdp_record_t *record;
404 sdp_data_t *psm[2], *version, *features;
405 uint16_t lp = AVCTP_CONTROL_PSM, ap = AVCTP_BROWSING_PSM;
406 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
407 uint16_t avctp_ver = 0x0104;
409 #ifdef ENABLE_AVRCP_CATEGORY1
410 feat = AVRCP_FEATURE_CATEGORY_1;
412 #ifdef ENABLE_AVRCP_CATEGORY2
413 feat = feat | AVRCP_FEATURE_CATEGORY_2;
416 uint16_t avctp_ver = 0x0103;
417 uint16_t feat = (AVRCP_FEATURE_CATEGORY_1 |
418 AVRCP_FEATURE_CATEGORY_2 |
419 AVRCP_FEATURE_CATEGORY_3 |
420 AVRCP_FEATURE_CATEGORY_4 |
421 AVRCP_FEATURE_BROWSING);
424 record = sdp_record_alloc();
428 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
429 root = sdp_list_append(NULL, &root_uuid);
430 sdp_set_browse_groups(record, root);
432 /* Service Class ID List */
433 sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID);
434 svclass_id = sdp_list_append(NULL, &avrct);
435 sdp_uuid16_create(&avrctr, AV_REMOTE_CONTROLLER_SVCLASS_ID);
436 svclass_id = sdp_list_append(svclass_id, &avrctr);
437 sdp_set_service_classes(record, svclass_id);
439 /* Protocol Descriptor List */
440 sdp_uuid16_create(&l2cap, L2CAP_UUID);
441 proto[0] = sdp_list_append(NULL, &l2cap);
442 psm[0] = sdp_data_alloc(SDP_UINT16, &lp);
443 proto[0] = sdp_list_append(proto[0], psm[0]);
444 apseq = sdp_list_append(NULL, proto[0]);
446 sdp_uuid16_create(&avctp, AVCTP_UUID);
447 proto[1] = sdp_list_append(NULL, &avctp);
448 version = sdp_data_alloc(SDP_UINT16, &avctp_ver);
449 proto[1] = sdp_list_append(proto[1], version);
450 apseq = sdp_list_append(apseq, proto[1]);
452 aproto = sdp_list_append(NULL, apseq);
453 sdp_set_access_protos(record, aproto);
455 /* Additional Protocol Descriptor List */
456 sdp_uuid16_create(&l2cap, L2CAP_UUID);
457 proto1[0] = sdp_list_append(NULL, &l2cap);
458 psm[1] = sdp_data_alloc(SDP_UINT16, &ap);
459 proto1[0] = sdp_list_append(proto1[0], psm[1]);
460 apseq1 = sdp_list_append(NULL, proto1[0]);
462 sdp_uuid16_create(&avctp, AVCTP_UUID);
463 proto1[1] = sdp_list_append(NULL, &avctp);
464 proto1[1] = sdp_list_append(proto1[1], version);
465 apseq1 = sdp_list_append(apseq1, proto1[1]);
467 aproto1 = sdp_list_append(NULL, apseq1);
468 sdp_set_add_access_protos(record, aproto1);
470 /* Bluetooth Profile Descriptor List */
471 sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
472 profile[0].version = AVRCP_CT_VERSION;
473 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
474 adapter_avrcp_ct_ver = AVRCP_CT_VERSION;
476 pfseq = sdp_list_append(NULL, &profile[0]);
477 sdp_set_profile_descs(record, pfseq);
479 features = sdp_data_alloc(SDP_UINT16, &feat);
480 sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
482 sdp_set_info_attr(record, "AVRCP CT", NULL, NULL);
487 sdp_list_free(proto[0], NULL);
488 sdp_list_free(proto[1], NULL);
489 sdp_list_free(apseq, NULL);
490 sdp_list_free(proto1[0], NULL);
491 sdp_list_free(proto1[1], NULL);
492 sdp_list_free(aproto1, NULL);
493 sdp_list_free(apseq1, NULL);
494 sdp_list_free(pfseq, NULL);
495 sdp_list_free(aproto, NULL);
496 sdp_list_free(root, NULL);
497 sdp_list_free(svclass_id, NULL);
503 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_TARGET
504 static sdp_record_t *avrcp_tg_record(void)
506 sdp_list_t *svclass_id, *pfseq, *apseq, *root, *apseq_browsing;
507 uuid_t root_uuid, l2cap, avctp, avrtg;
508 sdp_profile_desc_t profile[1];
509 sdp_list_t *aproto_control, *proto_control[2];
510 sdp_record_t *record;
511 sdp_data_t *psm_control, *version, *features, *psm_browsing;
512 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
513 sdp_list_t *aproto_browsing;
515 sdp_list_t *proto_browsing[2] = {0};
516 uint16_t lp = AVCTP_CONTROL_PSM;
517 uint16_t lp_browsing = AVCTP_BROWSING_PSM;
518 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
519 uint16_t avctp_ver = 0x0104;
521 #ifdef ENABLE_AVRCP_CATEGORY1
522 feat = AVRCP_FEATURE_CATEGORY_1 |
523 AVRCP_FEATURE_PLAYER_SETTINGS;
525 #ifdef ENABLE_AVRCP_CATEGORY2
526 feat = feat | AVRCP_FEATURE_CATEGORY_2;
529 uint16_t avctp_ver = 0x0103;
530 uint16_t feat = (AVRCP_FEATURE_CATEGORY_1 |
531 AVRCP_FEATURE_CATEGORY_2 |
532 AVRCP_FEATURE_CATEGORY_3 |
533 AVRCP_FEATURE_CATEGORY_4 |
534 AVRCP_FEATURE_BROWSING |
535 AVRCP_FEATURE_PLAYER_SETTINGS);
537 record = sdp_record_alloc();
541 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
542 root = sdp_list_append(NULL, &root_uuid);
543 sdp_set_browse_groups(record, root);
545 /* Service Class ID List */
546 sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
547 svclass_id = sdp_list_append(NULL, &avrtg);
548 sdp_set_service_classes(record, svclass_id);
550 /* Protocol Descriptor List */
551 sdp_uuid16_create(&l2cap, L2CAP_UUID);
552 proto_control[0] = sdp_list_append(NULL, &l2cap);
553 psm_control = sdp_data_alloc(SDP_UINT16, &lp);
554 proto_control[0] = sdp_list_append(proto_control[0], psm_control);
555 apseq = sdp_list_append(NULL, proto_control[0]);
557 sdp_uuid16_create(&avctp, AVCTP_UUID);
558 proto_control[1] = sdp_list_append(NULL, &avctp);
559 version = sdp_data_alloc(SDP_UINT16, &avctp_ver);
560 proto_control[1] = sdp_list_append(proto_control[1], version);
561 apseq = sdp_list_append(apseq, proto_control[1]);
563 aproto_control = sdp_list_append(NULL, apseq);
564 sdp_set_access_protos(record, aproto_control);
565 proto_browsing[0] = sdp_list_append(NULL, &l2cap);
566 psm_browsing = sdp_data_alloc(SDP_UINT16, &lp_browsing);
567 proto_browsing[0] = sdp_list_append(proto_browsing[0], psm_browsing);
568 apseq_browsing = sdp_list_append(NULL, proto_browsing[0]);
570 proto_browsing[1] = sdp_list_append(NULL, &avctp);
571 proto_browsing[1] = sdp_list_append(proto_browsing[1], version);
572 apseq_browsing = sdp_list_append(apseq_browsing, proto_browsing[1]);
574 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
575 aproto_browsing = sdp_list_append(NULL, apseq_browsing);
576 sdp_set_add_access_protos(record, aproto_browsing);
579 /* Bluetooth Profile Descriptor List */
580 sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
581 profile[0].version = AVRCP_TG_VERSION;
582 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
583 adapter_avrcp_tg_ver = AVRCP_TG_VERSION;
585 pfseq = sdp_list_append(NULL, &profile[0]);
586 sdp_set_profile_descs(record, pfseq);
588 features = sdp_data_alloc(SDP_UINT16, &feat);
589 sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
591 sdp_set_info_attr(record, "AVRCP TG", NULL, NULL);
594 sdp_list_free(proto_browsing[0], NULL);
595 sdp_list_free(proto_browsing[1], NULL);
596 sdp_list_free(apseq_browsing, NULL);
597 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
598 sdp_list_free(aproto_browsing, NULL);
603 sdp_list_free(proto_control[0], NULL);
604 sdp_list_free(proto_control[1], NULL);
605 sdp_list_free(apseq, NULL);
606 sdp_list_free(aproto_control, NULL);
607 sdp_list_free(pfseq, NULL);
608 sdp_list_free(root, NULL);
609 sdp_list_free(svclass_id, NULL);
615 static void populate_default_features(void)
619 for (i = 0; passthrough_map[i].feature_bit != 0xff; i++) {
620 if (avctp_supports_avc(passthrough_map[i].avc)) {
621 uint8_t bit = passthrough_map[i].feature_bit;
623 default_features[bit >> 3] |= (1 << (bit & 7));
627 /* supports at least AVRCP 1.4 */
628 default_features[7] |= (1 << 2);
631 static unsigned int attr_get_max_val(uint8_t attr)
634 case AVRCP_ATTRIBUTE_EQUALIZER:
635 return AVRCP_EQUALIZER_ON;
636 case AVRCP_ATTRIBUTE_REPEAT_MODE:
637 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
638 return AVRCP_REPEAT_MODE_ALL;
640 return AVRCP_REPEAT_MODE_GROUP;
642 case AVRCP_ATTRIBUTE_SHUFFLE:
643 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
644 return AVRCP_SHUFFLE_ALL;
646 return AVRCP_SHUFFLE_GROUP;
648 case AVRCP_ATTRIBUTE_SCAN:
649 return AVRCP_SCAN_GROUP;
655 static const char *battery_status_to_str(uint8_t status)
658 case AVRCP_BATTERY_STATUS_NORMAL:
660 case AVRCP_BATTERY_STATUS_WARNING:
662 case AVRCP_BATTERY_STATUS_CRITICAL:
664 case AVRCP_BATTERY_STATUS_EXTERNAL:
666 case AVRCP_BATTERY_STATUS_FULL_CHARGE:
676 * Get three-byte Company_ID from incoming AVRCP message
678 static uint32_t get_company_id(const uint8_t cid[3])
680 return cid[0] << 16 | cid[1] << 8 | cid[2];
686 * Set three-byte Company_ID into outgoing AVRCP message
688 static void set_company_id(uint8_t cid[3], uint32_t cid_in)
690 cid[0] = (cid_in & 0xff0000) >> 16;
691 cid[1] = (cid_in & 0x00ff00) >> 8;
692 cid[2] = (cid_in & 0x0000ff);
695 static const char *attr_to_str(uint8_t attr)
698 case AVRCP_ATTRIBUTE_EQUALIZER:
700 case AVRCP_ATTRIBUTE_REPEAT_MODE:
702 case AVRCP_ATTRIBUTE_SHUFFLE:
704 case AVRCP_ATTRIBUTE_SCAN:
711 static int attrval_to_val(uint8_t attr, const char *value)
716 case AVRCP_ATTRIBUTE_EQUALIZER:
717 if (!strcmp(value, "off"))
718 ret = AVRCP_EQUALIZER_OFF;
719 else if (!strcmp(value, "on"))
720 ret = AVRCP_EQUALIZER_ON;
725 case AVRCP_ATTRIBUTE_REPEAT_MODE:
726 if (!strcmp(value, "off"))
727 ret = AVRCP_REPEAT_MODE_OFF;
728 else if (!strcmp(value, "singletrack"))
729 ret = AVRCP_REPEAT_MODE_SINGLE;
730 else if (!strcmp(value, "alltracks"))
731 ret = AVRCP_REPEAT_MODE_ALL;
732 else if (!strcmp(value, "group"))
733 ret = AVRCP_REPEAT_MODE_GROUP;
738 case AVRCP_ATTRIBUTE_SHUFFLE:
739 if (!strcmp(value, "off"))
740 ret = AVRCP_SHUFFLE_OFF;
741 else if (!strcmp(value, "alltracks"))
742 ret = AVRCP_SHUFFLE_ALL;
743 else if (!strcmp(value, "group"))
744 ret = AVRCP_SHUFFLE_GROUP;
749 case AVRCP_ATTRIBUTE_SCAN:
750 if (!strcmp(value, "off"))
751 ret = AVRCP_SCAN_OFF;
752 else if (!strcmp(value, "alltracks"))
753 ret = AVRCP_SCAN_ALL;
754 else if (!strcmp(value, "group"))
755 ret = AVRCP_SCAN_GROUP;
765 static int attr_to_val(const char *str)
767 if (!strcasecmp(str, "Equalizer"))
768 return AVRCP_ATTRIBUTE_EQUALIZER;
769 else if (!strcasecmp(str, "Repeat"))
770 return AVRCP_ATTRIBUTE_REPEAT_MODE;
771 else if (!strcasecmp(str, "Shuffle"))
772 return AVRCP_ATTRIBUTE_SHUFFLE;
773 else if (!strcasecmp(str, "Scan"))
774 return AVRCP_ATTRIBUTE_SCAN;
779 static int player_get_setting(struct avrcp_player *player, uint8_t id)
787 key = attr_to_str(id);
791 value = player->cb->get_setting(key, player->user_data);
795 return attrval_to_val(id, value);
798 static int play_status_to_val(const char *status)
800 if (!strcasecmp(status, "stopped"))
801 return AVRCP_PLAY_STATUS_STOPPED;
802 else if (!strcasecmp(status, "playing"))
803 return AVRCP_PLAY_STATUS_PLAYING;
804 else if (!strcasecmp(status, "paused"))
805 return AVRCP_PLAY_STATUS_PAUSED;
806 else if (!strcasecmp(status, "forward-seek"))
807 return AVRCP_PLAY_STATUS_FWD_SEEK;
808 else if (!strcasecmp(status, "reverse-seek"))
809 return AVRCP_PLAY_STATUS_REV_SEEK;
810 else if (!strcasecmp(status, "error"))
811 return AVRCP_PLAY_STATUS_ERROR;
816 static uint16_t player_settings_changed(struct avrcp_player *player,
817 struct avrcp_header *pdu)
819 GList *settings = player_list_settings(player);
822 for (; settings; settings = settings->next) {
823 const char *key = settings->data;
827 attr = attr_to_val(key);
831 val = player_get_setting(player, attr);
835 pdu->params[size++] = attr;
836 pdu->params[size++] = val;
839 g_list_free(settings);
841 pdu->params[1] = (size - 2) >> 1;
845 void avrcp_player_event(struct avrcp_player *player, uint8_t id,
848 uint8_t buf[AVRCP_HEADER_LENGTH + 9];
849 struct avrcp_header *pdu = (void *) buf;
853 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
854 uint32_t *position_val = NULL;
857 if (player->sessions == NULL)
860 memset(buf, 0, sizeof(buf));
862 set_company_id(pdu->company_id, IEEEID_BTSIG);
864 pdu->pdu_id = AVRCP_REGISTER_NOTIFICATION;
868 if (id != AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED && player->changed_id) {
869 code = AVC_CTYPE_REJECTED;
871 pdu->params[0] = AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED;
875 code = AVC_CTYPE_CHANGED;
879 case AVRCP_EVENT_STATUS_CHANGED:
881 pdu->params[1] = play_status_to_val(data);
884 case AVRCP_EVENT_TRACK_CHANGED:
886 memcpy(&pdu->params[1], data, sizeof(uint64_t));
889 case AVRCP_EVENT_TRACK_REACHED_END:
890 case AVRCP_EVENT_TRACK_REACHED_START:
893 case AVRCP_EVENT_SETTINGS_CHANGED:
894 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
895 size = player_settings_changed(player, pdu);
897 size = player_settings_changed(player, pdu);
898 #endif /* __TIZEN__PATCH__ */
900 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
901 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
903 position_val = (uint32_t *) data;
904 *position_val = (*position_val & 0x000000ff) << 24 |
905 (*position_val & 0x0000ff00) << 8 |
906 (*position_val & 0x00ff0000) >> 8 |
907 (*position_val & 0xff000000) >> 24;
908 memcpy(&pdu->params[1], position_val, sizeof(uint32_t));
911 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
913 memcpy(&pdu->params[1], &player->id, sizeof(uint16_t));
914 memcpy(&pdu->params[3], &player->uid_counter, sizeof(uint16_t));
916 case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
920 error("Unknown event %u", id);
925 pdu->params_len = htons(size);
926 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
927 if (id == AVRCP_EVENT_PLAYBACK_POS_CHANGED &&
929 /* Remove the timer function which was added for register notification.
930 * As we are sending changed event eariler then time interval.
932 DBG("Removing the timer function added by register notification");
933 g_source_remove(pos_timer_id);
938 for (l = player->sessions; l; l = l->next) {
939 struct avrcp *session = l->data;
942 if (!(session->registered_events & (1 << id)))
945 err = avctp_send_vendordep(session->conn,
946 session->transaction_events[id],
947 code, AVC_SUBUNIT_PANEL,
948 buf, size + AVRCP_HEADER_LENGTH);
953 /* Unregister event as per AVRCP 1.3 spec, section 5.4.2 */
954 session->registered_events ^= 1 << id;
960 static const char *metadata_to_str(uint32_t id)
963 case AVRCP_MEDIA_ATTRIBUTE_TITLE:
965 case AVRCP_MEDIA_ATTRIBUTE_ARTIST:
967 case AVRCP_MEDIA_ATTRIBUTE_ALBUM:
969 case AVRCP_MEDIA_ATTRIBUTE_GENRE:
971 case AVRCP_MEDIA_ATTRIBUTE_TRACK:
972 return "TrackNumber";
973 case AVRCP_MEDIA_ATTRIBUTE_N_TRACKS:
974 return "NumberOfTracks";
975 case AVRCP_MEDIA_ATTRIBUTE_DURATION:
982 static const char *player_get_metadata(struct avrcp_player *player,
987 key = metadata_to_str(id);
992 return player->cb->get_metadata(key, player->user_data);
994 if (id == AVRCP_MEDIA_ATTRIBUTE_TITLE)
1000 static uint16_t player_write_media_attribute(struct avrcp_player *player,
1001 uint32_t id, uint8_t *buf,
1007 const char *value = NULL;
1011 value = player_get_metadata(player, id);
1012 if (value == NULL) {
1017 attr_len = strlen(value);
1018 value = ((char *) value) + *offset;
1019 len = attr_len - *offset;
1021 if (len > AVRCP_PDU_MTU - *pos) {
1022 len = AVRCP_PDU_MTU - *pos;
1028 memcpy(&buf[*pos], value, len);
1034 static GList *player_fill_media_attribute(struct avrcp_player *player,
1035 GList *attr_ids, uint8_t *buf,
1036 uint16_t *pos, uint16_t *offset)
1038 struct media_attribute_header {
1045 for (l = attr_ids; l != NULL; l = g_list_delete_link(l, l)) {
1046 uint32_t attr = GPOINTER_TO_UINT(l->data);
1050 if (*pos + sizeof(*hdr) >= AVRCP_PDU_MTU)
1053 hdr = (void *) &buf[*pos];
1054 hdr->id = htonl(attr);
1055 /* Always use UTF-8 */
1056 hdr->charset = htons(AVRCP_CHARSET_UTF8);
1057 *pos += sizeof(*hdr);
1060 attr_len = player_write_media_attribute(player, attr, buf,
1064 hdr->len = htons(attr_len);
1073 static struct pending_pdu *pending_pdu_new(uint8_t pdu_id, GList *attr_ids,
1074 unsigned int offset)
1076 struct pending_pdu *pending = g_new(struct pending_pdu, 1);
1078 pending->pdu_id = pdu_id;
1079 pending->attr_ids = attr_ids;
1080 pending->offset = offset;
1085 static gboolean session_abort_pending_pdu(struct avrcp *session)
1087 if (session->pending_pdu == NULL)
1090 g_list_free(session->pending_pdu->attr_ids);
1091 g_free(session->pending_pdu);
1092 session->pending_pdu = NULL;
1097 static const char *attrval_to_str(uint8_t attr, uint8_t value)
1100 case AVRCP_ATTRIBUTE_EQUALIZER:
1102 case AVRCP_EQUALIZER_ON:
1104 case AVRCP_EQUALIZER_OFF:
1109 case AVRCP_ATTRIBUTE_REPEAT_MODE:
1111 case AVRCP_REPEAT_MODE_OFF:
1113 case AVRCP_REPEAT_MODE_SINGLE:
1114 return "singletrack";
1115 case AVRCP_REPEAT_MODE_ALL:
1117 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
1118 case AVRCP_REPEAT_MODE_GROUP:
1124 /* Shuffle and scan have the same values */
1125 case AVRCP_ATTRIBUTE_SHUFFLE:
1126 case AVRCP_ATTRIBUTE_SCAN:
1128 case AVRCP_SCAN_OFF:
1130 case AVRCP_SCAN_ALL:
1132 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
1133 case AVRCP_SCAN_GROUP:
1144 static int player_set_setting(struct avrcp_player *player, uint8_t id,
1147 const char *key, *value;
1149 key = attr_to_str(id);
1153 value = attrval_to_str(id, val);
1160 return player->cb->set_setting(key, value, player->user_data);
1163 static uint8_t avrcp_handle_get_capabilities(struct avrcp *session,
1164 struct avrcp_header *pdu,
1165 uint8_t transaction)
1167 uint16_t len = ntohs(pdu->params_len);
1173 DBG("id=%u", pdu->params[0]);
1175 switch (pdu->params[0]) {
1176 case CAP_COMPANY_ID:
1177 for (i = 0; i < G_N_ELEMENTS(company_ids); i++) {
1178 set_company_id(&pdu->params[2 + i * 3],
1182 pdu->params_len = htons(2 + (3 * G_N_ELEMENTS(company_ids)));
1183 pdu->params[1] = G_N_ELEMENTS(company_ids);
1185 return AVC_CTYPE_STABLE;
1186 case CAP_EVENTS_SUPPORTED:
1188 for (i = 1; i <= AVRCP_EVENT_LAST; i++) {
1189 if (session->supported_events & (1 << i)) {
1191 pdu->params[pdu->params[1] + 1] = i;
1195 pdu->params_len = htons(2 + pdu->params[1]);
1196 return AVC_CTYPE_STABLE;
1200 pdu->params_len = htons(1);
1201 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1203 return AVC_CTYPE_REJECTED;
1206 static struct avrcp_player *target_get_player(struct avrcp *session)
1208 if (!session->target)
1211 return session->target->player;
1214 static uint8_t avrcp_handle_list_player_attributes(struct avrcp *session,
1215 struct avrcp_header *pdu,
1216 uint8_t transaction)
1218 struct avrcp_player *player = target_get_player(session);
1219 uint16_t len = ntohs(pdu->params_len);
1223 pdu->params_len = htons(1);
1224 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1225 return AVC_CTYPE_REJECTED;
1231 for (i = 1; i <= AVRCP_ATTRIBUTE_SCAN; i++) {
1232 if (player_get_setting(player, i) < 0)
1236 pdu->params[len] = i;
1240 pdu->params[0] = len;
1241 pdu->params_len = htons(len + 1);
1243 return AVC_CTYPE_STABLE;
1246 static uint8_t avrcp_handle_list_player_values(struct avrcp *session,
1247 struct avrcp_header *pdu,
1248 uint8_t transaction)
1250 struct avrcp_player *player = target_get_player(session);
1251 uint16_t len = ntohs(pdu->params_len);
1257 if (player_get_setting(player, pdu->params[0]) < 0)
1260 len = attr_get_max_val(pdu->params[0]);
1262 for (i = 1; i <= len; i++)
1265 pdu->params[0] = len;
1266 pdu->params_len = htons(len + 1);
1268 return AVC_CTYPE_STABLE;
1271 pdu->params_len = htons(1);
1272 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1273 return AVC_CTYPE_REJECTED;
1276 static uint32_t str_to_metadata(const char *str)
1278 if (strcasecmp(str, "Title") == 0)
1279 return AVRCP_MEDIA_ATTRIBUTE_TITLE;
1280 else if (strcasecmp(str, "Artist") == 0)
1281 return AVRCP_MEDIA_ATTRIBUTE_ARTIST;
1282 else if (strcasecmp(str, "Album") == 0)
1283 return AVRCP_MEDIA_ATTRIBUTE_ALBUM;
1284 else if (strcasecmp(str, "Genre") == 0)
1285 return AVRCP_MEDIA_ATTRIBUTE_GENRE;
1286 else if (strcasecmp(str, "TrackNumber") == 0)
1287 return AVRCP_MEDIA_ATTRIBUTE_TRACK;
1288 else if (strcasecmp(str, "NumberOfTracks") == 0)
1289 return AVRCP_MEDIA_ATTRIBUTE_N_TRACKS;
1290 else if (strcasecmp(str, "Duration") == 0)
1291 return AVRCP_MEDIA_ATTRIBUTE_DURATION;
1296 static GList *player_list_metadata(struct avrcp_player *player)
1298 GList *l, *attrs = NULL;
1301 return g_list_prepend(NULL,
1302 GUINT_TO_POINTER(AVRCP_MEDIA_ATTRIBUTE_TITLE));
1304 l = player->cb->list_metadata(player->user_data);
1305 for (; l; l = l->next) {
1306 const char *key = l->data;
1308 attrs = g_list_append(attrs,
1309 GUINT_TO_POINTER(str_to_metadata(key)));
1315 static uint8_t avrcp_handle_get_element_attributes(struct avrcp *session,
1316 struct avrcp_header *pdu,
1317 uint8_t transaction)
1319 struct avrcp_player *player = target_get_player(session);
1320 uint16_t len = ntohs(pdu->params_len);
1321 uint64_t identifier = get_le64(&pdu->params[0]);
1327 if (len < 9 || identifier != 0)
1330 nattr = pdu->params[8];
1332 if (len < nattr * sizeof(uint32_t) + 1)
1337 * Return all available information, at least
1338 * title must be returned if there's a track selected.
1340 attr_ids = player_list_metadata(player);
1341 len = g_list_length(attr_ids);
1344 for (i = 0, len = 0, attr_ids = NULL; i < nattr; i++) {
1347 id = get_be32(&pdu->params[9] + (i * sizeof(id)));
1349 /* Don't add invalid attributes */
1350 if (id == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL ||
1351 id > AVRCP_MEDIA_ATTRIBUTE_LAST)
1355 attr_ids = g_list_prepend(attr_ids,
1356 GUINT_TO_POINTER(id));
1359 attr_ids = g_list_reverse(attr_ids);
1365 session_abort_pending_pdu(session);
1368 attr_ids = player_fill_media_attribute(player, attr_ids, pdu->params,
1371 if (attr_ids != NULL) {
1372 session->pending_pdu = pending_pdu_new(pdu->pdu_id, attr_ids,
1374 pdu->packet_type = AVRCP_PACKET_TYPE_START;
1377 pdu->params[0] = len;
1378 pdu->params_len = htons(pos);
1380 return AVC_CTYPE_STABLE;
1382 pdu->params_len = htons(1);
1383 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1384 return AVC_CTYPE_REJECTED;
1387 static uint8_t avrcp_handle_get_current_player_value(struct avrcp *session,
1388 struct avrcp_header *pdu,
1389 uint8_t transaction)
1391 struct avrcp_player *player = target_get_player(session);
1392 uint16_t len = ntohs(pdu->params_len);
1396 if (len <= 1 || pdu->params[0] != len - 1)
1400 * Save a copy of requested settings because we can override them
1403 settings = g_memdup(&pdu->params[1], pdu->params[0]);
1407 * From sec. 5.7 of AVRCP 1.3 spec, we should igore non-existent IDs
1408 * and send a response with the existent ones. Only if all IDs are
1409 * non-existent we should send an error.
1411 for (i = 0; i < pdu->params[0]; i++) {
1414 if (settings[i] < AVRCP_ATTRIBUTE_EQUALIZER ||
1415 settings[i] > AVRCP_ATTRIBUTE_SCAN) {
1416 DBG("Ignoring %u", settings[i]);
1420 val = player_get_setting(player, settings[i]);
1424 pdu->params[++len] = settings[i];
1425 pdu->params[++len] = val;
1431 pdu->params[0] = len / 2;
1432 pdu->params_len = htons(len + 1);
1434 return AVC_CTYPE_STABLE;
1437 error("No valid attributes in request");
1440 pdu->params_len = htons(1);
1441 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1443 return AVC_CTYPE_REJECTED;
1446 static uint8_t avrcp_handle_set_player_value(struct avrcp *session,
1447 struct avrcp_header *pdu,
1448 uint8_t transaction)
1450 struct avrcp_player *player = target_get_player(session);
1451 uint16_t len = ntohs(pdu->params_len);
1455 if (len < 3 || len > 2 * pdu->params[0] + 1U || player == NULL)
1459 * From sec. 5.7 of AVRCP 1.3 spec, we should igore non-existent IDs
1460 * and set the existent ones. Sec. 5.2.4 is not clear however how to
1461 * indicate that a certain ID was not accepted. If at least one
1462 * attribute is valid, we respond with no parameters. Otherwise an
1463 * AVRCP_STATUS_INVALID_PARAM is sent.
1465 for (len = 0, i = 0, param = &pdu->params[1]; i < pdu->params[0];
1467 if (player_set_setting(player, param[0], param[1]) < 0)
1474 pdu->params_len = 0;
1476 return AVC_CTYPE_ACCEPTED;
1480 pdu->params_len = htons(1);
1481 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1482 return AVC_CTYPE_REJECTED;
1485 static uint8_t avrcp_handle_displayable_charset(struct avrcp *session,
1486 struct avrcp_header *pdu,
1487 uint8_t transaction)
1489 uint16_t len = ntohs(pdu->params_len);
1492 pdu->params_len = htons(1);
1493 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1494 return AVC_CTYPE_REJECTED;
1498 * We acknowledge the commands, but we always use UTF-8 for
1499 * encoding since CT is obliged to support it.
1501 pdu->params_len = 0;
1502 return AVC_CTYPE_STABLE;
1505 static uint8_t avrcp_handle_ct_battery_status(struct avrcp *session,
1506 struct avrcp_header *pdu,
1507 uint8_t transaction)
1509 uint16_t len = ntohs(pdu->params_len);
1515 valstr = battery_status_to_str(pdu->params[0]);
1519 pdu->params_len = 0;
1521 return AVC_CTYPE_STABLE;
1524 pdu->params_len = htons(1);
1525 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1526 return AVC_CTYPE_REJECTED;
1529 static uint32_t player_get_position(struct avrcp_player *player)
1534 return player->cb->get_position(player->user_data);
1537 static uint32_t player_get_duration(struct avrcp_player *player)
1544 num = player->cb->get_duration(player->user_data);
1551 static uint8_t player_get_status(struct avrcp_player *player)
1556 return AVRCP_PLAY_STATUS_STOPPED;
1558 value = player->cb->get_status(player->user_data);
1560 return AVRCP_PLAY_STATUS_STOPPED;
1562 return play_status_to_val(value);
1565 static uint16_t player_get_id(struct avrcp_player *player)
1573 static uint16_t player_get_uid_counter(struct avrcp_player *player)
1578 return player->uid_counter;
1581 static uint8_t avrcp_handle_get_play_status(struct avrcp *session,
1582 struct avrcp_header *pdu,
1583 uint8_t transaction)
1585 struct avrcp_player *player = target_get_player(session);
1586 uint16_t len = ntohs(pdu->params_len);
1591 pdu->params_len = htons(1);
1592 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1593 return AVC_CTYPE_REJECTED;
1596 position = player_get_position(player);
1597 duration = player_get_duration(player);
1599 position = htonl(position);
1600 duration = htonl(duration);
1602 memcpy(&pdu->params[0], &duration, 4);
1603 memcpy(&pdu->params[4], &position, 4);
1604 pdu->params[8] = player_get_status(player);
1606 pdu->params_len = htons(9);
1608 return AVC_CTYPE_STABLE;
1611 static uint64_t player_get_uid(struct avrcp_player *player)
1616 return player->cb->get_uid(player->user_data);
1619 static GList *player_list_settings(struct avrcp_player *player)
1624 return player->cb->list_settings(player->user_data);
1627 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1628 static uint32_t player_get_playback_position(struct avrcp_player *player)
1633 return player->cb->get_position(player->user_data);
1637 static bool avrcp_handle_play(struct avrcp *session)
1639 struct avrcp_player *player = target_get_player(session);
1644 return player->cb->play(player->user_data);
1647 static bool avrcp_handle_stop(struct avrcp *session)
1649 struct avrcp_player *player = target_get_player(session);
1654 return player->cb->stop(player->user_data);
1657 static bool avrcp_handle_pause(struct avrcp *session)
1659 struct avrcp_player *player = target_get_player(session);
1664 return player->cb->pause(player->user_data);
1667 static bool avrcp_handle_next(struct avrcp *session)
1669 struct avrcp_player *player = target_get_player(session);
1674 return player->cb->next(player->user_data);
1677 static bool avrcp_handle_previous(struct avrcp *session)
1679 struct avrcp_player *player = target_get_player(session);
1684 return player->cb->previous(player->user_data);
1687 static const struct passthrough_handler passthrough_handlers[] = {
1688 { AVC_PLAY, avrcp_handle_play },
1689 { AVC_STOP, avrcp_handle_stop },
1690 { AVC_PAUSE, avrcp_handle_pause },
1691 { AVC_FORWARD, avrcp_handle_next },
1692 { AVC_BACKWARD, avrcp_handle_previous },
1696 static bool handle_passthrough(struct avctp *conn, uint8_t op, bool pressed,
1699 struct avrcp *session = user_data;
1700 const struct passthrough_handler *handler;
1702 for (handler = session->passthrough_handlers; handler->func;
1704 if (handler->op == op)
1708 if (handler->func == NULL)
1711 /* Do not trigger handler on release */
1715 return handler->func(session);
1718 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1719 void avrcp_stop_position_timer(void)
1721 if (pos_timer_id > 0) {
1722 DBG("Removing position timer id");
1723 g_source_remove(pos_timer_id);
1727 gboolean send_playback_position_event(gpointer user_data)
1729 struct avrcp_player *player = user_data;
1730 uint32_t playback_position;
1731 uint8_t play_status;
1733 play_status = player_get_status(player);
1734 if (play_status != AVRCP_PLAY_STATUS_PLAYING)
1737 playback_position = player_get_playback_position(player);
1739 avrcp_player_event(player, AVRCP_EVENT_PLAYBACK_POS_CHANGED,
1740 &playback_position);
1745 static uint8_t avrcp_handle_register_notification(struct avrcp *session,
1746 struct avrcp_header *pdu,
1747 uint8_t transaction)
1749 struct avrcp_player *player = target_get_player(session);
1750 struct btd_device *dev = session->dev;
1751 uint16_t len = ntohs(pdu->params_len);
1754 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1755 uint32_t playback_interval;
1756 uint32_t playback_position;
1757 uint8_t play_status;
1761 * 1 byte for EventID, 4 bytes for Playback interval but the latest
1762 * one is applicable only for EVENT_PLAYBACK_POS_CHANGED. See AVRCP
1763 * 1.3 spec, section 5.4.2.
1768 /* Check if event is supported otherwise reject */
1769 if (!(session->supported_events & (1 << pdu->params[0])))
1772 switch (pdu->params[0]) {
1773 case AVRCP_EVENT_STATUS_CHANGED:
1775 pdu->params[1] = player_get_status(player);
1778 case AVRCP_EVENT_TRACK_CHANGED:
1780 uid = player_get_uid(player);
1781 memcpy(&pdu->params[1], &uid, sizeof(uint64_t));
1784 case AVRCP_EVENT_TRACK_REACHED_END:
1785 case AVRCP_EVENT_TRACK_REACHED_START:
1788 case AVRCP_EVENT_SETTINGS_CHANGED:
1789 len = player_settings_changed(player, pdu);
1791 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
1793 bt_put_be16(player_get_id(player), &pdu->params[1]);
1794 bt_put_be16(player_get_uid_counter(player), &pdu->params[3]);
1796 case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
1799 case AVRCP_EVENT_VOLUME_CHANGED:
1800 volume = media_transport_get_device_volume(dev);
1804 pdu->params[1] = volume;
1808 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1809 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
1812 /* time interval in seconds at which the change in playback position
1813 shall be notified */
1814 memcpy(&playback_interval, &pdu->params[1], sizeof(uint32_t));
1815 playback_interval = ((playback_interval>>24)&0xff) |
1816 ((playback_interval<<8)&0xff0000) |
1817 ((playback_interval>>8)&0xff00) |
1818 ((playback_interval<<24)&0xff000000);
1820 play_status = player_get_status(player);
1822 if (play_status != AVRCP_PLAY_STATUS_PLAYING) {
1823 DBG("Play Pos Changed Event is skipped(%d)", play_status);
1825 DBG("Playback interval : %d secs", playback_interval);
1826 pos_timer_id = g_timeout_add_seconds(
1828 send_playback_position_event, player);
1831 /* retrieve current playback position for interim response */
1832 playback_position = player_get_playback_position(player);
1833 playback_position = (playback_position & 0x000000ff) << 24 |
1834 (playback_position & 0x0000ff00) << 8 |
1835 (playback_position & 0x00ff0000) >> 8 |
1836 (playback_position & 0xff000000) >> 24;
1837 memcpy(&pdu->params[1], &playback_position, sizeof(uint32_t));
1843 /* All other events are not supported yet */
1847 /* Register event and save the transaction used */
1848 session->registered_events |= (1 << pdu->params[0]);
1849 session->transaction_events[pdu->params[0]] = transaction;
1851 pdu->params_len = htons(len);
1853 return AVC_CTYPE_INTERIM;
1856 pdu->params_len = htons(1);
1857 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1858 return AVC_CTYPE_REJECTED;
1861 static uint8_t avrcp_handle_request_continuing(struct avrcp *session,
1862 struct avrcp_header *pdu,
1863 uint8_t transaction)
1865 struct avrcp_player *player = target_get_player(session);
1866 uint16_t len = ntohs(pdu->params_len);
1867 struct pending_pdu *pending;
1869 if (len != 1 || session->pending_pdu == NULL)
1872 pending = session->pending_pdu;
1874 if (pending->pdu_id != pdu->params[0])
1878 pending->attr_ids = player_fill_media_attribute(player,
1882 pdu->pdu_id = pending->pdu_id;
1884 if (pending->attr_ids == NULL) {
1885 g_free(session->pending_pdu);
1886 session->pending_pdu = NULL;
1887 pdu->packet_type = AVRCP_PACKET_TYPE_END;
1889 pdu->packet_type = AVRCP_PACKET_TYPE_CONTINUING;
1892 pdu->params_len = htons(len);
1894 return AVC_CTYPE_STABLE;
1896 pdu->params_len = htons(1);
1897 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1898 return AVC_CTYPE_REJECTED;
1901 static uint8_t avrcp_handle_abort_continuing(struct avrcp *session,
1902 struct avrcp_header *pdu,
1903 uint8_t transaction)
1905 uint16_t len = ntohs(pdu->params_len);
1906 struct pending_pdu *pending;
1908 if (len != 1 || session->pending_pdu == NULL)
1911 pending = session->pending_pdu;
1913 if (pending->pdu_id != pdu->params[0])
1916 session_abort_pending_pdu(session);
1917 pdu->params_len = 0;
1919 return AVC_CTYPE_ACCEPTED;
1922 pdu->params_len = htons(1);
1923 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1924 return AVC_CTYPE_REJECTED;
1927 static uint8_t avrcp_handle_set_absolute_volume(struct avrcp *session,
1928 struct avrcp_header *pdu,
1929 uint8_t transaction)
1931 uint16_t len = ntohs(pdu->params_len);
1937 volume = pdu->params[0] & 0x7F;
1939 media_transport_update_device_volume(session->dev, volume);
1941 return AVC_CTYPE_ACCEPTED;
1944 pdu->params_len = htons(1);
1945 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
1946 return AVC_CTYPE_REJECTED;
1949 static struct avrcp_player *find_tg_player(struct avrcp *session, uint16_t id)
1951 struct avrcp_server *server = session->server;
1954 for (l = server->players; l; l = l->next) {
1955 struct avrcp_player *player = l->data;
1957 if (player->id == id)
1964 static gboolean notify_addressed_player_changed(gpointer user_data)
1966 struct avrcp_player *player = user_data;
1967 uint8_t events[6] = { AVRCP_EVENT_STATUS_CHANGED,
1968 AVRCP_EVENT_TRACK_CHANGED,
1969 AVRCP_EVENT_TRACK_REACHED_START,
1970 AVRCP_EVENT_TRACK_REACHED_END,
1971 AVRCP_EVENT_SETTINGS_CHANGED,
1972 AVRCP_EVENT_PLAYBACK_POS_CHANGED
1976 avrcp_player_event(player, AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED, NULL);
1979 * TG shall complete all player specific
1980 * notifications with AV/C C-Type REJECTED
1981 * with error code as Addressed Player Changed.
1983 for (i = 0; i < sizeof(events); i++)
1984 avrcp_player_event(player, events[i], NULL);
1986 player->changed_id = 0;
1991 static uint8_t avrcp_handle_set_addressed_player(struct avrcp *session,
1992 struct avrcp_header *pdu,
1993 uint8_t transaction)
1995 struct avrcp_player *player;
1996 uint16_t len = ntohs(pdu->params_len);
1997 uint16_t player_id = 0;
2001 status = AVRCP_STATUS_INVALID_PARAM;
2005 player_id = bt_get_be16(&pdu->params[0]);
2006 player = find_tg_player(session, player_id);
2007 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
2010 player->addressed = true;
2011 status = AVRCP_STATUS_SUCCESS;
2012 pdu->params_len = htons(len);
2013 pdu->params[0] = status;
2015 status = AVRCP_STATUS_INVALID_PLAYER_ID;
2019 /* Don't emit player changed immediately since PTS expect the
2020 * response of SetAddressedPlayer before the event.
2022 player->changed_id = g_idle_add(notify_addressed_player_changed,
2025 return AVC_CTYPE_ACCEPTED;
2028 pdu->params_len = htons(sizeof(status));
2029 pdu->params[0] = status;
2030 return AVC_CTYPE_REJECTED;
2033 static const struct control_pdu_handler control_handlers[] = {
2034 { AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
2035 avrcp_handle_get_capabilities },
2036 { AVRCP_LIST_PLAYER_ATTRIBUTES, AVC_CTYPE_STATUS,
2037 avrcp_handle_list_player_attributes },
2038 { AVRCP_LIST_PLAYER_VALUES, AVC_CTYPE_STATUS,
2039 avrcp_handle_list_player_values },
2040 { AVRCP_GET_ELEMENT_ATTRIBUTES, AVC_CTYPE_STATUS,
2041 avrcp_handle_get_element_attributes },
2042 { AVRCP_GET_CURRENT_PLAYER_VALUE, AVC_CTYPE_STATUS,
2043 avrcp_handle_get_current_player_value },
2044 { AVRCP_SET_PLAYER_VALUE, AVC_CTYPE_CONTROL,
2045 avrcp_handle_set_player_value },
2046 { AVRCP_GET_PLAYER_ATTRIBUTE_TEXT, AVC_CTYPE_STATUS,
2048 { AVRCP_GET_PLAYER_VALUE_TEXT, AVC_CTYPE_STATUS,
2050 { AVRCP_DISPLAYABLE_CHARSET, AVC_CTYPE_STATUS,
2051 avrcp_handle_displayable_charset },
2052 { AVRCP_CT_BATTERY_STATUS, AVC_CTYPE_STATUS,
2053 avrcp_handle_ct_battery_status },
2054 { AVRCP_GET_PLAY_STATUS, AVC_CTYPE_STATUS,
2055 avrcp_handle_get_play_status },
2056 { AVRCP_REGISTER_NOTIFICATION, AVC_CTYPE_NOTIFY,
2057 avrcp_handle_register_notification },
2058 { AVRCP_SET_ABSOLUTE_VOLUME, AVC_CTYPE_CONTROL,
2059 avrcp_handle_set_absolute_volume },
2060 { AVRCP_REQUEST_CONTINUING, AVC_CTYPE_CONTROL,
2061 avrcp_handle_request_continuing },
2062 { AVRCP_ABORT_CONTINUING, AVC_CTYPE_CONTROL,
2063 avrcp_handle_abort_continuing },
2064 { AVRCP_SET_ADDRESSED_PLAYER, AVC_CTYPE_CONTROL,
2065 avrcp_handle_set_addressed_player },
2069 /* handle vendordep pdu inside an avctp packet */
2070 static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
2071 uint8_t *code, uint8_t *subunit,
2072 uint8_t *operands, size_t operand_count,
2075 struct avrcp *session = user_data;
2076 const struct control_pdu_handler *handler;
2077 struct avrcp_header *pdu = (void *) operands;
2078 uint32_t company_id = get_company_id(pdu->company_id);
2080 if (company_id != IEEEID_BTSIG) {
2081 *code = AVC_CTYPE_NOT_IMPLEMENTED;
2085 DBG("AVRCP PDU 0x%02X, company 0x%06X len 0x%04X",
2086 pdu->pdu_id, company_id, ntohs(pdu->params_len));
2088 pdu->packet_type = 0;
2091 if (operand_count < AVRCP_HEADER_LENGTH) {
2092 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
2096 for (handler = session->control_handlers; handler->pdu_id; handler++) {
2097 if (handler->pdu_id == pdu->pdu_id)
2101 if (handler->pdu_id != pdu->pdu_id || handler->code != *code) {
2102 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
2106 if (!handler->func) {
2107 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
2111 *code = handler->func(session, pdu, transaction);
2113 if (*code != AVC_CTYPE_REJECTED &&
2114 pdu->pdu_id != AVRCP_GET_ELEMENT_ATTRIBUTES &&
2115 pdu->pdu_id != AVRCP_REQUEST_CONTINUING &&
2116 pdu->pdu_id != AVRCP_ABORT_CONTINUING)
2117 session_abort_pending_pdu(session);
2119 return AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
2122 pdu->params_len = htons(1);
2123 *code = AVC_CTYPE_REJECTED;
2125 return AVRCP_HEADER_LENGTH + 1;
2128 static void avrcp_handle_media_player_list(struct avrcp *session,
2129 struct avrcp_browsing_header *pdu,
2130 uint32_t start_item, uint32_t end_item)
2132 struct avrcp_player *player = session->target->player;
2133 struct get_folder_items_rsp *rsp;
2134 const char *name = NULL;
2137 rsp = (void *)pdu->params;
2138 rsp->status = AVRCP_STATUS_SUCCESS;
2139 rsp->uid_counter = htons(player_get_uid_counter(player));
2141 pdu->param_len = sizeof(*rsp);
2143 for (l = g_slist_nth(session->server->players, start_item);
2144 l; l = g_slist_next(l)) {
2145 struct avrcp_player *player = l->data;
2146 struct folder_item *folder;
2147 struct player_item *item;
2150 if (rsp->num_items == (end_item - start_item) + 1)
2153 folder = (void *)&pdu->params[pdu->param_len];
2154 folder->type = 0x01; /* Media Player */
2156 pdu->param_len += sizeof(*folder);
2158 item = (void *)folder->data;
2159 item->player_id = htons(player->id);
2160 item->type = 0x01; /* Audio */
2161 item->subtype = htonl(0x01); /* Audio Book */
2162 item->status = player_get_status(player);
2163 /* Assign Default Feature Bit Mask */
2164 memcpy(&item->features, &default_features,
2165 sizeof(default_features));
2167 item->charset = htons(AVRCP_CHARSET_UTF8);
2169 name = player->cb->get_name(player->user_data);
2170 namelen = strlen(name);
2171 item->namelen = htons(namelen);
2172 memcpy(item->name, name, namelen);
2174 folder->len = htons(sizeof(*item) + namelen);
2175 pdu->param_len += sizeof(*item) + namelen;
2179 /* If no player could be found respond with an error */
2180 if (!rsp->num_items)
2183 rsp->num_items = htons(rsp->num_items);
2184 pdu->param_len = htons(pdu->param_len);
2189 pdu->params[0] = AVRCP_STATUS_OUT_OF_BOUNDS;
2190 pdu->param_len = htons(1);
2193 static void avrcp_handle_get_folder_items(struct avrcp *session,
2194 struct avrcp_browsing_header *pdu,
2195 uint8_t transaction)
2197 uint32_t start_item = 0;
2198 uint32_t end_item = 0;
2200 uint8_t status = AVRCP_STATUS_SUCCESS;
2202 if (ntohs(pdu->param_len) < 10) {
2203 status = AVRCP_STATUS_INVALID_PARAM;
2207 scope = pdu->params[0];
2208 start_item = bt_get_be32(&pdu->params[1]);
2209 end_item = bt_get_be32(&pdu->params[5]);
2211 DBG("scope 0x%02x start_item 0x%08x end_item 0x%08x", scope,
2212 start_item, end_item);
2214 if (end_item < start_item) {
2215 status = AVRCP_STATUS_INVALID_PARAM;
2220 case AVRCP_SCOPE_MEDIA_PLAYER_LIST:
2221 avrcp_handle_media_player_list(session, pdu,
2222 start_item, end_item);
2224 case AVRCP_SCOPE_MEDIA_PLAYER_VFS:
2225 case AVRCP_SCOPE_SEARCH:
2226 case AVRCP_SCOPE_NOW_PLAYING:
2228 status = AVRCP_STATUS_INVALID_PARAM;
2235 pdu->params[0] = status;
2236 pdu->param_len = htons(1);
2239 static struct browsing_pdu_handler {
2241 void (*func) (struct avrcp *session, struct avrcp_browsing_header *pdu,
2242 uint8_t transaction);
2243 } browsing_handlers[] = {
2244 { AVRCP_GET_FOLDER_ITEMS, avrcp_handle_get_folder_items },
2248 size_t avrcp_browsing_general_reject(uint8_t *operands)
2250 struct avrcp_browsing_header *pdu = (void *) operands;
2253 pdu->pdu_id = AVRCP_GENERAL_REJECT;
2254 status = AVRCP_STATUS_INVALID_COMMAND;
2256 pdu->param_len = htons(sizeof(status));
2257 memcpy(pdu->params, &status, (sizeof(status)));
2258 return AVRCP_BROWSING_HEADER_LENGTH + sizeof(status);
2261 static size_t handle_browsing_pdu(struct avctp *conn,
2262 uint8_t transaction, uint8_t *operands,
2263 size_t operand_count, void *user_data)
2265 struct avrcp *session = user_data;
2266 struct browsing_pdu_handler *handler;
2267 struct avrcp_browsing_header *pdu = (void *) operands;
2269 DBG("AVRCP Browsing PDU 0x%02X, len 0x%04X", pdu->pdu_id,
2270 ntohs(pdu->param_len));
2272 for (handler = browsing_handlers; handler->pdu_id; handler++) {
2273 if (handler->pdu_id == pdu->pdu_id)
2277 return avrcp_browsing_general_reject(operands);
2280 session->transaction = transaction;
2281 handler->func(session, pdu, transaction);
2282 return AVRCP_BROWSING_HEADER_LENGTH + ntohs(pdu->param_len);
2285 size_t avrcp_handle_vendor_reject(uint8_t *code, uint8_t *operands)
2287 struct avrcp_header *pdu = (void *) operands;
2288 uint32_t company_id = get_company_id(pdu->company_id);
2290 *code = AVC_CTYPE_REJECTED;
2291 pdu->params_len = htons(1);
2292 pdu->params[0] = AVRCP_STATUS_INTERNAL_ERROR;
2294 DBG("rejecting AVRCP PDU 0x%02X, company 0x%06X len 0x%04X",
2295 pdu->pdu_id, company_id, ntohs(pdu->params_len));
2297 return AVRCP_HEADER_LENGTH + 1;
2300 static struct avrcp_server *find_server(GSList *list, struct btd_adapter *a)
2302 for (; list; list = list->next) {
2303 struct avrcp_server *server = list->data;
2305 if (server->adapter == a)
2312 static const char *status_to_string(uint8_t status)
2315 case AVRCP_PLAY_STATUS_STOPPED:
2317 case AVRCP_PLAY_STATUS_PLAYING:
2319 case AVRCP_PLAY_STATUS_PAUSED:
2321 case AVRCP_PLAY_STATUS_FWD_SEEK:
2322 return "forward-seek";
2323 case AVRCP_PLAY_STATUS_REV_SEEK:
2324 return "reverse-seek";
2325 case AVRCP_PLAY_STATUS_ERROR:
2332 static gboolean avrcp_get_play_status_rsp(struct avctp *conn, uint8_t code,
2333 uint8_t subunit, uint8_t transaction,
2334 uint8_t *operands, size_t operand_count,
2337 struct avrcp *session = user_data;
2338 struct avrcp_player *player = session->controller->player;
2340 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2345 struct media_player *mp = player->user_data;
2346 struct avrcp_header *pdu = (void *) operands;
2351 if (pdu == NULL || code == AVC_CTYPE_REJECTED ||
2352 ntohs(pdu->params_len) != 9)
2355 memcpy(&duration, pdu->params, sizeof(uint32_t));
2356 duration = ntohl(duration);
2357 media_player_set_duration(mp, duration);
2359 memcpy(&position, pdu->params + 4, sizeof(uint32_t));
2360 position = ntohl(position);
2361 media_player_set_position(mp, position);
2363 memcpy(&status, pdu->params + 8, sizeof(uint8_t));
2364 media_player_set_status(mp, status_to_string(status));
2369 static void avrcp_get_play_status(struct avrcp *session)
2371 uint8_t buf[AVRCP_HEADER_LENGTH];
2372 struct avrcp_header *pdu = (void *) buf;
2374 memset(buf, 0, sizeof(buf));
2376 set_company_id(pdu->company_id, IEEEID_BTSIG);
2377 pdu->pdu_id = AVRCP_GET_PLAY_STATUS;
2378 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
2380 avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
2381 AVC_SUBUNIT_PANEL, buf, sizeof(buf),
2382 avrcp_get_play_status_rsp,
2386 static const char *status_to_str(uint8_t status)
2389 case AVRCP_STATUS_INVALID_COMMAND:
2390 return "Invalid Command";
2391 case AVRCP_STATUS_INVALID_PARAM:
2392 return "Invalid Parameter";
2393 case AVRCP_STATUS_INTERNAL_ERROR:
2394 return "Internal Error";
2395 case AVRCP_STATUS_SUCCESS:
2402 static gboolean avrcp_player_value_rsp(struct avctp *conn, uint8_t code,
2403 uint8_t subunit, uint8_t transaction,
2404 uint8_t *operands, size_t operand_count,
2407 struct avrcp *session = user_data;
2408 struct avrcp_player *player = session->controller->player;
2410 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2415 struct media_player *mp = player->user_data;
2416 struct avrcp_header *pdu = (void *) operands;
2421 media_player_set_setting(mp, "Error", "Timeout");
2425 if (code == AVC_CTYPE_REJECTED) {
2426 media_player_set_setting(mp, "Error",
2427 status_to_str(pdu->params[0]));
2431 count = pdu->params[0];
2433 if (pdu->params_len < count * 2)
2436 for (i = 1; count > 0; count--, i += 2) {
2440 key = attr_to_str(pdu->params[i]);
2444 value = attrval_to_str(pdu->params[i], pdu->params[i + 1]);
2448 media_player_set_setting(mp, key, value);
2454 static void avrcp_get_current_player_value(struct avrcp *session,
2455 uint8_t *attrs, uint8_t count)
2457 uint8_t buf[AVRCP_HEADER_LENGTH + AVRCP_ATTRIBUTE_LAST + 1];
2458 struct avrcp_header *pdu = (void *) buf;
2459 uint16_t length = AVRCP_HEADER_LENGTH + count + 1;
2461 memset(buf, 0, sizeof(buf));
2463 set_company_id(pdu->company_id, IEEEID_BTSIG);
2464 pdu->pdu_id = AVRCP_GET_CURRENT_PLAYER_VALUE;
2465 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
2466 pdu->params_len = htons(count + 1);
2467 pdu->params[0] = count;
2469 memcpy(pdu->params + 1, attrs, count);
2471 avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
2472 AVC_SUBUNIT_PANEL, buf, length,
2473 avrcp_player_value_rsp, session);
2476 static gboolean avrcp_list_player_attributes_rsp(struct avctp *conn,
2477 uint8_t code, uint8_t subunit,
2478 uint8_t transaction, uint8_t *operands,
2479 size_t operand_count, void *user_data)
2481 uint8_t attrs[AVRCP_ATTRIBUTE_LAST];
2482 struct avrcp *session = user_data;
2483 struct avrcp_header *pdu = (void *) operands;
2484 uint8_t len, count = 0;
2487 if (code == AVC_CTYPE_REJECTED || code == AVC_CTYPE_NOT_IMPLEMENTED)
2490 len = pdu->params[0];
2492 if (ntohs(pdu->params_len) < count) {
2493 error("Invalid parameters");
2497 for (i = 0; len > 0; len--, i++) {
2498 /* Don't query invalid attributes */
2499 if (pdu->params[i + 1] == AVRCP_ATTRIBUTE_ILEGAL ||
2500 pdu->params[i + 1] > AVRCP_ATTRIBUTE_LAST)
2503 attrs[count++] = pdu->params[i + 1];
2506 avrcp_get_current_player_value(session, attrs, count);
2511 static void avrcp_list_player_attributes(struct avrcp *session)
2513 uint8_t buf[AVRCP_HEADER_LENGTH];
2514 struct avrcp_header *pdu = (void *) buf;
2516 memset(buf, 0, sizeof(buf));
2518 set_company_id(pdu->company_id, IEEEID_BTSIG);
2519 pdu->pdu_id = AVRCP_LIST_PLAYER_ATTRIBUTES;
2520 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
2522 avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
2523 AVC_SUBUNIT_PANEL, buf, sizeof(buf),
2524 avrcp_list_player_attributes_rsp,
2528 static void avrcp_parse_attribute_list(struct avrcp_player *player,
2529 uint8_t *operands, uint8_t count)
2531 struct media_player *mp = player->user_data;
2532 struct media_item *item;
2535 item = media_player_set_playlist_item(mp, player->uid);
2537 for (i = 0; count > 0; count--) {
2539 uint16_t charset, len;
2541 id = get_be32(&operands[i]);
2542 i += sizeof(uint32_t);
2544 charset = get_be16(&operands[i]);
2545 i += sizeof(uint16_t);
2547 len = get_be16(&operands[i]);
2548 i += sizeof(uint16_t);
2550 if (charset == 106) {
2551 const char *key = metadata_to_str(id);
2554 media_player_set_metadata(mp, item,
2555 metadata_to_str(id),
2563 static gboolean avrcp_get_element_attributes_rsp(struct avctp *conn,
2564 uint8_t code, uint8_t subunit,
2565 uint8_t transaction,
2567 size_t operand_count,
2570 struct avrcp *session = user_data;
2571 struct avrcp_player *player = session->controller->player;
2572 struct avrcp_header *pdu = (void *) operands;
2575 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2580 if (code == AVC_CTYPE_REJECTED)
2583 count = pdu->params[0];
2585 if (ntohs(pdu->params_len) - 1 < count * 8) {
2586 error("Invalid parameters");
2590 avrcp_parse_attribute_list(player, &pdu->params[1], count);
2592 avrcp_get_play_status(session);
2597 static void avrcp_get_element_attributes(struct avrcp *session)
2599 uint8_t buf[AVRCP_HEADER_LENGTH + 9];
2600 struct avrcp_header *pdu = (void *) buf;
2603 memset(buf, 0, sizeof(buf));
2605 set_company_id(pdu->company_id, IEEEID_BTSIG);
2606 pdu->pdu_id = AVRCP_GET_ELEMENT_ATTRIBUTES;
2607 pdu->params_len = htons(9);
2608 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
2610 length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
2612 avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
2613 AVC_SUBUNIT_PANEL, buf, length,
2614 avrcp_get_element_attributes_rsp,
2618 static const char *type_to_string(uint8_t type)
2620 switch (type & 0x0F) {
2626 return "Audio, Video";
2628 return "Audio Broadcasting";
2630 return "Audio, Audio Broadcasting";
2632 return "Video, Audio Broadcasting";
2634 return "Audio, Video, Audio Broadcasting";
2636 return "Video Broadcasting";
2638 return "Audio, Video Broadcasting";
2640 return "Video, Video Broadcasting";
2642 return "Audio, Video, Video Broadcasting";
2644 return "Audio Broadcasting, Video Broadcasting";
2646 return "Audio, Audio Broadcasting, Video Broadcasting";
2648 return "Video, Audio Broadcasting, Video Broadcasting";
2650 return "Audio, Video, Audio Broadcasting, Video Broadcasting";
2656 static const char *subtype_to_string(uint32_t subtype)
2658 switch (subtype & 0x03) {
2660 return "Audio Book";
2664 return "Audio Book, Podcast";
2670 static struct media_item *parse_media_element(struct avrcp *session,
2671 uint8_t *operands, uint16_t len)
2673 struct avrcp_player *player;
2674 struct media_player *mp;
2675 struct media_item *item;
2683 uid = get_be64(&operands[0]);
2685 namelen = MIN(get_be16(&operands[11]), sizeof(name) - 1);
2687 memcpy(name, &operands[13], namelen);
2688 name[namelen] = '\0';
2691 player = session->controller->player;
2693 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2698 mp = player->user_data;
2700 item = media_player_create_item(mp, name, PLAYER_ITEM_TYPE_AUDIO, uid);
2704 media_item_set_playable(item, true);
2709 static struct media_item *parse_media_folder(struct avrcp *session,
2710 uint8_t *operands, uint16_t len)
2712 struct avrcp_player *player = session->controller->player;
2714 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2719 struct media_player *mp = player->user_data;
2720 struct media_item *item;
2730 uid = get_be64(&operands[0]);
2732 playable = operands[9];
2734 namelen = MIN(get_be16(&operands[12]), sizeof(name) - 1);
2736 memcpy(name, &operands[14], namelen);
2737 name[namelen] = '\0';
2740 item = media_player_create_folder(mp, name, type, uid);
2744 media_item_set_playable(item, playable & 0x01);
2749 static void avrcp_list_items(struct avrcp *session, uint32_t start,
2751 static gboolean avrcp_list_items_rsp(struct avctp *conn, uint8_t *operands,
2752 size_t operand_count, void *user_data)
2754 struct avrcp_browsing_header *pdu = (void *) operands;
2755 struct avrcp *session = user_data;
2756 struct avrcp_player *player = session->controller->player;
2758 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2763 struct pending_list_items *p = player->p;
2774 /* AVRCP 1.5 - Page 76:
2775 * If the TG receives a GetFolderItems command for an empty folder then
2776 * the TG shall return the error (= Range Out of Bounds) in the status
2777 * field of the GetFolderItems response.
2779 if (pdu->params[0] == AVRCP_STATUS_OUT_OF_BOUNDS)
2782 if (pdu->params[0] != AVRCP_STATUS_SUCCESS || operand_count < 5) {
2787 count = get_be16(&operands[6]);
2791 for (i = 8; count && i + 3 < operand_count; count--) {
2792 struct media_item *item;
2796 type = operands[i++];
2797 len = get_be16(&operands[i]);
2800 if (type != 0x03 && type != 0x02) {
2805 if (i + len > operand_count) {
2806 error("Invalid item length");
2811 item = parse_media_element(session, &operands[i], len);
2813 item = parse_media_folder(session, &operands[i], len);
2816 p->items = g_slist_append(p->items, item);
2821 items = g_slist_length(p->items);
2823 DBG("start %u end %u items %" PRIu64 " total %" PRIu64 "", p->start,
2824 p->end, items, p->total);
2826 if (items < p->total) {
2827 avrcp_list_items(session, p->start + items, p->end);
2832 media_player_list_complete(player->user_data, p->items, err);
2834 g_slist_free(p->items);
2841 static void avrcp_list_items(struct avrcp *session, uint32_t start,
2844 uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 10 +
2845 AVRCP_MEDIA_ATTRIBUTE_LAST * sizeof(uint32_t)];
2846 struct avrcp_player *player = session->controller->player;
2847 struct avrcp_browsing_header *pdu = (void *) buf;
2848 uint16_t length = AVRCP_BROWSING_HEADER_LENGTH + 10;
2851 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2856 memset(buf, 0, sizeof(buf));
2858 pdu->pdu_id = AVRCP_GET_FOLDER_ITEMS;
2859 pdu->param_len = htons(10 + sizeof(uint32_t));
2861 pdu->params[0] = player->scope;
2863 put_be32(start, &pdu->params[1]);
2864 put_be32(end, &pdu->params[5]);
2868 /* Only the title (0x01) is mandatory. This can be extended to
2869 * support AVRCP_MEDIA_ATTRIBUTE_* attributes */
2870 attribute = htonl(AVRCP_MEDIA_ATTRIBUTE_TITLE);
2871 memcpy(&pdu->params[10], &attribute, sizeof(uint32_t));
2873 length += sizeof(uint32_t);
2875 avctp_send_browsing_req(session->conn, buf, length,
2876 avrcp_list_items_rsp, session);
2879 static gboolean avrcp_change_path_rsp(struct avctp *conn,
2880 uint8_t *operands, size_t operand_count,
2883 struct avrcp_browsing_header *pdu = (void *) operands;
2884 struct avrcp *session = user_data;
2885 struct avrcp_player *player = session->controller->player;
2887 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2892 struct media_player *mp = player->user_data;
2900 if (pdu->params[0] != AVRCP_STATUS_SUCCESS) {
2905 ret = get_be32(&pdu->params[1]);
2909 g_free(player->change_path);
2910 player->change_path = NULL;
2912 g_free(player->path);
2913 player->path = player->change_path;
2914 player->change_path = NULL;
2917 media_player_change_folder_complete(mp, player->path,
2918 player->change_uid, ret);
2920 player->change_uid = 0;
2925 static gboolean avrcp_set_browsed_player_rsp(struct avctp *conn,
2927 size_t operand_count,
2930 struct avrcp *session = user_data;
2931 struct avrcp_player *player = session->controller->player;
2933 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2938 struct media_player *mp = player->user_data;
2939 struct avrcp_browsing_header *pdu = (void *) operands;
2942 uint8_t depth, count;
2945 if (pdu == NULL || pdu->params[0] != AVRCP_STATUS_SUCCESS ||
2949 player->uid_counter = get_be16(&pdu->params[1]);
2950 player->browsed = true;
2952 items = get_be32(&pdu->params[3]);
2954 depth = pdu->params[9];
2956 folders = g_new0(char *, depth + 2);
2957 folders[0] = g_strdup("/Filesystem");
2959 for (i = 10, count = 1; count - 1 < depth && i < operand_count;
2963 len = pdu->params[i++];
2967 if (i + len > operand_count) {
2968 error("Invalid folder length");
2972 folders[count] = g_memdup(&pdu->params[i], len);
2976 player->path = g_build_pathv("/", folders);
2977 g_strfreev(folders);
2979 media_player_set_folder(mp, player->path, items);
2984 static void avrcp_set_browsed_player(struct avrcp *session,
2985 struct avrcp_player *player)
2987 uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 2];
2988 struct avrcp_browsing_header *pdu = (void *) buf;
2991 memset(buf, 0, sizeof(buf));
2993 pdu->pdu_id = AVRCP_SET_BROWSED_PLAYER;
2994 id = htons(player->id);
2995 memcpy(pdu->params, &id, 2);
2996 pdu->param_len = htons(2);
2998 avctp_send_browsing_req(session->conn, buf, sizeof(buf),
2999 avrcp_set_browsed_player_rsp, session);
3002 static gboolean avrcp_get_item_attributes_rsp(struct avctp *conn,
3004 size_t operand_count,
3007 struct avrcp *session = user_data;
3008 struct avrcp_player *player = session->controller->player;
3010 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3015 struct avrcp_browsing_header *pdu = (void *) operands;
3019 avrcp_get_element_attributes(session);
3023 if (pdu->params[0] != AVRCP_STATUS_SUCCESS || operand_count < 4) {
3024 avrcp_get_element_attributes(session);
3028 count = pdu->params[1];
3030 if (ntohs(pdu->param_len) - 1 < count * 8) {
3031 error("Invalid parameters");
3035 avrcp_parse_attribute_list(player, &pdu->params[2], count);
3037 avrcp_get_play_status(session);
3042 static void avrcp_get_item_attributes(struct avrcp *session, uint64_t uid)
3044 struct avrcp_player *player = session->controller->player;
3045 uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 12];
3046 struct avrcp_browsing_header *pdu = (void *) buf;
3048 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3053 memset(buf, 0, sizeof(buf));
3055 pdu->pdu_id = AVRCP_GET_ITEM_ATTRIBUTES;
3056 pdu->params[0] = 0x03;
3057 put_be64(uid, &pdu->params[1]);
3058 put_be16(player->uid_counter, &pdu->params[9]);
3059 pdu->param_len = htons(12);
3061 avctp_send_browsing_req(session->conn, buf, sizeof(buf),
3062 avrcp_get_item_attributes_rsp, session);
3065 static void avrcp_player_parse_features(struct avrcp_player *player,
3068 struct media_player *mp = player->user_data;
3070 player->features = g_memdup(features, 16);
3072 if (features[7] & 0x08) {
3073 media_player_set_browsable(mp, true);
3074 media_player_create_folder(mp, "/Filesystem",
3075 PLAYER_FOLDER_TYPE_MIXED, 0);
3078 if (features[7] & 0x10)
3079 media_player_set_searchable(mp, true);
3081 if (features[8] & 0x02) {
3082 media_player_create_folder(mp, "/NowPlaying",
3083 PLAYER_FOLDER_TYPE_MIXED, 0);
3084 media_player_set_playlist(mp, "/NowPlaying");
3088 static void avrcp_set_player_value(struct avrcp *session, uint8_t attr,
3091 uint8_t buf[AVRCP_HEADER_LENGTH + 3];
3092 struct avrcp_header *pdu = (void *) buf;
3095 memset(buf, 0, sizeof(buf));
3097 set_company_id(pdu->company_id, IEEEID_BTSIG);
3098 pdu->pdu_id = AVRCP_SET_PLAYER_VALUE;
3099 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
3101 pdu->params[1] = attr;
3102 pdu->params[2] = val;
3103 pdu->params_len = htons(3);
3105 length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
3107 avctp_send_vendordep_req(session->conn, AVC_CTYPE_CONTROL,
3108 AVC_SUBUNIT_PANEL, buf, length,
3109 avrcp_player_value_rsp, session);
3112 static gboolean avrcp_set_addressed_player_rsp(struct avctp *conn, uint8_t code,
3113 uint8_t subunit, uint8_t transaction,
3114 uint8_t *operands, size_t operand_count,
3117 struct avrcp *session = user_data;
3118 struct avrcp_player *player = session->controller->player;
3119 struct avrcp_header *pdu = (void *) operands;
3121 if (!pdu || code != AVC_CTYPE_ACCEPTED)
3124 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3129 player->addressed = true;
3134 static void avrcp_set_addressed_player(struct avrcp *session,
3135 struct avrcp_player *player)
3137 uint8_t buf[AVRCP_HEADER_LENGTH + 2];
3138 struct avrcp_header *pdu = (void *) buf;
3141 memset(buf, 0, sizeof(buf));
3143 set_company_id(pdu->company_id, IEEEID_BTSIG);
3144 pdu->pdu_id = AVRCP_SET_ADDRESSED_PLAYER;
3145 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
3146 id = htons(player->id);
3147 memcpy(pdu->params, &id, 2);
3148 pdu->params_len = htons(2);
3150 avctp_send_vendordep_req(session->conn, AVC_CTYPE_CONTROL,
3151 AVC_SUBUNIT_PANEL, buf, sizeof(buf),
3152 avrcp_set_addressed_player_rsp,
3156 static void set_addressed_player(struct avrcp *session,
3157 struct avrcp_player *player)
3159 if (!player || !player->id || player->addressed ||
3160 session->controller->version < 0x0104)
3163 /* Set player as addressed */
3164 avrcp_set_addressed_player(session, player);
3167 static void set_browsed_player(struct avrcp *session,
3168 struct avrcp_player *player)
3170 if (!player || !player->id || player->browsed)
3173 if (media_player_get_browsable(player->user_data))
3174 avrcp_set_browsed_player(session, player);
3177 static void set_ct_player(struct avrcp *session, struct avrcp_player *player)
3179 struct btd_service *service;
3181 if (session->controller->player == player)
3184 session->controller->player = player;
3185 service = btd_device_get_service(session->dev, AVRCP_TARGET_UUID);
3186 control_set_player(service, player ?
3187 media_player_get_path(player->user_data) : NULL);
3190 set_addressed_player(session, player);
3191 set_browsed_player(session, player);
3194 static bool ct_set_setting(struct media_player *mp, const char *key,
3195 const char *value, void *user_data)
3197 struct avrcp_player *player = user_data;
3200 struct avrcp *session;
3202 session = player->sessions->data;
3203 if (session == NULL)
3206 if (session->controller->version < 0x0103)
3209 set_ct_player(session, player);
3211 attr = attr_to_val(key);
3215 val = attrval_to_val(attr, value);
3219 avrcp_set_player_value(session, attr, val);
3224 static int ct_press(struct avrcp_player *player, uint8_t op)
3227 struct avrcp *session;
3229 session = player->sessions->data;
3230 if (session == NULL)
3233 set_ct_player(session, player);
3235 err = avctp_send_passthrough(session->conn, op);
3242 #if defined(TIZEN_FEATURE_BLUEZ_MODIFY) && defined(TIZEN_FEATURE_BLUEZ_A2DP_MULTISTREAM)
3243 static int ct_press_send_atonce(struct avrcp_player *player, uint8_t op)
3246 struct avrcp *session;
3248 session = player->sessions->data;
3249 if (session == NULL)
3252 set_ct_player(session, player);
3254 err = avctp_send_passthrough_send_fast(session->conn, op);
3262 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3263 static int ct_release(struct avrcp_player *player, uint8_t op)
3267 struct avrcp *session;
3269 session = player->sessions->data;
3270 if (session == NULL)
3273 err = avctp_send_release_passthrough(session->conn, op);
3282 static int ct_play(struct media_player *mp, void *user_data)
3284 struct avrcp_player *player = user_data;
3286 return ct_press(player, AVC_PLAY);
3289 static int ct_pause(struct media_player *mp, void *user_data)
3291 struct avrcp_player *player = user_data;
3293 return ct_press(player, AVC_PAUSE);
3296 static int ct_stop(struct media_player *mp, void *user_data)
3298 struct avrcp_player *player = user_data;
3300 return ct_press(player, AVC_STOP);
3303 static int ct_next(struct media_player *mp, void *user_data)
3305 struct avrcp_player *player = user_data;
3307 return ct_press(player, AVC_FORWARD);
3310 static int ct_previous(struct media_player *mp, void *user_data)
3312 struct avrcp_player *player = user_data;
3314 return ct_press(player, AVC_BACKWARD);
3317 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3318 static int ct_press_fast_forward(struct media_player *mp, void *user_data)
3321 struct avrcp_player *player = user_data;
3324 return ct_press(player, AVC_FAST_FORWARD);
3327 static int ct_release_fast_forward(struct media_player *mp, void *user_data)
3330 struct avrcp_player *player = user_data;
3333 return ct_release(player, AVC_FAST_FORWARD);
3336 static int ct_press_rewind(struct media_player *mp, void *user_data)
3339 struct avrcp_player *player = user_data;
3342 return ct_press(player, AVC_REWIND);
3345 static int ct_release_rewind(struct media_player *mp, void *user_data)
3348 struct avrcp_player *player = user_data;
3351 return ct_release(player, AVC_REWIND);
3354 static int ct_volume_up(struct media_player *mp, void *user_data)
3357 struct avrcp_player *player = user_data;
3360 return ct_press(player, AVC_VOLUME_UP);
3363 static int ct_volume_down(struct media_player *mp, void *user_data)
3366 struct avrcp_player *player = user_data;
3369 return ct_press(player, AVC_VOLUME_DOWN);
3372 static int ct_fast_forward(struct media_player *mp, void *user_data)
3374 struct avrcp_player *player = user_data;
3376 return ct_press(player, AVC_FAST_FORWARD);
3379 static int ct_rewind(struct media_player *mp, void *user_data)
3381 struct avrcp_player *player = user_data;
3383 return ct_press(player, AVC_REWIND);
3387 static int ct_list_items(struct media_player *mp, const char *name,
3388 uint32_t start, uint32_t end, void *user_data)
3390 struct avrcp_player *player = user_data;
3391 struct avrcp *session;
3392 struct pending_list_items *p;
3394 if (player->p != NULL)
3397 session = player->sessions->data;
3399 set_ct_player(session, player);
3401 if (g_str_has_prefix(name, "/NowPlaying"))
3402 player->scope = 0x03;
3403 else if (g_str_has_suffix(name, "/search"))
3404 player->scope = 0x02;
3406 player->scope = 0x01;
3408 avrcp_list_items(session, start, end);
3410 p = g_new0(struct pending_list_items, 1);
3413 p->total = (uint64_t) (p->end - p->start) + 1;
3419 static void avrcp_change_path(struct avrcp *session, uint8_t direction,
3422 struct avrcp_player *player = session->controller->player;
3423 uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 11];
3424 struct avrcp_browsing_header *pdu = (void *) buf;
3426 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3431 memset(buf, 0, sizeof(buf));
3432 put_be16(player->uid_counter, &pdu->params[0]);
3433 pdu->params[2] = direction;
3434 put_be64(uid, &pdu->params[3]);
3435 pdu->pdu_id = AVRCP_CHANGE_PATH;
3436 pdu->param_len = htons(11);
3438 avctp_send_browsing_req(session->conn, buf, sizeof(buf),
3439 avrcp_change_path_rsp, session);
3442 static int ct_change_folder(struct media_player *mp, const char *path,
3443 uint64_t uid, void *user_data)
3445 struct avrcp_player *player = user_data;
3446 struct avrcp *session;
3449 session = player->sessions->data;
3450 set_ct_player(session, player);
3451 player->change_path = g_strdup(path);
3452 player->change_uid = uid;
3454 direction = g_str_has_prefix(path, player->path) ? 0x01 : 0x00;
3456 avrcp_change_path(session, direction, uid);
3461 static gboolean avrcp_search_rsp(struct avctp *conn, uint8_t *operands,
3462 size_t operand_count, void *user_data)
3464 struct avrcp_browsing_header *pdu = (void *) operands;
3465 struct avrcp *session = (void *) user_data;
3466 struct avrcp_player *player = session->controller->player;
3468 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3473 struct media_player *mp = player->user_data;
3481 if (pdu->params[0] != AVRCP_STATUS_SUCCESS || operand_count < 7) {
3486 player->uid_counter = get_be16(&pdu->params[1]);
3487 ret = get_be32(&pdu->params[3]);
3490 media_player_search_complete(mp, ret);
3495 static void avrcp_search(struct avrcp *session, const char *string)
3497 uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 255];
3498 struct avrcp_browsing_header *pdu = (void *) buf;
3499 uint16_t len, stringlen;
3501 memset(buf, 0, sizeof(buf));
3502 len = AVRCP_BROWSING_HEADER_LENGTH + 4;
3503 stringlen = strnlen(string, sizeof(buf) - len);
3506 put_be16(AVRCP_CHARSET_UTF8, &pdu->params[0]);
3507 put_be16(stringlen, &pdu->params[2]);
3508 memcpy(&pdu->params[4], string, stringlen);
3509 pdu->pdu_id = AVRCP_SEARCH;
3510 pdu->param_len = htons(len - AVRCP_BROWSING_HEADER_LENGTH);
3512 avctp_send_browsing_req(session->conn, buf, len, avrcp_search_rsp,
3516 static int ct_search(struct media_player *mp, const char *string,
3519 struct avrcp_player *player = user_data;
3520 struct avrcp *session;
3522 session = player->sessions->data;
3524 set_ct_player(session, player);
3525 avrcp_search(session, string);
3530 static gboolean avrcp_play_item_rsp(struct avctp *conn, uint8_t code,
3531 uint8_t subunit, uint8_t transaction,
3532 uint8_t *operands, size_t operand_count,
3535 struct avrcp_header *pdu = (void *) operands;
3536 struct avrcp *session = (void *) user_data;
3537 struct avrcp_player *player = session->controller->player;
3538 struct media_player *mp = player->user_data;
3546 if (pdu->params[0] != AVRCP_STATUS_SUCCESS) {
3547 switch (pdu->params[0]) {
3548 case AVRCP_STATUS_UID_CHANGED:
3549 case AVRCP_STATUS_DOES_NOT_EXIST:
3560 media_player_play_item_complete(mp, ret);
3565 static void avrcp_play_item(struct avrcp *session, uint64_t uid)
3567 uint8_t buf[AVRCP_HEADER_LENGTH + 11];
3568 struct avrcp_player *player = session->controller->player;
3569 struct avrcp_header *pdu = (void *) buf;
3572 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3577 memset(buf, 0, sizeof(buf));
3579 set_company_id(pdu->company_id, IEEEID_BTSIG);
3580 pdu->pdu_id = AVRCP_PLAY_ITEM;
3581 pdu->params_len = htons(11);
3582 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
3584 pdu->params[0] = player->scope;
3585 put_be64(uid, &pdu->params[1]);
3586 put_be16(player->uid_counter, &pdu->params[9]);
3588 length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
3590 avctp_send_vendordep_req(session->conn, AVC_CTYPE_CONTROL,
3591 AVC_SUBUNIT_PANEL, buf, length,
3592 avrcp_play_item_rsp, session);
3595 static int ct_play_item(struct media_player *mp, const char *name,
3596 uint64_t uid, void *user_data)
3598 struct avrcp_player *player = user_data;
3599 struct avrcp *session;
3601 if (player->p != NULL)
3604 session = player->sessions->data;
3605 set_ct_player(session, player);
3607 if (g_strrstr(name, "/NowPlaying"))
3608 player->scope = 0x03;
3609 else if (g_strrstr(name, "/Search"))
3610 player->scope = 0x02;
3612 player->scope = 0x01;
3614 avrcp_play_item(session, uid);
3619 static void avrcp_add_to_nowplaying(struct avrcp *session, uint64_t uid)
3621 uint8_t buf[AVRCP_HEADER_LENGTH + 11];
3622 struct avrcp_player *player = session->controller->player;
3623 struct avrcp_header *pdu = (void *) buf;
3626 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3631 memset(buf, 0, sizeof(buf));
3633 set_company_id(pdu->company_id, IEEEID_BTSIG);
3634 pdu->pdu_id = AVRCP_ADD_TO_NOW_PLAYING;
3635 pdu->params_len = htons(11);
3636 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
3638 pdu->params[0] = player->scope;
3639 put_be64(uid, &pdu->params[1]);
3640 put_be16(player->uid_counter, &pdu->params[9]);
3642 length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
3644 avctp_send_vendordep_req(session->conn, AVC_CTYPE_CONTROL,
3645 AVC_SUBUNIT_PANEL, buf, length,
3649 static int ct_add_to_nowplaying(struct media_player *mp, const char *name,
3650 uint64_t uid, void *user_data)
3652 struct avrcp_player *player = user_data;
3653 struct avrcp *session;
3655 if (player->p != NULL)
3658 session = player->sessions->data;
3660 if (g_strrstr(name, "/NowPlaying"))
3661 player->scope = 0x03;
3663 player->scope = 0x01;
3665 set_ct_player(session, player);
3666 avrcp_add_to_nowplaying(session, uid);
3671 static gboolean avrcp_get_total_numberofitems_rsp(struct avctp *conn,
3672 uint8_t *operands, size_t operand_count,
3675 struct avrcp_browsing_header *pdu = (void *) operands;
3676 struct avrcp *session = user_data;
3677 struct avrcp_player *player = session->controller->player;
3679 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3684 struct media_player *mp = player->user_data;
3685 uint32_t num_of_items = 0;
3690 if (pdu->params[0] != AVRCP_STATUS_SUCCESS || operand_count < 7)
3693 if (pdu->params[0] == AVRCP_STATUS_OUT_OF_BOUNDS)
3696 player->uid_counter = get_be16(&pdu->params[1]);
3697 num_of_items = get_be32(&pdu->params[3]);
3703 media_player_total_items_complete(mp, num_of_items);
3707 static void avrcp_get_total_numberofitems(struct avrcp *session)
3709 uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 7];
3710 struct avrcp_player *player = session->controller->player;
3711 struct avrcp_browsing_header *pdu = (void *) buf;
3713 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3718 memset(buf, 0, sizeof(buf));
3720 pdu->pdu_id = AVRCP_GET_TOTAL_NUMBER_OF_ITEMS;
3721 pdu->param_len = htons(7 + sizeof(uint32_t));
3723 pdu->params[0] = player->scope;
3725 avctp_send_browsing_req(session->conn, buf, sizeof(buf),
3726 avrcp_get_total_numberofitems_rsp, session);
3729 static int ct_get_total_numberofitems(struct media_player *mp, const char *name,
3732 struct avrcp_player *player = user_data;
3733 struct avrcp *session;
3735 session = player->sessions->data;
3736 set_ct_player(session, player);
3738 if (session->controller->version != 0x0106) {
3739 error("version not supported");
3743 if (g_str_has_prefix(name, "/NowPlaying"))
3744 player->scope = 0x03;
3745 else if (g_str_has_suffix(name, "/search"))
3746 player->scope = 0x02;
3748 player->scope = 0x01;
3750 avrcp_get_total_numberofitems(session);
3755 static const struct media_player_callback ct_cbs = {
3756 .set_setting = ct_set_setting,
3761 .previous = ct_previous,
3762 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3763 .press_fast_forward = ct_press_fast_forward,
3764 .release_fast_forward = ct_release_fast_forward,
3765 .press_rewind = ct_press_rewind,
3766 .release_rewind = ct_release_rewind,
3767 .volume_up = ct_volume_up,
3768 .volume_down = ct_volume_down,
3770 .fast_forward = ct_fast_forward,
3771 .rewind = ct_rewind,
3773 .list_items = ct_list_items,
3774 .change_folder = ct_change_folder,
3775 .search = ct_search,
3776 .play_item = ct_play_item,
3777 .add_to_nowplaying = ct_add_to_nowplaying,
3778 .total_items = ct_get_total_numberofitems,
3781 static struct avrcp_player *create_ct_player(struct avrcp *session,
3784 struct avrcp_player *player;
3785 struct media_player *mp;
3788 player = g_new0(struct avrcp_player, 1);
3790 player->sessions = g_slist_prepend(player->sessions, session);
3792 path = device_get_path(session->dev);
3794 mp = media_player_controller_create(path, id);
3798 media_player_set_callbacks(mp, &ct_cbs, player);
3799 player->user_data = mp;
3800 player->destroy = (GDestroyNotify) media_player_destroy;
3802 if (session->controller->player == NULL)
3803 set_ct_player(session, player);
3805 session->controller->players = g_slist_prepend(
3806 session->controller->players,
3812 static struct avrcp_player *find_ct_player(struct avrcp *session, uint16_t id)
3816 for (l = session->controller->players; l; l = l->next) {
3817 struct avrcp_player *player = l->data;
3819 if (player->id == 0) {
3824 if (player->id == id)
3831 static struct avrcp_player *
3832 avrcp_parse_media_player_item(struct avrcp *session, uint8_t *operands,
3835 struct avrcp_player *player;
3836 struct media_player *mp;
3837 uint16_t id, namelen;
3839 const char *curval, *strval;
3845 id = get_be16(&operands[0]);
3847 player = find_ct_player(session, id);
3848 if (player == NULL) {
3849 player = create_ct_player(session, id);
3852 } else if (player->features != NULL)
3855 mp = player->user_data;
3857 media_player_set_type(mp, type_to_string(operands[2]));
3859 subtype = get_be32(&operands[3]);
3861 media_player_set_subtype(mp, subtype_to_string(subtype));
3863 curval = media_player_get_status(mp);
3864 strval = status_to_string(operands[7]);
3866 if (g_strcmp0(curval, strval) != 0) {
3867 media_player_set_status(mp, strval);
3868 avrcp_get_play_status(session);
3871 avrcp_player_parse_features(player, &operands[8]);
3873 namelen = get_be16(&operands[26]);
3874 if (namelen > 0 && namelen + 28 == len) {
3875 namelen = MIN(namelen, sizeof(name) - 1);
3876 memcpy(name, &operands[28], namelen);
3877 name[namelen] = '\0';
3878 media_player_set_name(mp, name);
3881 if (player->addressed)
3882 set_browsed_player(session, player);
3887 static void player_destroy(gpointer data)
3889 struct avrcp_player *player = data;
3891 if (player->destroy)
3892 player->destroy(player->user_data);
3894 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
3895 avrcp_stop_position_timer();
3898 if (player->changed_id > 0)
3899 g_source_remove(player->changed_id);
3901 g_slist_free(player->sessions);
3902 g_free(player->path);
3903 g_free(player->change_path);
3904 g_free(player->features);
3908 static void player_remove(gpointer data)
3910 struct avrcp_player *player = data;
3913 /* Don't remove reserved player */
3917 for (l = player->sessions; l; l = l->next) {
3918 struct avrcp *session = l->data;
3919 struct avrcp_data *controller = session->controller;
3921 controller->players = g_slist_remove(controller->players,
3924 /* Check if current player is being removed */
3925 if (controller->player == player)
3926 set_ct_player(session, g_slist_nth_data(
3927 controller->players, 0));
3930 player_destroy(player);
3933 static gboolean avrcp_get_media_player_list_rsp(struct avctp *conn,
3935 size_t operand_count,
3938 struct avrcp_browsing_header *pdu = (void *) operands;
3939 struct avrcp *session = user_data;
3944 if (pdu == NULL || pdu->params[0] != AVRCP_STATUS_SUCCESS ||
3948 removed = g_slist_copy(session->controller->players);
3949 count = get_be16(&operands[6]);
3951 for (i = 8; count && i < operand_count; count--) {
3952 struct avrcp_player *player;
3956 type = operands[i++];
3957 len = get_be16(&operands[i]);
3965 if (i + len > operand_count) {
3966 error("Invalid player item length");
3970 player = avrcp_parse_media_player_item(session, &operands[i],
3973 removed = g_slist_remove(removed, player);
3978 g_slist_free_full(removed, player_remove);
3980 /* There should always be an active player */
3981 if (!session->controller->player)
3982 create_ct_player(session, 0);
3987 static void avrcp_get_media_player_list(struct avrcp *session)
3989 uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 10];
3990 struct avrcp_browsing_header *pdu = (void *) buf;
3992 memset(buf, 0, sizeof(buf));
3994 pdu->pdu_id = AVRCP_GET_FOLDER_ITEMS;
3995 put_be32(0, &pdu->params[1]);
3996 put_be32(UINT32_MAX, &pdu->params[5]);
3997 pdu->param_len = htons(10);
3999 avctp_send_browsing_req(session->conn, buf, sizeof(buf),
4000 avrcp_get_media_player_list_rsp, session);
4003 static void avrcp_volume_changed(struct avrcp *session,
4004 struct avrcp_header *pdu)
4006 struct avrcp_player *player = target_get_player(session);
4009 volume = pdu->params[1] & 0x7F;
4011 /* Always attempt to update the transport volume */
4012 media_transport_update_device_volume(session->dev, volume);
4015 player->cb->set_volume(volume, session->dev, player->user_data);
4018 static void avrcp_status_changed(struct avrcp *session,
4019 struct avrcp_header *pdu)
4021 struct avrcp_player *player = session->controller->player;
4023 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4028 struct media_player *mp = player->user_data;
4030 const char *curval, *strval;
4032 value = pdu->params[1];
4034 curval = media_player_get_status(mp);
4035 strval = status_to_string(value);
4037 #if defined(TIZEN_FEATURE_BLUEZ_MODIFY) && defined(TIZEN_FEATURE_BLUEZ_A2DP_MULTISTREAM)
4038 DBG("AVRCP status changed to : %s", strval);
4040 if (value == AVRCP_PLAY_STATUS_PAUSED)
4041 media_transport_set_stream_status(session->dev, true);
4042 else if ( value == AVRCP_PLAY_STATUS_PLAYING)
4043 media_transport_set_stream_status(session->dev, false);
4046 if (g_strcmp0(curval, strval) == 0)
4049 media_player_set_status(mp, strval);
4050 avrcp_get_play_status(session);
4053 static void avrcp_track_changed(struct avrcp *session,
4054 struct avrcp_header *pdu)
4056 if (session->browsing_id) {
4057 struct avrcp_player *player = session->controller->player;
4059 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4063 player->uid = get_be64(&pdu->params[1]);
4064 avrcp_get_item_attributes(session, player->uid);
4066 avrcp_get_element_attributes(session);
4069 static void avrcp_playback_pos_changed(struct avrcp *session,
4070 struct avrcp_header *pdu)
4072 struct avrcp_player *player = session->controller->player;
4074 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4079 struct media_player *mp = player->user_data;
4082 position = get_be32(&pdu->params[1]);
4083 media_player_set_position(mp, position);
4086 static void avrcp_setting_changed(struct avrcp *session,
4087 struct avrcp_header *pdu)
4089 struct avrcp_player *player = session->controller->player;
4091 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4096 struct media_player *mp = player->user_data;
4097 uint8_t count = pdu->params[1];
4100 for (i = 2; count > 0; count--, i += 2) {
4104 key = attr_to_str(pdu->params[i]);
4108 value = attrval_to_str(pdu->params[i], pdu->params[i + 1]);
4112 media_player_set_setting(mp, key, value);
4116 static void avrcp_available_players_changed(struct avrcp *session,
4117 struct avrcp_header *pdu)
4119 avrcp_get_media_player_list(session);
4122 static void avrcp_addressed_player_changed(struct avrcp *session,
4123 struct avrcp_header *pdu)
4125 struct avrcp_player *player = session->controller->player;
4126 uint16_t id = get_be16(&pdu->params[1]);
4128 if (player != NULL && player->id == id)
4131 player = find_ct_player(session, id);
4132 if (player == NULL) {
4133 player = create_ct_player(session, id);
4138 player->addressed = true;
4139 player->uid_counter = get_be16(&pdu->params[3]);
4140 set_ct_player(session, player);
4142 if (player->features != NULL)
4145 avrcp_get_media_player_list(session);
4148 static void avrcp_uids_changed(struct avrcp *session, struct avrcp_header *pdu)
4150 struct avrcp_player *player = session->controller->player;
4152 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4157 player->uid_counter = get_be16(&pdu->params[1]);
4160 static gboolean avrcp_handle_event(struct avctp *conn, uint8_t code,
4161 uint8_t subunit, uint8_t transaction,
4162 uint8_t *operands, size_t operand_count,
4165 struct avrcp *session = user_data;
4166 struct avrcp_header *pdu = (void *) operands;
4172 if ((code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED)) {
4173 if (pdu->params[0] == AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED &&
4174 code == AVC_CTYPE_REJECTED) {
4177 /* Lookup event by transaction */
4178 for (i = 0; i <= AVRCP_EVENT_LAST; i++) {
4179 if (session->transaction_events[i] ==
4189 event = pdu->params[0];
4191 if (code == AVC_CTYPE_CHANGED)
4195 case AVRCP_EVENT_VOLUME_CHANGED:
4196 avrcp_volume_changed(session, pdu);
4198 case AVRCP_EVENT_STATUS_CHANGED:
4199 avrcp_status_changed(session, pdu);
4201 case AVRCP_EVENT_TRACK_CHANGED:
4202 avrcp_track_changed(session, pdu);
4204 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
4205 avrcp_playback_pos_changed(session, pdu);
4207 case AVRCP_EVENT_SETTINGS_CHANGED:
4208 avrcp_setting_changed(session, pdu);
4210 case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
4211 avrcp_available_players_changed(session, pdu);
4213 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
4214 avrcp_addressed_player_changed(session, pdu);
4216 case AVRCP_EVENT_UIDS_CHANGED:
4217 avrcp_uids_changed(session, pdu);
4221 session->registered_events |= (1 << event);
4222 session->transaction_events[event] = transaction;
4227 session->registered_events ^= (1 << event);
4228 session->transaction_events[event] = 0;
4229 avrcp_register_notification(session, event);
4233 static void avrcp_register_notification(struct avrcp *session, uint8_t event)
4235 uint8_t buf[AVRCP_HEADER_LENGTH + AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH];
4236 struct avrcp_header *pdu = (void *) buf;
4239 memset(buf, 0, sizeof(buf));
4241 set_company_id(pdu->company_id, IEEEID_BTSIG);
4242 pdu->pdu_id = AVRCP_REGISTER_NOTIFICATION;
4243 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
4244 pdu->params[0] = event;
4247 * Set maximum interval possible for position changed as we only
4250 if (event == AVRCP_EVENT_PLAYBACK_POS_CHANGED)
4251 bt_put_be32(UINT32_MAX / 1000, &pdu->params[1]);
4253 pdu->params_len = htons(AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH);
4255 length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
4257 avctp_send_vendordep_req(session->conn, AVC_CTYPE_NOTIFY,
4258 AVC_SUBUNIT_PANEL, buf, length,
4259 avrcp_handle_event, session);
4262 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4263 static char *avrcp_event_to_string(uint8_t event)
4267 case AVRCP_EVENT_STATUS_CHANGED:
4268 return "AVRCP EVENT STATUS CHANGED";
4269 case AVRCP_EVENT_TRACK_CHANGED:
4270 return "AVRCP EVENT TRACK CHANGED";
4271 case AVRCP_EVENT_SETTINGS_CHANGED:
4272 return "AVRCP EVENT SETTINGS CHANGED";
4273 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
4274 return "AVRCP EVENT ADDRESSED PLAYER CHANGED";
4275 case AVRCP_EVENT_UIDS_CHANGED:
4276 return "AVRCP EVENT UIDS CHANGED";
4277 case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
4278 return "AVRCP EVENT AVAILABLE PLAYERS CHANGED";
4279 case AVRCP_EVENT_VOLUME_CHANGED:
4280 return "AVRCP EVENT VOLUME CHANGED";
4282 return "Unknown Event";
4286 static gboolean avrcp_get_playback_status(gpointer user_data)
4288 struct avrcp *session = user_data;
4290 avrcp_get_play_status(session);
4296 static gboolean avrcp_get_capabilities_resp(struct avctp *conn, uint8_t code,
4297 uint8_t subunit, uint8_t transaction,
4298 uint8_t *operands, size_t operand_count,
4301 struct avrcp *session = user_data;
4302 struct avrcp_header *pdu = (void *) operands;
4303 uint16_t events = 0;
4306 if (code == AVC_CTYPE_REJECTED || code == AVC_CTYPE_NOT_IMPLEMENTED ||
4307 pdu == NULL || pdu->params[0] != CAP_EVENTS_SUPPORTED)
4310 /* Connect browsing if pending */
4311 if (session->browsing_timer > 0) {
4312 g_source_remove(session->browsing_timer);
4313 session->browsing_timer = 0;
4314 avctp_connect_browsing(session->conn);
4317 count = pdu->params[1];
4319 for (; count > 0; count--) {
4320 uint8_t event = pdu->params[1 + count];
4322 events |= (1 << event);
4323 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4324 DBG("Supported Event %s", avrcp_event_to_string(event));
4327 case AVRCP_EVENT_STATUS_CHANGED:
4328 case AVRCP_EVENT_TRACK_CHANGED:
4329 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
4330 case AVRCP_EVENT_SETTINGS_CHANGED:
4331 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
4332 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
4333 case AVRCP_EVENT_UIDS_CHANGED:
4334 case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
4335 /* These events above requires a player */
4336 if (!session->controller ||
4337 !session->controller->player)
4341 case AVRCP_EVENT_VOLUME_CHANGED:
4342 avrcp_register_notification(session, event);
4347 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4348 session->remote_supported_events = events;
4351 if (!session->controller || !session->controller->player)
4354 /* Skip if player status/metadata if only volume changes is supported */
4355 if (events == (1 << AVRCP_EVENT_VOLUME_CHANGED))
4358 if ((session->controller->features & AVRCP_FEATURE_PLAYER_SETTINGS) &&
4359 !(events & (1 << AVRCP_EVENT_SETTINGS_CHANGED)))
4360 avrcp_list_player_attributes(session);
4362 if (!(events & (1 << AVRCP_EVENT_STATUS_CHANGED)))
4363 avrcp_get_play_status(session);
4365 if (!(events & (1 << AVRCP_EVENT_STATUS_CHANGED)))
4366 avrcp_get_element_attributes(session);
4368 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4369 if ((events & (1 << AVRCP_EVENT_STATUS_CHANGED)) == 0) {
4370 session->playback_status_id = g_timeout_add_seconds(1,
4371 avrcp_get_playback_status, session);
4377 static void avrcp_get_capabilities(struct avrcp *session)
4379 uint8_t buf[AVRCP_HEADER_LENGTH + AVRCP_GET_CAPABILITIES_PARAM_LENGTH];
4380 struct avrcp_header *pdu = (void *) buf;
4383 memset(buf, 0, sizeof(buf));
4385 set_company_id(pdu->company_id, IEEEID_BTSIG);
4386 pdu->pdu_id = AVRCP_GET_CAPABILITIES;
4387 pdu->packet_type = AVRCP_PACKET_TYPE_SINGLE;
4388 pdu->params[0] = CAP_EVENTS_SUPPORTED;
4389 pdu->params_len = htons(AVRCP_GET_CAPABILITIES_PARAM_LENGTH);
4391 length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
4393 avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
4394 AVC_SUBUNIT_PANEL, buf, length,
4395 avrcp_get_capabilities_resp,
4399 static struct avrcp *find_session(GSList *list, struct btd_device *dev)
4401 for (; list; list = list->next) {
4402 struct avrcp *session = list->data;
4404 if (session->dev == dev)
4411 static void destroy_browsing(void *data)
4413 struct avrcp *session = data;
4415 session->browsing_id = 0;
4418 static void session_init_browsing(struct avrcp *session)
4420 if (session->browsing_timer > 0) {
4421 g_source_remove(session->browsing_timer);
4422 session->browsing_timer = 0;
4425 session->browsing_id = avctp_register_browsing_pdu_handler(
4427 handle_browsing_pdu,
4432 static struct avrcp_data *data_init(struct avrcp *session, const char *uuid)
4434 struct avrcp_data *data;
4435 const sdp_record_t *rec;
4437 sdp_profile_desc_t *desc;
4439 data = g_new0(struct avrcp_data, 1);
4441 rec = btd_device_get_record(session->dev, uuid);
4445 if (sdp_get_profile_descs(rec, &list) == 0) {
4447 data->version = desc->version;
4450 sdp_get_int_attr(rec, SDP_ATTR_SUPPORTED_FEATURES, &data->features);
4451 sdp_list_free(list, free);
4456 static gboolean connect_browsing(gpointer user_data)
4458 struct avrcp *session = user_data;
4460 session->browsing_timer = 0;
4462 avctp_connect_browsing(session->conn);
4467 static void avrcp_connect_browsing(struct avrcp *session)
4469 /* Immediately connect browsing channel if initiator otherwise delay
4470 * it to avoid possible collisions
4472 if (avctp_is_initiator(session->conn)) {
4473 avctp_connect_browsing(session->conn);
4477 if (session->browsing_timer > 0)
4480 session->browsing_timer = g_timeout_add_seconds(AVRCP_BROWSING_TIMEOUT,
4485 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_TARGET
4486 static void target_init(struct avrcp *session)
4488 struct avrcp_server *server = session->server;
4489 struct avrcp_data *target;
4490 struct avrcp_player *player;
4491 struct btd_service *service;
4493 if (session->target != NULL)
4496 target = data_init(session, AVRCP_REMOTE_UUID);
4497 session->target = target;
4499 DBG("%p version 0x%04x", target, target->version);
4501 service = btd_device_get_service(session->dev, AVRCP_REMOTE_UUID);
4502 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4504 btd_service_connecting_complete(service, 0);
4506 btd_service_connecting_complete(service, 0);
4509 player = g_slist_nth_data(server->players, 0);
4510 if (player != NULL) {
4512 target->player = player;
4513 player->sessions = g_slist_prepend(player->sessions, session);
4515 init_volume = media_player_get_device_volume(session->dev);
4516 media_transport_update_device_volume(session->dev, init_volume);
4519 session->supported_events |= (1 << AVRCP_EVENT_STATUS_CHANGED) |
4520 (1 << AVRCP_EVENT_TRACK_CHANGED) |
4521 #ifndef TIZEN_FEATURE_BLUEZ_MODIFY
4522 (1 << AVRCP_EVENT_TRACK_REACHED_START) |
4523 (1 << AVRCP_EVENT_TRACK_REACHED_END) |
4525 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4526 (1 << AVRCP_EVENT_PLAYBACK_POS_CHANGED) |
4528 (1 << AVRCP_EVENT_SETTINGS_CHANGED);
4530 if (target->version < 0x0104)
4533 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4534 if (adapter_avrcp_tg_ver < 0x0104)
4538 session->supported_events |=
4539 (1 << AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED) |
4540 (1 << AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED) |
4541 (1 << AVRCP_EVENT_VOLUME_CHANGED);
4543 /* Only check capabilities if controller is not supported */
4544 if (session->controller == NULL)
4545 avrcp_get_capabilities(session);
4547 if (!(target->features & AVRCP_FEATURE_BROWSING))
4550 avrcp_connect_browsing(session);
4554 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_CONTROL
4555 static void controller_init(struct avrcp *session)
4557 struct avrcp_player *player;
4558 struct btd_service *service;
4559 struct avrcp_data *controller;
4561 if (session->controller != NULL)
4564 controller = data_init(session, AVRCP_TARGET_UUID);
4565 session->controller = controller;
4567 DBG("%p version 0x%04x", controller, controller->version);
4569 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4570 session->controller->player = NULL;
4572 if ((controller->version >= 0x0104) && (adapter_avrcp_ct_ver >= 0x0104))
4573 session->supported_events |= (1 << AVRCP_EVENT_VOLUME_CHANGED);
4576 service = btd_device_get_service(session->dev, AVRCP_TARGET_UUID);
4577 btd_service_connecting_complete(service, 0);
4579 /* Only create player if category 1 is supported */
4580 if (controller->features & AVRCP_FEATURE_CATEGORY_1) {
4581 player = create_ct_player(session, 0);
4586 if (controller->version < 0x0103)
4589 avrcp_get_capabilities(session);
4591 if (controller->version < 0x0104)
4594 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4595 if (adapter_avrcp_ct_ver < 0x0104)
4599 if (!(controller->features & AVRCP_FEATURE_BROWSING))
4602 avrcp_connect_browsing(session);
4606 static void session_init_control(struct avrcp *session)
4608 session->passthrough_id = avctp_register_passthrough_handler(
4612 session->passthrough_handlers = passthrough_handlers;
4613 session->control_id = avctp_register_pdu_handler(session->conn,
4615 handle_vendordep_pdu,
4617 session->control_handlers = control_handlers;
4618 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_CONTROL
4619 if (btd_device_get_service(session->dev, AVRCP_TARGET_UUID) != NULL)
4620 controller_init(session);
4622 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_TARGET
4623 if (btd_device_get_service(session->dev, AVRCP_REMOTE_UUID) != NULL)
4624 target_init(session);
4628 static void controller_destroy(struct avrcp *session)
4630 struct avrcp_data *controller = session->controller;
4632 DBG("%p", controller);
4634 g_slist_free_full(controller->players, player_destroy);
4639 static void target_destroy(struct avrcp *session)
4641 struct avrcp_data *target = session->target;
4642 struct avrcp_player *player = target->player;
4647 player->sessions = g_slist_remove(player->sessions, session);
4652 static void session_destroy(struct avrcp *session, int err)
4654 struct avrcp_server *server = session->server;
4655 struct btd_service *service;
4657 server->sessions = g_slist_remove(server->sessions, session);
4659 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
4660 if (session->playback_status_id > 0) {
4661 DBG("Removing the timer for playback status polling");
4662 g_source_remove(session->playback_status_id);
4663 session->playback_status_id = 0;
4667 session_abort_pending_pdu(session);
4669 service = btd_device_get_service(session->dev, AVRCP_TARGET_UUID);
4670 if (service != NULL) {
4671 if (session->control_id == 0)
4672 btd_service_connecting_complete(service, err);
4674 btd_service_disconnecting_complete(service, 0);
4677 service = btd_device_get_service(session->dev, AVRCP_REMOTE_UUID);
4678 if (service != NULL) {
4679 if (session->control_id == 0)
4680 btd_service_connecting_complete(service, err);
4682 btd_service_disconnecting_complete(service, 0);
4685 if (session->browsing_timer > 0)
4686 g_source_remove(session->browsing_timer);
4688 if (session->controller != NULL)
4689 controller_destroy(session);
4691 if (session->target != NULL)
4692 target_destroy(session);
4694 if (session->passthrough_id > 0)
4695 avctp_unregister_passthrough_handler(session->passthrough_id);
4697 if (session->control_id > 0)
4698 avctp_unregister_pdu_handler(session->control_id);
4700 if (session->browsing_id > 0)
4701 avctp_unregister_browsing_pdu_handler(session->browsing_id);
4706 static struct avrcp *session_create(struct avrcp_server *server,
4707 struct btd_device *device)
4709 struct avrcp *session;
4711 session = g_new0(struct avrcp, 1);
4712 session->server = server;
4713 session->conn = avctp_connect(device);
4714 session->dev = device;
4716 server->sessions = g_slist_append(server->sessions, session);
4721 static void state_changed(struct btd_device *device, avctp_state_t old_state,
4722 avctp_state_t new_state, int err,
4725 struct avrcp_server *server;
4726 struct avrcp *session;
4728 server = find_server(servers, device_get_adapter(device));
4732 session = find_session(server->sessions, device);
4734 switch (new_state) {
4735 case AVCTP_STATE_DISCONNECTED:
4736 if (session == NULL)
4739 session_destroy(session, err);
4742 case AVCTP_STATE_CONNECTING:
4743 if (session != NULL)
4746 session_create(server, device);
4749 case AVCTP_STATE_CONNECTED:
4750 if (session == NULL || session->control_id > 0)
4753 session_init_control(session);
4756 case AVCTP_STATE_BROWSING_CONNECTED:
4757 if (session == NULL || session->browsing_id > 0)
4760 session_init_browsing(session);
4763 case AVCTP_STATE_BROWSING_CONNECTING:
4769 static struct avrcp_server *avrcp_server_register(struct btd_adapter *adapter)
4771 struct avrcp_server *server;
4773 if (avctp_register(adapter, TRUE) < 0)
4776 server = g_new0(struct avrcp_server, 1);
4777 server->adapter = btd_adapter_ref(adapter);
4779 servers = g_slist_append(servers, server);
4782 avctp_id = avctp_add_state_cb(NULL, state_changed, NULL);
4787 static void avrcp_server_unregister(struct avrcp_server *server)
4789 g_slist_free_full(server->sessions, g_free);
4790 g_slist_free_full(server->players, player_destroy);
4792 servers = g_slist_remove(servers, server);
4794 avctp_unregister(server->adapter);
4795 btd_adapter_unref(server->adapter);
4802 avctp_remove_state_cb(avctp_id);
4807 struct avrcp_player *avrcp_register_player(struct btd_adapter *adapter,
4808 struct avrcp_player_cb *cb,
4810 GDestroyNotify destroy)
4812 struct avrcp_server *server;
4813 struct avrcp_player *player;
4815 static uint16_t id = 0;
4817 server = find_server(servers, adapter);
4821 player = g_new0(struct avrcp_player, 1);
4823 player->server = server;
4825 player->user_data = user_data;
4826 player->destroy = destroy;
4828 server->players = g_slist_append(server->players, player);
4830 /* Assign player to session without current player */
4831 for (l = server->sessions; l; l = l->next) {
4832 struct avrcp *session = l->data;
4833 struct avrcp_data *target = session->target;
4838 if (target->player == NULL) {
4839 target->player = player;
4840 player->sessions = g_slist_append(player->sessions,
4845 avrcp_player_event(player,
4846 AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED, NULL);
4851 void avrcp_unregister_player(struct avrcp_player *player)
4853 struct avrcp_server *server = player->server;
4856 server->players = g_slist_remove(server->players, player);
4858 /* Remove player from sessions using it */
4859 for (l = player->sessions; l; l = l->next) {
4860 struct avrcp *session = l->data;
4861 struct avrcp_data *target = session->target;
4866 if (target->player == player)
4867 target->player = g_slist_nth_data(server->players, 0);
4870 avrcp_player_event(player,
4871 AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED, NULL);
4873 player_destroy(player);
4876 static gboolean avrcp_handle_set_volume(struct avctp *conn, uint8_t code,
4877 uint8_t subunit, uint8_t transaction,
4878 uint8_t *operands, size_t operand_count,
4881 struct avrcp *session = user_data;
4882 struct avrcp_player *player = target_get_player(session);
4883 struct avrcp_header *pdu = (void *) operands;
4886 if (code == AVC_CTYPE_REJECTED || code == AVC_CTYPE_NOT_IMPLEMENTED ||
4890 volume = pdu->params[0] & 0x7F;
4892 /* Always attempt to update the transport volume */
4893 media_transport_update_device_volume(session->dev, volume);
4896 player->cb->set_volume(volume, session->dev, player->user_data);
4901 static int avrcp_event(struct avrcp *session, uint8_t id, const void *data)
4903 uint8_t buf[AVRCP_HEADER_LENGTH + 2];
4904 struct avrcp_header *pdu = (void *) buf;
4909 /* Verify that the event is registered */
4910 if (!(session->registered_events & (1 << id)))
4913 memset(buf, 0, sizeof(buf));
4915 set_company_id(pdu->company_id, IEEEID_BTSIG);
4916 pdu->pdu_id = AVRCP_REGISTER_NOTIFICATION;
4917 code = AVC_CTYPE_CHANGED;
4918 pdu->params[0] = id;
4923 case AVRCP_EVENT_VOLUME_CHANGED:
4925 memcpy(&pdu->params[1], data, sizeof(uint8_t));
4928 error("Unknown event %u", id);
4932 pdu->params_len = htons(size);
4934 err = avctp_send_vendordep(session->conn,
4935 session->transaction_events[id],
4936 code, AVC_SUBUNIT_PANEL,
4937 buf, size + AVRCP_HEADER_LENGTH);
4941 /* Unregister event as per AVRCP 1.3 spec, section 5.4.2 */
4942 session->registered_events ^= 1 << id;
4947 int avrcp_set_volume(struct btd_device *dev, int8_t volume, bool notify)
4949 struct avrcp_server *server;
4950 struct avrcp *session;
4951 uint8_t buf[AVRCP_HEADER_LENGTH + 1];
4952 struct avrcp_header *pdu = (void *) buf;
4957 server = find_server(servers, device_get_adapter(dev));
4961 session = find_session(server->sessions, dev);
4962 if (session == NULL)
4966 if (!session->target)
4968 return avrcp_event(session, AVRCP_EVENT_VOLUME_CHANGED,
4972 if (!session->controller || session->controller->version < 0x0104)
4975 memset(buf, 0, sizeof(buf));
4977 set_company_id(pdu->company_id, IEEEID_BTSIG);
4979 pdu->pdu_id = AVRCP_SET_ABSOLUTE_VOLUME;
4980 pdu->params[0] = volume;
4981 pdu->params_len = htons(1);
4983 return avctp_send_vendordep_req(session->conn,
4984 AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
4986 avrcp_handle_set_volume, session);
4989 struct avrcp_player *avrcp_get_target_player_by_device(struct btd_device *dev)
4991 struct avrcp_server *server;
4992 struct avrcp *session;
4993 struct avrcp_data *target;
4995 server = find_server(servers, device_get_adapter(dev));
4999 session = find_session(server->sessions, dev);
5000 if (session == NULL)
5003 target = session->target;
5007 return target->player;
5010 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5011 int avrcp_get_target_volume(struct btd_device *dev, uint8_t* volume)
5013 struct avrcp_server *server;
5014 struct avrcp *session;
5015 struct avrcp_player *player;
5018 DBG("avrcp_get_target_volume");
5020 server = find_server(servers, device_get_adapter(dev));
5024 session = find_session(server->sessions, dev);
5025 if (!session || !session->controller || !session->target->player)
5028 if (!(session->remote_supported_events & (1 << AVRCP_EVENT_VOLUME_CHANGED)))
5031 player = session->target->player;
5032 if (!player || !player->user_data || !player->cb)
5035 vol = player->cb->get_volume(session->dev, player->user_data);
5037 DBG("avrcp_get_target_volume [%d]", vol);
5045 #if defined(TIZEN_FEATURE_BLUEZ_MODIFY) && defined(TIZEN_FEATURE_BLUEZ_A2DP_MULTISTREAM)
5046 int avrcp_pause(struct btd_device *dev)
5048 struct avrcp_server *server;
5049 struct avrcp *session;
5053 server = find_server(servers, device_get_adapter(dev));
5057 session = find_session(server->sessions, dev);
5058 if (session == NULL)
5061 if (session->controller) {
5062 DBG("Calling controller pause");
5063 ct_press_send_atonce(session->controller->player, AVC_PAUSE);
5065 DBG("Controller not found");
5073 static int avrcp_connect(struct btd_service *service)
5075 struct btd_device *dev = btd_service_get_device(service);
5076 const char *path = device_get_path(dev);
5077 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5080 DBG("path %s", path);
5082 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
5083 device_get_name(dev, name, sizeof(name));
5084 DBG("name : %s", name);
5085 if (g_str_equal(name, "PLT_M50")) {
5086 DBG("Don't initiate avrcp connection with this headset");
5090 /* Device unpairing failed if AVRCP connection is triggered
5092 if (device_is_temporary(dev))
5095 return control_connect(service);
5098 static int avrcp_disconnect(struct btd_service *service)
5100 struct btd_device *dev = btd_service_get_device(service);
5101 const char *path = device_get_path(dev);
5103 DBG("path %s", path);
5105 return control_disconnect(service);
5108 static int avrcp_target_probe(struct btd_service *service)
5110 struct btd_device *dev = btd_service_get_device(service);
5112 DBG("path %s", device_get_path(dev));
5114 return control_init_target(service);
5117 static void avrcp_target_remove(struct btd_service *service)
5119 control_unregister(service);
5122 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_TARGET
5123 static void avrcp_target_server_remove(struct btd_profile *p,
5124 struct btd_adapter *adapter)
5126 struct avrcp_server *server;
5128 DBG("path %s", adapter_get_path(adapter));
5130 server = find_server(servers, adapter);
5134 if (server->tg_record_id != 0) {
5135 adapter_service_remove(adapter, server->tg_record_id);
5136 server->tg_record_id = 0;
5139 if (server->ct_record_id == 0)
5140 avrcp_server_unregister(server);
5144 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_TARGET
5145 static int avrcp_target_server_probe(struct btd_profile *p,
5146 struct btd_adapter *adapter)
5148 sdp_record_t *record;
5149 struct avrcp_server *server;
5151 DBG("path %s", adapter_get_path(adapter));
5153 server = find_server(servers, adapter);
5157 server = avrcp_server_register(adapter);
5159 return -EPROTONOSUPPORT;
5162 record = avrcp_tg_record();
5164 error("Unable to allocate new service record");
5165 avrcp_target_server_remove(p, adapter);
5169 if (adapter_service_add(adapter, record) < 0) {
5170 error("Unable to register AVRCP target service record");
5171 avrcp_target_server_remove(p, adapter);
5172 sdp_record_free(record);
5175 server->tg_record_id = record->handle;
5181 static struct btd_profile avrcp_target_profile = {
5182 .name = "audio-avrcp-target",
5184 .remote_uuid = AVRCP_TARGET_UUID,
5185 .device_probe = avrcp_target_probe,
5186 .device_remove = avrcp_target_remove,
5188 .connect = avrcp_connect,
5189 .disconnect = avrcp_disconnect,
5190 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_TARGET
5191 .adapter_probe = avrcp_target_server_probe,
5192 .adapter_remove = avrcp_target_server_remove,
5196 static int avrcp_controller_probe(struct btd_service *service)
5198 struct btd_device *dev = btd_service_get_device(service);
5200 DBG("path %s", device_get_path(dev));
5202 return control_init_remote(service);
5205 static void avrcp_controller_remove(struct btd_service *service)
5207 control_unregister(service);
5210 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_CONTROL
5211 static void avrcp_controller_server_remove(struct btd_profile *p,
5212 struct btd_adapter *adapter)
5214 struct avrcp_server *server;
5216 DBG("path %s", adapter_get_path(adapter));
5218 server = find_server(servers, adapter);
5222 if (server->ct_record_id != 0) {
5223 adapter_service_remove(adapter, server->ct_record_id);
5224 server->ct_record_id = 0;
5227 if (server->tg_record_id == 0)
5228 avrcp_server_unregister(server);
5232 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_CONTROL
5233 static int avrcp_controller_server_probe(struct btd_profile *p,
5234 struct btd_adapter *adapter)
5236 sdp_record_t *record;
5237 struct avrcp_server *server;
5239 DBG("path %s", adapter_get_path(adapter));
5241 server = find_server(servers, adapter);
5245 server = avrcp_server_register(adapter);
5247 return -EPROTONOSUPPORT;
5250 record = avrcp_ct_record();
5252 error("Unable to allocate new service record");
5253 avrcp_controller_server_remove(p, adapter);
5257 if (adapter_service_add(adapter, record) < 0) {
5258 error("Unable to register AVRCP service record");
5259 avrcp_controller_server_remove(p, adapter);
5260 sdp_record_free(record);
5263 server->ct_record_id = record->handle;
5269 static struct btd_profile avrcp_controller_profile = {
5270 .name = "avrcp-controller",
5272 .remote_uuid = AVRCP_REMOTE_UUID,
5273 .device_probe = avrcp_controller_probe,
5274 .device_remove = avrcp_controller_remove,
5276 .connect = avrcp_connect,
5277 .disconnect = avrcp_disconnect,
5278 #ifdef TIZEN_FEATURE_BLUEZ_AVRCP_CONTROL
5279 .adapter_probe = avrcp_controller_server_probe,
5280 .adapter_remove = avrcp_controller_server_remove,
5284 static int avrcp_init(void)
5286 btd_profile_register(&avrcp_controller_profile);
5287 btd_profile_register(&avrcp_target_profile);
5289 populate_default_features();
5294 static void avrcp_exit(void)
5296 btd_profile_unregister(&avrcp_controller_profile);
5297 btd_profile_unregister(&avrcp_target_profile);
5300 BLUETOOTH_PLUGIN_DEFINE(avrcp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
5301 avrcp_init, avrcp_exit)