• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 static 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 ******************************************************************************/
avrc_ctrl_cback(UINT8 handle,UINT8 event,UINT16 result,BD_ADDR peer_addr)67 static 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 ******************************************************************************/
avrc_get_data_ptr(BT_HDR * p_pkt)95 static 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 ******************************************************************************/
avrc_prep_end_frag(UINT8 handle)124 static 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 ******************************************************************************/
avrc_send_continue_frag(UINT8 handle,UINT8 label)162 static 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 ******************************************************************************/
avrc_proc_vendor_command(UINT8 handle,UINT8 label,BT_HDR * p_pkt,tAVRC_MSG_VENDOR * p_msg)233 static 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 ******************************************************************************/
avrc_proc_far_msg(UINT8 handle,UINT8 label,UINT8 cr,BT_HDR ** pp_pkt,tAVRC_MSG_VENDOR * p_msg)346 static 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 ******************************************************************************/
avrc_msg_cback(UINT8 handle,UINT8 label,UINT8 cr,BT_HDR * p_pkt)471 static 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 ******************************************************************************/
avrc_pass_msg(tAVRC_MSG_PASS * p_msg)736 static 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 ******************************************************************************/
AVRC_Open(UINT8 * p_handle,tAVRC_CONN_CB * p_ccb,BD_ADDR_PTR peer_addr)821 UINT16 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 ******************************************************************************/
AVRC_Close(UINT8 handle)865 UINT16 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 ******************************************************************************/
AVRC_MsgReq(UINT8 handle,UINT8 label,UINT8 ctype,BT_HDR * p_pkt)888 UINT16 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 ******************************************************************************/
AVRC_PassCmd(UINT8 handle,UINT8 label,tAVRC_MSG_PASS * p_msg)1017 UINT16 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 ******************************************************************************/
AVRC_PassRsp(UINT8 handle,UINT8 label,tAVRC_MSG_PASS * p_msg)1056 UINT16 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