Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / android / avrcp-lib.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2014  Intel Corporation. All rights reserved.
6  *
7  *
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.
12  *
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.
17  *
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
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdbool.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <string.h>
32
33 #include "lib/bluetooth.h"
34
35 #include "src/shared/util.h"
36 #include "src/log.h"
37
38 #include "avctp.h"
39 #include "avrcp-lib.h"
40
41
42 /* Packet types */
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
47
48 #define AVRCP_CHARSET_UTF8      0x006a
49
50 #if __BYTE_ORDER == __LITTLE_ENDIAN
51
52 struct avrcp_header {
53         uint8_t company_id[3];
54         uint8_t pdu_id;
55         uint8_t packet_type:2;
56         uint8_t rsvd:6;
57         uint16_t params_len;
58         uint8_t params[0];
59 } __attribute__ ((packed));
60 #define AVRCP_HEADER_LENGTH 7
61
62 #elif __BYTE_ORDER == __BIG_ENDIAN
63
64 struct avrcp_header {
65         uint8_t company_id[3];
66         uint8_t pdu_id;
67         uint8_t rsvd:6;
68         uint8_t packet_type:2;
69         uint16_t params_len;
70         uint8_t params[0];
71 } __attribute__ ((packed));
72 #define AVRCP_HEADER_LENGTH 7
73
74 #else
75 #error "Unknown byte order"
76 #endif
77
78 struct avrcp_browsing_header {
79         uint8_t pdu_id;
80         uint16_t params_len;
81         uint8_t params[0];
82 } __attribute__ ((packed));
83 #define AVRCP_BROWSING_HEADER_LENGTH 3
84
85 struct get_capabilities_req {
86         uint8_t cap;
87         uint8_t params[0];
88 } __attribute__ ((packed));
89
90 struct get_capabilities_rsp {
91         uint8_t cap;
92         uint8_t number;
93         uint8_t params[0];
94 } __attribute__ ((packed));
95
96 struct list_attributes_rsp {
97         uint8_t number;
98         uint8_t params[0];
99 } __attribute__ ((packed));
100
101 struct list_values_req {
102         uint8_t attr;
103 } __attribute__ ((packed));
104
105 struct list_values_rsp {
106         uint8_t number;
107         uint8_t params[0];
108 } __attribute__ ((packed));
109
110 struct get_value_req {
111         uint8_t number;
112         uint8_t attrs[0];
113 } __attribute__ ((packed));
114
115 struct attr_value {
116         uint8_t attr;
117         uint8_t value;
118 } __attribute__ ((packed));
119
120 struct value_rsp {
121         uint8_t number;
122         struct attr_value values[0];
123 } __attribute__ ((packed));
124
125 struct set_value_req {
126         uint8_t number;
127         struct attr_value values[0];
128 } __attribute__ ((packed));
129
130 struct get_attribute_text_req {
131         uint8_t number;
132         uint8_t attrs[0];
133 } __attribute__ ((packed));
134
135 struct text_value {
136         uint8_t attr;
137         uint16_t charset;
138         uint8_t len;
139         char data[0];
140 } __attribute__ ((packed));
141
142 struct get_attribute_text_rsp {
143         uint8_t number;
144         struct text_value values[0];
145 } __attribute__ ((packed));
146
147 struct get_value_text_req {
148         uint8_t attr;
149         uint8_t number;
150         uint8_t values[0];
151 } __attribute__ ((packed));
152
153 struct get_value_text_rsp {
154         uint8_t number;
155         struct text_value values[0];
156 } __attribute__ ((packed));
157
158 struct media_item {
159         uint32_t attr;
160         uint16_t charset;
161         uint16_t len;
162         char data[0];
163 } __attribute__ ((packed));
164
165 struct get_element_attributes_req {
166         uint64_t id;
167         uint8_t number;
168         uint32_t attrs[0];
169 } __attribute__ ((packed));
170
171 struct get_element_attributes_rsp {
172         uint8_t number;
173         struct media_item items[0];
174 } __attribute__ ((packed));
175
176 struct get_play_status_rsp {
177         uint32_t duration;
178         uint32_t position;
179         uint8_t status;
180 } __attribute__ ((packed));
181
182 struct register_notification_req {
183         uint8_t event;
184         uint32_t interval;
185 } __attribute__ ((packed));
186
187 struct register_notification_rsp {
188         uint8_t event;
189         uint8_t data[0];
190 } __attribute__ ((packed));
191
192 struct set_volume_req {
193         uint8_t value;
194 } __attribute__ ((packed));
195
196 struct set_volume_rsp {
197         uint8_t value;
198 } __attribute__ ((packed));
199
200 struct set_addressed_req {
201         uint16_t id;
202 } __attribute__ ((packed));
203
204 struct set_addressed_rsp {
205         uint8_t status;
206 } __attribute__ ((packed));
207
208 struct set_browsed_req {
209         uint16_t id;
210 } __attribute__ ((packed));
211
212 struct set_browsed_rsp {
213         uint8_t status;
214         uint16_t counter;
215         uint32_t items;
216         uint16_t charset;
217         uint8_t depth;
218         uint8_t data[0];
219 } __attribute__ ((packed));
220
221 struct get_folder_items_req {
222         uint8_t scope;
223         uint32_t start;
224         uint32_t end;
225         uint8_t number;
226         uint32_t attrs[0];
227 } __attribute__ ((packed));
228
229 struct get_folder_items_rsp {
230         uint8_t status;
231         uint16_t counter;
232         uint16_t number;
233         uint8_t data[0];
234 } __attribute__ ((packed));
235
236 struct change_path_req {
237         uint16_t counter;
238         uint8_t direction;
239         uint64_t uid;
240 } __attribute__ ((packed));
241
242 struct change_path_rsp {
243         uint8_t status;
244         uint32_t items;
245 } __attribute__ ((packed));
246
247 struct get_item_attributes_req {
248         uint8_t scope;
249         uint64_t uid;
250         uint16_t counter;
251         uint8_t number;
252         uint32_t attrs[0];
253 } __attribute__ ((packed));
254
255 struct get_item_attributes_rsp {
256         uint8_t status;
257         uint8_t number;
258         struct media_item items[0];
259 } __attribute__ ((packed));
260
261 struct play_item_req {
262         uint8_t scope;
263         uint64_t uid;
264         uint16_t counter;
265 } __attribute__ ((packed));
266
267 struct play_item_rsp {
268         uint8_t status;
269 } __attribute__ ((packed));
270
271 struct search_req {
272         uint16_t charset;
273         uint16_t len;
274         char string[0];
275 } __attribute__ ((packed));
276
277 struct search_rsp {
278         uint8_t status;
279         uint16_t counter;
280         uint32_t items;
281 } __attribute__ ((packed));
282
283 struct add_to_now_playing_req {
284         uint8_t scope;
285         uint64_t uid;
286         uint16_t counter;
287 } __attribute__ ((packed));
288
289 struct add_to_now_playing_rsp {
290         uint8_t status;
291 } __attribute__ ((packed));
292
293 struct avrcp_control_handler {
294         uint8_t id;
295         uint8_t code;
296         uint8_t rsp;
297         ssize_t (*func) (struct avrcp *session, uint8_t transaction,
298                         uint16_t params_len, uint8_t *params, void *user_data);
299 };
300
301 struct avrcp_browsing_handler {
302         uint8_t id;
303         ssize_t (*func) (struct avrcp *session, uint8_t transaction,
304                         uint16_t params_len, uint8_t *params, void *user_data);
305 };
306
307 struct avrcp_continuing {
308         uint8_t pdu_id;
309         struct iovec pdu;
310 };
311
312 struct avrcp {
313         struct avctp *conn;
314         struct avrcp_player *player;
315
316         const struct avrcp_control_handler *control_handlers;
317         void *control_data;
318         unsigned int control_id;
319         uint16_t control_mtu;
320
321         struct avrcp_continuing *continuing;
322
323         const struct avrcp_passthrough_handler *passthrough_handlers;
324         void *passthrough_data;
325         unsigned int passthrough_id;
326
327         const struct avrcp_browsing_handler *browsing_handlers;
328         void *browsing_data;
329         unsigned int browsing_id;
330
331         avrcp_destroy_cb_t destroy;
332         void *destroy_data;
333 };
334
335 struct avrcp_player {
336         const struct avrcp_control_ind *ind;
337         const struct avrcp_control_cfm *cfm;
338
339         void *user_data;
340 };
341
342 static inline uint32_t ntoh24(const uint8_t src[3])
343 {
344         return src[0] << 16 | src[1] << 8 | src[2];
345 }
346
347 static inline void hton24(uint8_t dst[3], uint32_t src)
348 {
349         dst[0] = (src & 0xff0000) >> 16;
350         dst[1] = (src & 0x00ff00) >> 8;
351         dst[2] = (src & 0x0000ff);
352 }
353
354 static void continuing_free(struct avrcp_continuing *continuing)
355 {
356         g_free(continuing->pdu.iov_base);
357         g_free(continuing);
358 }
359
360 void avrcp_shutdown(struct avrcp *session)
361 {
362         if (session->conn) {
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);
369
370                 if (session->browsing_id > 0)
371                         avctp_unregister_browsing_pdu_handler(session->conn,
372                                                         session->browsing_id);
373
374                 /* clear destroy callback that would call shutdown again */
375                 avctp_set_destroy_cb(session->conn, NULL, NULL);
376                 avctp_shutdown(session->conn);
377         }
378
379         if (session->destroy)
380                 session->destroy(session->destroy_data);
381
382         if (session->continuing)
383                 continuing_free(session->continuing);
384
385         g_free(session->player);
386         g_free(session);
387 }
388
389 static struct avrcp_header *parse_pdu(uint8_t *operands, size_t operand_count)
390 {
391         struct avrcp_header *pdu;
392
393         if (!operands || operand_count < sizeof(*pdu)) {
394                 error("AVRCP: packet too small (%zu bytes)", operand_count);
395                 return NULL;
396         }
397
398         pdu = (void *) operands;
399         pdu->params_len = ntohs(pdu->params_len);
400
401         if (operand_count != pdu->params_len + sizeof(*pdu)) {
402                 error("AVRCP: invalid parameter length (%u bytes)",
403                                                         pdu->params_len);
404                 return NULL;
405         }
406
407         return pdu;
408 }
409
410 static struct avrcp_browsing_header *parse_browsing_pdu(uint8_t *operands,
411                                                         size_t operand_count)
412 {
413         struct avrcp_browsing_header *pdu;
414
415         if (!operands || operand_count < sizeof(*pdu)) {
416                 error("AVRCP: packet too small (%zu bytes)", operand_count);
417                 return NULL;
418         }
419
420         pdu = (void *) operands;
421         pdu->params_len = ntohs(pdu->params_len);
422
423         if (operand_count != pdu->params_len + sizeof(*pdu)) {
424                 error("AVRCP: invalid parameter length (%u bytes)",
425                                                         pdu->params_len);
426                 return NULL;
427         }
428
429         return pdu;
430 }
431
432 static uint8_t errno2status(int err)
433 {
434         switch (err) {
435         case -ENOSYS:
436                 return AVRCP_STATUS_INVALID_COMMAND;
437         case -EINVAL:
438                 return AVRCP_STATUS_INVALID_PARAM;
439         case 0:
440                 return AVRCP_STATUS_SUCCESS;
441         case -ENOTDIR:
442                 return AVRCP_STATUS_NOT_DIRECTORY;
443         case -EBADRQC:
444                 return AVRCP_STATUS_INVALID_SCOPE;
445         case -ERANGE:
446                 return AVRCP_STATUS_OUT_OF_BOUNDS;
447         case -ENOENT:
448                 return AVRCP_STATUS_DOES_NOT_EXIST;
449         default:
450                 return AVRCP_STATUS_INTERNAL_ERROR;
451         }
452 }
453
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,
457                                         void *user_data)
458 {
459         struct avrcp *session = user_data;
460         const struct avrcp_control_handler *handler;
461         struct avrcp_header *pdu;
462         uint32_t company_id;
463         ssize_t ret;
464
465         pdu = parse_pdu(operands, operand_count);
466         if (!pdu) {
467                 pdu = (void *) operands;
468                 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
469                 goto reject;
470         }
471
472         company_id = ntoh24(pdu->company_id);
473         if (company_id != IEEEID_BTSIG) {
474                 *code = AVC_CTYPE_NOT_IMPLEMENTED;
475                 return 0;
476         }
477
478         DBG("AVRCP PDU 0x%02X, len 0x%04X", pdu->pdu_id, pdu->params_len);
479
480         pdu->packet_type = 0;
481         pdu->rsvd = 0;
482
483         if (!session->control_handlers)
484                 goto reject;
485
486         for (handler = session->control_handlers; handler->id; handler++) {
487                 if (handler->id == pdu->pdu_id)
488                         break;
489         }
490
491         if (handler->id != pdu->pdu_id || handler->code != *code) {
492                 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
493                 goto reject;
494         }
495
496         if (!handler->func) {
497                 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
498                 goto reject;
499         }
500
501         ret = handler->func(session, transaction, pdu->params_len, pdu->params,
502                                                         session->control_data);
503         if (ret == 0)
504                 return -EAGAIN;
505
506         if (ret < 0) {
507                 if (ret == -EAGAIN)
508                         return ret;
509                 pdu->params[0] = errno2status(ret);
510                 goto reject;
511         }
512
513         *code = handler->rsp;
514         pdu->params_len = htons(ret);
515
516         return AVRCP_HEADER_LENGTH + ret;
517
518 reject:
519         pdu->params_len = htons(1);
520         *code = AVC_CTYPE_REJECTED;
521
522         return AVRCP_HEADER_LENGTH + 1;
523 }
524
525 static bool handle_passthrough_pdu(struct avctp *conn, uint8_t op,
526                                                 bool pressed, void *user_data)
527 {
528         struct avrcp *session = user_data;
529         const struct avrcp_passthrough_handler *handler;
530
531         if (!session->passthrough_handlers)
532                 return false;
533
534         for (handler = session->passthrough_handlers; handler->func;
535                                                                 handler++) {
536                 if (handler->op == op)
537                         break;
538         }
539
540         if (handler->func == NULL)
541                 return false;
542
543         return handler->func(session, pressed, session->passthrough_data);
544 }
545
546 static void disconnect_cb(void *data)
547 {
548         struct avrcp *session = data;
549
550         session->conn = NULL;
551
552         avrcp_shutdown(session);
553 }
554
555 struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
556 {
557         struct avrcp *session;
558
559         session = g_new0(struct avrcp, 1);
560
561         session->conn = avctp_new(fd, imtu, omtu, version);
562         if (!session->conn) {
563                 g_free(session);
564                 return NULL;
565         }
566
567         session->passthrough_id = avctp_register_passthrough_handler(
568                                                         session->conn,
569                                                         handle_passthrough_pdu,
570                                                         session);
571         session->control_id = avctp_register_pdu_handler(session->conn,
572                                                         AVC_OP_VENDORDEP,
573                                                         handle_vendordep_pdu,
574                                                         session);
575         session->control_mtu = omtu - AVC_DATA_OFFSET;
576
577         /*
578          * 27.1.2 AV/C Command Frame
579          * An AV/C command frame contains up to 512 octets of data
580          */
581         if (session->control_mtu > AVC_DATA_MTU)
582                 session->control_mtu = AVC_DATA_MTU;
583
584         avctp_set_destroy_cb(session->conn, disconnect_cb, session);
585
586         return session;
587 }
588
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)
592 {
593         struct avrcp *session = user_data;
594         const struct avrcp_browsing_handler *handler;
595         struct avrcp_browsing_header *pdu;
596         int ret;
597
598         pdu = parse_browsing_pdu(operands, operand_count);
599         if (!pdu) {
600                 pdu = (void *) operands;
601                 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
602                 goto reject;
603         }
604
605         DBG("AVRCP Browsing PDU 0x%02X, len 0x%04X", pdu->pdu_id,
606                                                         pdu->params_len);
607
608         if (!session->browsing_handlers) {
609                 pdu->pdu_id = AVRCP_GENERAL_REJECT;
610                 pdu->params[0] = AVRCP_STATUS_INTERNAL_ERROR;
611                 goto reject;
612         }
613
614         for (handler = session->browsing_handlers; handler->id; handler++) {
615                 if (handler->id == pdu->pdu_id)
616                         break;
617         }
618
619         if (handler->id != pdu->pdu_id) {
620                 pdu->pdu_id = AVRCP_GENERAL_REJECT;
621                 pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
622                 goto reject;
623         }
624
625         if (!handler->func) {
626                 pdu->params[0] = AVRCP_STATUS_INVALID_PARAM;
627                 goto reject;
628         }
629
630         ret = handler->func(session, transaction, pdu->params_len, pdu->params,
631                                                         session->control_data);
632         if (ret == 0)
633                 return -EAGAIN;
634
635         if (ret < 0) {
636                 if (ret == -EAGAIN)
637                         return ret;
638                 pdu->params[0] = errno2status(ret);
639                 goto reject;
640         }
641
642         pdu->params_len = htons(ret);
643
644         return AVRCP_BROWSING_HEADER_LENGTH + ret;
645
646 reject:
647         pdu->params_len = htons(1);
648
649         return AVRCP_BROWSING_HEADER_LENGTH + 1;
650 }
651
652 static void browsing_disconnect_cb(void *data)
653 {
654         struct avrcp *session = data;
655
656         session->browsing_id = 0;
657 }
658
659 int avrcp_connect_browsing(struct avrcp *session, int fd, size_t imtu,
660                                                                 size_t omtu)
661 {
662         int err;
663
664         err = avctp_connect_browsing(session->conn, fd, imtu, omtu);
665         if (err < 0)
666                 return err;
667
668         session->browsing_id = avctp_register_browsing_pdu_handler(
669                                                         session->conn,
670                                                         handle_browsing_pdu,
671                                                         session,
672                                                         browsing_disconnect_cb);
673
674         return 0;
675 }
676
677 void avrcp_set_destroy_cb(struct avrcp *session, avrcp_destroy_cb_t cb,
678                                                         void *user_data)
679 {
680         session->destroy = cb;
681         session->destroy_data = user_data;
682 }
683
684 static ssize_t get_capabilities(struct avrcp *session, uint8_t transaction,
685                                 uint16_t params_len, uint8_t *params,
686                                 void *user_data)
687 {
688         struct avrcp_player *player = user_data;
689         struct get_capabilities_req *req;
690
691         if (!params || params_len != sizeof(*req))
692                 return -EINVAL;
693
694         req = (void *) params;
695
696         switch (req->cap) {
697         case CAP_COMPANY_ID:
698                 req->params[0] = 1;
699                 hton24(&req->params[1], IEEEID_BTSIG);
700                 return 5;
701         case CAP_EVENTS_SUPPORTED:
702                 if (!player->ind || !player->ind->get_capabilities)
703                         return -ENOSYS;
704                 return player->ind->get_capabilities(session, transaction,
705                                                         player->user_data);
706         }
707
708         return -EINVAL;
709 }
710
711 static ssize_t list_attributes(struct avrcp *session, uint8_t transaction,
712                                 uint16_t params_len, uint8_t *params,
713                                 void *user_data)
714 {
715         struct avrcp_player *player = user_data;
716
717         DBG("");
718
719         if (!player->ind || !player->ind->list_attributes)
720                 return -ENOSYS;
721
722         return player->ind->list_attributes(session, transaction,
723                                                         player->user_data);
724 }
725
726 static bool check_attributes(uint8_t number, const uint8_t *attrs)
727 {
728         int i;
729
730         for (i = 0; i < number; i++) {
731                 if (attrs[i] > AVRCP_ATTRIBUTE_LAST ||
732                                         attrs[i] == AVRCP_ATTRIBUTE_ILEGAL)
733                         return false;
734         }
735
736         return true;
737 }
738
739 static ssize_t get_attribute_text(struct avrcp *session, uint8_t transaction,
740                                         uint16_t params_len, uint8_t *params,
741                                         void *user_data)
742 {
743         struct avrcp_player *player = user_data;
744         struct get_attribute_text_req *req;
745
746         DBG("");
747
748         if (!player->ind || !player->ind->get_attribute_text)
749                 return -ENOSYS;
750
751         if (!params || params_len < sizeof(*req))
752                 return -EINVAL;
753
754         req = (void *) params;
755         if (params_len != sizeof(*req) + req->number)
756                 return -EINVAL;
757
758         if (!check_attributes(req->number, req->attrs))
759                 return -EINVAL;
760
761         return player->ind->get_attribute_text(session, transaction,
762                                                 req->number, req->attrs,
763                                                 player->user_data);
764 }
765
766 static ssize_t list_values(struct avrcp *session, uint8_t transaction,
767                                         uint16_t params_len, uint8_t *params,
768                                         void *user_data)
769 {
770         struct avrcp_player *player = user_data;
771         struct list_values_req *req;
772
773         DBG("");
774
775         if (!params || params_len != sizeof(*req))
776                 return -EINVAL;
777
778         req = (void *) params;
779         if (req->attr > AVRCP_ATTRIBUTE_LAST ||
780                                         req->attr == AVRCP_ATTRIBUTE_ILEGAL)
781                 return -EINVAL;
782
783         if (!player->ind || !player->ind->list_values)
784                 return -ENOSYS;
785
786         return player->ind->list_values(session, transaction, req->attr,
787                                                         player->user_data);
788 }
789
790 static bool check_value(uint8_t attr, uint8_t number, const uint8_t *values)
791 {
792         int i;
793
794         for (i = 0; i < number; i++) {
795                 /* Check for invalid value */
796                 switch (attr) {
797                 case AVRCP_ATTRIBUTE_EQUALIZER:
798                         if (values[i] < AVRCP_EQUALIZER_OFF ||
799                                                 values[i] > AVRCP_EQUALIZER_ON)
800                                 return false;
801                         break;
802                 case AVRCP_ATTRIBUTE_REPEAT_MODE:
803                         if (values[i] < AVRCP_REPEAT_MODE_OFF ||
804                                         values[i] > AVRCP_REPEAT_MODE_GROUP)
805                                 return false;
806                         break;
807                 case AVRCP_ATTRIBUTE_SHUFFLE:
808                         if (values[i] < AVRCP_SHUFFLE_OFF ||
809                                         values[i] > AVRCP_SHUFFLE_GROUP)
810                                 return false;
811                         break;
812                 case AVRCP_ATTRIBUTE_SCAN:
813                         if (values[i] < AVRCP_SCAN_OFF ||
814                                         values[i] > AVRCP_SCAN_GROUP)
815                                 return false;
816                         break;
817                 }
818         }
819
820         return true;
821 }
822
823 static ssize_t get_value_text(struct avrcp *session, uint8_t transaction,
824                                         uint16_t params_len, uint8_t *params,
825                                         void *user_data)
826 {
827         struct avrcp_player *player = user_data;
828         struct get_value_text_req *req;
829
830         DBG("");
831
832         if (!player->ind || !player->ind->get_value_text)
833                 return -ENOSYS;
834
835         if (!params || params_len < sizeof(*req))
836                 return -EINVAL;
837
838         req = (void *) params;
839         if (params_len != sizeof(*req) + req->number)
840                 return -EINVAL;
841
842         if (req->number > AVRCP_ATTRIBUTE_LAST ||
843                                         req->number == AVRCP_ATTRIBUTE_ILEGAL)
844                 return -EINVAL;
845
846         if (!check_value(req->attr, req->number, req->values))
847                 return -EINVAL;
848
849         return player->ind->get_value_text(session, transaction, params[0],
850                                                 params[1], &params[2],
851                                                 player->user_data);
852 }
853
854 static ssize_t get_value(struct avrcp *session, uint8_t transaction,
855                                         uint16_t params_len, uint8_t *params,
856                                         void *user_data)
857 {
858         struct avrcp_player *player = user_data;
859         struct get_value_req *req;
860
861         DBG("");
862
863         if (!player->ind || !player->ind->get_value)
864                 return -ENOSYS;
865
866         if (!params || params_len < sizeof(*req))
867                 return -EINVAL;
868
869         req = (void *) params;
870         if (params_len < sizeof(*req) + req->number)
871                 return -EINVAL;
872
873         if (!check_attributes(req->number, req->attrs))
874                 return -EINVAL;
875
876         return player->ind->get_value(session, transaction, params[0],
877                                         &params[1], player->user_data);
878 }
879
880 static ssize_t set_value(struct avrcp *session, uint8_t transaction,
881                                         uint16_t params_len, uint8_t *params,
882                                         void *user_data)
883 {
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];
888         int i;
889
890         DBG("");
891
892         if (!player->ind || !player->ind->set_value)
893                 return -ENOSYS;
894
895         if (!params || params_len < sizeof(*req))
896                 return -EINVAL;
897
898         req = (void *) params;
899         if (params_len < sizeof(*req) + req->number * sizeof(*req->values))
900                 return -EINVAL;
901
902         for (i = 0; i < req->number; i++) {
903                 attrs[i] = req->values[i].attr;
904                 values[i] = req->values[i].value;
905
906                 if (!check_value(attrs[i], 1, &values[i]))
907                         return -EINVAL;
908         }
909
910         return player->ind->set_value(session, transaction, req->number,
911                                         attrs, values, player->user_data);
912 }
913
914 static ssize_t get_play_status(struct avrcp *session, uint8_t transaction,
915                                         uint16_t params_len, uint8_t *params,
916                                         void *user_data)
917 {
918         struct avrcp_player *player = user_data;
919
920         DBG("");
921
922         if (!player->ind || !player->ind->get_play_status)
923                 return -ENOSYS;
924
925         return player->ind->get_play_status(session, transaction,
926                                                         player->user_data);
927 }
928
929 static bool parse_attributes(uint32_t *params, uint16_t params_len,
930                                         uint8_t number, uint32_t *attrs)
931 {
932         int i;
933
934         for (i = 0; i < number && params_len >= sizeof(*attrs); i++,
935                                         params_len -= sizeof(*attrs)) {
936                 attrs[i] = be32_to_cpu(params[i]);
937
938                 if (attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL ||
939                                 attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST)
940                         return false;
941         }
942
943         return true;
944 }
945
946 static ssize_t get_element_attributes(struct avrcp *session,
947                                                 uint8_t transaction,
948                                                 uint16_t params_len,
949                                                 uint8_t *params,
950                                                 void *user_data)
951 {
952         struct avrcp_player *player = user_data;
953         struct get_element_attributes_req *req;
954         uint64_t uid;
955         uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
956
957         DBG("");
958
959         if (!player->ind || !player->ind->get_element_attributes)
960                 return -ENOSYS;
961
962         req = (void *) params;
963         if (!params || params_len < sizeof(*req))
964                 return -EINVAL;
965
966         if (!parse_attributes(req->attrs, params_len - sizeof(*req),
967                                                         req->number, attrs))
968                 return -EINVAL;
969
970         uid = get_be64(params);
971
972         return player->ind->get_element_attributes(session, transaction, uid,
973                                                         req->number, attrs,
974                                                         player->user_data);
975 }
976
977 static ssize_t register_notification(struct avrcp *session, uint8_t transaction,
978                                         uint16_t params_len, uint8_t *params,
979                                         void *user_data)
980 {
981         struct avrcp_player *player = user_data;
982         struct register_notification_req *req;
983         uint32_t interval;
984
985         DBG("");
986
987         if (!player->ind || !player->ind->register_notification)
988                 return -ENOSYS;
989
990         if (!params || params_len != sizeof(*req))
991                 return -EINVAL;
992
993         req = (void *) params;
994
995         interval = be32_to_cpu(req->interval);
996
997         return player->ind->register_notification(session, transaction,
998                                                         req->event, interval,
999                                                         player->user_data);
1000 }
1001
1002 static ssize_t set_volume(struct avrcp *session, uint8_t transaction,
1003                                         uint16_t params_len, uint8_t *params,
1004                                         void *user_data)
1005 {
1006         struct avrcp_player *player = user_data;
1007         struct set_volume_req *req;
1008         uint8_t volume;
1009
1010         DBG("");
1011
1012         if (!player->ind || !player->ind->set_volume)
1013                 return -ENOSYS;
1014
1015         if (!params || params_len != sizeof(volume))
1016                 return -EINVAL;
1017
1018         req = (void *) params;
1019
1020         volume = req->value & 0x7f;
1021
1022         return player->ind->set_volume(session, transaction, volume,
1023                                                         player->user_data);
1024 }
1025
1026 static ssize_t set_addressed(struct avrcp *session, uint8_t transaction,
1027                                         uint16_t params_len, uint8_t *params,
1028                                         void *user_data)
1029 {
1030         struct avrcp_player *player = user_data;
1031         struct set_addressed_req *req;
1032         uint16_t id;
1033
1034         DBG("");
1035
1036         if (!player->ind || !player->ind->set_addressed)
1037                 return -ENOSYS;
1038
1039         if (!params || params_len != sizeof(*req))
1040                 return -EINVAL;
1041
1042         req = (void *) params;
1043
1044         id = be16_to_cpu(req->id);
1045
1046         return player->ind->set_addressed(session, transaction, id,
1047                                                         player->user_data);
1048 }
1049
1050 static void continuing_new(struct avrcp *session, uint8_t pdu_id,
1051                                         const struct iovec *iov, int iov_cnt,
1052                                         size_t offset)
1053 {
1054         struct avrcp_continuing *continuing;
1055         int i;
1056         size_t len = 0;
1057
1058         continuing = g_new0(struct avrcp_continuing, 1);
1059         continuing->pdu_id = pdu_id;
1060
1061         for (i = 0; i < iov_cnt; i++) {
1062                 if (i == 0 && offset) {
1063                         len += iov[i].iov_len - offset;
1064                         continue;
1065                 }
1066
1067                 len += iov[i].iov_len;
1068         }
1069
1070         continuing->pdu.iov_base = g_malloc0(len);
1071
1072         DBG("len %zu", len);
1073
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;
1080                         continue;
1081                 }
1082
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;
1086         }
1087
1088         session->continuing = continuing;
1089 }
1090
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)
1095 {
1096         struct iovec pdu[iov_cnt + 1];
1097         struct avrcp_header hdr;
1098         int i;
1099
1100         /*
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
1104          * aborted.
1105          */
1106         if (session->continuing) {
1107                 continuing_free(session->continuing);
1108                 session->continuing = NULL;
1109         }
1110
1111         memset(&hdr, 0, sizeof(hdr));
1112
1113         pdu[0].iov_base = &hdr;
1114         pdu[0].iov_len = sizeof(hdr);
1115
1116         hdr.packet_type = type;
1117
1118         for (i = 0; i < iov_cnt; i++) {
1119                 pdu[i + 1].iov_base = iov[i].iov_base;
1120
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;
1127                         continue;
1128                 }
1129
1130                 /*
1131                  * Only send what can fit and store the remaining in the
1132                  * continuing iovec
1133                  */
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;
1137
1138                 continuing_new(session, pdu_id, &iov[i], iov_cnt - i,
1139                                                         pdu[i + 1].iov_len);
1140
1141                 hdr.packet_type = hdr.packet_type != AVRCP_PACKET_TYPE_SINGLE ?
1142                                                 AVRCP_PACKET_TYPE_CONTINUING :
1143                                                 AVRCP_PACKET_TYPE_START;
1144                 break;
1145         }
1146
1147         hton24(hdr.company_id, IEEEID_BTSIG);
1148         hdr.pdu_id = pdu_id;
1149         hdr.params_len = htons(hdr.params_len);
1150
1151         return avctp_send_vendor(session->conn, transaction, code, subunit,
1152                                                         pdu, iov_cnt + 1);
1153 }
1154
1155 static ssize_t request_continuing(struct avrcp *session, uint8_t transaction,
1156                                         uint16_t params_len, uint8_t *params,
1157                                         void *user_data)
1158 {
1159         struct iovec iov;
1160         int err;
1161
1162         DBG("");
1163
1164         if (!params || params_len != 1 || !session->continuing ||
1165                                 session->continuing->pdu_id != params[0])
1166                 return -EINVAL;
1167
1168         iov.iov_base = session->continuing->pdu.iov_base;
1169         iov.iov_len = session->continuing->pdu.iov_len;
1170
1171         DBG("len %zu", iov.iov_len);
1172
1173         session->continuing->pdu.iov_base = NULL;
1174
1175         err = avrcp_send_internal(session, transaction, AVC_CTYPE_STABLE,
1176                                         AVC_SUBUNIT_PANEL, params[0],
1177                                         AVRCP_PACKET_TYPE_CONTINUING, &iov, 1);
1178
1179         g_free(iov.iov_base);
1180
1181         if (err < 0)
1182                 return -EINVAL;
1183
1184         return 0;
1185 }
1186
1187 static ssize_t abort_continuing(struct avrcp *session, uint8_t transaction,
1188                                         uint16_t params_len, uint8_t *params,
1189                                         void *user_data)
1190 {
1191         DBG("");
1192
1193         if (!params || params_len != 1 || !session->continuing)
1194                 return -EINVAL;
1195
1196         continuing_free(session->continuing);
1197         session->continuing = NULL;
1198
1199         avrcp_send_internal(session, transaction, AVC_CTYPE_ACCEPTED,
1200                                 AVC_SUBUNIT_PANEL, AVRCP_ABORT_CONTINUING,
1201                                 AVRCP_PACKET_TYPE_SINGLE, NULL, 0);
1202
1203         return 0;
1204 }
1205
1206 static const struct avrcp_control_handler player_handlers[] = {
1207                 { AVRCP_GET_CAPABILITIES,
1208                                         AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1209                                         get_capabilities },
1210                 { AVRCP_LIST_PLAYER_ATTRIBUTES,
1211                                         AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1212                                         list_attributes },
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,
1218                                         list_values },
1219                 { AVRCP_GET_PLAYER_VALUE_TEXT,
1220                                         AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1221                                         get_value_text },
1222                 { AVRCP_GET_CURRENT_PLAYER_VALUE,
1223                                         AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1224                                         get_value },
1225                 { AVRCP_SET_PLAYER_VALUE,
1226                                         AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
1227                                         set_value },
1228                 { AVRCP_GET_PLAY_STATUS,
1229                                         AVC_CTYPE_STATUS, AVC_CTYPE_STABLE,
1230                                         get_play_status },
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,
1239                                         set_volume },
1240                 { AVRCP_SET_ADDRESSED_PLAYER,
1241                                         AVC_CTYPE_CONTROL, AVC_CTYPE_STABLE,
1242                                         set_addressed },
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,
1248                                         abort_continuing },
1249                 { },
1250 };
1251
1252 static void avrcp_set_control_handlers(struct avrcp *session,
1253                                 const struct avrcp_control_handler *handlers,
1254                                 void *user_data)
1255 {
1256         session->control_handlers = handlers;
1257         session->control_data = user_data;
1258 }
1259
1260 static ssize_t set_browsed(struct avrcp *session, uint8_t transaction,
1261                                         uint16_t params_len, uint8_t *params,
1262                                         void *user_data)
1263 {
1264         struct avrcp_player *player = user_data;
1265         struct set_browsed_req *req;
1266         uint16_t id;
1267
1268         DBG("");
1269
1270         if (!player->ind || !player->ind->set_browsed)
1271                 return -ENOSYS;
1272
1273         if (!params || params_len != sizeof(*req))
1274                 return -EINVAL;
1275
1276         req = (void *) params;
1277
1278         id = be16_to_cpu(req->id);
1279
1280         return player->ind->set_browsed(session, transaction, id,
1281                                                         player->user_data);
1282 }
1283
1284 static ssize_t get_folder_items(struct avrcp *session, uint8_t transaction,
1285                                         uint16_t params_len, uint8_t *params,
1286                                         void *user_data)
1287 {
1288         struct avrcp_player *player = user_data;
1289         struct get_folder_items_req *req;
1290         uint32_t start, end;
1291         uint16_t number;
1292         uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
1293         int i;
1294
1295         DBG("");
1296
1297         if (!player->ind || !player->ind->get_folder_items)
1298                 return -ENOSYS;
1299
1300         if (!params || params_len < sizeof(*req))
1301                 return -EINVAL;
1302
1303         req = (void *) params;
1304
1305         if (req->scope > AVRCP_MEDIA_NOW_PLAYING)
1306                 return -EBADRQC;
1307
1308         start = be32_to_cpu(req->start);
1309         end = be32_to_cpu(req->end);
1310
1311         if (start > end)
1312                 return -ERANGE;
1313
1314         number = be16_to_cpu(req->number);
1315
1316         for (i = 0; i < number; i++) {
1317                 attrs[i] = be32_to_cpu(req->attrs[i]);
1318
1319                 if (attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL ||
1320                                 attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST)
1321                         return -EINVAL;
1322         }
1323
1324         return player->ind->get_folder_items(session, transaction, req->scope,
1325                                                 start, end, number, attrs,
1326                                                 player->user_data);
1327 }
1328
1329 static ssize_t change_path(struct avrcp *session, uint8_t transaction,
1330                                         uint16_t params_len, uint8_t *params,
1331                                         void *user_data)
1332 {
1333         struct avrcp_player *player = user_data;
1334         struct change_path_req *req;
1335         uint16_t counter;
1336         uint64_t uid;
1337
1338         DBG("");
1339
1340         if (!player->ind || !player->ind->change_path)
1341                 return -ENOSYS;
1342
1343         if (!params || params_len < sizeof(*req))
1344                 return -EINVAL;
1345
1346         req = (void *) params;
1347
1348         counter = be16_to_cpu(req->counter);
1349         uid = be64_to_cpu(req->uid);
1350
1351         return player->ind->change_path(session, transaction, counter,
1352                                         req->direction, uid, player->user_data);
1353 }
1354
1355 static ssize_t get_item_attributes(struct avrcp *session, uint8_t transaction,
1356                                         uint16_t params_len, uint8_t *params,
1357                                         void *user_data)
1358 {
1359         struct avrcp_player *player = user_data;
1360         struct get_item_attributes_req *req;
1361         uint64_t uid;
1362         uint16_t counter;
1363         uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
1364         int i;
1365
1366         DBG("");
1367
1368         if (!player->ind || !player->ind->get_item_attributes)
1369                 return -ENOSYS;
1370
1371         if (!params || params_len < sizeof(*req))
1372                 return -EINVAL;
1373
1374         req = (void *) params;
1375
1376         if (req->scope > AVRCP_MEDIA_NOW_PLAYING)
1377                 return -EBADRQC;
1378
1379         uid = be64_to_cpu(req->uid);
1380         counter = be16_to_cpu(req->counter);
1381
1382         for (i = 0; i < req->number; i++) {
1383                 attrs[i] = be32_to_cpu(req->attrs[i]);
1384
1385                 if (attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL ||
1386                                 attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST)
1387                         return -EINVAL;
1388         }
1389
1390         return player->ind->get_item_attributes(session, transaction,
1391                                                 req->scope, uid, counter,
1392                                                 req->number, attrs,
1393                                                 player->user_data);
1394 }
1395
1396 static ssize_t play_item(struct avrcp *session, uint8_t transaction,
1397                                         uint16_t params_len, uint8_t *params,
1398                                         void *user_data)
1399 {
1400         struct avrcp_player *player = user_data;
1401         struct play_item_req *req;
1402         uint64_t uid;
1403         uint16_t counter;
1404
1405         DBG("");
1406
1407         if (!player->ind || !player->ind->play_item)
1408                 return -ENOSYS;
1409
1410         if (!params || params_len < sizeof(*req))
1411                 return -EINVAL;
1412
1413         req = (void *) params;
1414
1415         if (req->scope > AVRCP_MEDIA_NOW_PLAYING)
1416                 return -EBADRQC;
1417
1418         uid = be64_to_cpu(req->uid);
1419         counter = be16_to_cpu(req->counter);
1420
1421         return player->ind->play_item(session, transaction, req->scope, uid,
1422                                                 counter, player->user_data);
1423 }
1424
1425 static ssize_t search(struct avrcp *session, uint8_t transaction,
1426                                         uint16_t params_len, uint8_t *params,
1427                                         void *user_data)
1428 {
1429         struct avrcp_player *player = user_data;
1430         struct search_req *req;
1431         char *string;
1432         uint16_t len;
1433         int ret;
1434
1435         DBG("");
1436
1437         if (!player->ind || !player->ind->search)
1438                 return -ENOSYS;
1439
1440         if (!params || params_len < sizeof(*req))
1441                 return -EINVAL;
1442
1443         req = (void *) params;
1444
1445         len = be16_to_cpu(req->len);
1446         if (!len)
1447                 return -EINVAL;
1448
1449         string = strndup(req->string, len);
1450
1451         ret = player->ind->search(session, transaction, string,
1452                                                         player->user_data);
1453
1454         free(string);
1455
1456         return ret;
1457 }
1458
1459 static ssize_t add_to_now_playing(struct avrcp *session, uint8_t transaction,
1460                                         uint16_t params_len, uint8_t *params,
1461                                         void *user_data)
1462 {
1463         struct avrcp_player *player = user_data;
1464         struct add_to_now_playing_req *req;
1465         uint64_t uid;
1466         uint16_t counter;
1467
1468         DBG("");
1469
1470         if (!player->ind || !player->ind->add_to_now_playing)
1471                 return -ENOSYS;
1472
1473         if (!params || params_len < sizeof(*req))
1474                 return -EINVAL;
1475
1476         req = (void *) params;
1477
1478         if (req->scope > AVRCP_MEDIA_NOW_PLAYING)
1479                 return -EBADRQC;
1480
1481         uid = be64_to_cpu(req->uid);
1482         counter = be16_to_cpu(req->counter);
1483
1484         return player->ind->add_to_now_playing(session, transaction, req->scope,
1485                                                         uid, counter,
1486                                                         player->user_data);
1487 }
1488
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 },
1497                 { },
1498 };
1499
1500 static void avrcp_set_browsing_handlers(struct avrcp *session,
1501                                 const struct avrcp_browsing_handler *handlers,
1502                                 void *user_data)
1503 {
1504         session->browsing_handlers = handlers;
1505         session->browsing_data = user_data;
1506 }
1507
1508 void avrcp_register_player(struct avrcp *session,
1509                                 const struct avrcp_control_ind *ind,
1510                                 const struct avrcp_control_cfm *cfm,
1511                                 void *user_data)
1512 {
1513         struct avrcp_player *player;
1514
1515         player = g_new0(struct avrcp_player, 1);
1516         player->ind = ind;
1517         player->cfm = cfm;
1518         player->user_data = user_data;
1519
1520         avrcp_set_control_handlers(session, player_handlers, player);
1521         avrcp_set_browsing_handlers(session, browsing_handlers, player);
1522         session->player = player;
1523 }
1524
1525 void avrcp_set_passthrough_handlers(struct avrcp *session,
1526                         const struct avrcp_passthrough_handler *handlers,
1527                         void *user_data)
1528 {
1529         session->passthrough_handlers = handlers;
1530         session->passthrough_data = user_data;
1531 }
1532
1533 int avrcp_init_uinput(struct avrcp *session, const char *name,
1534                                                         const char *address)
1535 {
1536         return avctp_init_uinput(session->conn, name, address);
1537 }
1538
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)
1542 {
1543         return avrcp_send_internal(session, transaction, code, subunit, pdu_id,
1544                                         AVRCP_PACKET_TYPE_SINGLE, iov, iov_cnt);
1545 }
1546
1547 static int status2errno(uint8_t status)
1548 {
1549         switch (status) {
1550         case AVRCP_STATUS_INVALID_COMMAND:
1551                 return -ENOSYS;
1552         case AVRCP_STATUS_INVALID_PARAM:
1553                 return -EINVAL;
1554         case AVRCP_STATUS_SUCCESS:
1555                 return 0;
1556         case AVRCP_STATUS_NOT_DIRECTORY:
1557                 return -ENOTDIR;
1558         case AVRCP_STATUS_INVALID_SCOPE:
1559                 return -EBADRQC;
1560         case AVRCP_STATUS_OUT_OF_BOUNDS:
1561                 return -ERANGE;
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:
1567                 return -EPERM;
1568         default:
1569                 return -EPROTO;
1570         }
1571 }
1572
1573 static int parse_status(struct avrcp_header *pdu)
1574 {
1575         if (pdu->params_len < 1)
1576                 return -EPROTO;
1577
1578         return status2errno(pdu->params[0]);
1579 }
1580
1581 static int parse_browsing_status(struct avrcp_browsing_header *pdu)
1582 {
1583         if (pdu->params_len < 1)
1584                 return -EPROTO;
1585
1586         return status2errno(pdu->params[0]);
1587 }
1588
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,
1592                                         void *user_data)
1593 {
1594         struct iovec pdu[iov_cnt + 1];
1595         struct avrcp_header hdr;
1596         int i;
1597
1598         memset(&hdr, 0, sizeof(hdr));
1599
1600         pdu[0].iov_base = &hdr;
1601         pdu[0].iov_len = sizeof(hdr);
1602
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;
1607         }
1608
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);
1613
1614         return avctp_send_vendor_req(session->conn, code, subunit, pdu,
1615                                                 iov_cnt + 1, func, user_data);
1616 }
1617
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,
1621                                         void *user_data)
1622 {
1623         struct iovec pdu[iov_cnt + 1];
1624         struct avrcp_browsing_header hdr;
1625         int i;
1626
1627         memset(&hdr, 0, sizeof(hdr));
1628
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;
1633         }
1634
1635         hdr.pdu_id = pdu_id;
1636         hdr.params_len = htons(hdr.params_len);
1637
1638         pdu[0].iov_base = &hdr;
1639         pdu[0].iov_len = sizeof(hdr);
1640
1641         return avctp_send_browsing_req(session->conn, pdu, iov_cnt + 1,
1642                                                         func, user_data);
1643 }
1644
1645 static int avrcp_send_browsing(struct avrcp *session, uint8_t transaction,
1646                                 uint8_t pdu_id, const struct iovec *iov,
1647                                 int iov_cnt)
1648 {
1649         struct iovec pdu[iov_cnt + 1];
1650         struct avrcp_browsing_header hdr;
1651         int i;
1652
1653         memset(&hdr, 0, sizeof(hdr));
1654
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;
1659         }
1660
1661         hdr.pdu_id = pdu_id;
1662         hdr.params_len = htons(hdr.params_len);
1663
1664         pdu[0].iov_base = &hdr;
1665         pdu[0].iov_len = sizeof(hdr);
1666
1667         return avctp_send_browsing(session->conn, transaction, pdu,
1668                                                                 iov_cnt + 1);
1669 }
1670
1671 static gboolean get_capabilities_rsp(struct avctp *conn,
1672                                         uint8_t code, uint8_t subunit,
1673                                         uint8_t *operands, size_t operand_count,
1674                                         void *user_data)
1675 {
1676         struct avrcp *session = user_data;
1677         struct avrcp_player *player = session->player;
1678         struct avrcp_header *pdu;
1679         struct get_capabilities_rsp *rsp;
1680         uint8_t number = 0;
1681         uint8_t *params = NULL;
1682         int err;
1683
1684         DBG("");
1685
1686         if (!player || !player->cfm || !player->cfm->get_capabilities)
1687                 return FALSE;
1688
1689         pdu = parse_pdu(operands, operand_count);
1690         if (!pdu) {
1691                 err = -EPROTO;
1692                 goto done;
1693         }
1694
1695         if (code == AVC_CTYPE_REJECTED) {
1696                 err = parse_status(pdu);
1697                 goto done;
1698         }
1699
1700         if (pdu->params_len < sizeof(*rsp)) {
1701                 err = -EPROTO;
1702                 goto done;
1703         }
1704
1705         rsp = (void *) pdu->params;
1706
1707         switch (rsp->cap) {
1708         case CAP_COMPANY_ID:
1709         case CAP_EVENTS_SUPPORTED:
1710                 break;
1711         default:
1712                 err = -EPROTO;
1713                 goto done;
1714         }
1715
1716         if (rsp->number > 0) {
1717                 number = rsp->number;
1718                 params = rsp->params;
1719         }
1720
1721         err = 0;
1722
1723 done:
1724         player->cfm->get_capabilities(session, err, number, params,
1725                                                         player->user_data);
1726
1727         return FALSE;
1728 }
1729
1730
1731 int avrcp_get_capabilities(struct avrcp *session, uint8_t param)
1732 {
1733         struct iovec iov;
1734         struct get_capabilities_req req;
1735
1736         req.cap = param;
1737
1738         iov.iov_base = &req;
1739         iov.iov_len = sizeof(req);
1740
1741         return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
1742                                         AVRCP_GET_CAPABILITIES, &iov, 1,
1743                                         get_capabilities_rsp, session);
1744 }
1745
1746 static gboolean register_notification_rsp(struct avctp *conn,
1747                                         uint8_t code, uint8_t subunit,
1748                                         uint8_t *operands, size_t operand_count,
1749                                         void *user_data)
1750 {
1751         struct avrcp *session = user_data;
1752         struct avrcp_player *player = session->player;
1753         struct avrcp_header *pdu;
1754         struct register_notification_rsp *rsp;
1755         uint8_t event = 0;
1756         uint16_t value16, value16_2[2];
1757         uint32_t value32;
1758         uint64_t value64;
1759         uint8_t *params = NULL;
1760         int err;
1761
1762         DBG("");
1763
1764         if (!player || !player->cfm || !player->cfm->register_notification)
1765                 return FALSE;
1766
1767         pdu = parse_pdu(operands, operand_count);
1768         if (!pdu) {
1769                 err = -EPROTO;
1770                 goto done;
1771         }
1772
1773         if (code == AVC_CTYPE_REJECTED) {
1774                 err = parse_status(pdu);
1775                 goto done;
1776         }
1777
1778         if (pdu->params_len < sizeof(*rsp)) {
1779                 err = -EPROTO;
1780                 goto done;
1781         }
1782
1783         rsp = (void *) pdu->params;
1784         event = rsp->event;
1785
1786         if (event > AVRCP_EVENT_LAST) {
1787                 err = -EPROTO;
1788                 goto done;
1789         }
1790
1791         switch (event) {
1792         case AVRCP_EVENT_STATUS_CHANGED:
1793                 if (pdu->params_len != sizeof(*rsp) + sizeof(uint8_t)) {
1794                         err = -EPROTO;
1795                         goto done;
1796                 }
1797                 params = rsp->data;
1798                 break;
1799         case AVRCP_EVENT_VOLUME_CHANGED:
1800                 if (pdu->params_len != sizeof(*rsp) + sizeof(uint8_t)) {
1801                         err = -EPROTO;
1802                         goto done;
1803                 }
1804                 params = rsp->data;
1805                 params[0] &= 0x7f;
1806                 break;
1807         case AVRCP_EVENT_TRACK_CHANGED:
1808                 if (pdu->params_len != sizeof(*rsp) + sizeof(value64)) {
1809                         err = -EPROTO;
1810                         goto done;
1811                 }
1812                 value64 = get_be64(rsp->data);
1813                 params = (uint8_t *) &value64;
1814                 break;
1815         case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
1816                 if (pdu->params_len != sizeof(*rsp) + sizeof(value32)) {
1817                         err = -EPROTO;
1818                         goto done;
1819                 }
1820                 value32 = get_be32(rsp->data);
1821                 params = (uint8_t *) &value32;
1822                 break;
1823         case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
1824                 if (pdu->params_len < sizeof(*rsp) + sizeof(value16_2)) {
1825                         err = -EPROTO;
1826                         goto done;
1827                 }
1828                 value16_2[0] = get_be16(rsp->data);
1829                 value16_2[1] = get_be16(rsp->data + 2);
1830                 params = (uint8_t *) value16_2;
1831                 break;
1832         case AVRCP_EVENT_SETTINGS_CHANGED:
1833                 if (pdu->params_len < sizeof(*rsp) + sizeof(uint8_t)) {
1834                         err = -EPROTO;
1835                         goto done;
1836                 }
1837                 params = rsp->data;
1838                 break;
1839         case AVRCP_EVENT_UIDS_CHANGED:
1840                 if (pdu->params_len < sizeof(*rsp) + sizeof(value16)) {
1841                         err = -EPROTO;
1842                         goto done;
1843                 }
1844                 value16 = get_be16(rsp->data);
1845                 params = (uint8_t *) &value16;
1846                 break;
1847         }
1848
1849         err = 0;
1850
1851 done:
1852         return player->cfm->register_notification(session, err, code, event,
1853                                                 params, player->user_data);
1854 }
1855
1856 int avrcp_register_notification(struct avrcp *session, uint8_t event,
1857                                                         uint32_t interval)
1858 {
1859         struct iovec iov;
1860         struct register_notification_req req;
1861
1862         if (event > AVRCP_EVENT_LAST)
1863                 return -EINVAL;
1864
1865         req.event = event;
1866         req.interval = cpu_to_be32(interval);
1867
1868         iov.iov_base = &req;
1869         iov.iov_len = sizeof(req);
1870
1871         return avrcp_send_req(session, AVC_CTYPE_NOTIFY, AVC_SUBUNIT_PANEL,
1872                                 AVRCP_REGISTER_NOTIFICATION, &iov, 1,
1873                                 register_notification_rsp, session);
1874 }
1875
1876 static gboolean list_attributes_rsp(struct avctp *conn,
1877                                         uint8_t code, uint8_t subunit,
1878                                         uint8_t *operands, size_t operand_count,
1879                                         void *user_data)
1880 {
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;
1885         uint8_t number = 0;
1886         uint8_t *attrs = NULL;
1887         int err;
1888
1889         DBG("");
1890
1891         if (!player || !player->cfm || !player->cfm->list_attributes)
1892                 return FALSE;
1893
1894         pdu = parse_pdu(operands, operand_count);
1895         if (!pdu) {
1896                 err = -EPROTO;
1897                 goto done;
1898         }
1899
1900         if (code == AVC_CTYPE_REJECTED) {
1901                 err = parse_status(pdu);
1902                 goto done;
1903         }
1904
1905         rsp = (void *) pdu->params;
1906
1907         if (pdu->params_len < sizeof(*rsp)) {
1908                 err = -EPROTO;
1909                 goto done;
1910         }
1911
1912         number = rsp->number;
1913         if (number > 0)
1914                 attrs = rsp->params;
1915
1916         err = 0;
1917
1918 done:
1919         player->cfm->list_attributes(session, err, number, attrs,
1920                                                         player->user_data);
1921
1922         return FALSE;
1923 }
1924
1925 int avrcp_list_player_attributes(struct avrcp *session)
1926 {
1927         return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
1928                                 AVRCP_LIST_PLAYER_ATTRIBUTES, NULL, 0,
1929                                 list_attributes_rsp, session);
1930 }
1931
1932 static int parse_text_rsp(struct avrcp_header *pdu, uint8_t *number,
1933                                         uint8_t *attrs, char **text)
1934 {
1935         uint8_t *ptr;
1936         uint16_t params_len;
1937         int i;
1938
1939         if (pdu->params_len < 1)
1940                 return -EPROTO;
1941
1942         *number = pdu->params[0];
1943         if (*number > AVRCP_ATTRIBUTE_LAST) {
1944                 *number = 0;
1945                 return -EPROTO;
1946         }
1947
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;
1951
1952                 if (params_len < sizeof(*val))
1953                         goto fail;
1954
1955                 val = (void *) ptr;
1956
1957                 attrs[i] = val->attr;
1958
1959                 params_len -= sizeof(*val);
1960                 ptr += sizeof(*val);
1961
1962                 if (val->len > params_len)
1963                         goto fail;
1964
1965                 if (val->len > 0) {
1966                         text[i] = g_strndup(val->data, val->len);
1967                         params_len -= val->len;
1968                         ptr += val->len;
1969                 }
1970         }
1971
1972         if (i != *number)
1973                 goto fail;
1974
1975         return 0;
1976
1977 fail:
1978         for (i -= 1; i >= 0; i--)
1979                 g_free(text[i]);
1980
1981         *number = 0;
1982
1983         return -EPROTO;
1984 }
1985
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,
1989                                         void *user_data)
1990 {
1991         struct avrcp *session = user_data;
1992         struct avrcp_player *player = session->player;
1993         struct avrcp_header *pdu;
1994         uint8_t number = 0;
1995         uint8_t attrs[AVRCP_ATTRIBUTE_LAST];
1996         char *text[AVRCP_ATTRIBUTE_LAST];
1997         int err;
1998
1999         DBG("");
2000
2001         if (!player || !player->cfm || !player->cfm->get_attribute_text)
2002                 return FALSE;
2003
2004         pdu = parse_pdu(operands, operand_count);
2005         if (!pdu) {
2006                 err = -EPROTO;
2007                 goto done;
2008         }
2009
2010         if (code == AVC_CTYPE_REJECTED) {
2011                 err = parse_status(pdu);
2012                 goto done;
2013         }
2014
2015         err = parse_text_rsp(pdu, &number, attrs, text);
2016
2017 done:
2018         player->cfm->get_attribute_text(session, err, number, attrs, text,
2019                                                         player->user_data);
2020
2021         return FALSE;
2022 }
2023
2024 int avrcp_get_player_attribute_text(struct avrcp *session, uint8_t number,
2025                                                                 uint8_t *attrs)
2026 {
2027         struct iovec iov[2];
2028
2029         if (!number || number > AVRCP_ATTRIBUTE_LAST)
2030                 return -EINVAL;
2031
2032         iov[0].iov_base = &number;
2033         iov[0].iov_len = sizeof(number);
2034
2035         iov[1].iov_base = attrs;
2036         iov[1].iov_len = number;
2037
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);
2041 }
2042
2043 static gboolean list_values_rsp(struct avctp *conn,
2044                                         uint8_t code, uint8_t subunit,
2045                                         uint8_t *operands, size_t operand_count,
2046                                         void *user_data)
2047 {
2048         struct avrcp *session = user_data;
2049         struct avrcp_player *player = session->player;
2050         struct avrcp_header *pdu;
2051         struct list_values_rsp *rsp;
2052         uint8_t number = 0;
2053         uint8_t *values = NULL;
2054         int err;
2055
2056         DBG("");
2057
2058         if (!player || !player->cfm || !player->cfm->list_values)
2059                 return FALSE;
2060
2061         pdu = parse_pdu(operands, operand_count);
2062         if (!pdu) {
2063                 err = -EPROTO;
2064                 goto done;
2065         }
2066
2067         if (code == AVC_CTYPE_REJECTED) {
2068                 err = parse_status(pdu);
2069                 goto done;
2070         }
2071
2072         if (pdu->params_len < sizeof(*rsp)) {
2073                 err = -EPROTO;
2074                 goto done;
2075         }
2076
2077         rsp = (void *) pdu->params;
2078
2079         if (rsp->number > 0) {
2080                 number = rsp->number;
2081                 values = rsp->params;
2082         }
2083
2084         err = 0;
2085
2086 done:
2087         player->cfm->list_values(session, err, number, values,
2088                                                         player->user_data);
2089
2090         return FALSE;
2091 }
2092
2093 int avrcp_list_player_values(struct avrcp *session, uint8_t attr)
2094 {
2095         struct iovec iov;
2096
2097         iov.iov_base = &attr;
2098         iov.iov_len = sizeof(attr);
2099
2100         return avrcp_send_req(session, AVC_CTYPE_STATUS, AVC_SUBUNIT_PANEL,
2101                                         AVRCP_LIST_PLAYER_VALUES, &iov, 1,
2102                                         list_values_rsp, session);
2103 }
2104
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,
2108                                         void *user_data)
2109 {
2110         struct avrcp *session = user_data;
2111         struct avrcp_player *player = session->player;
2112         struct avrcp_header *pdu;
2113         uint8_t number = 0;
2114         uint8_t values[AVRCP_ATTRIBUTE_LAST];
2115         char *text[AVRCP_ATTRIBUTE_LAST];
2116         int err;
2117
2118         DBG("");
2119
2120         if (!player || !player->cfm || !player->cfm->get_value_text)
2121                 return FALSE;
2122
2123         pdu = parse_pdu(operands, operand_count);
2124         if (!pdu) {
2125                 err = -EPROTO;
2126                 goto done;
2127         }
2128
2129         if (code == AVC_CTYPE_REJECTED) {
2130                 err = parse_status(pdu);
2131                 goto done;
2132         }
2133
2134         err = parse_text_rsp(pdu, &number, values, text);
2135
2136 done:
2137         player->cfm->get_value_text(session, err, number, values, text,
2138                                                         player->user_data);
2139
2140         return FALSE;
2141 }
2142
2143 int avrcp_get_player_value_text(struct avrcp *session, uint8_t attr,
2144                                         uint8_t number, uint8_t *values)
2145 {
2146         struct iovec iov[2];
2147         struct get_value_text_req req;
2148
2149         if (!number)
2150                 return -EINVAL;
2151
2152         req.attr = attr;
2153         req.number = number;
2154
2155         iov[0].iov_base = &req;
2156         iov[0].iov_len = sizeof(req);
2157
2158         iov[1].iov_base = values;
2159         iov[1].iov_len = number;
2160
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);
2164 }
2165
2166 static int parse_value(struct avrcp_header *pdu, uint8_t *number,
2167                                         uint8_t *attrs, uint8_t *values)
2168 {
2169         int i;
2170         struct value_rsp *rsp;
2171
2172         if (pdu->params_len < sizeof(*rsp))
2173                 return -EPROTO;
2174
2175         rsp = (void *) pdu->params;
2176
2177         /*
2178          * Check if PDU is big enough to hold the number of (attribute, value)
2179          * tuples.
2180          */
2181         if (rsp->number > AVRCP_ATTRIBUTE_LAST ||
2182                         sizeof(*rsp) + rsp->number * 2 != pdu->params_len) {
2183                 *number = 0;
2184                 return -EPROTO;
2185         }
2186
2187         for (i = 0; i < rsp->number; i++) {
2188                 attrs[i] = rsp->values[i].attr;
2189                 values[i] = rsp->values[i].value;
2190         }
2191
2192         *number = rsp->number;
2193
2194         return 0;
2195 }
2196
2197 static gboolean get_value_rsp(struct avctp *conn,
2198                                         uint8_t code, uint8_t subunit,
2199                                         uint8_t *operands, size_t operand_count,
2200                                         void *user_data)
2201 {
2202         struct avrcp *session = user_data;
2203         struct avrcp_player *player = session->player;
2204         struct avrcp_header *pdu;
2205         uint8_t number = 0;
2206         uint8_t attrs[AVRCP_ATTRIBUTE_LAST];
2207         uint8_t values[AVRCP_ATTRIBUTE_LAST];
2208         int err;
2209
2210         DBG("");
2211
2212         if (!player || !player->cfm || !player->cfm->get_value)
2213                 return FALSE;
2214
2215         pdu = parse_pdu(operands, operand_count);
2216         if (!pdu) {
2217                 err = -EPROTO;
2218                 goto done;
2219         }
2220
2221         if (code == AVC_CTYPE_REJECTED) {
2222                 err = parse_status(pdu);
2223                 goto done;
2224         }
2225
2226         err = parse_value(pdu, &number, attrs, values);
2227
2228 done:
2229         player->cfm->get_value(session, err, number, attrs, values,
2230                                                         player->user_data);
2231
2232         return FALSE;
2233 }
2234
2235 int avrcp_get_current_player_value(struct avrcp *session, uint8_t number,
2236                                                         uint8_t *attrs)
2237
2238 {
2239         struct iovec iov[2];
2240
2241         if (number > AVRCP_ATTRIBUTE_LAST)
2242                 return -EINVAL;
2243
2244         iov[0].iov_base = &number;
2245         iov[0].iov_len = sizeof(number);
2246
2247         iov[1].iov_base = attrs;
2248         iov[1].iov_len = number;
2249
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);
2253 }
2254
2255 static gboolean set_value_rsp(struct avctp *conn,
2256                                         uint8_t code, uint8_t subunit,
2257                                         uint8_t *operands, size_t operand_count,
2258                                         void *user_data)
2259 {
2260         struct avrcp *session = user_data;
2261         struct avrcp_player *player = session->player;
2262         struct avrcp_header *pdu;
2263         int err;
2264
2265         DBG("");
2266
2267         if (!player || !player->cfm || !player->cfm->set_value)
2268                 return FALSE;
2269
2270         pdu = parse_pdu(operands, operand_count);
2271         if (!pdu) {
2272                 err = -EPROTO;
2273                 goto done;
2274         }
2275
2276         if (code == AVC_CTYPE_REJECTED) {
2277                 err = parse_status(pdu);
2278                 goto done;
2279         }
2280
2281         err = 0;
2282
2283 done:
2284         player->cfm->set_value(session, err, player->user_data);
2285
2286         return FALSE;
2287 }
2288
2289 int avrcp_set_player_value(struct avrcp *session, uint8_t number,
2290                                         uint8_t *attrs, uint8_t *values)
2291 {
2292         struct iovec iov[2];
2293         struct attr_value val[AVRCP_ATTRIBUTE_LAST];
2294         int i;
2295
2296         if (number > AVRCP_ATTRIBUTE_LAST)
2297                 return -EINVAL;
2298
2299         iov[0].iov_base = &number;
2300         iov[0].iov_len = sizeof(number);
2301
2302         for (i = 0; i < number; i++) {
2303                 val[i].attr = attrs[i];
2304                 val[i].value = values[i];
2305         }
2306
2307         iov[1].iov_base = val;
2308         iov[1].iov_len = sizeof(*val) * number;
2309
2310         return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
2311                                         AVRCP_SET_PLAYER_VALUE, iov, 2,
2312                                         set_value_rsp, session);
2313 }
2314
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,
2318                                         void *user_data)
2319 {
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;
2324         uint8_t status = 0;
2325         uint32_t position = 0;
2326         uint32_t duration = 0;
2327         int err;
2328
2329         DBG("");
2330
2331         if (!player || !player->cfm || !player->cfm->get_play_status)
2332                 return FALSE;
2333
2334         pdu = parse_pdu(operands, operand_count);
2335         if (!pdu) {
2336                 err = -EPROTO;
2337                 goto done;
2338         }
2339
2340         if (code == AVC_CTYPE_REJECTED) {
2341                 err = parse_status(pdu);
2342                 goto done;
2343         }
2344
2345         if (pdu->params_len < sizeof(*rsp)) {
2346                 err = -EPROTO;
2347                 goto done;
2348         }
2349
2350         rsp = (void *) pdu->params;
2351
2352         duration = be32_to_cpu(rsp->duration);
2353         position = be32_to_cpu(rsp->position);
2354         status = rsp->status;
2355         err = 0;
2356
2357 done:
2358         player->cfm->get_play_status(session, err, status, position, duration,
2359                                                         player->user_data);
2360
2361         return FALSE;
2362 }
2363
2364 int avrcp_get_play_status(struct avrcp *session)
2365 {
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);
2369 }
2370
2371 static gboolean set_volume_rsp(struct avctp *conn,
2372                                         uint8_t code, uint8_t subunit,
2373                                         uint8_t *operands, size_t operand_count,
2374                                         void *user_data)
2375 {
2376         struct avrcp *session = user_data;
2377         struct avrcp_player *player = session->player;
2378         struct avrcp_header *pdu;
2379         struct set_volume_rsp *rsp;
2380         uint8_t value = 0;
2381         int err;
2382
2383         DBG("");
2384
2385         if (!player || !player->cfm || !player->cfm->set_volume)
2386                 return FALSE;
2387
2388         pdu = parse_pdu(operands, operand_count);
2389         if (!pdu) {
2390                 err = -EPROTO;
2391                 goto done;
2392         }
2393
2394         if (code == AVC_CTYPE_REJECTED) {
2395                 err = parse_status(pdu);
2396                 goto done;
2397         }
2398
2399         if (pdu->params_len < sizeof(*rsp)) {
2400                 err = -EPROTO;
2401                 goto done;
2402         }
2403
2404         rsp = (void *) pdu->params;
2405
2406         value = rsp->value & 0x7f;
2407         err = 0;
2408
2409 done:
2410         player->cfm->set_volume(session, err, value, player->user_data);
2411
2412         return FALSE;
2413 }
2414
2415 int avrcp_set_volume(struct avrcp *session, uint8_t volume)
2416 {
2417         struct iovec iov;
2418
2419         iov.iov_base = &volume;
2420         iov.iov_len = sizeof(volume);
2421
2422         return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
2423                                 AVRCP_SET_ABSOLUTE_VOLUME, &iov, 1,
2424                                 set_volume_rsp, session);
2425 }
2426
2427 static int parse_attribute_list(uint8_t *params, uint16_t params_len,
2428                                 uint8_t number, uint32_t *attrs, char **text)
2429 {
2430         struct media_item *item;
2431         int i;
2432
2433         if (number > AVRCP_MEDIA_ATTRIBUTE_LAST)
2434                 return -EPROTO;
2435
2436         for (i = 0; i < number && params_len >= sizeof(*item); i++) {
2437                 item = (void *) params;
2438
2439                 item->attr = be32_to_cpu(item->attr);
2440                 item->charset = be16_to_cpu(item->charset);
2441                 item->len = be16_to_cpu(item->len);
2442
2443                 params_len -= sizeof(*item);
2444                 params += sizeof(*item);
2445                 if (item->len > params_len)
2446                         goto fail;
2447
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;
2453                 } else {
2454                         text[i] = NULL;
2455                         attrs[i] = 0;
2456                 }
2457         }
2458
2459         return 0;
2460
2461 fail:
2462         for (i -= 1; i >= 0; i--)
2463                 g_free(text[i]);
2464
2465         return -EPROTO;
2466 }
2467
2468 static void free_attribute_list(uint8_t number, char **text)
2469 {
2470         while(number--)
2471                 g_free(text[number]);
2472 }
2473
2474 static int parse_elements(struct avrcp_header *pdu, uint8_t *number,
2475                                                 uint32_t *attrs, char **text)
2476 {
2477         struct get_element_attributes_rsp *rsp;
2478
2479         if (pdu->params_len < sizeof(*rsp))
2480                 return -EPROTO;
2481
2482         rsp = (void *) pdu->params;
2483         if (rsp->number > AVRCP_MEDIA_ATTRIBUTE_LAST)
2484                 return -EPROTO;
2485
2486         *number = rsp->number;
2487
2488         return parse_attribute_list(pdu->params + sizeof(*rsp),
2489                                                 pdu->params_len - sizeof(*rsp),
2490                                                 *number, attrs, text);
2491 }
2492
2493 static int parse_items(struct avrcp_browsing_header *pdu, uint8_t *number,
2494                                                 uint32_t *attrs, char **text)
2495 {
2496         struct get_item_attributes_rsp *rsp;
2497
2498         if (pdu->params_len < sizeof(*rsp))
2499                 return -EPROTO;
2500
2501         rsp = (void *) pdu->params;
2502
2503         if (rsp->number > AVRCP_MEDIA_ATTRIBUTE_LAST)
2504                 return -EPROTO;
2505
2506         *number = rsp->number;
2507
2508         return parse_attribute_list(pdu->params + sizeof(*rsp),
2509                                                 pdu->params_len - sizeof(*rsp),
2510                                                 *number, attrs, text);
2511 }
2512
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,
2516                                         void *user_data)
2517 {
2518         struct avrcp *session = user_data;
2519         struct avrcp_player *player = session->player;
2520         struct avrcp_header *pdu;
2521         uint8_t number = 0;
2522         uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
2523         char *text[AVRCP_MEDIA_ATTRIBUTE_LAST];
2524         int err;
2525
2526         DBG("");
2527
2528         if (!player || !player->cfm || !player->cfm->get_element_attributes)
2529                 return FALSE;
2530
2531         pdu = parse_pdu(operands, operand_count);
2532         if (!pdu) {
2533                 err = -EPROTO;
2534                 goto done;
2535         }
2536
2537         if (code == AVC_CTYPE_REJECTED) {
2538                 err = parse_status(pdu);
2539                 goto done;
2540         }
2541
2542         err = parse_elements(pdu, &number, attrs, text);
2543
2544 done:
2545         player->cfm->get_element_attributes(session, err, number, attrs, text,
2546                                                         player->user_data);
2547
2548         if (err == 0)
2549                 free_attribute_list(number, text);
2550
2551         return FALSE;
2552 }
2553
2554 int avrcp_get_element_attributes(struct avrcp *session)
2555 {
2556         struct iovec iov;
2557         struct get_element_attributes_req req;
2558
2559         /* This returns all attributes */
2560         memset(&req, 0, sizeof(req));
2561
2562         iov.iov_base = &req;
2563         iov.iov_len = sizeof(req);
2564
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);
2568 }
2569
2570 static gboolean set_addressed_rsp(struct avctp *conn,
2571                                         uint8_t code, uint8_t subunit,
2572                                         uint8_t *operands, size_t operand_count,
2573                                         void *user_data)
2574 {
2575         struct avrcp *session = user_data;
2576         struct avrcp_player *player = session->player;
2577         struct avrcp_header *pdu;
2578         int err;
2579
2580         DBG("");
2581
2582         if (!player || !player->cfm || !player->cfm->set_addressed)
2583                 return FALSE;
2584
2585         pdu = parse_pdu(operands, operand_count);
2586         if (!pdu) {
2587                 err = -EPROTO;
2588                 goto done;
2589         }
2590
2591         err = parse_status(pdu);
2592
2593 done:
2594         player->cfm->set_addressed(session, err, player->user_data);
2595
2596         return FALSE;
2597 }
2598
2599 int avrcp_set_addressed_player(struct avrcp *session, uint16_t player_id)
2600 {
2601         struct iovec iov;
2602         struct set_addressed_req req;
2603
2604         req.id = cpu_to_be16(player_id);
2605
2606         iov.iov_base = &req;
2607         iov.iov_len = sizeof(req);
2608
2609         return avrcp_send_req(session, AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
2610                                         AVRCP_SET_ADDRESSED_PLAYER, &iov, 1,
2611                                         set_addressed_rsp, session);
2612 }
2613
2614 static char *parse_folder_list(uint8_t *params, uint16_t params_len,
2615                                                                 uint8_t depth)
2616 {
2617         char **folders, *path;
2618         uint8_t count;
2619         size_t i;
2620
2621         folders = g_new0(char *, depth + 2);
2622         folders[0] = g_strdup("/Filesystem");
2623
2624         for (i = 0, count = 1; count <= depth && i < params_len; count++) {
2625                 uint8_t len;
2626
2627                 len = params[i++];
2628
2629                 if (i + len > params_len || len == 0) {
2630                         g_strfreev(folders);
2631                         return NULL;
2632                 }
2633
2634                 folders[count] = g_memdup(&params[i], len);
2635                 i += len;
2636         }
2637
2638         path = g_build_pathv("/", folders);
2639         g_strfreev(folders);
2640
2641         return path;
2642 }
2643
2644 static gboolean set_browsed_rsp(struct avctp *conn, uint8_t *operands,
2645                                         size_t operand_count, void *user_data)
2646 {
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;
2652         uint32_t items = 0;
2653         char *path = NULL;
2654         int err;
2655
2656         DBG("");
2657
2658         if (!player || !player->cfm || !player->cfm->set_browsed)
2659                 return FALSE;
2660
2661         pdu = parse_browsing_pdu(operands, operand_count);
2662         if (!pdu) {
2663                 err = -EPROTO;
2664                 goto done;
2665         }
2666
2667         err = parse_browsing_status(pdu);
2668         if (err < 0)
2669                 goto done;
2670
2671         if (pdu->params_len < sizeof(*rsp)) {
2672                 err = -EPROTO;
2673                 goto done;
2674         }
2675
2676         rsp = (void *) pdu->params;
2677
2678         counter = be16_to_cpu(rsp->counter);
2679         items = be32_to_cpu(rsp->items);
2680
2681         path = parse_folder_list(rsp->data, pdu->params_len - sizeof(*rsp),
2682                                                                 rsp->depth);
2683         if (!path)
2684                 err = -EPROTO;
2685
2686 done:
2687         player->cfm->set_browsed(session, err, counter, items, path,
2688                                                         player->user_data);
2689
2690         return FALSE;
2691 }
2692
2693 int avrcp_set_browsed_player(struct avrcp *session, uint16_t player_id)
2694 {
2695         struct iovec iov;
2696         struct set_browsed_req req;
2697
2698         req.id = cpu_to_be16(player_id);
2699
2700         iov.iov_base = &req;
2701         iov.iov_len = sizeof(req);
2702
2703         return avrcp_send_browsing_req(session, AVRCP_SET_BROWSED_PLAYER,
2704                                         &iov, 1, set_browsed_rsp, session);
2705 }
2706
2707 static gboolean get_folder_items_rsp(struct avctp *conn,
2708                                         uint8_t *operands, size_t operand_count,
2709                                         void *user_data)
2710 {
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;
2717         int err;
2718
2719         DBG("");
2720
2721         if (!player || !player->cfm || !player->cfm->get_folder_items)
2722                 return FALSE;
2723
2724         pdu = parse_browsing_pdu(operands, operand_count);
2725         if (!pdu) {
2726                 err = -EPROTO;
2727                 goto done;
2728         }
2729
2730         err = parse_browsing_status(pdu);
2731         if (err < 0)
2732                 goto done;
2733
2734         if (pdu->params_len < sizeof(*rsp)) {
2735                 err = -EPROTO;
2736                 goto done;
2737         }
2738
2739         rsp = (void *) pdu->params;
2740
2741         counter = be16_to_cpu(rsp->counter);
2742         number = be16_to_cpu(rsp->number);
2743         params = rsp->data;
2744
2745         /* FIXME: Add proper parsing for each item type */
2746
2747 done:
2748         player->cfm->get_folder_items(session, err, counter, number, params,
2749                                                         player->user_data);
2750
2751         return FALSE;
2752 }
2753
2754 int avrcp_get_folder_items(struct avrcp *session, uint8_t scope,
2755                                 uint32_t start, uint32_t end, uint8_t number,
2756                                 uint32_t *attrs)
2757 {
2758
2759         struct iovec iov[2];
2760         struct get_folder_items_req req;
2761         int i;
2762
2763         req.scope = scope;
2764         req.start = cpu_to_be32(start);
2765         req.end = cpu_to_be32(end);
2766         req.number = number;
2767
2768         iov[0].iov_base = &req;
2769         iov[0].iov_len = sizeof(req);
2770
2771         if (!number)
2772                 return avrcp_send_browsing_req(session, AVRCP_GET_FOLDER_ITEMS,
2773                                                 iov, 1, get_folder_items_rsp,
2774                                                 session);
2775
2776         for (i = 0; i < number; i++)
2777                 attrs[i] = cpu_to_be32(attrs[i]);
2778
2779         iov[1].iov_base = attrs;
2780         iov[1].iov_len = number * sizeof(*attrs);
2781
2782         return avrcp_send_browsing_req(session, AVRCP_GET_FOLDER_ITEMS,
2783                                         iov, 2, get_folder_items_rsp, session);
2784 }
2785
2786 static gboolean change_path_rsp(struct avctp *conn, uint8_t *operands,
2787                                         size_t operand_count, void *user_data)
2788 {
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;
2793         uint32_t items = 0;
2794         int err;
2795
2796         DBG("");
2797
2798         if (!player || !player->cfm || !player->cfm->change_path)
2799                 return FALSE;
2800
2801         pdu = parse_browsing_pdu(operands, operand_count);
2802         if (!pdu) {
2803                 err = -EPROTO;
2804                 goto done;
2805         }
2806
2807         err = parse_browsing_status(pdu);
2808         if (err < 0)
2809                 goto done;
2810
2811         if (pdu->params_len < sizeof(*rsp)) {
2812                 err = -EPROTO;
2813                 goto done;
2814         }
2815
2816         rsp = (void *) pdu->params;
2817
2818         items = be32_to_cpu(rsp->items);
2819
2820 done:
2821         player->cfm->change_path(session, err, items, player->user_data);
2822
2823         return FALSE;
2824 }
2825
2826 int avrcp_change_path(struct avrcp *session, uint8_t direction, uint64_t uid,
2827                                                         uint16_t counter)
2828 {
2829         struct iovec iov;
2830         struct change_path_req req;
2831
2832         req.counter = cpu_to_be16(counter);
2833         req.direction = direction;
2834         req.uid = cpu_to_be64(uid);
2835
2836         iov.iov_base = &req;
2837         iov.iov_len = sizeof(req);
2838
2839         return avrcp_send_browsing_req(session, AVRCP_CHANGE_PATH,
2840                                         &iov, 1, change_path_rsp, session);
2841 }
2842
2843 static gboolean get_item_attributes_rsp(struct avctp *conn, uint8_t *operands,
2844                                         size_t operand_count, void *user_data)
2845 {
2846         struct avrcp *session = user_data;
2847         struct avrcp_player *player = session->player;
2848         struct avrcp_browsing_header *pdu;
2849         uint8_t number = 0;
2850         uint32_t attrs[AVRCP_MEDIA_ATTRIBUTE_LAST];
2851         char *text[AVRCP_MEDIA_ATTRIBUTE_LAST];
2852         int err;
2853
2854         DBG("");
2855
2856         if (!player || !player->cfm || !player->cfm->get_item_attributes)
2857                 return FALSE;
2858
2859         pdu = parse_browsing_pdu(operands, operand_count);
2860         if (!pdu) {
2861                 err = -EPROTO;
2862                 goto done;
2863         }
2864
2865         err = parse_browsing_status(pdu);
2866         if (err < 0)
2867                 goto done;
2868
2869         err = parse_items(pdu, &number, attrs, text);
2870
2871 done:
2872         player->cfm->get_item_attributes(session, err, number, attrs, text,
2873                                                         player->user_data);
2874
2875         if (err == 0)
2876                 free_attribute_list(number, text);
2877
2878         return FALSE;
2879 }
2880
2881 int avrcp_get_item_attributes(struct avrcp *session, uint8_t scope,
2882                                 uint64_t uid, uint16_t counter, uint8_t number,
2883                                 uint32_t *attrs)
2884 {
2885         struct iovec iov[2];
2886         struct get_item_attributes_req req;
2887         int i;
2888
2889         req.scope = scope;
2890         req.uid = cpu_to_be64(uid);
2891         req.counter = cpu_to_be16(counter);
2892         req.number = number;
2893
2894         iov[0].iov_base = &req;
2895         iov[0].iov_len = sizeof(req);
2896
2897         if (!number)
2898                 return avrcp_send_browsing_req(session,
2899                                                 AVRCP_GET_ITEM_ATTRIBUTES,
2900                                                 iov, 1, get_item_attributes_rsp,
2901                                                 session);
2902
2903         if (number > AVRCP_MEDIA_ATTRIBUTE_LAST)
2904                 return -EINVAL;
2905
2906         for (i = 0; i < number; i++) {
2907                 if (attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST ||
2908                                 attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL)
2909                         return -EINVAL;
2910                 attrs[i] = cpu_to_be32(attrs[i]);
2911         }
2912
2913         iov[1].iov_base = attrs;
2914         iov[1].iov_len = number * sizeof(*attrs);
2915
2916         return avrcp_send_browsing_req(session, AVRCP_GET_ITEM_ATTRIBUTES,
2917                                         iov, 2, get_item_attributes_rsp,
2918                                         session);
2919 }
2920
2921 static gboolean play_item_rsp(struct avctp *conn, uint8_t *operands,
2922                                         size_t operand_count, void *user_data)
2923 {
2924         struct avrcp *session = user_data;
2925         struct avrcp_player *player = session->player;
2926         struct avrcp_browsing_header *pdu;
2927         int err;
2928
2929         DBG("");
2930
2931         if (!player || !player->cfm || !player->cfm->play_item)
2932                 return FALSE;
2933
2934         pdu = parse_browsing_pdu(operands, operand_count);
2935         if (!pdu) {
2936                 err = -EPROTO;
2937                 goto done;
2938         }
2939
2940         err = parse_browsing_status(pdu);
2941
2942 done:
2943         player->cfm->play_item(session, err, player->user_data);
2944
2945         return FALSE;
2946 }
2947
2948 int avrcp_play_item(struct avrcp *session, uint8_t scope, uint64_t uid,
2949                                                         uint16_t counter)
2950 {
2951         struct iovec iov;
2952         struct play_item_req req;
2953
2954         if (scope > AVRCP_MEDIA_NOW_PLAYING)
2955                 return -EINVAL;
2956
2957         req.scope = scope;
2958         req.uid = cpu_to_be64(uid);
2959         req.counter = cpu_to_be16(counter);
2960
2961         iov.iov_base = &req;
2962         iov.iov_len = sizeof(req);
2963
2964         return avrcp_send_browsing_req(session, AVRCP_PLAY_ITEM, &iov, 1,
2965                                                 play_item_rsp, session);
2966 }
2967
2968 static gboolean search_rsp(struct avctp *conn, uint8_t *operands,
2969                                         size_t operand_count, void *user_data)
2970 {
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;
2976         uint32_t items = 0;
2977         int err;
2978
2979         DBG("");
2980
2981         if (!player || !player->cfm || !player->cfm->search)
2982                 return FALSE;
2983
2984         pdu = parse_browsing_pdu(operands, operand_count);
2985         if (!pdu) {
2986                 err = -EPROTO;
2987                 goto done;
2988         }
2989
2990         err = parse_browsing_status(pdu);
2991         if (err < 0)
2992                 goto done;
2993
2994         if (pdu->params_len < sizeof(*rsp)) {
2995                 err = -EPROTO;
2996                 goto done;
2997         }
2998
2999         rsp = (void *) pdu->params;
3000
3001         counter = be16_to_cpu(rsp->counter);
3002         items = be32_to_cpu(rsp->items);
3003
3004         err = 0;
3005
3006 done:
3007         player->cfm->search(session, err, counter, items, player->user_data);
3008
3009         return FALSE;
3010 }
3011
3012 int avrcp_search(struct avrcp *session, const char *string)
3013 {
3014         struct iovec iov[2];
3015         struct search_req req;
3016         size_t len;
3017
3018         if (!string)
3019                 return -EINVAL;
3020
3021         len = strnlen(string, UINT8_MAX);
3022
3023         req.charset = cpu_to_be16(AVRCP_CHARSET_UTF8);
3024         req.len = cpu_to_be16(len);
3025
3026         iov[0].iov_base = &req;
3027         iov[0].iov_len = sizeof(req);
3028
3029         iov[1].iov_base = (void *) string;
3030         iov[1].iov_len = len;
3031
3032         return avrcp_send_browsing_req(session, AVRCP_SEARCH, iov, 2,
3033                                                         search_rsp, session);
3034 }
3035
3036 static gboolean add_to_now_playing_rsp(struct avctp *conn, uint8_t *operands,
3037                                         size_t operand_count, void *user_data)
3038 {
3039         struct avrcp *session = user_data;
3040         struct avrcp_player *player = session->player;
3041         struct avrcp_browsing_header *pdu;
3042         int err;
3043
3044         DBG("");
3045
3046         if (!player || !player->cfm || !player->cfm->add_to_now_playing)
3047                 return FALSE;
3048
3049         pdu = parse_browsing_pdu(operands, operand_count);
3050         if (!pdu) {
3051                 err = -EPROTO;
3052                 goto done;
3053         }
3054
3055         err = parse_browsing_status(pdu);
3056
3057 done:
3058         player->cfm->add_to_now_playing(session, err, player->user_data);
3059
3060         return FALSE;
3061 }
3062
3063 int avrcp_add_to_now_playing(struct avrcp *session, uint8_t scope, uint64_t uid,
3064                                                         uint16_t counter)
3065 {
3066         struct iovec iov;
3067         struct add_to_now_playing_req req;
3068
3069         if (scope > AVRCP_MEDIA_NOW_PLAYING)
3070                 return -EINVAL;
3071
3072         req.scope = scope;
3073         req.uid = cpu_to_be64(uid);
3074         req.counter = cpu_to_be16(counter);
3075
3076         iov.iov_base = &req;
3077         iov.iov_len = sizeof(req);
3078
3079         return avrcp_send_browsing_req(session, AVRCP_ADD_TO_NOW_PLAYING,
3080                                         &iov, 1, add_to_now_playing_rsp,
3081                                         session);
3082 }
3083
3084 int avrcp_get_capabilities_rsp(struct avrcp *session, uint8_t transaction,
3085                                                 uint8_t number, uint8_t *events)
3086 {
3087         struct iovec iov[2];
3088         struct get_capabilities_rsp rsp;
3089
3090         if (number > AVRCP_EVENT_LAST)
3091                 return -EINVAL;
3092
3093         rsp.cap = CAP_EVENTS_SUPPORTED;
3094         rsp.number = number;
3095
3096         iov[0].iov_base = &rsp;
3097         iov[0].iov_len = sizeof(rsp);
3098
3099         iov[1].iov_base = events;
3100         iov[1].iov_len = number;
3101
3102         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3103                                 AVC_SUBUNIT_PANEL, AVRCP_GET_CAPABILITIES,
3104                                 iov, 2);
3105 }
3106
3107 int avrcp_list_player_attributes_rsp(struct avrcp *session, uint8_t transaction,
3108                                         uint8_t number, uint8_t *attrs)
3109 {
3110         struct iovec iov[2];
3111         struct list_attributes_rsp rsp;
3112
3113         if (number > AVRCP_ATTRIBUTE_LAST)
3114                 return -EINVAL;
3115
3116         rsp.number = number;
3117
3118         iov[0].iov_base = &rsp;
3119         iov[0].iov_len = sizeof(rsp);
3120
3121         if (!number)
3122                 return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3123                                 AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_ATTRIBUTES,
3124                                 iov, 1);
3125
3126         iov[1].iov_base = attrs;
3127         iov[1].iov_len = number;
3128
3129         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3130                                 AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_ATTRIBUTES,
3131                                 iov, 2);
3132 }
3133
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)
3137 {
3138         struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST * 2];
3139         struct text_value val[AVRCP_ATTRIBUTE_LAST];
3140         int i;
3141
3142         if (number > AVRCP_ATTRIBUTE_LAST)
3143                 return -EINVAL;
3144
3145         iov[0].iov_base = &number;
3146         iov[0].iov_len = sizeof(number);
3147
3148         for (i = 0; i < number; i++) {
3149                 uint8_t len = 0;
3150
3151                 if (attrs[i] > AVRCP_ATTRIBUTE_LAST ||
3152                                         attrs[i] == AVRCP_ATTRIBUTE_ILEGAL)
3153                         return -EINVAL;
3154
3155                 if (text[i])
3156                         len = strlen(text[i]);
3157
3158                 val[i].attr = attrs[i];
3159                 val[i].charset = cpu_to_be16(AVRCP_CHARSET_UTF8);
3160                 val[i].len = len;
3161
3162                 iov[i + 1].iov_base = &val[i];
3163                 iov[i + 1].iov_len = sizeof(val[i]);
3164
3165                 iov[i + 2].iov_base = (void *) text[i];
3166                 iov[i + 2].iov_len = len;
3167         }
3168
3169         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3170                         AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
3171                         iov, 1 + i * 2);
3172 }
3173
3174 int avrcp_list_player_values_rsp(struct avrcp *session, uint8_t transaction,
3175                                         uint8_t number, uint8_t *values)
3176 {
3177         struct iovec iov[2];
3178
3179         if (number > AVRCP_ATTRIBUTE_LAST)
3180                 return -EINVAL;
3181
3182         iov[0].iov_base = &number;
3183         iov[0].iov_len = sizeof(number);
3184
3185         iov[1].iov_base = values;
3186         iov[1].iov_len = number;
3187
3188         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3189                                 AVC_SUBUNIT_PANEL, AVRCP_LIST_PLAYER_VALUES,
3190                                 iov, 2);
3191 }
3192
3193 int avrcp_get_play_status_rsp(struct avrcp *session, uint8_t transaction,
3194                                 uint32_t position, uint32_t duration,
3195                                 uint8_t status)
3196 {
3197         struct iovec iov;
3198         struct get_play_status_rsp rsp;
3199
3200         rsp.duration = cpu_to_be32(duration);
3201         rsp.position = cpu_to_be32(position);
3202         rsp.status = status;
3203
3204         iov.iov_base = &rsp;
3205         iov.iov_len = sizeof(rsp);
3206
3207         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3208                                 AVC_SUBUNIT_PANEL, AVRCP_GET_PLAY_STATUS,
3209                                 &iov, 1);
3210 }
3211
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)
3215 {
3216         struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST * 2];
3217         struct text_value val[AVRCP_ATTRIBUTE_LAST];
3218         int i;
3219
3220         if (number > AVRCP_ATTRIBUTE_LAST)
3221                 return -EINVAL;
3222
3223         iov[0].iov_base = &number;
3224         iov[0].iov_len = sizeof(number);
3225
3226         for (i = 0; i < number; i++) {
3227                 uint8_t len = 0;
3228
3229                 if (text[i])
3230                         len = strlen(text[i]);
3231
3232                 val[i].attr = values[i];
3233                 val[i].charset = cpu_to_be16(AVRCP_CHARSET_UTF8);
3234                 val[i].len = len;
3235
3236                 iov[i + 1].iov_base = &val[i];
3237                 iov[i + 1].iov_len = sizeof(val[i]);
3238
3239                 iov[i + 2].iov_base = (void *) text[i];
3240                 iov[i + 2].iov_len = len;
3241         }
3242
3243         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3244                                 AVC_SUBUNIT_PANEL, AVRCP_GET_PLAYER_VALUE_TEXT,
3245                                 iov, 1 + i * 2);
3246 }
3247
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)
3251 {
3252         struct iovec iov[1 + AVRCP_ATTRIBUTE_LAST];
3253         struct attr_value val[AVRCP_ATTRIBUTE_LAST];
3254         int i;
3255
3256         if (number > AVRCP_ATTRIBUTE_LAST)
3257                 return -EINVAL;
3258
3259         iov[0].iov_base = &number;
3260         iov[0].iov_len = sizeof(number);
3261
3262         for (i = 0; i < number; i++) {
3263                 val[i].attr = attrs[i];
3264                 val[i].value = values[i];
3265
3266                 iov[i + 1].iov_base = &val[i];
3267                 iov[i + 1].iov_len = sizeof(val[i]);
3268         }
3269
3270         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3271                         AVC_SUBUNIT_PANEL, AVRCP_GET_CURRENT_PLAYER_VALUE,
3272                         iov, 1 + i);
3273 }
3274
3275 int avrcp_set_player_value_rsp(struct avrcp *session, uint8_t transaction)
3276 {
3277         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3278                         AVC_SUBUNIT_PANEL, AVRCP_SET_PLAYER_VALUE, NULL, 0);
3279 }
3280
3281 int avrcp_get_element_attrs_rsp(struct avrcp *session, uint8_t transaction,
3282                                         uint8_t *params, size_t params_len)
3283 {
3284         struct iovec iov;
3285
3286         iov.iov_base = params;
3287         iov.iov_len = params_len;
3288
3289         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3290                                 AVC_SUBUNIT_PANEL, AVRCP_GET_ELEMENT_ATTRIBUTES,
3291                                 &iov, 1);
3292 }
3293
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)
3297 {
3298         struct iovec iov[2];
3299         uint16_t *player;
3300         uint8_t *volume;
3301
3302         if (event > AVRCP_EVENT_LAST)
3303                 return -EINVAL;
3304
3305         iov[0].iov_base = &event;
3306         iov[0].iov_len = sizeof(event);
3307
3308         switch (event) {
3309         case AVRCP_EVENT_STATUS_CHANGED:
3310                 if (len != sizeof(uint8_t))
3311                         return -EINVAL;
3312                 break;
3313         case AVRCP_EVENT_VOLUME_CHANGED:
3314                 if (len != sizeof(uint8_t))
3315                         return -EINVAL;
3316                 volume = data;
3317                 if (volume[0] > 127)
3318                         return -EINVAL;
3319                 break;
3320         case AVRCP_EVENT_TRACK_CHANGED:
3321                 if (len != sizeof(uint64_t))
3322                         return -EINVAL;
3323
3324                 put_be64(*(uint64_t *) data, data);
3325                 break;
3326         case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
3327                 if (len != sizeof(uint32_t))
3328                         return -EINVAL;
3329
3330                 put_be32(*(uint32_t *) data, data);
3331                 break;
3332         case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
3333                 if (len != 4)
3334                         return -EINVAL;
3335
3336                 player = data;
3337                 player[0] = cpu_to_be16(player[0]);
3338                 player[1] = cpu_to_be16(player[1]);
3339
3340                 break;
3341         case AVRCP_EVENT_SETTINGS_CHANGED:
3342                 if (len < sizeof(uint8_t))
3343                         return -EINVAL;
3344                 break;
3345         case AVRCP_EVENT_UIDS_CHANGED:
3346                 if (len != sizeof(uint16_t))
3347                         return -EINVAL;
3348
3349                 put_be16(*(uint16_t *) data, data);
3350                 break;
3351         default:
3352                 return avrcp_send(session, transaction, code, AVC_SUBUNIT_PANEL,
3353                                         AVRCP_REGISTER_NOTIFICATION, iov, 1);
3354         }
3355
3356         iov[1].iov_base = data;
3357         iov[1].iov_len = len;
3358
3359         return avrcp_send(session, transaction, code, AVC_SUBUNIT_PANEL,
3360                                         AVRCP_REGISTER_NOTIFICATION, iov, 2);
3361 }
3362
3363 int avrcp_set_volume_rsp(struct avrcp *session, uint8_t transaction,
3364                                                         uint8_t volume)
3365 {
3366         struct iovec iov;
3367
3368         if (volume > 127)
3369                 return -EINVAL;
3370
3371         iov.iov_base = &volume;
3372         iov.iov_len = sizeof(volume);
3373
3374         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3375                                 AVC_SUBUNIT_PANEL, AVRCP_SET_ABSOLUTE_VOLUME,
3376                                 &iov, 1);
3377 }
3378
3379 int avrcp_set_addressed_player_rsp(struct avrcp *session, uint8_t transaction,
3380                                                         uint8_t status)
3381 {
3382         struct iovec iov;
3383
3384         iov.iov_base = &status;
3385         iov.iov_len = sizeof(status);
3386
3387         return avrcp_send(session, transaction, AVC_CTYPE_STABLE,
3388                                 AVC_SUBUNIT_PANEL, AVRCP_SET_ADDRESSED_PLAYER,
3389                                 &iov, 1);
3390 }
3391
3392 static int avrcp_status_rsp(struct avrcp *session, uint8_t transaction,
3393                                                 uint8_t pdu_id, uint8_t status)
3394 {
3395         struct iovec iov;
3396
3397         if (status > AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED)
3398                 return -EINVAL;
3399
3400         iov.iov_base = &status;
3401         iov.iov_len = sizeof(status);
3402
3403         return avrcp_send_browsing(session, transaction, pdu_id, &iov, 1);
3404 }
3405
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)
3410 {
3411         struct iovec iov[UINT8_MAX * 2 + 1];
3412         struct set_browsed_rsp rsp;
3413         uint16_t len[UINT8_MAX];
3414         int i;
3415
3416         if (status != AVRCP_STATUS_SUCCESS)
3417                 return avrcp_status_rsp(session, transaction,
3418                                         AVRCP_SET_BROWSED_PLAYER, status);
3419
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);
3424         rsp.depth = depth;
3425
3426         iov[0].iov_base = &rsp;
3427         iov[0].iov_len = sizeof(rsp);
3428
3429         if (!depth)
3430                 return avrcp_send_browsing(session, transaction,
3431                                                 AVRCP_SET_BROWSED_PLAYER,
3432                                                 iov, 1);
3433
3434         for (i = 0; i < depth; i++) {
3435                 if (!folders[i])
3436                         return -EINVAL;
3437
3438                 len[i] = strlen(folders[i]);
3439
3440                 iov[i * 2 + 2].iov_base = (void *) folders[i];
3441                 iov[i * 2 + 2].iov_len = len[i];
3442
3443                 len[i] = cpu_to_be16(len[i]);
3444
3445                 iov[i * 2 + 1].iov_base = &len[i];
3446                 iov[i * 2 + 1].iov_len = sizeof(len[i]);
3447         }
3448
3449         return avrcp_send_browsing(session, transaction,
3450                                         AVRCP_SET_BROWSED_PLAYER, iov,
3451                                         depth * 2 + 1);
3452 }
3453
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)
3458 {
3459         struct iovec iov[UINT8_MAX * 2 + 1];
3460         struct get_folder_items_rsp rsp;
3461         uint8_t item[UINT8_MAX][3];
3462         int i;
3463
3464         if (status != AVRCP_STATUS_SUCCESS)
3465                 return avrcp_status_rsp(session, transaction,
3466                                         AVRCP_GET_FOLDER_ITEMS, status);
3467
3468         rsp.status = status;
3469         rsp.counter = cpu_to_be16(counter);
3470         rsp.number = cpu_to_be16(number);
3471
3472         iov[0].iov_base = &rsp;
3473         iov[0].iov_len = sizeof(rsp);
3474
3475         for (i = 0; i < number; i++) {
3476                 item[i][0] = type[i];
3477                 put_be16(len[i], &item[i][1]);
3478
3479                 iov[i * 2 + 1].iov_base = item[i];
3480                 iov[i * 2 + 1].iov_len = sizeof(item[i]);
3481
3482                 iov[i * 2 + 2].iov_base = params[i];
3483                 iov[i * 2 + 2].iov_len = len[i];
3484         }
3485
3486         return avrcp_send_browsing(session, transaction, AVRCP_GET_FOLDER_ITEMS,
3487                                                         iov, number * 2 + 1);
3488 }
3489
3490 int avrcp_change_path_rsp(struct avrcp *session, uint8_t transaction,
3491                                                 uint8_t status, uint32_t items)
3492 {
3493         struct iovec iov;
3494         struct change_path_rsp rsp;
3495
3496         if (status != AVRCP_STATUS_SUCCESS)
3497                 return avrcp_status_rsp(session, transaction, AVRCP_CHANGE_PATH,
3498                                                                         status);
3499
3500         rsp.status = status;
3501         rsp.items = cpu_to_be32(items);
3502
3503         iov.iov_base = &rsp;
3504         iov.iov_len = sizeof(rsp);
3505
3506         return avrcp_send_browsing(session, transaction, AVRCP_CHANGE_PATH,
3507                                                                 &iov, 1);
3508 }
3509
3510 static bool pack_attribute_list(struct iovec *iov, uint8_t number,
3511                                         uint32_t *attrs, const char **text)
3512 {
3513         int i;
3514         struct media_item val[AVRCP_MEDIA_ATTRIBUTE_LAST];
3515
3516         for (i = 0; i < number; i++) {
3517                 uint16_t len = 0;
3518
3519                 if (attrs[i] > AVRCP_MEDIA_ATTRIBUTE_LAST ||
3520                                 attrs[i] == AVRCP_MEDIA_ATTRIBUTE_ILLEGAL)
3521                         return false;
3522
3523                 if (text[i])
3524                         len = strlen(text[i]);
3525
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);
3529
3530                 iov[i].iov_base = &val[i];
3531                 iov[i].iov_len = sizeof(val[i]);
3532
3533                 iov[i + 1].iov_base = (void *) text[i];
3534                 iov[i + 1].iov_len = len;
3535         }
3536
3537         return true;
3538 }
3539
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)
3543 {
3544         struct iovec iov[AVRCP_MEDIA_ATTRIBUTE_LAST * 2 + 1];
3545         struct get_item_attributes_rsp rsp;
3546
3547         if (number > AVRCP_MEDIA_ATTRIBUTE_LAST)
3548                 return -EINVAL;
3549
3550         if (status != AVRCP_STATUS_SUCCESS)
3551                 return avrcp_status_rsp(session, transaction,
3552                                         AVRCP_GET_ITEM_ATTRIBUTES, status);
3553
3554         rsp.status = status;
3555         rsp.number = number;
3556
3557         iov[0].iov_base = &rsp;
3558         iov[0].iov_len = sizeof(rsp);
3559
3560         if (!pack_attribute_list(&iov[1], number, attrs, text))
3561                 return -EINVAL;
3562
3563         return avrcp_send_browsing(session, transaction,
3564                                         AVRCP_GET_ITEM_ATTRIBUTES, iov,
3565                                         number * 2 + 1);
3566 }
3567
3568 int avrcp_play_item_rsp(struct avrcp *session, uint8_t transaction,
3569                                                                 uint8_t status)
3570 {
3571         return avrcp_status_rsp(session, transaction, AVRCP_PLAY_ITEM,
3572                                                                 status);
3573 }
3574
3575 int avrcp_search_rsp(struct avrcp *session, uint8_t transaction, uint8_t status,
3576                                         uint16_t counter, uint32_t items)
3577 {
3578         struct iovec iov;
3579         struct search_rsp rsp;
3580
3581         if (status != AVRCP_STATUS_SUCCESS)
3582                 return avrcp_status_rsp(session, transaction, AVRCP_SEARCH,
3583                                                                 status);
3584
3585         rsp.status = status;
3586         rsp.counter = cpu_to_be16(counter);
3587         rsp.items = cpu_to_be32(items);
3588
3589         iov.iov_base = &rsp;
3590         iov.iov_len = sizeof(rsp);
3591
3592         return avrcp_send_browsing(session, transaction, AVRCP_SEARCH,
3593                                                                 &iov, 1);
3594 }
3595
3596 int avrcp_add_to_now_playing_rsp(struct avrcp *session, uint8_t transaction,
3597                                                                 uint8_t status)
3598 {
3599         return avrcp_status_rsp(session, transaction, AVRCP_ADD_TO_NOW_PLAYING,
3600                                                                 status);
3601 }
3602
3603 int avrcp_send_passthrough(struct avrcp *session, uint32_t vendor, uint8_t op)
3604 {
3605         uint8_t params[5];
3606
3607         if (!vendor)
3608                 return avctp_send_passthrough(session->conn, op, NULL, 0);
3609
3610         hton24(params, vendor);
3611         put_be16(op, &params[3]);
3612
3613         return avctp_send_passthrough(session->conn, AVC_VENDOR_UNIQUE, params,
3614                                                                 sizeof(params));
3615 }