avrc_api.c revision 9adddf4965e9ddb01e339b934c343fcbd842a977
1/******************************************************************************
2 *
3 *  Copyright (C) 2003-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 *  Interface to AVRCP mandatory commands
22 *
23 ******************************************************************************/
24#include <string.h>
25
26#include "gki.h"
27#include "avrc_api.h"
28#include "avrc_int.h"
29#include "wcassert.h"
30
31/*****************************************************************************
32**  Global data
33*****************************************************************************/
34
35
36#define AVRC_MAX_RCV_CTRL_EVT   AVCT_BROWSE_UNCONG_IND_EVT
37
38static const UINT8 avrc_ctrl_event_map[] =
39{
40    AVRC_OPEN_IND_EVT,  /* AVCT_CONNECT_CFM_EVT */
41    AVRC_OPEN_IND_EVT,  /* AVCT_CONNECT_IND_EVT */
42    AVRC_CLOSE_IND_EVT, /* AVCT_DISCONNECT_CFM_EVT */
43    AVRC_CLOSE_IND_EVT, /* AVCT_DISCONNECT_IND_EVT */
44    AVRC_CONG_IND_EVT,  /* AVCT_CONG_IND_EVT */
45    AVRC_UNCONG_IND_EVT,/* AVCT_UNCONG_IND_EVT */
46    AVRC_BROWSE_OPEN_IND_EVT,  /* AVCT_BROWSE_CONN_CFM_EVT   */
47    AVRC_BROWSE_OPEN_IND_EVT,  /* AVCT_BROWSE_CONN_IND_EVT   */
48    AVRC_BROWSE_CLOSE_IND_EVT, /* AVCT_BROWSE_DISCONN_CFM_EVT */
49    AVRC_BROWSE_CLOSE_IND_EVT, /* AVCT_BROWSE_DISCONN_IND_EVT */
50    AVRC_BROWSE_CONG_IND_EVT,  /* AVCT_BROWSE_CONG_IND_EVT    */
51    AVRC_BROWSE_UNCONG_IND_EVT /* AVCT_BROWSE_UNCONG_IND_EVT  */
52};
53
54#define AVRC_OP_DROP        0xFE    /* use this unused opcode to indication no need to call the callback function */
55#define AVRC_OP_DROP_N_FREE 0xFD    /* use this unused opcode to indication no need to call the callback function & free buffer */
56
57/******************************************************************************
58**
59** Function         avrc_ctrl_cback
60**
61** Description      This is the callback function used by AVCTP to report
62**                  received link events.
63**
64** Returns          Nothing.
65**
66******************************************************************************/
67static void avrc_ctrl_cback(UINT8 handle, UINT8 event, UINT16 result,
68                                BD_ADDR peer_addr)
69{
70    UINT8   avrc_event;
71
72    if (event <= AVRC_MAX_RCV_CTRL_EVT && avrc_cb.ccb[handle].p_ctrl_cback)
73    {
74        avrc_event = avrc_ctrl_event_map[event];
75        if (event == AVCT_CONNECT_CFM_EVT)
76        {
77            if (result != 0) /* failed */
78                avrc_event = AVRC_CLOSE_IND_EVT;
79        }
80        (*avrc_cb.ccb[handle].p_ctrl_cback)(handle, avrc_event, result, peer_addr);
81    }
82    /* else drop the unknown event*/
83}
84
85/******************************************************************************
86**
87** Function         avrc_get_data_ptr
88**
89** Description      If the offset in the received buffer is smaller than required
90**                  move the portion of data AVRC cares.
91**
92** Returns          Nothing.
93**
94******************************************************************************/
95static UINT8 * avrc_get_data_ptr(BT_HDR *p_pkt)
96{
97    UINT8   *p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
98    int     i, gap;
99
100    if (p_pkt->offset < AVCT_MSG_OFFSET)
101    {
102        gap = AVCT_MSG_OFFSET - p_pkt->offset;
103        for(i=p_pkt->len; i>0; i--)
104        {
105            *(p_data + i + gap) = *(p_data + i);
106        }
107        p_pkt->offset   += gap;
108        p_data          = (UINT8 *)(p_pkt+1) + p_pkt->offset;
109    }
110    *p_data         = AVRC_RSP_IMPL_STBL;
111    return p_data;
112}
113
114#if (AVRC_METADATA_INCLUDED == TRUE)
115/******************************************************************************
116**
117** Function         avrc_prep_end_frag
118**
119** Description      This function prepares an end response fragment
120**
121** Returns          Nothing.
122**
123******************************************************************************/
124static void avrc_prep_end_frag(UINT8 handle)
125{
126    tAVRC_FRAG_CB   *p_fcb;
127    BT_HDR  *p_pkt_new;
128    UINT8   *p_data, *p_orig_data;
129    UINT8   rsp_type;
130
131    AVRC_TRACE_DEBUG0 ("avrc_prep_end_frag" );
132    p_fcb = &avrc_cb.fcb[handle];
133
134    /* The response type of the end fragment should be the same as the the PDU of "End Fragment
135    ** Respose" Errata: https://www.bluetooth.org/errata/errata_view.cfm?errata_id=4383 */
136    p_orig_data = ((UINT8 *)(p_fcb->p_fmsg + 1) + p_fcb->p_fmsg->offset);
137    rsp_type = ((*p_orig_data) & AVRC_CTYPE_MASK);
138
139    p_pkt_new           = p_fcb->p_fmsg;
140    p_pkt_new->len      -= (AVRC_MAX_CTRL_DATA_LEN - AVRC_VENDOR_HDR_SIZE - AVRC_MIN_META_HDR_SIZE);
141    p_pkt_new->offset   += (AVRC_MAX_CTRL_DATA_LEN - AVRC_VENDOR_HDR_SIZE - AVRC_MIN_META_HDR_SIZE);
142    p_data = (UINT8 *)(p_pkt_new+1) + p_pkt_new->offset;
143    *p_data++       = rsp_type;
144    *p_data++       = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
145    *p_data++       = AVRC_OP_VENDOR;
146    AVRC_CO_ID_TO_BE_STREAM(p_data, AVRC_CO_METADATA);
147    *p_data++       = p_fcb->frag_pdu;
148    *p_data++       = AVRC_PKT_END;
149    /* 4=pdu, pkt_type & len */
150    UINT16_TO_BE_STREAM(p_data, (p_pkt_new->len - AVRC_VENDOR_HDR_SIZE - AVRC_MIN_META_HDR_SIZE));
151}
152
153/******************************************************************************
154**
155** Function         avrc_send_continue_frag
156**
157** Description      This function sends a continue response fragment
158**
159** Returns          Nothing.
160**
161******************************************************************************/
162static void avrc_send_continue_frag(UINT8 handle, UINT8 label)
163{
164    tAVRC_FRAG_CB   *p_fcb;
165    BT_HDR  *p_pkt_old, *p_pkt;
166    UINT8   *p_old, *p_data;
167    UINT8   cr = AVCT_RSP;
168    tAVRC_RSP   rej_rsp;
169
170    p_fcb = &avrc_cb.fcb[handle];
171    p_pkt = p_fcb->p_fmsg;
172
173    AVRC_TRACE_DEBUG1 ("avrc_send_continue_frag len(%d) / AVRC_MAX_CTRL_DATA_LEN", p_pkt->len );
174    if (p_pkt->len > AVRC_MAX_CTRL_DATA_LEN)
175    {
176        p_pkt_old = p_fcb->p_fmsg;
177        p_pkt = (BT_HDR *)GKI_getbuf((UINT16)(AVRC_PACKET_LEN + AVCT_MSG_OFFSET + BT_HDR_SIZE));
178        if (p_pkt)
179        {
180            p_pkt->len          = AVRC_MAX_CTRL_DATA_LEN;
181            p_pkt->offset       = AVCT_MSG_OFFSET;
182            p_pkt->layer_specific = p_pkt_old->layer_specific;
183            p_pkt->event = p_pkt_old->event;
184            p_old = (UINT8 *)(p_pkt_old+1) + p_pkt_old->offset;
185            p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
186            memcpy (p_data, p_old, AVRC_MAX_CTRL_DATA_LEN);
187            /* use AVRC continue packet type */
188            p_data += AVRC_VENDOR_HDR_SIZE;
189            p_data++; /* pdu */
190            *p_data++ = AVRC_PKT_CONTINUE;
191            /* 4=pdu, pkt_type & len */
192            UINT16_TO_BE_STREAM(p_data, (AVRC_MAX_CTRL_DATA_LEN - AVRC_VENDOR_HDR_SIZE - 4));
193
194            /* prepare the left over for as an end fragment */
195            avrc_prep_end_frag (handle);
196        }
197        else
198        {
199            /* use the current GKI buffer to send Internal error status */
200            p_pkt = p_fcb->p_fmsg;
201            p_fcb->p_fmsg = NULL;
202            p_fcb->frag_enabled = FALSE;
203            AVRC_TRACE_ERROR0 ("AVRC_MsgReq no buffers for fragmentation - send internal error" );
204            p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
205            *p_data++ = AVRC_PDU_REQUEST_CONTINUATION_RSP;
206            *p_data++ = 0;
207            UINT16_TO_BE_STREAM(p_data, 0);
208            p_pkt->len = 4;
209            rej_rsp.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP;
210            rej_rsp.status = AVRC_STS_INTERNAL_ERR;
211            AVRC_BldResponse( handle, (tAVRC_RESPONSE *)&rej_rsp, &p_pkt);
212            cr = AVCT_RSP;
213        }
214    }
215    else
216    {
217        /* end fragment. clean the control block */
218        p_fcb->frag_enabled = FALSE;
219        p_fcb->p_fmsg       = NULL;
220    }
221    AVCT_MsgReq( handle, label, cr, p_pkt);
222}
223
224/******************************************************************************
225**
226** Function         avrc_proc_vendor_command
227**
228** Description      This function processes received vendor command.
229**
230** Returns          if not NULL, the response to send right away.
231**
232******************************************************************************/
233static BT_HDR * avrc_proc_vendor_command(UINT8 handle, UINT8 label,
234                               BT_HDR *p_pkt, tAVRC_MSG_VENDOR *p_msg)
235{
236    BT_HDR      *p_rsp = NULL;
237    UINT8       *p_data;
238    UINT8       *p_begin;
239    UINT8       pkt_type;
240    BOOLEAN     abort_frag = FALSE;
241    tAVRC_STS   status = AVRC_STS_NO_ERROR;
242    tAVRC_FRAG_CB   *p_fcb;
243
244    p_begin  = (UINT8 *)(p_pkt+1) + p_pkt->offset;
245    p_data   = p_begin + AVRC_VENDOR_HDR_SIZE;
246    pkt_type = *(p_data + 1) & AVRC_PKT_TYPE_MASK;
247
248    if (pkt_type != AVRC_PKT_SINGLE)
249    {
250        /* reject - commands can only be in single packets at AVRCP level */
251        AVRC_TRACE_ERROR1 ("commands must be in single packet pdu:0x%x", *p_data );
252        /* use the current GKI buffer to send the reject */
253        status = AVRC_STS_BAD_CMD;
254    }
255    /* check if there are fragments waiting to be sent */
256    else if (avrc_cb.fcb[handle].frag_enabled)
257    {
258        p_fcb = &avrc_cb.fcb[handle];
259        if (p_msg->company_id == AVRC_CO_METADATA)
260        {
261            switch (*p_data)
262            {
263            case AVRC_PDU_ABORT_CONTINUATION_RSP:
264                /* aborted by CT - send accept response */
265                abort_frag = TRUE;
266                p_begin = (UINT8 *)(p_pkt+1) + p_pkt->offset;
267                *p_begin = (AVRC_RSP_ACCEPT & AVRC_CTYPE_MASK);
268                if (*(p_data + 4) != p_fcb->frag_pdu)
269                {
270                    *p_begin = (AVRC_RSP_REJ & AVRC_CTYPE_MASK);
271                    *(p_data + 4) = AVRC_STS_BAD_PARAM;
272                }
273                else
274                {
275                    p_data = (p_begin + AVRC_VENDOR_HDR_SIZE + 2);
276                    UINT16_TO_BE_STREAM(p_data, 0);
277                    p_pkt->len = (p_data - p_begin);
278                }
279                AVCT_MsgReq( handle, label, AVCT_RSP, p_pkt);
280                p_msg->hdr.opcode = AVRC_OP_DROP; /* used the p_pkt to send response */
281                break;
282
283            case AVRC_PDU_REQUEST_CONTINUATION_RSP:
284                if (*(p_data + 4) == p_fcb->frag_pdu)
285                {
286                    avrc_send_continue_frag(handle, label);
287                    p_msg->hdr.opcode = AVRC_OP_DROP_N_FREE;
288                }
289                else
290                {
291                    /* the pdu id does not match - reject the command using the current GKI buffer */
292                    AVRC_TRACE_ERROR2("avrc_proc_vendor_command continue pdu: 0x%x does not match \
293                    current re-assembly pdu: 0x%x",
294                        *(p_data + 4), p_fcb->frag_pdu);
295                    status = AVRC_STS_BAD_PARAM;
296                    abort_frag = TRUE;
297                }
298                break;
299
300            default:
301                /* implicit abort */
302                abort_frag = TRUE;
303            }
304        }
305        else
306        {
307            abort_frag = TRUE;
308            /* implicit abort */
309        }
310
311        if (abort_frag)
312        {
313            if (p_fcb->p_fmsg)
314                GKI_freebuf(p_fcb->p_fmsg);
315            p_fcb->p_fmsg = NULL;
316            p_fcb->frag_enabled = FALSE;
317        }
318    }
319
320    if (status != AVRC_STS_NO_ERROR)
321    {
322        /* use the current GKI buffer to build/send the reject message */
323        p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
324        *p_data++ = AVRC_RSP_REJ;
325        p_data += AVRC_VENDOR_HDR_SIZE; /* pdu */
326        *p_data++ = 0;                  /* pkt_type */
327        UINT16_TO_BE_STREAM(p_data, 1); /* len */
328        *p_data++ = status;             /* error code */
329        p_pkt->len = AVRC_VENDOR_HDR_SIZE + 5;
330        p_rsp = p_pkt;
331    }
332
333    return p_rsp;
334}
335
336/******************************************************************************
337**
338** Function         avrc_proc_far_msg
339**
340** Description      This function processes vendor command/response fragmetation
341**                  and reassembly
342**
343** Returns          0, to report the message with msg_cback .
344**
345******************************************************************************/
346static UINT8 avrc_proc_far_msg(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR **pp_pkt,
347    tAVRC_MSG_VENDOR *p_msg)
348{
349    BT_HDR      *p_pkt = *pp_pkt;
350    UINT8       *p_data;
351    BOOLEAN     drop = FALSE;
352    BT_HDR      *p_rsp = NULL;
353    BT_HDR      *p_cmd = NULL;
354    BOOLEAN     req_continue = FALSE;
355    BT_HDR      *p_pkt_new = NULL;
356    UINT8       pkt_type;
357    UINT16      buf_len;
358    tAVRC_RASM_CB   *p_rcb;
359    tAVRC_NEXT_CMD   avrc_cmd;
360
361    p_data  = (UINT8 *)(p_pkt+1) + p_pkt->offset;
362    pkt_type = *(p_data + 1) & AVRC_PKT_TYPE_MASK;
363    AVRC_TRACE_DEBUG1 ("pkt_type %d", pkt_type );
364    p_rcb = &avrc_cb.rcb[handle];
365    if (p_msg->company_id == AVRC_CO_METADATA)
366    {
367        /* check if the message needs to be re-assembled */
368        if (pkt_type == AVRC_PKT_SINGLE || pkt_type == AVRC_PKT_START)
369        {
370            /* previous fragments need to be dropped, when received another new message */
371            p_rcb->rasm_offset = 0;
372            if (p_rcb->p_rmsg)
373            {
374                GKI_freebuf(p_rcb->p_rmsg);
375                p_rcb->p_rmsg = NULL;
376            }
377        }
378
379        if (pkt_type != AVRC_PKT_SINGLE && cr == AVCT_RSP)
380        {
381            /* not a single response packet - need to re-assemble metadata messages */
382            if (pkt_type == AVRC_PKT_START)
383            {
384                p_rcb->rasm_offset = p_pkt->offset;
385                p_rcb->p_rmsg = p_pkt;
386                /* set offset to point to where to copy next - use the same re-asm logic as AVCT */
387                p_rcb->p_rmsg->offset += p_rcb->p_rmsg->len;
388                p_rcb->rasm_pdu = *p_data;
389                req_continue = TRUE;
390            }
391            else
392            {
393                /* get size of buffer holding assembled message */
394                buf_len = GKI_get_buf_size (p_rcb->p_rmsg) - sizeof(BT_HDR);
395                /* adjust offset and len of fragment for header byte */
396                p_pkt->offset += (AVRC_VENDOR_HDR_SIZE + AVRC_MIN_META_HDR_SIZE);
397                p_pkt->len -= (AVRC_VENDOR_HDR_SIZE + AVRC_MIN_META_HDR_SIZE);
398                /* verify length */
399                if ((p_rcb->p_rmsg->offset + p_pkt->len) > buf_len)
400                {
401                    AVRC_TRACE_WARNING0("Fragmented message too big! - report the partial message");
402                    p_pkt->len = buf_len - p_rcb->p_rmsg->offset;
403                    pkt_type = AVRC_PKT_END;
404                }
405
406                /* copy contents of p_pkt to p_rx_msg */
407                memcpy((UINT8 *)(p_rcb->p_rmsg + 1) + p_rcb->p_rmsg->offset,
408                       (UINT8 *)(p_pkt + 1) + p_pkt->offset, p_pkt->len);
409
410                if (pkt_type == AVRC_PKT_END)
411                {
412                    p_rcb->p_rmsg->offset = p_rcb->rasm_offset;
413                    p_rcb->p_rmsg->len += p_pkt->len;
414                    p_pkt_new = p_rcb->p_rmsg;
415                    p_rcb->rasm_offset = 0;
416                    p_rcb->p_rmsg = NULL;
417                    p_msg->p_vendor_data   = (UINT8 *)(p_pkt_new+1) + p_pkt_new->offset;
418                    p_msg->hdr.ctype       = p_msg->p_vendor_data[0] & AVRC_CTYPE_MASK;
419                    /* 6 = ctype, subunit*, opcode & CO_ID */
420                    p_msg->p_vendor_data  += AVRC_VENDOR_HDR_SIZE;
421                    p_msg->vendor_len      = p_pkt_new->len - AVRC_VENDOR_HDR_SIZE;
422                    p_data = p_msg->p_vendor_data + 1; /* skip pdu */
423                    *p_data++ = AVRC_PKT_SINGLE;
424                    UINT16_TO_BE_STREAM(p_data, (p_msg->vendor_len - AVRC_MIN_META_HDR_SIZE));
425                    AVRC_TRACE_DEBUG3("end frag:%d, total len:%d, offset:%d", p_pkt->len,
426                        p_pkt_new->len, p_pkt_new->offset);
427                }
428                else
429                {
430                    p_rcb->p_rmsg->offset += p_pkt->len;
431                    p_rcb->p_rmsg->len += p_pkt->len;
432                    p_pkt_new = NULL;
433                    req_continue = TRUE;
434                }
435                GKI_freebuf(p_pkt);
436                *pp_pkt = p_pkt_new;
437            }
438        }
439
440        if (cr == AVCT_CMD)
441        {
442            p_rsp = avrc_proc_vendor_command(handle, label, *pp_pkt, p_msg);
443            if (p_rsp)
444            {
445                AVCT_MsgReq( handle, label, AVCT_RSP, p_rsp);
446                drop = 3;
447            }
448            else if (p_msg->hdr.opcode == AVRC_OP_DROP)
449            {
450                drop = 1;
451            }
452            else if (p_msg->hdr.opcode == AVRC_OP_DROP_N_FREE)
453                drop = 4;
454
455        }
456    }
457    return drop;
458}
459#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
460
461/******************************************************************************
462**
463** Function         avrc_msg_cback
464**
465** Description      This is the callback function used by AVCTP to report
466**                  received AV control messages.
467**
468** Returns          Nothing.
469**
470******************************************************************************/
471static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr,
472                               BT_HDR *p_pkt)
473{
474    UINT8       opcode;
475    tAVRC_MSG   msg;
476    UINT8       *p_data;
477    UINT8       *p_begin;
478    BOOLEAN     drop = FALSE;
479    BOOLEAN     free = TRUE;
480    BT_HDR      *p_rsp = NULL;
481    UINT8       *p_rsp_data;
482    int         xx;
483    BOOLEAN     reject = FALSE;
484#if (BT_USE_TRACES == TRUE)
485    char        *p_drop_msg = "dropped";
486#endif
487    tAVRC_MSG_VENDOR *p_msg = &msg.vendor;
488
489    if (cr == AVCT_CMD &&
490        (p_pkt->layer_specific & AVCT_DATA_CTRL && AVRC_PACKET_LEN < sizeof(p_pkt->len)))
491    {
492        /* Ignore the invalid AV/C command frame */
493#if (BT_USE_TRACES == TRUE)
494        p_drop_msg = "dropped - too long AV/C cmd frame size";
495#endif
496        GKI_freebuf(p_pkt);
497        return;
498    }
499
500    if (cr == AVCT_REJ)
501    {
502        /* The peer thinks that this PID is no longer open - remove this handle */
503        /*  */
504        GKI_freebuf(p_pkt);
505        AVCT_RemoveConn(handle);
506        return;
507    }
508
509    p_data  = (UINT8 *)(p_pkt+1) + p_pkt->offset;
510    memset(&msg, 0, sizeof(tAVRC_MSG) );
511    {
512        msg.hdr.ctype           = p_data[0] & AVRC_CTYPE_MASK;
513        AVRC_TRACE_DEBUG4("avrc_msg_cback handle:%d, ctype:%d, offset:%d, len: %d",
514                handle, msg.hdr.ctype, p_pkt->offset, p_pkt->len);
515        msg.hdr.subunit_type    = (p_data[1] & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
516        msg.hdr.subunit_id      = p_data[1] & AVRC_SUBID_MASK;
517        opcode                  = p_data[2];
518    }
519
520    if ( ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD)) ||
521        ((avrc_cb.ccb[handle].control & AVRC_CT_CONTROL) && (cr == AVCT_RSP)) )
522    {
523
524        switch(opcode)
525        {
526        case AVRC_OP_UNIT_INFO:
527            if (cr == AVCT_CMD)
528            {
529                /* send the response to the peer */
530                p_rsp           = p_pkt; /* this also sets free = FALSE, drop = TRUE */
531                /* check & set the offset. set response code, set subunit_type & subunit_id,
532                   set AVRC_OP_UNIT_INFO */
533                /* 3 bytes: ctype, subunit*, opcode */
534                p_rsp_data      = avrc_get_data_ptr(p_pkt) + AVRC_AVC_HDR_SIZE;
535                *p_rsp_data++   = 7;
536                /* Panel subunit & id=0 */
537                *p_rsp_data++   = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
538                AVRC_CO_ID_TO_BE_STREAM(p_rsp_data, avrc_cb.ccb[handle].company_id);
539                p_rsp->len      = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
540                cr = AVCT_RSP;
541#if (BT_USE_TRACES == TRUE)
542                p_drop_msg = "auto respond";
543#endif
544            }
545            else
546            {
547                /* parse response */
548                p_data += 4; /* 3 bytes: ctype, subunit*, opcode + octet 3 (is 7)*/
549                msg.unit.unit_type  = (*p_data & AVRC_SUBTYPE_MASK) >> AVRC_SUBTYPE_SHIFT;
550                msg.unit.unit       = *p_data & AVRC_SUBID_MASK;
551                p_data++;
552                AVRC_BE_STREAM_TO_CO_ID(msg.unit.company_id, p_data);
553            }
554            break;
555
556        case AVRC_OP_SUB_INFO:
557            if (cr == AVCT_CMD)
558            {
559                /* send the response to the peer */
560                p_rsp           = p_pkt; /* this also sets free = FALSE, drop = TRUE */
561                /* check & set the offset. set response code, set (subunit_type & subunit_id),
562                   set AVRC_OP_SUB_INFO, set (page & extention code) */
563                p_rsp_data      = avrc_get_data_ptr(p_pkt) + 4;
564                /* Panel subunit & id=0 */
565                *p_rsp_data++   = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
566                memset(p_rsp_data, AVRC_CMD_OPRND_PAD, AVRC_SUBRSP_OPRND_BYTES);
567                p_rsp_data      += AVRC_SUBRSP_OPRND_BYTES;
568                p_rsp->len      = (UINT16) (p_rsp_data - (UINT8 *)(p_rsp + 1) - p_rsp->offset);
569                cr = AVCT_RSP;
570#if (BT_USE_TRACES == TRUE)
571                p_drop_msg = "auto responded";
572#endif
573            }
574            else
575            {
576                /* parse response */
577                p_data += AVRC_AVC_HDR_SIZE; /* 3 bytes: ctype, subunit*, opcode */
578                msg.sub.page    = (*p_data++ >> AVRC_SUB_PAGE_SHIFT) & AVRC_SUB_PAGE_MASK;
579                xx      = 0;
580                while (*p_data != AVRC_CMD_OPRND_PAD && xx<AVRC_SUB_TYPE_LEN)
581                {
582                    msg.sub.subunit_type[xx] = *p_data++ >> AVRC_SUBTYPE_SHIFT;
583                    if (msg.sub.subunit_type[xx] == AVRC_SUB_PANEL)
584                        msg.sub.panel   = TRUE;
585                    xx++;
586                }
587            }
588            break;
589
590        case AVRC_OP_VENDOR:
591            p_data  = (UINT8 *)(p_pkt+1) + p_pkt->offset;
592            p_begin = p_data;
593            if (p_pkt->len < AVRC_VENDOR_HDR_SIZE) /* 6 = ctype, subunit*, opcode & CO_ID */
594            {
595                if (cr == AVCT_CMD)
596                    reject = TRUE;
597                else
598                    drop = TRUE;
599                break;
600            }
601            p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
602            AVRC_BE_STREAM_TO_CO_ID(p_msg->company_id, p_data);
603            p_msg->p_vendor_data   = p_data;
604            p_msg->vendor_len      = p_pkt->len - (p_data - p_begin);
605
606#if (AVRC_METADATA_INCLUDED == TRUE)
607            drop = avrc_proc_far_msg(handle, label, cr, &p_pkt, p_msg);
608            if (drop)
609            {
610                free = FALSE;
611                if (drop == 4)
612                    free = TRUE;
613#if (BT_USE_TRACES == TRUE)
614                switch (drop)
615                {
616                case 1:
617                    p_drop_msg = "sent_frag";
618                    break;
619                case 2:
620                    p_drop_msg = "req_cont";
621                    break;
622                case 3:
623                    p_drop_msg = "sent_frag3";
624                    break;
625                case 4:
626                    p_drop_msg = "sent_frag_free";
627                    break;
628                default:
629                    p_drop_msg = "sent_fragd";
630                }
631#endif
632            }
633#endif /* (AVRC_METADATA_INCLUDED == TRUE) */
634            break;
635
636        case AVRC_OP_PASS_THRU:
637            if (p_pkt->len < 5) /* 3 bytes: ctype, subunit*, opcode & op_id & len */
638            {
639                if (cr == AVCT_CMD)
640                    reject = TRUE;
641                else
642                    drop = TRUE;
643                break;
644            }
645            p_data += AVRC_AVC_HDR_SIZE; /* skip the first 3 bytes: ctype, subunit*, opcode */
646            msg.pass.op_id  = (AVRC_PASS_OP_ID_MASK & *p_data);
647            if (AVRC_PASS_STATE_MASK & *p_data)
648                msg.pass.state  = TRUE;
649            else
650                msg.pass.state  = FALSE;
651            p_data++;
652            msg.pass.pass_len    = *p_data++;
653            if (msg.pass.pass_len != p_pkt->len - 5)
654                msg.pass.pass_len = p_pkt->len - 5;
655            if (msg.pass.pass_len)
656                msg.pass.p_pass_data = p_data;
657            else
658                msg.pass.p_pass_data = NULL;
659            break;
660
661
662        default:
663            if ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD))
664            {
665                /* reject unsupported opcode */
666                reject = TRUE;
667            }
668            drop    = TRUE;
669            break;
670        }
671    }
672    else /* drop the event */
673    {
674            drop    = TRUE;
675    }
676
677    if (reject)
678    {
679        /* reject unsupported opcode */
680        p_rsp           = p_pkt; /* this also sets free = FALSE, drop = TRUE */
681        p_rsp_data      = avrc_get_data_ptr(p_pkt);
682        *p_rsp_data     = AVRC_RSP_REJ;
683#if (BT_USE_TRACES == TRUE)
684        p_drop_msg = "rejected";
685#endif
686        cr      = AVCT_RSP;
687        drop    = TRUE;
688    }
689
690    if (p_rsp)
691    {
692        /* set to send response right away */
693        AVCT_MsgReq( handle, label, cr, p_rsp);
694        free = FALSE;
695        drop = TRUE;
696    }
697
698    if (drop == FALSE)
699    {
700        msg.hdr.opcode = opcode;
701        (*avrc_cb.ccb[handle].p_msg_cback)(handle, label, opcode, &msg);
702    }
703#if (BT_USE_TRACES == TRUE)
704    else
705    {
706        AVRC_TRACE_WARNING5("avrc_msg_cback %s msg handle:%d, control:%d, cr:%d, opcode:x%x",
707                p_drop_msg,
708                handle, avrc_cb.ccb[handle].control, cr, opcode);
709    }
710#endif
711
712
713    if (free)
714        GKI_freebuf(p_pkt);
715}
716
717
718
719
720/******************************************************************************
721**
722** Function         avrc_pass_msg
723**
724** Description      Compose a PASS THROUGH command according to p_msg
725**
726**                  Input Parameters:
727**                      p_msg: Pointer to PASS THROUGH message structure.
728**
729**                  Output Parameters:
730**                      None.
731**
732** Returns          pointer to a valid GKI buffer if successful.
733**                  NULL if p_msg is NULL.
734**
735******************************************************************************/
736static BT_HDR  * avrc_pass_msg(tAVRC_MSG_PASS *p_msg)
737{
738    BT_HDR  *p_cmd = NULL;
739    UINT8   *p_data;
740
741    WC_ASSERT(p_msg != NULL);
742    WC_ASSERT(AVRC_CMD_POOL_SIZE > (AVRC_MIN_CMD_LEN+p_msg->pass_len));
743
744    if ((p_cmd = (BT_HDR *) GKI_getpoolbuf(AVRC_CMD_POOL_ID)) != NULL)
745    {
746        p_cmd->offset   = AVCT_MSG_OFFSET;
747        p_cmd->layer_specific   = AVCT_DATA_CTRL;
748        p_data          = (UINT8 *)(p_cmd + 1) + p_cmd->offset;
749        *p_data++       = (p_msg->hdr.ctype & AVRC_CTYPE_MASK);
750        *p_data++       = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT); /* Panel subunit & id=0 */
751        *p_data++       = AVRC_OP_PASS_THRU;
752        *p_data         = (AVRC_PASS_OP_ID_MASK&p_msg->op_id);
753        if (p_msg->state)
754            *p_data     |= AVRC_PASS_STATE_MASK;
755        p_data++;
756
757        if (p_msg->op_id == AVRC_ID_VENDOR)
758        {
759            *p_data++       = p_msg->pass_len;
760            if (p_msg->pass_len && p_msg->p_pass_data)
761            {
762                memcpy(p_data, p_msg->p_pass_data, p_msg->pass_len);
763                p_data += p_msg->pass_len;
764            }
765        }
766        else /* set msg len to 0 for other op_id */
767        {
768            /* set msg len to 0 for other op_id */
769            *p_data++       = 0;
770        }
771        p_cmd->len      = (UINT16) (p_data - (UINT8 *)(p_cmd + 1) - p_cmd->offset);
772    }
773    return p_cmd;
774}
775
776/******************************************************************************
777**
778** Function         AVRC_Open
779**
780** Description      This function is called to open a connection to AVCTP.
781**                  The connection can be either an initiator or acceptor, as
782**                  determined by the p_ccb->stream parameter.
783**                  The connection can be a target, a controller or for both role,
784**                  as determined by the p_ccb->control parameter.
785**                  By definition, a target connection is an acceptor connection
786**                  that waits for an incoming AVCTP connection from the peer.
787**                  The connection remains available to the application until
788**                  the application closes it by calling AVRC_Close().  The
789**                  application does not need to reopen the connection after an
790**                  AVRC_CLOSE_IND_EVT is received.
791**
792**                  Input Parameters:
793**                      p_ccb->company_id: Company Identifier.
794**
795**                      p_ccb->p_ctrl_cback:  Pointer to control callback function.
796**
797**                      p_ccb->p_msg_cback:  Pointer to message callback function.
798**
799**                      p_ccb->conn: AVCTP connection role.  This is set to
800**                      AVCTP_INT for initiator connections and AVCTP_ACP
801**                      for acceptor connections.
802**
803**                      p_ccb->control: Control role.  This is set to
804**                      AVRC_CT_TARGET for target connections, AVRC_CT_CONTROL
805**                      for control connections or (AVRC_CT_TARGET|AVRC_CT_CONTROL)
806**                      for connections that support both roles.
807**
808**                      peer_addr: BD address of peer device.  This value is
809**                      only used for initiator connections; for acceptor
810**                      connections it can be set to NULL.
811**
812**                  Output Parameters:
813**                      p_handle: Pointer to handle.  This parameter is only
814**                                valid if AVRC_SUCCESS is returned.
815**
816** Returns          AVRC_SUCCESS if successful.
817**                  AVRC_NO_RESOURCES if there are not enough resources to open
818**                  the connection.
819**
820******************************************************************************/
821UINT16 AVRC_Open(UINT8 *p_handle, tAVRC_CONN_CB *p_ccb, BD_ADDR_PTR peer_addr)
822{
823    UINT16      status;
824    tAVCT_CC    cc;
825
826    cc.p_ctrl_cback = avrc_ctrl_cback;      /* Control callback */
827    cc.p_msg_cback  = avrc_msg_cback;       /* Message callback */
828    cc.pid          = UUID_SERVCLASS_AV_REMOTE_CONTROL;  /* Profile ID */
829    cc.role         = p_ccb->conn;          /* Initiator/acceptor role */
830    cc.control      = p_ccb->control;       /* Control role (Control/Target) */
831
832    status = AVCT_CreateConn(p_handle, &cc, peer_addr);
833    if (status == AVCT_SUCCESS)
834    {
835        memcpy(&avrc_cb.ccb[*p_handle], p_ccb, sizeof(tAVRC_CONN_CB));
836#if (AVRC_METADATA_INCLUDED == TRUE)
837        memset(&avrc_cb.fcb[*p_handle], 0, sizeof(tAVRC_FRAG_CB));
838        memset(&avrc_cb.rcb[*p_handle], 0, sizeof(tAVRC_RASM_CB));
839#endif
840    }
841    AVRC_TRACE_DEBUG4("AVRC_Open role: %d, control:%d status:%d, handle:%d", cc.role, cc.control,
842        status, *p_handle);
843
844    return status;
845}
846
847/******************************************************************************
848**
849** Function         AVRC_Close
850**
851** Description      Close a connection opened with AVRC_Open().
852**                  This function is called when the
853**                  application is no longer using a connection.
854**
855**                  Input Parameters:
856**                      handle: Handle of this connection.
857**
858**                  Output Parameters:
859**                      None.
860**
861** Returns          AVRC_SUCCESS if successful.
862**                  AVRC_BAD_HANDLE if handle is invalid.
863**
864******************************************************************************/
865UINT16 AVRC_Close(UINT8 handle)
866{
867    AVRC_TRACE_DEBUG1("AVRC_Close handle:%d", handle);
868    return AVCT_RemoveConn(handle);
869}
870
871
872/******************************************************************************
873**
874** Function         AVRC_MsgReq
875**
876** Description      This function is used to send the AVRCP byte stream in p_pkt
877**                  down to AVCTP.
878**
879**                  It is expected that p_pkt->offset is at least AVCT_MSG_OFFSET
880**                  p_pkt->layer_specific is AVCT_DATA_CTRL or AVCT_DATA_BROWSE
881**                  p_pkt->event is AVRC_OP_VENDOR, AVRC_OP_PASS_THRU or AVRC_OP_BROWSE
882**                  The above BT_HDR settings are set by the AVRC_Bld* functions.
883**
884** Returns          AVRC_SUCCESS if successful.
885**                  AVRC_BAD_HANDLE if handle is invalid.
886**
887******************************************************************************/
888UINT16 AVRC_MsgReq (UINT8 handle, UINT8 label, UINT8 ctype, BT_HDR *p_pkt)
889{
890#if (AVRC_METADATA_INCLUDED == TRUE)
891    UINT8   *p_data;
892    UINT8   cr = AVCT_CMD;
893    BOOLEAN chk_frag = TRUE;
894    UINT8   *p_start = NULL;
895    tAVRC_FRAG_CB   *p_fcb;
896    UINT16  len;
897    BT_HDR  *p_pkt_new;
898
899    if (!p_pkt)
900        return AVRC_BAD_PARAM;
901
902    if (ctype >= AVRC_RSP_NOT_IMPL)
903        cr = AVCT_RSP;
904
905    if (p_pkt->event == AVRC_OP_VENDOR)
906    {
907        /* add AVRCP Vendor Dependent headers */
908        p_start = ((UINT8 *)(p_pkt + 1) + p_pkt->offset);
909        p_pkt->offset -= AVRC_VENDOR_HDR_SIZE;
910        p_pkt->len += AVRC_VENDOR_HDR_SIZE;
911        p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
912        *p_data++       = (ctype & AVRC_CTYPE_MASK);
913        *p_data++       = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
914        *p_data++       = AVRC_OP_VENDOR;
915        AVRC_CO_ID_TO_BE_STREAM(p_data, AVRC_CO_METADATA);
916    }
917    else if (p_pkt->event == AVRC_OP_PASS_THRU)
918    {
919        /* add AVRCP Pass Through headers */
920        p_start = ((UINT8 *)(p_pkt + 1) + p_pkt->offset);
921        p_pkt->offset -= AVRC_PASS_THRU_SIZE;
922        p_pkt->len += AVRC_PASS_THRU_SIZE;
923        p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
924        *p_data++       = (ctype & AVRC_CTYPE_MASK);
925        *p_data++       = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT);
926        *p_data++       = AVRC_OP_PASS_THRU;/* opcode */
927        *p_data++       = AVRC_ID_VENDOR;   /* operation id */
928        *p_data++       = 5;                /* operation data len */
929        AVRC_CO_ID_TO_BE_STREAM(p_data, AVRC_CO_METADATA);
930    }
931
932    /* abandon previous fragments */
933    p_fcb = &avrc_cb.fcb[handle];
934    if (p_fcb->frag_enabled)
935        p_fcb->frag_enabled = FALSE;
936
937    if (p_fcb->p_fmsg)
938    {
939        GKI_freebuf(p_fcb->p_fmsg);
940        p_fcb->p_fmsg = NULL;
941    }
942
943    /* AVRCP spec has not defined any control channel commands that needs fragmentation at this level
944     * check for fragmentation only on the response */
945    if ((cr == AVCT_RSP) && (chk_frag == TRUE))
946    {
947        if (p_pkt->len > AVRC_MAX_CTRL_DATA_LEN)
948        {
949            AVRC_TRACE_DEBUG1 ("p_pkt->len(%d) > AVRC_MAX_CTRL_DATA_LEN", p_pkt->len );
950            p_pkt_new = (BT_HDR *)GKI_getbuf((UINT16)(AVRC_PACKET_LEN + AVCT_MSG_OFFSET
951                + BT_HDR_SIZE));
952            if (p_pkt_new)
953            {
954                p_fcb->frag_enabled = TRUE;
955                p_fcb->p_fmsg       = p_pkt;
956                p_fcb->frag_pdu     = *p_start;
957                p_pkt               = p_pkt_new;
958                p_pkt_new           = p_fcb->p_fmsg;
959                p_pkt->len          = AVRC_MAX_CTRL_DATA_LEN;
960                p_pkt->offset       = p_pkt_new->offset;
961                p_pkt->layer_specific = p_pkt_new->layer_specific;
962                p_pkt->event = p_pkt_new->event;
963                p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset;
964                p_start -= AVRC_VENDOR_HDR_SIZE;
965                memcpy (p_data, p_start, AVRC_MAX_CTRL_DATA_LEN);
966                /* use AVRC start packet type */
967                p_data += AVRC_VENDOR_HDR_SIZE;
968                p_data++; /* pdu */
969                *p_data++ = AVRC_PKT_START;
970                /* 4 pdu, pkt_type & len */
971                len = (AVRC_MAX_CTRL_DATA_LEN - AVRC_VENDOR_HDR_SIZE - AVRC_MIN_META_HDR_SIZE);
972                UINT16_TO_BE_STREAM(p_data, len);
973
974                /* prepare the left over for as an end fragment */
975                avrc_prep_end_frag (handle);
976                AVRC_TRACE_DEBUG3 ("p_pkt len:%d/%d, next len:%d", p_pkt->len, len, p_fcb->p_fmsg->len );
977            }
978            else
979            {
980                AVRC_TRACE_ERROR0 ("AVRC_MsgReq no buffers for fragmentation" );
981                GKI_freebuf(p_pkt);
982    return AVRC_NO_RESOURCES;
983}
984        }
985    }
986
987    return AVCT_MsgReq( handle, label, cr, p_pkt);
988#else
989    return AVRC_NO_RESOURCES;
990#endif
991}
992
993
994/******************************************************************************
995**
996** Function         AVRC_PassCmd
997**
998** Description      Send a PASS THROUGH command to the peer device.  This
999**                  function can only be called for controller role connections.
1000**                  Any response message from the peer is passed back through
1001**                  the tAVRC_MSG_CBACK callback function.
1002**
1003**                  Input Parameters:
1004**                      handle: Handle of this connection.
1005**
1006**                      label: Transaction label.
1007**
1008**                      p_msg: Pointer to PASS THROUGH message structure.
1009**
1010**                  Output Parameters:
1011**                      None.
1012**
1013** Returns          AVRC_SUCCESS if successful.
1014**                  AVRC_BAD_HANDLE if handle is invalid.
1015**
1016******************************************************************************/
1017UINT16 AVRC_PassCmd(UINT8 handle, UINT8 label, tAVRC_MSG_PASS *p_msg)
1018{
1019    BT_HDR *p_buf;
1020    WC_ASSERT(p_msg != NULL);
1021    if (p_msg)
1022    {
1023        p_msg->hdr.ctype    = AVRC_CMD_CTRL;
1024        p_buf = avrc_pass_msg(p_msg);
1025        if (p_buf)
1026            return AVCT_MsgReq( handle, label, AVCT_CMD, p_buf);
1027    }
1028    return AVRC_NO_RESOURCES;
1029}
1030
1031/******************************************************************************
1032**
1033** Function         AVRC_PassRsp
1034**
1035** Description      Send a PASS THROUGH response to the peer device.  This
1036**                  function can only be called for target role connections.
1037**                  This function must be called when a PASS THROUGH command
1038**                  message is received from the peer through the
1039**                  tAVRC_MSG_CBACK callback function.
1040**
1041**                  Input Parameters:
1042**                      handle: Handle of this connection.
1043**
1044**                      label: Transaction label.  Must be the same value as
1045**                      passed with the command message in the callback function.
1046**
1047**                      p_msg: Pointer to PASS THROUGH message structure.
1048**
1049**                  Output Parameters:
1050**                      None.
1051**
1052** Returns          AVRC_SUCCESS if successful.
1053**                  AVRC_BAD_HANDLE if handle is invalid.
1054**
1055******************************************************************************/
1056UINT16 AVRC_PassRsp(UINT8 handle, UINT8 label, tAVRC_MSG_PASS *p_msg)
1057{
1058    BT_HDR *p_buf;
1059    WC_ASSERT(p_msg != NULL);
1060    if (p_msg)
1061    {
1062        p_buf = avrc_pass_msg(p_msg);
1063        if (p_buf)
1064            return AVCT_MsgReq( handle, label, AVCT_RSP, p_buf);
1065    }
1066    return AVRC_NO_RESOURCES;
1067}
1068
1069