3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2014 Intel Corporation. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "lib/bluetooth.h"
35 #include "src/shared/util.h"
39 #include "avrcp-lib.h"
43 #define AVRCP_PACKET_TYPE_SINGLE 0x00
44 #define AVRCP_PACKET_TYPE_START 0x01
45 #define AVRCP_PACKET_TYPE_CONTINUING 0x02
46 #define AVRCP_PACKET_TYPE_END 0x03
48 #define AVRCP_CHARSET_UTF8 0x006a
50 #if __BYTE_ORDER == __LITTLE_ENDIAN
53 uint8_t company_id[3];
55 uint8_t packet_type:2;
59 } __attribute__ ((packed));
60 #define AVRCP_HEADER_LENGTH 7
62 #elif __BYTE_ORDER == __BIG_ENDIAN
65 uint8_t company_id[3];
68 uint8_t packet_type:2;
71 } __attribute__ ((packed));
72 #define AVRCP_HEADER_LENGTH 7
75 #error "Unknown byte order"
78 struct avrcp_browsing_header {
82 } __attribute__ ((packed));
83 #define AVRCP_BROWSING_HEADER_LENGTH 3
85 struct get_capabilities_req {
88 } __attribute__ ((packed));
90 struct get_capabilities_rsp {
94 } __attribute__ ((packed));
96 struct list_attributes_rsp {
99 } __attribute__ ((packed));
101 struct list_values_req {
103 } __attribute__ ((packed));
105 struct list_values_rsp {
108 } __attribute__ ((packed));
110 struct get_value_req {
113 } __attribute__ ((packed));
118 } __attribute__ ((packed));
122 struct attr_value values[0];
123 } __attribute__ ((packed));
125 struct set_value_req {
127 struct attr_value values[0];
128 } __attribute__ ((packed));
130 struct get_attribute_text_req {
133 } __attribute__ ((packed));
140 } __attribute__ ((packed));
142 struct get_attribute_text_rsp {
144 struct text_value values[0];
145 } __attribute__ ((packed));
147 struct get_value_text_req {
151 } __attribute__ ((packed));
153 struct get_value_text_rsp {
155 struct text_value values[0];
156 } __attribute__ ((packed));
163 } __attribute__ ((packed));
165 struct get_element_attributes_req {
169 } __attribute__ ((packed));
171 struct get_element_attributes_rsp {
173 struct media_item items[0];
174 } __attribute__ ((packed));
176 struct get_play_status_rsp {
180 } __attribute__ ((packed));
182 struct register_notification_req {
185 } __attribute__ ((packed));
187 struct register_notification_rsp {
190 } __attribute__ ((packed));
192 struct set_volume_req {
194 } __attribute__ ((packed));
196 struct set_volume_rsp {
198 } __attribute__ ((packed));
200 struct set_addressed_req {
202 } __attribute__ ((packed));
204 struct set_addressed_rsp {
206 } __attribute__ ((packed));
208 struct set_browsed_req {
210 } __attribute__ ((packed));
212 struct set_browsed_rsp {
219 } __attribute__ ((packed));
221 struct get_folder_items_req {
227 } __attribute__ ((packed));
229 struct get_folder_items_rsp {
234 } __attribute__ ((packed));
236 struct change_path_req {
240 } __attribute__ ((packed));
242 struct change_path_rsp {
245 } __attribute__ ((packed));
247 struct get_item_attributes_req {
253 } __attribute__ ((packed));
255 struct get_item_attributes_rsp {
258 struct media_item items[0];
259 } __attribute__ ((packed));
261 struct play_item_req {
265 } __attribute__ ((packed));
267 struct play_item_rsp {
269 } __attribute__ ((packed));
275 } __attribute__ ((packed));
281 } __attribute__ ((packed));
283 struct add_to_now_playing_req {
287 } __attribute__ ((packed));
289 struct add_to_now_playing_rsp {
291 } __attribute__ ((packed));
293 struct avrcp_control_handler {
297 ssize_t (*func) (struct avrcp *session, uint8_t transaction,
298 uint16_t params_len, uint8_t *params, void *user_data);
301 struct avrcp_browsing_handler {
303 ssize_t (*func) (struct avrcp *session, uint8_t transaction,
304 uint16_t params_len, uint8_t *params, void *user_data);
307 struct avrcp_continuing {
314 struct avrcp_player *player;
316 const struct avrcp_control_handler *control_handlers;
318 unsigned int control_id;
319 uint16_t control_mtu;
321 struct avrcp_continuing *continuing;
323 const struct avrcp_passthrough_handler *passthrough_handlers;
324 void *passthrough_data;
325 unsigned int passthrough_id;
327 const struct avrcp_browsing_handler *browsing_handlers;
329 unsigned int browsing_id;
331 avrcp_destroy_cb_t destroy;
335 struct avrcp_player {
336 const struct avrcp_control_ind *ind;
337 const struct avrcp_control_cfm *cfm;
342 static inline uint32_t ntoh24(const uint8_t src[3])
344 return src[0] << 16 | src[1] << 8 | src[2];
347 static inline void hton24(uint8_t dst[3], uint32_t src)
349 dst[0] = (src & 0xff0000) >> 16;
350 dst[1] = (src & 0x00ff00) >> 8;
351 dst[2] = (src & 0x0000ff);
354 static void continuing_free(struct avrcp_continuing *continuing)
356 g_free(continuing->pdu.iov_base);
360 void avrcp_shutdown(struct avrcp *session)
363 if (session->control_id > 0)
364 avctp_unregister_pdu_handler(session->conn,
365 session->control_id);
366 if (session->passthrough_id > 0)
367 avctp_unregister_passthrough_handler(session->conn,
368 session->passthrough_id);
370 if (session->browsing_id > 0)
371 avctp_unregister_browsing_pdu_handler(session->conn,
372 session->browsing_id);
374 /* clear destroy callback that would call shutdown again */
375 avctp_set_destroy_cb(session->conn, NULL, NULL);
376 avctp_shutdown(session->conn);
379 if (session->destroy)
380 session->destroy(session->destroy_data);
382 if (session->continuing)
383 continuing_free(session->continuing);
385 g_free(session->player);
389 static struct avrcp_header *parse_pdu(uint8_t *operands, size_t operand_count)
391 struct avrcp_header *pdu;
393 if (!operands || operand_count < sizeof(*pdu)) {
394 error("AVRCP: packet too small (%zu bytes)", operand_count);
398 pdu = (void *) operands;
399 pdu->params_len = ntohs(pdu->params_len);
401 if (operand_count != pdu->params_len + sizeof(*pdu)) {
402 error("AVRCP: invalid parameter length (%u bytes)",
410 static struct avrcp_browsing_header *parse_browsing_pdu(uint8_t *operands,
411 size_t operand_count)
413 struct avrcp_browsing_header *pdu;
415 if (!operands || operand_count < sizeof(*pdu)) {
416 error("AVRCP: packet too small (%zu bytes)", operand_count);
420 pdu = (void *) operands;
421 pdu->params_len = ntohs(pdu->params_len);
423 if (operand_count != pdu->params_len + sizeof(*pdu)) {
424 error("AVRCP: invalid parameter length (%u bytes)",
432 static uint8_t errno2status(int err)
436 return AVRCP_STATUS_INVALID_COMMAND;
438 return AVRCP_STATUS_INVALID_PARAM;
440 return AVRCP_STATUS_SUCCESS;
442 return AVRCP_STATUS_NOT_DIRECTORY;
444 return AVRCP_STATUS_INVALID_SCOPE;
446 return AVRCP_STATUS_OUT_OF_BOUNDS;
448 return AVRCP_STATUS_DOES_NOT_EXIST;
450 return AVRCP_STATUS_INTERNAL_ERROR;
454 static ssize_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
455 uint8_t *code, uint8_t *subunit,
456 uint8_t *operands, size_t operand_count,
459 struct avrcp *session = user_data;
460 const struct avrcp_control_handler *handler;
461 struct avrcp_header *pdu;
465 pdu = parse_pdu(operands, operand_count);
467 pdu = (void *) operands;
468 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
472 company_id = ntoh24(pdu->company_id);
473 if (company_id != IEEEID_BTSIG) {
474 *code = AVC_CTYPE_NOT_IMPLEMENTED;
478 DBG("AVRCP PDU 0x%02X, len 0x%04X", pdu->pdu_id, pdu->params_len);
480 pdu->packet_type = 0;
483 if (!session->control_handlers)
486 for (handler = session->control_handlers; handler->id; handler++) {
487 if (handler->id == pdu->pdu_id)
491 if (handler->id != pdu->pdu_id || handler->code != *code) {
492 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
496 if (!handler->func) {
497 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
501 ret = handler->func(session, transaction, pdu->params_len, pdu->params,
502 session->control_data);
509 pdu->params[0] = errno2status(ret);
513 *code = handler->rsp;
514 pdu->params_len = htons(ret);
516 return AVRCP_HEADER_LENGTH + ret;
519 pdu->params_len = htons(1);
520 *code = AVC_CTYPE_REJECTED;
522 return AVRCP_HEADER_LENGTH + 1;
525 static bool handle_passthrough_pdu(struct avctp *conn, uint8_t op,
526 bool pressed, void *user_data)
528 struct avrcp *session = user_data;
529 const struct avrcp_passthrough_handler *handler;
531 if (!session->passthrough_handlers)
534 for (handler = session->passthrough_handlers; handler->func;
536 if (handler->op == op)
540 if (handler->func == NULL)
543 return handler->func(session, pressed, session->passthrough_data);
546 static void disconnect_cb(void *data)
548 struct avrcp *session = data;
550 session->conn = NULL;
552 avrcp_shutdown(session);
555 struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
557 struct avrcp *session;
559 session = g_new0(struct avrcp, 1);
561 session->conn = avctp_new(fd, imtu, omtu, version);
562 if (!session->conn) {
567 session->passthrough_id = avctp_register_passthrough_handler(
569 handle_passthrough_pdu,
571 session->control_id = avctp_register_pdu_handler(session->conn,
573 handle_vendordep_pdu,
575 session->control_mtu = omtu - AVC_DATA_OFFSET;
578 * 27.1.2 AV/C Command Frame
579 * An AV/C command frame contains up to 512 octets of data
581 if (session->control_mtu > AVC_DATA_MTU)
582 session->control_mtu = AVC_DATA_MTU;
584 avctp_set_destroy_cb(session->conn, disconnect_cb, session);
589 static ssize_t handle_browsing_pdu(struct avctp *conn,
590 uint8_t transaction, uint8_t *operands,
591 size_t operand_count, void *user_data)
593 struct avrcp *session = user_data;
594 const struct avrcp_browsing_handler *handler;
595 struct avrcp_browsing_header *pdu;
598 pdu = parse_browsing_pdu(operands, operand_count);
600 pdu = (void *) operands;
601 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
605 DBG("AVRCP Browsing PDU 0x%02X, len 0x%04X", pdu->pdu_id,
608 if (!session->browsing_handlers) {
609 pdu->pdu_id = AVRCP_GENERAL_REJECT;
610 pdu->params[0] = AVRCP_STATUS_INTERNAL_ERROR;
614 for (handler = session->browsing_handlers; handler->id; handler++) {
615 if (handler->id == pdu->pdu_id)
619 if (handler->id != pdu->pdu_id) {
620 pdu->pdu_id = AVRCP_GENERAL_REJECT;
621 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
625 if (!handler->func) {
626 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
630 ret = handler->func(session, transaction, pdu->params_len, pdu->params,
631 session->control_data);
638 pdu->params[0] = errno2status(ret);
642 pdu->params_len = htons(ret);
644 return AVRCP_BROWSING_HEADER_LENGTH + ret;
647 pdu->params_len = htons(1);
649 return AVRCP_BROWSING_HEADER_LENGTH + 1;
652 static void browsing_disconnect_cb(void *data)
654 struct avrcp *session = data;
656 session->browsing_id = 0;
659 int avrcp_connect_browsing(struct avrcp *session, int fd, size_t imtu,
664 err = avctp_connect_browsing(session->conn, fd, imtu, omtu);
668 session->browsing_id = avctp_register_browsing_pdu_handler(
672 browsing_disconnect_cb);
677 void avrcp_set_destroy_cb(struct avrcp *session, avrcp_destroy_cb_t cb,
680 session->destroy = cb;
681 session->destroy_data = user_data;
684 static ssize_t get_capabilities(struct avrcp *session, uint8_t transaction,
685 uint16_t params_len, uint8_t *params,
688 struct avrcp_player *player = user_data;
689 struct get_capabilities_req *req;
691 if (!params || params_len != sizeof(*req))
694 req = (void *) params;
699 hton24(&req->params[1], IEEEID_BTSIG);
701 case CAP_EVENTS_SUPPORTED:
702 if (!player->ind || !player->ind->get_capabilities)
704 return player->ind->get_capabilities(session, transaction,
711 static ssize_t list_attributes(struct avrcp *session, uint8_t transaction,
712 uint16_t params_len, uint8_t *params,
715 struct avrcp_player *player = user_data;
719 if (!player->ind || !player->ind->list_attributes)
722 return player->ind->list_attributes(session, transaction,
726 static bool check_attributes(uint8_t number, const uint8_t *attrs)
730 for (i = 0; i < number; i++) {
731 if (attrs[i] > AVRCP_ATTRIBUTE_LAST ||
732 attrs[i] == AVRCP_ATTRIBUTE_ILEGAL)
739 static ssize_t get_attribute_text(struct avrcp *session, uint8_t transaction,
740 uint16_t params_len, uint8_t *params,
743 struct avrcp_player *player = user_data;
744 struct get_attribute_text_req *req;
748 if (!player->ind || !player->ind->get_attribute_text)
751 if (!params || params_len < sizeof(*req))
754 req = (void *) params;
755 if (params_len != sizeof(*req) + req->number)
758 if (!check_attributes(req->number, req->attrs))
761 return player->ind->get_attribute_text(session, transaction,
762 req->number, req->attrs,
766 static ssize_t list_values(struct avrcp *session, uint8_t transaction,
767 uint16_t params_len, uint8_t *params,
770 struct avrcp_player *player = user_data;
771 struct list_values_req *req;
775 if (!params || params_len != sizeof(*req))
778 req = (void *) params;
779 if (req->attr > AVRCP_ATTRIBUTE_LAST ||
780 req->attr == AVRCP_ATTRIBUTE_ILEGAL)
783 if (!player->ind || !player->ind->list_values)
786 return player->ind->list_values(session, transaction, req->attr,
790 static bool check_value(uint8_t attr, uint8_t number, const uint8_t *values)
794 for (i = 0; i < number; i++) {
795 /* Check for invalid value */
797 case AVRCP_ATTRIBUTE_EQUALIZER:
798 if (values[i] < AVRCP_EQUALIZER_OFF ||
799 values[i] > AVRCP_EQUALIZER_ON)
802 case AVRCP_ATTRIBUTE_REPEAT_MODE:
803 if (values[i] < AVRCP_REPEAT_MODE_OFF ||
804 values[i] > AVRCP_REPEAT_MODE_GROUP)
807 case AVRCP_ATTRIBUTE_SHUFFLE:
808 if (values[i] < AVRCP_SHUFFLE_OFF ||
809 values[i] > AVRCP_SHUFFLE_GROUP)
812 case AVRCP_ATTRIBUTE_SCAN:
813 if (values[i] < AVRCP_SCAN_OFF ||
814 values[i] > AVRCP_SCAN_GROUP)
823 static ssize_t get_value_text(struct avrcp *session, uint8_t transaction,
824 uint16_t params_len, uint8_t *params,
827 struct avrcp_player *player = user_data;
828 struct get_value_text_req *req;
832 if (!player->ind || !player->ind->get_value_text)
835 if (!params || params_len < sizeof(*req))
838 req = (void *) params;
839 if (params_len != sizeof(*req) + req->number)
842 if (req->number > AVRCP_ATTRIBUTE_LAST ||
843 req->number == AVRCP_ATTRIBUTE_ILEGAL)
846 if (!check_value(req->attr, req->number, req->values))
849 return player->ind->get_value_text(session, transaction, params[0],
850 params[1], ¶ms[2],
854 static ssize_t get_value(struct avrcp *session, uint8_t transaction,
855 uint16_t params_len, uint8_t *params,
858 struct avrcp_player *player = user_data;
859 struct get_value_req *req;
863 if (!player->ind || !player->ind->get_value)
866 if (!params || params_len < sizeof(*req))
869 req = (void *) params;
870 if (params_len < sizeof(*req) + req->number)
873 if (!check_attributes(req->number, req->attrs))
876 return player->ind->get_value(session, transaction, params[0],
877 ¶ms[1], player->user_data);
880 static ssize_t set_value(struct avrcp *session, uint8_t transaction,
881 uint16_t params_len, uint8_t *params,
884 struct avrcp_player *player = user_data;
885 struct set_value_req *req;
886 uint8_t attrs[AVRCP_ATTRIBUTE_LAST];
887 uint8_t values[AVRCP_ATTRIBUTE_LAST];
892 if (!player->ind || !player->ind->set_value)
895 if (!params || params_len < sizeof(*req))
898 req = (void *) params;
899 if (params_len < sizeof(*req) + req->number * sizeof(*req->values))
902 for (i = 0; i < req->number; i++) {
903 attrs[i] = req->values[i].attr;
904 values[i] = req->values[i].value;
906 if (!check_value(attrs[i], 1, &values[i]))
910 return player->ind->set_value(session, transaction, req->number,
911 attrs, values, player->user_data);
914 static ssize_t get_play_status(struct avrcp *session, uint8_t transaction,
915 uint16_t params_len, uint8_t *params,
918 struct avrcp_player *player = user_data;
922 if (!player->ind || !player->ind->get_play_status)
925 return player->ind->get_play_status(session, transaction,
929 static bool parse_attributes(uint32_t *params, uint16_t params_len,
930 uint8_t number, uint32_t *attrs)
934 for (i = 0; i < number && params_len >= sizeof(*attrs); i++,
935 params_len -= sizeof(*attrs)) {
936 attrs[i] = be32_to_cpu(params[i]);
938 if (attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL ||
939 attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST)
946 static ssize_t get_element_attributes(struct avrcp *session,
952 struct avrcp_player *player = user_data;
953 struct get_element_attributes_req *req;
955 uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
959 if (!player->ind || !player->ind->get_element_attributes)
962 req = (void *) params;
963 if (!params || params_len < sizeof(*req))
966 if (!parse_attributes(req->attrs, params_len - sizeof(*req),
970 uid = get_be64(params);
972 return player->ind->get_element_attributes(session, transaction, uid,
977 static ssize_t register_notification(struct avrcp *session, uint8_t transaction,
978 uint16_t params_len, uint8_t *params,
981 struct avrcp_player *player = user_data;
982 struct register_notification_req *req;
987 if (!player->ind || !player->ind->register_notification)
990 if (!params || params_len != sizeof(*req))
993 req = (void *) params;
995 interval = be32_to_cpu(req->interval);
997 return player->ind->register_notification(session, transaction,
998 req->event, interval,
1002 static ssize_t set_volume(struct avrcp *session, uint8_t transaction,
1003 uint16_t params_len, uint8_t *params,
1006 struct avrcp_player *player = user_data;
1007 struct set_volume_req *req;
1012 if (!player->ind || !player->ind->set_volume)
1015 if (!params || params_len != sizeof(volume))
1018 req = (void *) params;
1020 volume = req->value & 0x7f;
1022 return player->ind->set_volume(session, transaction, volume,
1026 static ssize_t set_addressed(struct avrcp *session, uint8_t transaction,
1027 uint16_t params_len, uint8_t *params,
1030 struct avrcp_player *player = user_data;
1031 struct set_addressed_req *req;
1036 if (!player->ind || !player->ind->set_addressed)
1039 if (!params || params_len != sizeof(*req))
1042 req = (void *) params;
1044 id = be16_to_cpu(req->id);
1046 return player->ind->set_addressed(session, transaction, id,
1050 static void continuing_new(struct avrcp *session, uint8_t pdu_id,
1051 const struct iovec *iov, int iov_cnt,
1054 struct avrcp_continuing *continuing;
1058 continuing = g_new0(struct avrcp_continuing, 1);
1059 continuing->pdu_id = pdu_id;
1061 for (i = 0; i < iov_cnt; i++) {
1062 if (i == 0 && offset) {
1063 len += iov[i].iov_len - offset;
1067 len += iov[i].iov_len;
1070 continuing->pdu.iov_base = g_malloc0(len);
1072 DBG("len %zu", len);
1074 for (i = 0; i < iov_cnt; i++) {
1075 if (i == 0 && offset) {
1076 memcpy(continuing->pdu.iov_base,
1077 iov[i].iov_base + offset,
1078 iov[i].iov_len - offset);
1079 continuing->pdu.iov_len += iov[i].iov_len - offset;
1083 memcpy(continuing->pdu.iov_base + continuing->pdu.iov_len,
1084 iov[i].iov_base, iov[i].iov_len);
1085 continuing->pdu.iov_len += iov[i].iov_len;
1088 session->continuing = continuing;
1091 static int avrcp_send_internal(struct avrcp *session, uint8_t transaction,
1092 uint8_t code, uint8_t subunit,
1093 uint8_t pdu_id, uint8_t type,
1094 const struct iovec *iov, int iov_cnt)
1096 struct iovec pdu[iov_cnt + 1];
1097 struct avrcp_header hdr;
1101 * If a receiver receives a start fragment or non-fragmented AVRCP
1102 * Specific AV/C message when it already has an incomplete fragment
1103 * from that sender then the receiver shall consider the first PDU
1106 if (session->continuing) {
1107 continuing_free(session->continuing);
1108 session->continuing = NULL;
1111 memset(&hdr, 0, sizeof(hdr));
1113 pdu[0].iov_base = &hdr;
1114 pdu[0].iov_len = sizeof(hdr);
1116 hdr.packet_type = type;
1118 for (i = 0; i < iov_cnt; i++) {
1119 pdu[i + 1].iov_base = iov[i].iov_base;
1121 if (pdu[0].iov_len + hdr.params_len + iov[i].iov_len <=
1122 session->control_mtu) {
1123 pdu[i + 1].iov_len = iov[i].iov_len;
1124 hdr.params_len += iov[i].iov_len;
1125 if (hdr.packet_type != AVRCP_PACKET_TYPE_SINGLE)
1126 hdr.packet_type = AVRCP_PACKET_TYPE_END;
1131 * Only send what can fit and store the remaining in the
1134 pdu[i + 1].iov_len = session->control_mtu -
1135 (pdu[0].iov_len + hdr.params_len);
1136 hdr.params_len += pdu[i + 1].iov_len;
1138 continuing_new(session, pdu_id, &iov[i], iov_cnt - i,
1139 pdu[i + 1].iov_len);
1141 hdr.packet_type = hdr.packet_type != AVRCP_PACKET_TYPE_SINGLE ?
1142 AVRCP_PACKET_TYPE_CONTINUING :
1143 AVRCP_PACKET_TYPE_START;
1147 hton24(hdr.company_id, IEEEID_BTSIG);
1148 hdr.pdu_id = pdu_id;
1149 hdr.params_len = htons(hdr.params_len);
1151 return avctp_send_vendor(session->conn, transaction, code, subunit,
1155 static ssize_t request_continuing(struct avrcp *session, uint8_t transaction,
1156 uint16_t params_len, uint8_t *params,
1164 if (!params || params_len != 1 || !session->continuing ||
1165 session->continuing->pdu_id != params[0])
1168 iov.iov_base = session->continuing->pdu.iov_base;
1169 iov.iov_len = session->continuing->pdu.iov_len;
1171 DBG("len %zu", iov.iov_len);
1173 session->continuing->pdu.iov_base = NULL;
1175 err = avrcp_send_internal(session, transaction, AVC_CTYPE_STABLE,
1176 AVC_SUBUNIT_PANEL, params[0],
1177 AVRCP_PACKET_TYPE_CONTINUING, &iov, 1);
1179 g_free(iov.iov_base);
1187 static ssize_t abort_continuing(struct avrcp *session, uint8_t transaction,
1188 uint16_t params_len, uint8_t *params,
1193 if (!params || params_len != 1 || !session->continuing)
1196 continuing_free(session->continuing);
1197 session->continuing = NULL;
1199 avrcp_send_internal(session, transaction, AVC_CTYPE_ACCEPTED,
1200 AVC_SUBUNIT_PANEL, AVRCP_ABORT_CONTINUING,
1201 AVRCP_PACKET_TYPE_SINGLE, NULL, 0);
1206 static const struct avrcp_control_handler player_handlers[] = {
1207 { AVRCP_GET_CAPABILITIES,
1208 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1210 { AVRCP_LIST_PLAYER_ATTRIBUTES,
1211 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1213 { AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
1214 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1215 get_attribute_text },
1216 { AVRCP_LIST_PLAYER_VALUES,
1217 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1219 { AVRCP_GET_PLAYER_VALUE_TEXT,
1220 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1222 { AVRCP_GET_CURRENT_PLAYER_VALUE,
1223 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1225 { AVRCP_SET_PLAYER_VALUE,
1226 AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
1228 { AVRCP_GET_PLAY_STATUS,
1229 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1231 { AVRCP_GET_ELEMENT_ATTRIBUTES,
1232 AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1233 get_element_attributes },
1234 { AVRCP_REGISTER_NOTIFICATION,
1235 AVC_CTYPE_NOTIFY, AVC_CTYPE_INTERIM,
1236 register_notification },
1237 { AVRCP_SET_ABSOLUTE_VOLUME,
1238 AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
1240 { AVRCP_SET_ADDRESSED_PLAYER,
1241 AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
1243 { AVRCP_REQUEST_CONTINUING,
1244 AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
1245 request_continuing },
1246 { AVRCP_ABORT_CONTINUING,
1247 AVC_CTYPE_CONTROL, AVC_CTYPE_ACCEPTED,
1252 static void avrcp_set_control_handlers(struct avrcp *session,
1253 const struct avrcp_control_handler *handlers,
1256 session->control_handlers = handlers;
1257 session->control_data = user_data;
1260 static ssize_t set_browsed(struct avrcp *session, uint8_t transaction,
1261 uint16_t params_len, uint8_t *params,
1264 struct avrcp_player *player = user_data;
1265 struct set_browsed_req *req;
1270 if (!player->ind || !player->ind->set_browsed)
1273 if (!params || params_len != sizeof(*req))
1276 req = (void *) params;
1278 id = be16_to_cpu(req->id);
1280 return player->ind->set_browsed(session, transaction, id,
1284 static ssize_t get_folder_items(struct avrcp *session, uint8_t transaction,
1285 uint16_t params_len, uint8_t *params,
1288 struct avrcp_player *player = user_data;
1289 struct get_folder_items_req *req;
1290 uint32_t start, end;
1292 uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
1297 if (!player->ind || !player->ind->get_folder_items)
1300 if (!params || params_len < sizeof(*req))
1303 req = (void *) params;
1305 if (req->scope > AVRCP_MEDIA_NOW_PLAYING)
1308 start = be32_to_cpu(req->start);
1309 end = be32_to_cpu(req->end);
1314 number = be16_to_cpu(req->number);
1316 for (i = 0; i < number; i++) {
1317 attrs[i] = be32_to_cpu(req->attrs[i]);
1319 if (attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL ||
1320 attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST)
1324 return player->ind->get_folder_items(session, transaction, req->scope,
1325 start, end, number, attrs,
1329 static ssize_t change_path(struct avrcp *session, uint8_t transaction,
1330 uint16_t params_len, uint8_t *params,
1333 struct avrcp_player *player = user_data;
1334 struct change_path_req *req;
1340 if (!player->ind || !player->ind->change_path)
1343 if (!params || params_len < sizeof(*req))
1346 req = (void *) params;
1348 counter = be16_to_cpu(req->counter);
1349 uid = be64_to_cpu(req->uid);
1351 return player->ind->change_path(session, transaction, counter,
1352 req->direction, uid, player->user_data);
1355 static ssize_t get_item_attributes(struct avrcp *session, uint8_t transaction,
1356 uint16_t params_len, uint8_t *params,
1359 struct avrcp_player *player = user_data;
1360 struct get_item_attributes_req *req;
1363 uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
1368 if (!player->ind || !player->ind->get_item_attributes)
1371 if (!params || params_len < sizeof(*req))
1374 req = (void *) params;
1376 if (req->scope > AVRCP_MEDIA_NOW_PLAYING)
1379 uid = be64_to_cpu(req->uid);
1380 counter = be16_to_cpu(req->counter);
1382 for (i = 0; i < req->number; i++) {
1383 attrs[i] = be32_to_cpu(req->attrs[i]);
1385 if (attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL ||
1386 attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST)
1390 return player->ind->get_item_attributes(session, transaction,
1391 req->scope, uid, counter,
1396 static ssize_t play_item(struct avrcp *session, uint8_t transaction,
1397 uint16_t params_len, uint8_t *params,
1400 struct avrcp_player *player = user_data;
1401 struct play_item_req *req;
1407 if (!player->ind || !player->ind->play_item)
1410 if (!params || params_len < sizeof(*req))
1413 req = (void *) params;
1415 if (req->scope > AVRCP_MEDIA_NOW_PLAYING)
1418 uid = be64_to_cpu(req->uid);
1419 counter = be16_to_cpu(req->counter);
1421 return player->ind->play_item(session, transaction, req->scope, uid,
1422 counter, player->user_data);
1425 static ssize_t search(struct avrcp *session, uint8_t transaction,
1426 uint16_t params_len, uint8_t *params,
1429 struct avrcp_player *player = user_data;
1430 struct search_req *req;
1437 if (!player->ind || !player->ind->search)
1440 if (!params || params_len < sizeof(*req))
1443 req = (void *) params;
1445 len = be16_to_cpu(req->len);
1449 string = strndup(req->string, len);
1451 ret = player->ind->search(session, transaction, string,
1459 static ssize_t add_to_now_playing(struct avrcp *session, uint8_t transaction,
1460 uint16_t params_len, uint8_t *params,
1463 struct avrcp_player *player = user_data;
1464 struct add_to_now_playing_req *req;
1470 if (!player->ind || !player->ind->add_to_now_playing)
1473 if (!params || params_len < sizeof(*req))
1476 req = (void *) params;
1478 if (req->scope > AVRCP_MEDIA_NOW_PLAYING)
1481 uid = be64_to_cpu(req->uid);
1482 counter = be16_to_cpu(req->counter);
1484 return player->ind->add_to_now_playing(session, transaction, req->scope,
1489 static const struct avrcp_browsing_handler browsing_handlers[] = {
1490 { AVRCP_SET_BROWSED_PLAYER, set_browsed },
1491 { AVRCP_GET_FOLDER_ITEMS, get_folder_items },
1492 { AVRCP_CHANGE_PATH, change_path },
1493 { AVRCP_GET_ITEM_ATTRIBUTES, get_item_attributes },
1494 { AVRCP_PLAY_ITEM, play_item },
1495 { AVRCP_SEARCH, search },
1496 { AVRCP_ADD_TO_NOW_PLAYING, add_to_now_playing },
1500 static void avrcp_set_browsing_handlers(struct avrcp *session,
1501 const struct avrcp_browsing_handler *handlers,
1504 session->browsing_handlers = handlers;
1505 session->browsing_data = user_data;
1508 void avrcp_register_player(struct avrcp *session,
1509 const struct avrcp_control_ind *ind,
1510 const struct avrcp_control_cfm *cfm,
1513 struct avrcp_player *player;
1515 player = g_new0(struct avrcp_player, 1);
1518 player->user_data = user_data;
1520 avrcp_set_control_handlers(session, player_handlers, player);
1521 avrcp_set_browsing_handlers(session, browsing_handlers, player);
1522 session->player = player;
1525 void avrcp_set_passthrough_handlers(struct avrcp *session,
1526 const struct avrcp_passthrough_handler *handlers,
1529 session->passthrough_handlers = handlers;
1530 session->passthrough_data = user_data;
1533 int avrcp_init_uinput(struct avrcp *session, const char *name,
1534 const char *address)
1536 return avctp_init_uinput(session->conn, name, address);
1539 int avrcp_send(struct avrcp *session, uint8_t transaction, uint8_t code,
1540 uint8_t subunit, uint8_t pdu_id,
1541 const struct iovec *iov, int iov_cnt)
1543 return avrcp_send_internal(session, transaction, code, subunit, pdu_id,
1544 AVRCP_PACKET_TYPE_SINGLE, iov, iov_cnt);
1547 static int status2errno(uint8_t status)
1550 case AVRCP_STATUS_INVALID_COMMAND:
1552 case AVRCP_STATUS_INVALID_PARAM:
1554 case AVRCP_STATUS_SUCCESS:
1556 case AVRCP_STATUS_NOT_DIRECTORY:
1558 case AVRCP_STATUS_INVALID_SCOPE:
1560 case AVRCP_STATUS_OUT_OF_BOUNDS:
1562 case AVRCP_STATUS_INTERNAL_ERROR:
1563 case AVRCP_STATUS_INVALID_PLAYER_ID:
1564 case AVRCP_STATUS_PLAYER_NOT_BROWSABLE:
1565 case AVRCP_STATUS_NO_AVAILABLE_PLAYERS:
1566 case AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED:
1573 static int parse_status(struct avrcp_header *pdu)
1575 if (pdu->params_len < 1)
1578 return status2errno(pdu->params[0]);
1581 static int parse_browsing_status(struct avrcp_browsing_header *pdu)
1583 if (pdu->params_len < 1)
1586 return status2errno(pdu->params[0]);
1589 static int avrcp_send_req(struct avrcp *session, uint8_t code, uint8_t subunit,
1590 uint8_t pdu_id, const struct iovec *iov,
1591 int iov_cnt, avctp_rsp_cb func,
1594 struct iovec pdu[iov_cnt + 1];
1595 struct avrcp_header hdr;
1598 memset(&hdr, 0, sizeof(hdr));
1600 pdu[0].iov_base = &hdr;
1601 pdu[0].iov_len = sizeof(hdr);
1603 for (i = 0; i < iov_cnt; i++) {
1604 pdu[i + 1].iov_base = iov[i].iov_base;
1605 pdu[i + 1].iov_len = iov[i].iov_len;
1606 hdr.params_len += iov[i].iov_len;
1609 hton24(hdr.company_id, IEEEID_BTSIG);
1610 hdr.pdu_id = pdu_id;
1611 hdr.packet_type = AVRCP_PACKET_TYPE_SINGLE;
1612 hdr.params_len = htons(hdr.params_len);
1614 return avctp_send_vendor_req(session->conn, code, subunit, pdu,
1615 iov_cnt + 1, func, user_data);
1618 static int avrcp_send_browsing_req(struct avrcp *session, uint8_t pdu_id,
1619 const struct iovec *iov, int iov_cnt,
1620 avctp_browsing_rsp_cb func,
1623 struct iovec pdu[iov_cnt + 1];
1624 struct avrcp_browsing_header hdr;
1627 memset(&hdr, 0, sizeof(hdr));
1629 for (i = 0; i < iov_cnt; i++) {
1630 pdu[i + 1].iov_base = iov[i].iov_base;
1631 pdu[i + 1].iov_len = iov[i].iov_len;
1632 hdr.params_len += iov[i].iov_len;
1635 hdr.pdu_id = pdu_id;
1636 hdr.params_len = htons(hdr.params_len);
1638 pdu[0].iov_base = &hdr;
1639 pdu[0].iov_len = sizeof(hdr);
1641 return avctp_send_browsing_req(session->conn, pdu, iov_cnt + 1,
1645 static int avrcp_send_browsing(struct avrcp *session, uint8_t transaction,
1646 uint8_t pdu_id, const struct iovec *iov,
1649 struct iovec pdu[iov_cnt + 1];
1650 struct avrcp_browsing_header hdr;
1653 memset(&hdr, 0, sizeof(hdr));
1655 for (i = 0; i < iov_cnt; i++) {
1656 pdu[i + 1].iov_base = iov[i].iov_base;
1657 pdu[i + 1].iov_len = iov[i].iov_len;
1658 hdr.params_len += iov[i].iov_len;
1661 hdr.pdu_id = pdu_id;
1662 hdr.params_len = htons(hdr.params_len);
1664 pdu[0].iov_base = &hdr;
1665 pdu[0].iov_len = sizeof(hdr);
1667 return avctp_send_browsing(session->conn, transaction, pdu,
1671 static gboolean get_capabilities_rsp(struct avctp *conn,
1672 uint8_t code, uint8_t subunit,
1673 uint8_t *operands, size_t operand_count,
1676 struct avrcp *session = user_data;
1677 struct avrcp_player *player = session->player;
1678 struct avrcp_header *pdu;
1679 struct get_capabilities_rsp *rsp;
1681 uint8_t *params = NULL;
1686 if (!player || !player->cfm || !player->cfm->get_capabilities)
1689 pdu = parse_pdu(operands, operand_count);
1695 if (code == AVC_CTYPE_REJECTED) {
1696 err = parse_status(pdu);
1700 if (pdu->params_len < sizeof(*rsp)) {
1705 rsp = (void *) pdu->params;
1708 case CAP_COMPANY_ID:
1709 case CAP_EVENTS_SUPPORTED:
1716 if (rsp->number > 0) {
1717 number = rsp->number;
1718 params = rsp->params;
1724 player->cfm->get_capabilities(session, err, number, params,
1731 int avrcp_get_capabilities(struct avrcp *session, uint8_t param)
1734 struct get_capabilities_req req;
1738 iov.iov_base = &req;
1739 iov.iov_len = sizeof(req);
1741 return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
1742 AVRCP_GET_CAPABILITIES, &iov, 1,
1743 get_capabilities_rsp, session);
1746 static gboolean register_notification_rsp(struct avctp *conn,
1747 uint8_t code, uint8_t subunit,
1748 uint8_t *operands, size_t operand_count,
1751 struct avrcp *session = user_data;
1752 struct avrcp_player *player = session->player;
1753 struct avrcp_header *pdu;
1754 struct register_notification_rsp *rsp;
1756 uint16_t value16, value16_2[2];
1759 uint8_t *params = NULL;
1764 if (!player || !player->cfm || !player->cfm->register_notification)
1767 pdu = parse_pdu(operands, operand_count);
1773 if (code == AVC_CTYPE_REJECTED) {
1774 err = parse_status(pdu);
1778 if (pdu->params_len < sizeof(*rsp)) {
1783 rsp = (void *) pdu->params;
1786 if (event > AVRCP_EVENT_LAST) {
1792 case AVRCP_EVENT_STATUS_CHANGED:
1793 if (pdu->params_len != sizeof(*rsp) + sizeof(uint8_t)) {
1799 case AVRCP_EVENT_VOLUME_CHANGED:
1800 if (pdu->params_len != sizeof(*rsp) + sizeof(uint8_t)) {
1807 case AVRCP_EVENT_TRACK_CHANGED:
1808 if (pdu->params_len != sizeof(*rsp) + sizeof(value64)) {
1812 value64 = get_be64(rsp->data);
1813 params = (uint8_t *) &value64;
1815 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
1816 if (pdu->params_len != sizeof(*rsp) + sizeof(value32)) {
1820 value32 = get_be32(rsp->data);
1821 params = (uint8_t *) &value32;
1823 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
1824 if (pdu->params_len < sizeof(*rsp) + sizeof(value16_2)) {
1828 value16_2[0] = get_be16(rsp->data);
1829 value16_2[1] = get_be16(rsp->data + 2);
1830 params = (uint8_t *) value16_2;
1832 case AVRCP_EVENT_SETTINGS_CHANGED:
1833 if (pdu->params_len < sizeof(*rsp) + sizeof(uint8_t)) {
1839 case AVRCP_EVENT_UIDS_CHANGED:
1840 if (pdu->params_len < sizeof(*rsp) + sizeof(value16)) {
1844 value16 = get_be16(rsp->data);
1845 params = (uint8_t *) &value16;
1852 return player->cfm->register_notification(session, err, code, event,
1853 params, player->user_data);
1856 int avrcp_register_notification(struct avrcp *session, uint8_t event,
1860 struct register_notification_req req;
1862 if (event > AVRCP_EVENT_LAST)
1866 req.interval = cpu_to_be32(interval);
1868 iov.iov_base = &req;
1869 iov.iov_len = sizeof(req);
1871 return avrcp_send_req(session, AVC_CTYPE_NOTIFY, AVC_SUBUNIT_PANEL,
1872 AVRCP_REGISTER_NOTIFICATION, &iov, 1,
1873 register_notification_rsp, session);
1876 static gboolean list_attributes_rsp(struct avctp *conn,
1877 uint8_t code, uint8_t subunit,
1878 uint8_t *operands, size_t operand_count,
1881 struct avrcp *session = user_data;
1882 struct avrcp_player *player = session->player;
1883 struct avrcp_header *pdu = (void *) operands;
1884 struct list_attributes_rsp *rsp;
1886 uint8_t *attrs = NULL;
1891 if (!player || !player->cfm || !player->cfm->list_attributes)
1894 pdu = parse_pdu(operands, operand_count);
1900 if (code == AVC_CTYPE_REJECTED) {
1901 err = parse_status(pdu);
1905 rsp = (void *) pdu->params;
1907 if (pdu->params_len < sizeof(*rsp)) {
1912 number = rsp->number;
1914 attrs = rsp->params;
1919 player->cfm->list_attributes(session, err, number, attrs,
1925 int avrcp_list_player_attributes(struct avrcp *session)
1927 return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
1928 AVRCP_LIST_PLAYER_ATTRIBUTES, NULL, 0,
1929 list_attributes_rsp, session);
1932 static int parse_text_rsp(struct avrcp_header *pdu, uint8_t *number,
1933 uint8_t *attrs, char **text)
1936 uint16_t params_len;
1939 if (pdu->params_len < 1)
1942 *number = pdu->params[0];
1943 if (*number > AVRCP_ATTRIBUTE_LAST) {
1948 params_len = pdu->params_len - 1;
1949 for (i = 0, ptr = &pdu->params[1]; i < *number && params_len > 0; i++) {
1950 struct text_value *val;
1952 if (params_len < sizeof(*val))
1957 attrs[i] = val->attr;
1959 params_len -= sizeof(*val);
1960 ptr += sizeof(*val);
1962 if (val->len > params_len)
1966 text[i] = g_strndup(val->data, val->len);
1967 params_len -= val->len;
1978 for (i -= 1; i >= 0; i--)
1986 static gboolean get_attribute_text_rsp(struct avctp *conn,
1987 uint8_t code, uint8_t subunit,
1988 uint8_t *operands, size_t operand_count,
1991 struct avrcp *session = user_data;
1992 struct avrcp_player *player = session->player;
1993 struct avrcp_header *pdu;
1995 uint8_t attrs[AVRCP_ATTRIBUTE_LAST];
1996 char *text[AVRCP_ATTRIBUTE_LAST];
2001 if (!player || !player->cfm || !player->cfm->get_attribute_text)
2004 pdu = parse_pdu(operands, operand_count);
2010 if (code == AVC_CTYPE_REJECTED) {
2011 err = parse_status(pdu);
2015 err = parse_text_rsp(pdu, &number, attrs, text);
2018 player->cfm->get_attribute_text(session, err, number, attrs, text,
2024 int avrcp_get_player_attribute_text(struct avrcp *session, uint8_t number,
2027 struct iovec iov[2];
2029 if (!number || number > AVRCP_ATTRIBUTE_LAST)
2032 iov[0].iov_base = &number;
2033 iov[0].iov_len = sizeof(number);
2035 iov[1].iov_base = attrs;
2036 iov[1].iov_len = number;
2038 return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
2039 AVRCP_GET_PLAYER_ATTRIBUTE_TEXT, iov, 2,
2040 get_attribute_text_rsp, session);
2043 static gboolean list_values_rsp(struct avctp *conn,
2044 uint8_t code, uint8_t subunit,
2045 uint8_t *operands, size_t operand_count,
2048 struct avrcp *session = user_data;
2049 struct avrcp_player *player = session->player;
2050 struct avrcp_header *pdu;
2051 struct list_values_rsp *rsp;
2053 uint8_t *values = NULL;
2058 if (!player || !player->cfm || !player->cfm->list_values)
2061 pdu = parse_pdu(operands, operand_count);
2067 if (code == AVC_CTYPE_REJECTED) {
2068 err = parse_status(pdu);
2072 if (pdu->params_len < sizeof(*rsp)) {
2077 rsp = (void *) pdu->params;
2079 if (rsp->number > 0) {
2080 number = rsp->number;
2081 values = rsp->params;
2087 player->cfm->list_values(session, err, number, values,
2093 int avrcp_list_player_values(struct avrcp *session, uint8_t attr)
2097 iov.iov_base = &attr;
2098 iov.iov_len = sizeof(attr);
2100 return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
2101 AVRCP_LIST_PLAYER_VALUES, &iov, 1,
2102 list_values_rsp, session);
2105 static gboolean get_value_text_rsp(struct avctp *conn,
2106 uint8_t code, uint8_t subunit,
2107 uint8_t *operands, size_t operand_count,
2110 struct avrcp *session = user_data;
2111 struct avrcp_player *player = session->player;
2112 struct avrcp_header *pdu;
2114 uint8_t values[AVRCP_ATTRIBUTE_LAST];
2115 char *text[AVRCP_ATTRIBUTE_LAST];
2120 if (!player || !player->cfm || !player->cfm->get_value_text)
2123 pdu = parse_pdu(operands, operand_count);
2129 if (code == AVC_CTYPE_REJECTED) {
2130 err = parse_status(pdu);
2134 err = parse_text_rsp(pdu, &number, values, text);
2137 player->cfm->get_value_text(session, err, number, values, text,
2143 int avrcp_get_player_value_text(struct avrcp *session, uint8_t attr,
2144 uint8_t number, uint8_t *values)
2146 struct iovec iov[2];
2147 struct get_value_text_req req;
2153 req.number = number;
2155 iov[0].iov_base = &req;
2156 iov[0].iov_len = sizeof(req);
2158 iov[1].iov_base = values;
2159 iov[1].iov_len = number;
2161 return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
2162 AVRCP_GET_PLAYER_VALUE_TEXT, iov, 2,
2163 get_value_text_rsp, session);
2166 static int parse_value(struct avrcp_header *pdu, uint8_t *number,
2167 uint8_t *attrs, uint8_t *values)
2170 struct value_rsp *rsp;
2172 if (pdu->params_len < sizeof(*rsp))
2175 rsp = (void *) pdu->params;
2178 * Check if PDU is big enough to hold the number of (attribute, value)
2181 if (rsp->number > AVRCP_ATTRIBUTE_LAST ||
2182 sizeof(*rsp) + rsp->number * 2 != pdu->params_len) {
2187 for (i = 0; i < rsp->number; i++) {
2188 attrs[i] = rsp->values[i].attr;
2189 values[i] = rsp->values[i].value;
2192 *number = rsp->number;
2197 static gboolean get_value_rsp(struct avctp *conn,
2198 uint8_t code, uint8_t subunit,
2199 uint8_t *operands, size_t operand_count,
2202 struct avrcp *session = user_data;
2203 struct avrcp_player *player = session->player;
2204 struct avrcp_header *pdu;
2206 uint8_t attrs[AVRCP_ATTRIBUTE_LAST];
2207 uint8_t values[AVRCP_ATTRIBUTE_LAST];
2212 if (!player || !player->cfm || !player->cfm->get_value)
2215 pdu = parse_pdu(operands, operand_count);
2221 if (code == AVC_CTYPE_REJECTED) {
2222 err = parse_status(pdu);
2226 err = parse_value(pdu, &number, attrs, values);
2229 player->cfm->get_value(session, err, number, attrs, values,
2235 int avrcp_get_current_player_value(struct avrcp *session, uint8_t number,
2239 struct iovec iov[2];
2241 if (number > AVRCP_ATTRIBUTE_LAST)
2244 iov[0].iov_base = &number;
2245 iov[0].iov_len = sizeof(number);
2247 iov[1].iov_base = attrs;
2248 iov[1].iov_len = number;
2250 return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
2251 AVRCP_GET_CURRENT_PLAYER_VALUE, iov, 2,
2252 get_value_rsp, session);
2255 static gboolean set_value_rsp(struct avctp *conn,
2256 uint8_t code, uint8_t subunit,
2257 uint8_t *operands, size_t operand_count,
2260 struct avrcp *session = user_data;
2261 struct avrcp_player *player = session->player;
2262 struct avrcp_header *pdu;
2267 if (!player || !player->cfm || !player->cfm->set_value)
2270 pdu = parse_pdu(operands, operand_count);
2276 if (code == AVC_CTYPE_REJECTED) {
2277 err = parse_status(pdu);
2284 player->cfm->set_value(session, err, player->user_data);
2289 int avrcp_set_player_value(struct avrcp *session, uint8_t number,
2290 uint8_t *attrs, uint8_t *values)
2292 struct iovec iov[2];
2293 struct attr_value val[AVRCP_ATTRIBUTE_LAST];
2296 if (number > AVRCP_ATTRIBUTE_LAST)
2299 iov[0].iov_base = &number;
2300 iov[0].iov_len = sizeof(number);
2302 for (i = 0; i < number; i++) {
2303 val[i].attr = attrs[i];
2304 val[i].value = values[i];
2307 iov[1].iov_base = val;
2308 iov[1].iov_len = sizeof(*val) * number;
2310 return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
2311 AVRCP_SET_PLAYER_VALUE, iov, 2,
2312 set_value_rsp, session);
2315 static gboolean get_play_status_rsp(struct avctp *conn,
2316 uint8_t code, uint8_t subunit,
2317 uint8_t *operands, size_t operand_count,
2320 struct avrcp *session = user_data;
2321 struct avrcp_player *player = session->player;
2322 struct avrcp_header *pdu;
2323 struct get_play_status_rsp *rsp;
2325 uint32_t position = 0;
2326 uint32_t duration = 0;
2331 if (!player || !player->cfm || !player->cfm->get_play_status)
2334 pdu = parse_pdu(operands, operand_count);
2340 if (code == AVC_CTYPE_REJECTED) {
2341 err = parse_status(pdu);
2345 if (pdu->params_len < sizeof(*rsp)) {
2350 rsp = (void *) pdu->params;
2352 duration = be32_to_cpu(rsp->duration);
2353 position = be32_to_cpu(rsp->position);
2354 status = rsp->status;
2358 player->cfm->get_play_status(session, err, status, position, duration,
2364 int avrcp_get_play_status(struct avrcp *session)
2366 return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
2367 AVRCP_GET_PLAY_STATUS, NULL, 0,
2368 get_play_status_rsp, session);
2371 static gboolean set_volume_rsp(struct avctp *conn,
2372 uint8_t code, uint8_t subunit,
2373 uint8_t *operands, size_t operand_count,
2376 struct avrcp *session = user_data;
2377 struct avrcp_player *player = session->player;
2378 struct avrcp_header *pdu;
2379 struct set_volume_rsp *rsp;
2385 if (!player || !player->cfm || !player->cfm->set_volume)
2388 pdu = parse_pdu(operands, operand_count);
2394 if (code == AVC_CTYPE_REJECTED) {
2395 err = parse_status(pdu);
2399 if (pdu->params_len < sizeof(*rsp)) {
2404 rsp = (void *) pdu->params;
2406 value = rsp->value & 0x7f;
2410 player->cfm->set_volume(session, err, value, player->user_data);
2415 int avrcp_set_volume(struct avrcp *session, uint8_t volume)
2419 iov.iov_base = &volume;
2420 iov.iov_len = sizeof(volume);
2422 return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
2423 AVRCP_SET_ABSOLUTE_VOLUME, &iov, 1,
2424 set_volume_rsp, session);
2427 static int parse_attribute_list(uint8_t *params, uint16_t params_len,
2428 uint8_t number, uint32_t *attrs, char **text)
2430 struct media_item *item;
2433 if (number > AVRCP_MEDIA_ATTRIBUTE_LAST)
2436 for (i = 0; i < number && params_len >= sizeof(*item); i++) {
2437 item = (void *) params;
2439 item->attr = be32_to_cpu(item->attr);
2440 item->charset = be16_to_cpu(item->charset);
2441 item->len = be16_to_cpu(item->len);
2443 params_len -= sizeof(*item);
2444 params += sizeof(*item);
2445 if (item->len > params_len)
2448 if (item->len > 0) {
2449 text[i] = g_strndup(item->data, item->len);
2450 attrs[i] = item->attr;
2451 params_len -= item->len;
2452 params += item->len;
2462 for (i -= 1; i >= 0; i--)
2468 static void free_attribute_list(uint8_t number, char **text)
2471 g_free(text[number]);
2474 static int parse_elements(struct avrcp_header *pdu, uint8_t *number,
2475 uint32_t *attrs, char **text)
2477 struct get_element_attributes_rsp *rsp;
2479 if (pdu->params_len < sizeof(*rsp))
2482 rsp = (void *) pdu->params;
2483 if (rsp->number > AVRCP_MEDIA_ATTRIBUTE_LAST)
2486 *number = rsp->number;
2488 return parse_attribute_list(pdu->params + sizeof(*rsp),
2489 pdu->params_len - sizeof(*rsp),
2490 *number, attrs, text);
2493 static int parse_items(struct avrcp_browsing_header *pdu, uint8_t *number,
2494 uint32_t *attrs, char **text)
2496 struct get_item_attributes_rsp *rsp;
2498 if (pdu->params_len < sizeof(*rsp))
2501 rsp = (void *) pdu->params;
2503 if (rsp->number > AVRCP_MEDIA_ATTRIBUTE_LAST)
2506 *number = rsp->number;
2508 return parse_attribute_list(pdu->params + sizeof(*rsp),
2509 pdu->params_len - sizeof(*rsp),
2510 *number, attrs, text);
2513 static gboolean get_element_attributes_rsp(struct avctp *conn,
2514 uint8_t code, uint8_t subunit,
2515 uint8_t *operands, size_t operand_count,
2518 struct avrcp *session = user_data;
2519 struct avrcp_player *player = session->player;
2520 struct avrcp_header *pdu;
2522 uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
2523 char *text[AVRCP_MEDIA_ATTRIBUTE_LAST];
2528 if (!player || !player->cfm || !player->cfm->get_element_attributes)
2531 pdu = parse_pdu(operands, operand_count);
2537 if (code == AVC_CTYPE_REJECTED) {
2538 err = parse_status(pdu);
2542 err = parse_elements(pdu, &number, attrs, text);
2545 player->cfm->get_element_attributes(session, err, number, attrs, text,
2549 free_attribute_list(number, text);
2554 int avrcp_get_element_attributes(struct avrcp *session)
2557 struct get_element_attributes_req req;
2559 /* This returns all attributes */
2560 memset(&req, 0, sizeof(req));
2562 iov.iov_base = &req;
2563 iov.iov_len = sizeof(req);
2565 return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
2566 AVRCP_GET_ELEMENT_ATTRIBUTES, &iov, 1,
2567 get_element_attributes_rsp, session);
2570 static gboolean set_addressed_rsp(struct avctp *conn,
2571 uint8_t code, uint8_t subunit,
2572 uint8_t *operands, size_t operand_count,
2575 struct avrcp *session = user_data;
2576 struct avrcp_player *player = session->player;
2577 struct avrcp_header *pdu;
2582 if (!player || !player->cfm || !player->cfm->set_addressed)
2585 pdu = parse_pdu(operands, operand_count);
2591 err = parse_status(pdu);
2594 player->cfm->set_addressed(session, err, player->user_data);
2599 int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id)
2602 struct set_addressed_req req;
2604 req.id = cpu_to_be16(player_id);
2606 iov.iov_base = &req;
2607 iov.iov_len = sizeof(req);
2609 return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
2610 AVRCP_SET_ADDRESSED_PLAYER, &iov, 1,
2611 set_addressed_rsp, session);
2614 static char *parse_folder_list(uint8_t *params, uint16_t params_len,
2617 char **folders, *path;
2621 folders = g_new0(char *, depth + 2);
2622 folders[0] = g_strdup("/Filesystem");
2624 for (i = 0, count = 1; count <= depth && i < params_len; count++) {
2629 if (i + len > params_len || len == 0) {
2630 g_strfreev(folders);
2634 folders[count] = g_memdup(¶ms[i], len);
2638 path = g_build_pathv("/", folders);
2639 g_strfreev(folders);
2644 static gboolean set_browsed_rsp(struct avctp *conn, uint8_t *operands,
2645 size_t operand_count, void *user_data)
2647 struct avrcp *session = user_data;
2648 struct avrcp_player *player = session->player;
2649 struct avrcp_browsing_header *pdu;
2650 struct set_browsed_rsp *rsp;
2651 uint16_t counter = 0;
2658 if (!player || !player->cfm || !player->cfm->set_browsed)
2661 pdu = parse_browsing_pdu(operands, operand_count);
2667 err = parse_browsing_status(pdu);
2671 if (pdu->params_len < sizeof(*rsp)) {
2676 rsp = (void *) pdu->params;
2678 counter = be16_to_cpu(rsp->counter);
2679 items = be32_to_cpu(rsp->items);
2681 path = parse_folder_list(rsp->data, pdu->params_len - sizeof(*rsp),
2687 player->cfm->set_browsed(session, err, counter, items, path,
2693 int avrcp_set_browsed_player(struct avrcp *session, uint16_t player_id)
2696 struct set_browsed_req req;
2698 req.id = cpu_to_be16(player_id);
2700 iov.iov_base = &req;
2701 iov.iov_len = sizeof(req);
2703 return avrcp_send_browsing_req(session, AVRCP_SET_BROWSED_PLAYER,
2704 &iov, 1, set_browsed_rsp, session);
2707 static gboolean get_folder_items_rsp(struct avctp *conn,
2708 uint8_t *operands, size_t operand_count,
2711 struct avrcp *session = user_data;
2712 struct avrcp_player *player = session->player;
2713 struct avrcp_browsing_header *pdu;
2714 struct get_folder_items_rsp *rsp;
2715 uint16_t counter = 0, number = 0;
2716 uint8_t *params = NULL;
2721 if (!player || !player->cfm || !player->cfm->get_folder_items)
2724 pdu = parse_browsing_pdu(operands, operand_count);
2730 err = parse_browsing_status(pdu);
2734 if (pdu->params_len < sizeof(*rsp)) {
2739 rsp = (void *) pdu->params;
2741 counter = be16_to_cpu(rsp->counter);
2742 number = be16_to_cpu(rsp->number);
2745 /* FIXME: Add proper parsing for each item type */
2748 player->cfm->get_folder_items(session, err, counter, number, params,
2754 int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
2755 uint32_t start, uint32_t end, uint8_t number,
2759 struct iovec iov[2];
2760 struct get_folder_items_req req;
2764 req.start = cpu_to_be32(start);
2765 req.end = cpu_to_be32(end);
2766 req.number = number;
2768 iov[0].iov_base = &req;
2769 iov[0].iov_len = sizeof(req);
2772 return avrcp_send_browsing_req(session, AVRCP_GET_FOLDER_ITEMS,
2773 iov, 1, get_folder_items_rsp,
2776 for (i = 0; i < number; i++)
2777 attrs[i] = cpu_to_be32(attrs[i]);
2779 iov[1].iov_base = attrs;
2780 iov[1].iov_len = number * sizeof(*attrs);
2782 return avrcp_send_browsing_req(session, AVRCP_GET_FOLDER_ITEMS,
2783 iov, 2, get_folder_items_rsp, session);
2786 static gboolean change_path_rsp(struct avctp *conn, uint8_t *operands,
2787 size_t operand_count, void *user_data)
2789 struct avrcp *session = user_data;
2790 struct avrcp_player *player = session->player;
2791 struct avrcp_browsing_header *pdu;
2792 struct change_path_rsp *rsp;
2798 if (!player || !player->cfm || !player->cfm->change_path)
2801 pdu = parse_browsing_pdu(operands, operand_count);
2807 err = parse_browsing_status(pdu);
2811 if (pdu->params_len < sizeof(*rsp)) {
2816 rsp = (void *) pdu->params;
2818 items = be32_to_cpu(rsp->items);
2821 player->cfm->change_path(session, err, items, player->user_data);
2826 int avrcp_change_path(struct avrcp *session, uint8_t direction, uint64_t uid,
2830 struct change_path_req req;
2832 req.counter = cpu_to_be16(counter);
2833 req.direction = direction;
2834 req.uid = cpu_to_be64(uid);
2836 iov.iov_base = &req;
2837 iov.iov_len = sizeof(req);
2839 return avrcp_send_browsing_req(session, AVRCP_CHANGE_PATH,
2840 &iov, 1, change_path_rsp, session);
2843 static gboolean get_item_attributes_rsp(struct avctp *conn, uint8_t *operands,
2844 size_t operand_count, void *user_data)
2846 struct avrcp *session = user_data;
2847 struct avrcp_player *player = session->player;
2848 struct avrcp_browsing_header *pdu;
2850 uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
2851 char *text[AVRCP_MEDIA_ATTRIBUTE_LAST];
2856 if (!player || !player->cfm || !player->cfm->get_item_attributes)
2859 pdu = parse_browsing_pdu(operands, operand_count);
2865 err = parse_browsing_status(pdu);
2869 err = parse_items(pdu, &number, attrs, text);
2872 player->cfm->get_item_attributes(session, err, number, attrs, text,
2876 free_attribute_list(number, text);
2881 int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
2882 uint64_t uid, uint16_t counter, uint8_t number,
2885 struct iovec iov[2];
2886 struct get_item_attributes_req req;
2890 req.uid = cpu_to_be64(uid);
2891 req.counter = cpu_to_be16(counter);
2892 req.number = number;
2894 iov[0].iov_base = &req;
2895 iov[0].iov_len = sizeof(req);
2898 return avrcp_send_browsing_req(session,
2899 AVRCP_GET_ITEM_ATTRIBUTES,
2900 iov, 1, get_item_attributes_rsp,
2903 if (number > AVRCP_MEDIA_ATTRIBUTE_LAST)
2906 for (i = 0; i < number; i++) {
2907 if (attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST ||
2908 attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL)
2910 attrs[i] = cpu_to_be32(attrs[i]);
2913 iov[1].iov_base = attrs;
2914 iov[1].iov_len = number * sizeof(*attrs);
2916 return avrcp_send_browsing_req(session, AVRCP_GET_ITEM_ATTRIBUTES,
2917 iov, 2, get_item_attributes_rsp,
2921 static gboolean play_item_rsp(struct avctp *conn, uint8_t *operands,
2922 size_t operand_count, void *user_data)
2924 struct avrcp *session = user_data;
2925 struct avrcp_player *player = session->player;
2926 struct avrcp_browsing_header *pdu;
2931 if (!player || !player->cfm || !player->cfm->play_item)
2934 pdu = parse_browsing_pdu(operands, operand_count);
2940 err = parse_browsing_status(pdu);
2943 player->cfm->play_item(session, err, player->user_data);
2948 int avrcp_play_item(struct avrcp *session, uint8_t scope, uint64_t uid,
2952 struct play_item_req req;
2954 if (scope > AVRCP_MEDIA_NOW_PLAYING)
2958 req.uid = cpu_to_be64(uid);
2959 req.counter = cpu_to_be16(counter);
2961 iov.iov_base = &req;
2962 iov.iov_len = sizeof(req);
2964 return avrcp_send_browsing_req(session, AVRCP_PLAY_ITEM, &iov, 1,
2965 play_item_rsp, session);
2968 static gboolean search_rsp(struct avctp *conn, uint8_t *operands,
2969 size_t operand_count, void *user_data)
2971 struct avrcp *session = user_data;
2972 struct avrcp_player *player = session->player;
2973 struct avrcp_browsing_header *pdu;
2974 struct search_rsp *rsp;
2975 uint16_t counter = 0;
2981 if (!player || !player->cfm || !player->cfm->search)
2984 pdu = parse_browsing_pdu(operands, operand_count);
2990 err = parse_browsing_status(pdu);
2994 if (pdu->params_len < sizeof(*rsp)) {
2999 rsp = (void *) pdu->params;
3001 counter = be16_to_cpu(rsp->counter);
3002 items = be32_to_cpu(rsp->items);
3007 player->cfm->search(session, err, counter, items, player->user_data);
3012 int avrcp_search(struct avrcp *session, const char *string)
3014 struct iovec iov[2];
3015 struct search_req req;
3021 len = strnlen(string, UINT8_MAX);
3023 req.charset = cpu_to_be16(AVRCP_CHARSET_UTF8);
3024 req.len = cpu_to_be16(len);
3026 iov[0].iov_base = &req;
3027 iov[0].iov_len = sizeof(req);
3029 iov[1].iov_base = (void *) string;
3030 iov[1].iov_len = len;
3032 return avrcp_send_browsing_req(session, AVRCP_SEARCH, iov, 2,
3033 search_rsp, session);
3036 static gboolean add_to_now_playing_rsp(struct avctp *conn, uint8_t *operands,
3037 size_t operand_count, void *user_data)
3039 struct avrcp *session = user_data;
3040 struct avrcp_player *player = session->player;
3041 struct avrcp_browsing_header *pdu;
3046 if (!player || !player->cfm || !player->cfm->add_to_now_playing)
3049 pdu = parse_browsing_pdu(operands, operand_count);
3055 err = parse_browsing_status(pdu);
3058 player->cfm->add_to_now_playing(session, err, player->user_data);
3063 int avrcp_add_to_now_playing(struct avrcp *session, uint8_t scope, uint64_t uid,
3067 struct add_to_now_playing_req req;
3069 if (scope > AVRCP_MEDIA_NOW_PLAYING)
3073 req.uid = cpu_to_be64(uid);
3074 req.counter = cpu_to_be16(counter);
3076 iov.iov_base = &req;
3077 iov.iov_len = sizeof(req);
3079 return avrcp_send_browsing_req(session, AVRCP_ADD_TO_NOW_PLAYING,
3080 &iov, 1, add_to_now_playing_rsp,
3084 int avrcp_get_capabilities_rsp(struct avrcp *session, uint8_t transaction,
3085 uint8_t number, uint8_t *events)
3087 struct iovec iov[2];
3088 struct get_capabilities_rsp rsp;
3090 if (number > AVRCP_EVENT_LAST)
3093 rsp.cap = CAP_EVENTS_SUPPORTED;
3094 rsp.number = number;
3096 iov[0].iov_base = &rsp;
3097 iov[0].iov_len = sizeof(rsp);
3099 iov[1].iov_base = events;
3100 iov[1].iov_len = number;
3102 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3103 AVC_SUBUNIT_PANEL, AVRCP_GET_CAPABILITIES,
3107 int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
3108 uint8_t number, uint8_t *attrs)
3110 struct iovec iov[2];
3111 struct list_attributes_rsp rsp;
3113 if (number > AVRCP_ATTRIBUTE_LAST)
3116 rsp.number = number;
3118 iov[0].iov_base = &rsp;
3119 iov[0].iov_len = sizeof(rsp);
3122 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3123 AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_ATTRIBUTES,
3126 iov[1].iov_base = attrs;
3127 iov[1].iov_len = number;
3129 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3130 AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_ATTRIBUTES,
3134 int avrcp_get_player_attribute_text_rsp(struct avrcp *session,
3135 uint8_t transaction, uint8_t number,
3136 uint8_t *attrs, const char **text)
3138 struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST * 2];
3139 struct text_value val[AVRCP_ATTRIBUTE_LAST];
3142 if (number > AVRCP_ATTRIBUTE_LAST)
3145 iov[0].iov_base = &number;
3146 iov[0].iov_len = sizeof(number);
3148 for (i = 0; i < number; i++) {
3151 if (attrs[i] > AVRCP_ATTRIBUTE_LAST ||
3152 attrs[i] == AVRCP_ATTRIBUTE_ILEGAL)
3156 len = strlen(text[i]);
3158 val[i].attr = attrs[i];
3159 val[i].charset = cpu_to_be16(AVRCP_CHARSET_UTF8);
3162 iov[i + 1].iov_base = &val[i];
3163 iov[i + 1].iov_len = sizeof(val[i]);
3165 iov[i + 2].iov_base = (void *) text[i];
3166 iov[i + 2].iov_len = len;
3169 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3170 AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
3174 int avrcp_list_player_values_rsp(struct avrcp *session, uint8_t transaction,
3175 uint8_t number, uint8_t *values)
3177 struct iovec iov[2];
3179 if (number > AVRCP_ATTRIBUTE_LAST)
3182 iov[0].iov_base = &number;
3183 iov[0].iov_len = sizeof(number);
3185 iov[1].iov_base = values;
3186 iov[1].iov_len = number;
3188 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3189 AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_VALUES,
3193 int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
3194 uint32_t position, uint32_t duration,
3198 struct get_play_status_rsp rsp;
3200 rsp.duration = cpu_to_be32(duration);
3201 rsp.position = cpu_to_be32(position);
3202 rsp.status = status;
3204 iov.iov_base = &rsp;
3205 iov.iov_len = sizeof(rsp);
3207 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3208 AVC_SUBUNIT_PANEL, AVRCP_GET_PLAY_STATUS,
3212 int avrcp_get_player_values_text_rsp(struct avrcp *session,
3213 uint8_t transaction, uint8_t number,
3214 uint8_t *values, const char **text)
3216 struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST * 2];
3217 struct text_value val[AVRCP_ATTRIBUTE_LAST];
3220 if (number > AVRCP_ATTRIBUTE_LAST)
3223 iov[0].iov_base = &number;
3224 iov[0].iov_len = sizeof(number);
3226 for (i = 0; i < number; i++) {
3230 len = strlen(text[i]);
3232 val[i].attr = values[i];
3233 val[i].charset = cpu_to_be16(AVRCP_CHARSET_UTF8);
3236 iov[i + 1].iov_base = &val[i];
3237 iov[i + 1].iov_len = sizeof(val[i]);
3239 iov[i + 2].iov_base = (void *) text[i];
3240 iov[i + 2].iov_len = len;
3243 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3244 AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_VALUE_TEXT,
3248 int avrcp_get_current_player_value_rsp(struct avrcp *session,
3249 uint8_t transaction, uint8_t number,
3250 uint8_t *attrs, uint8_t *values)
3252 struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST];
3253 struct attr_value val[AVRCP_ATTRIBUTE_LAST];
3256 if (number > AVRCP_ATTRIBUTE_LAST)
3259 iov[0].iov_base = &number;
3260 iov[0].iov_len = sizeof(number);
3262 for (i = 0; i < number; i++) {
3263 val[i].attr = attrs[i];
3264 val[i].value = values[i];
3266 iov[i + 1].iov_base = &val[i];
3267 iov[i + 1].iov_len = sizeof(val[i]);
3270 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3271 AVC_SUBUNIT_PANEL, AVRCP_GET_CURRENT_PLAYER_VALUE,
3275 int avrcp_set_player_value_rsp(struct avrcp *session, uint8_t transaction)
3277 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3278 AVC_SUBUNIT_PANEL, AVRCP_SET_PLAYER_VALUE, NULL, 0);
3281 int avrcp_get_element_attrs_rsp(struct avrcp *session, uint8_t transaction,
3282 uint8_t *params, size_t params_len)
3286 iov.iov_base = params;
3287 iov.iov_len = params_len;
3289 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3290 AVC_SUBUNIT_PANEL, AVRCP_GET_ELEMENT_ATTRIBUTES,
3294 int avrcp_register_notification_rsp(struct avrcp *session, uint8_t transaction,
3295 uint8_t code, uint8_t event,
3296 void *data, size_t len)
3298 struct iovec iov[2];
3302 if (event > AVRCP_EVENT_LAST)
3305 iov[0].iov_base = &event;
3306 iov[0].iov_len = sizeof(event);
3309 case AVRCP_EVENT_STATUS_CHANGED:
3310 if (len != sizeof(uint8_t))
3313 case AVRCP_EVENT_VOLUME_CHANGED:
3314 if (len != sizeof(uint8_t))
3317 if (volume[0] > 127)
3320 case AVRCP_EVENT_TRACK_CHANGED:
3321 if (len != sizeof(uint64_t))
3324 put_be64(*(uint64_t *) data, data);
3326 case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
3327 if (len != sizeof(uint32_t))
3330 put_be32(*(uint32_t *) data, data);
3332 case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
3337 player[0] = cpu_to_be16(player[0]);
3338 player[1] = cpu_to_be16(player[1]);
3341 case AVRCP_EVENT_SETTINGS_CHANGED:
3342 if (len < sizeof(uint8_t))
3345 case AVRCP_EVENT_UIDS_CHANGED:
3346 if (len != sizeof(uint16_t))
3349 put_be16(*(uint16_t *) data, data);
3352 return avrcp_send(session, transaction, code, AVC_SUBUNIT_PANEL,
3353 AVRCP_REGISTER_NOTIFICATION, iov, 1);
3356 iov[1].iov_base = data;
3357 iov[1].iov_len = len;
3359 return avrcp_send(session, transaction, code, AVC_SUBUNIT_PANEL,
3360 AVRCP_REGISTER_NOTIFICATION, iov, 2);
3363 int avrcp_set_volume_rsp(struct avrcp *session, uint8_t transaction,
3371 iov.iov_base = &volume;
3372 iov.iov_len = sizeof(volume);
3374 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3375 AVC_SUBUNIT_PANEL, AVRCP_SET_ABSOLUTE_VOLUME,
3379 int avrcp_set_addressed_player_rsp(struct avrcp *session, uint8_t transaction,
3384 iov.iov_base = &status;
3385 iov.iov_len = sizeof(status);
3387 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3388 AVC_SUBUNIT_PANEL, AVRCP_SET_ADDRESSED_PLAYER,
3392 static int avrcp_status_rsp(struct avrcp *session, uint8_t transaction,
3393 uint8_t pdu_id, uint8_t status)
3397 if (status > AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED)
3400 iov.iov_base = &status;
3401 iov.iov_len = sizeof(status);
3403 return avrcp_send_browsing(session, transaction, pdu_id, &iov, 1);
3406 int avrcp_set_browsed_player_rsp(struct avrcp *session, uint8_t transaction,
3407 uint8_t status, uint16_t counter,
3408 uint32_t items, uint8_t depth,
3409 const char **folders)
3411 struct iovec iov[UINT8_MAX * 2 + 1];
3412 struct set_browsed_rsp rsp;
3413 uint16_t len[UINT8_MAX];
3416 if (status != AVRCP_STATUS_SUCCESS)
3417 return avrcp_status_rsp(session, transaction,
3418 AVRCP_SET_BROWSED_PLAYER, status);
3420 rsp.status = status;
3421 rsp.counter = cpu_to_be16(counter);
3422 rsp.items = cpu_to_be32(items);
3423 rsp.charset = cpu_to_be16(AVRCP_CHARSET_UTF8);
3426 iov[0].iov_base = &rsp;
3427 iov[0].iov_len = sizeof(rsp);
3430 return avrcp_send_browsing(session, transaction,
3431 AVRCP_SET_BROWSED_PLAYER,
3434 for (i = 0; i < depth; i++) {
3438 len[i] = strlen(folders[i]);
3440 iov[i * 2 + 2].iov_base = (void *) folders[i];
3441 iov[i * 2 + 2].iov_len = len[i];
3443 len[i] = cpu_to_be16(len[i]);
3445 iov[i * 2 + 1].iov_base = &len[i];
3446 iov[i * 2 + 1].iov_len = sizeof(len[i]);
3449 return avrcp_send_browsing(session, transaction,
3450 AVRCP_SET_BROWSED_PLAYER, iov,
3454 int avrcp_get_folder_items_rsp(struct avrcp *session, uint8_t transaction,
3455 uint8_t status, uint16_t counter,
3456 uint8_t number, uint8_t *type,
3457 uint16_t *len, uint8_t **params)
3459 struct iovec iov[UINT8_MAX * 2 + 1];
3460 struct get_folder_items_rsp rsp;
3461 uint8_t item[UINT8_MAX][3];
3464 if (status != AVRCP_STATUS_SUCCESS)
3465 return avrcp_status_rsp(session, transaction,
3466 AVRCP_GET_FOLDER_ITEMS, status);
3468 rsp.status = status;
3469 rsp.counter = cpu_to_be16(counter);
3470 rsp.number = cpu_to_be16(number);
3472 iov[0].iov_base = &rsp;
3473 iov[0].iov_len = sizeof(rsp);
3475 for (i = 0; i < number; i++) {
3476 item[i][0] = type[i];
3477 put_be16(len[i], &item[i][1]);
3479 iov[i * 2 + 1].iov_base = item[i];
3480 iov[i * 2 + 1].iov_len = sizeof(item[i]);
3482 iov[i * 2 + 2].iov_base = params[i];
3483 iov[i * 2 + 2].iov_len = len[i];
3486 return avrcp_send_browsing(session, transaction, AVRCP_GET_FOLDER_ITEMS,
3487 iov, number * 2 + 1);
3490 int avrcp_change_path_rsp(struct avrcp *session, uint8_t transaction,
3491 uint8_t status, uint32_t items)
3494 struct change_path_rsp rsp;
3496 if (status != AVRCP_STATUS_SUCCESS)
3497 return avrcp_status_rsp(session, transaction, AVRCP_CHANGE_PATH,
3500 rsp.status = status;
3501 rsp.items = cpu_to_be32(items);
3503 iov.iov_base = &rsp;
3504 iov.iov_len = sizeof(rsp);
3506 return avrcp_send_browsing(session, transaction, AVRCP_CHANGE_PATH,
3510 static bool pack_attribute_list(struct iovec *iov, uint8_t number,
3511 uint32_t *attrs, const char **text)
3514 struct media_item val[AVRCP_MEDIA_ATTRIBUTE_LAST];
3516 for (i = 0; i < number; i++) {
3519 if (attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST ||
3520 attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL)
3524 len = strlen(text[i]);
3526 val[i].attr = cpu_to_be32(attrs[i]);
3527 val[i].charset = cpu_to_be16(AVRCP_CHARSET_UTF8);
3528 val[i].len = cpu_to_be16(len);
3530 iov[i].iov_base = &val[i];
3531 iov[i].iov_len = sizeof(val[i]);
3533 iov[i + 1].iov_base = (void *) text[i];
3534 iov[i + 1].iov_len = len;
3540 int avrcp_get_item_attributes_rsp(struct avrcp *session, uint8_t transaction,
3541 uint8_t status, uint8_t number,
3542 uint32_t *attrs, const char **text)
3544 struct iovec iov[AVRCP_MEDIA_ATTRIBUTE_LAST * 2 + 1];
3545 struct get_item_attributes_rsp rsp;
3547 if (number > AVRCP_MEDIA_ATTRIBUTE_LAST)
3550 if (status != AVRCP_STATUS_SUCCESS)
3551 return avrcp_status_rsp(session, transaction,
3552 AVRCP_GET_ITEM_ATTRIBUTES, status);
3554 rsp.status = status;
3555 rsp.number = number;
3557 iov[0].iov_base = &rsp;
3558 iov[0].iov_len = sizeof(rsp);
3560 if (!pack_attribute_list(&iov[1], number, attrs, text))
3563 return avrcp_send_browsing(session, transaction,
3564 AVRCP_GET_ITEM_ATTRIBUTES, iov,
3568 int avrcp_play_item_rsp(struct avrcp *session, uint8_t transaction,
3571 return avrcp_status_rsp(session, transaction, AVRCP_PLAY_ITEM,
3575 int avrcp_search_rsp(struct avrcp *session, uint8_t transaction, uint8_t status,
3576 uint16_t counter, uint32_t items)
3579 struct search_rsp rsp;
3581 if (status != AVRCP_STATUS_SUCCESS)
3582 return avrcp_status_rsp(session, transaction, AVRCP_SEARCH,
3585 rsp.status = status;
3586 rsp.counter = cpu_to_be16(counter);
3587 rsp.items = cpu_to_be32(items);
3589 iov.iov_base = &rsp;
3590 iov.iov_len = sizeof(rsp);
3592 return avrcp_send_browsing(session, transaction, AVRCP_SEARCH,
3596 int avrcp_add_to_now_playing_rsp(struct avrcp *session, uint8_t transaction,
3599 return avrcp_status_rsp(session, transaction, AVRCP_ADD_TO_NOW_PLAYING,
3603 int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op)
3608 return avctp_send_passthrough(session->conn, op, NULL, 0);
3610 hton24(params, vendor);
3611 put_be16(op, ¶ms[3]);
3613 return avctp_send_passthrough(session->conn, AVC_VENDOR_UNIQUE, params,