1 /******************************************************************************
2  *
3  *  Copyright (C) 2011-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  *  This is the implementation of the API for the advanced audio/video (AV)
22  *  subsystem of BTA, Broadcom's Bluetooth application layer for mobile
23  *  phones.
24  *
25  ******************************************************************************/
26 
27 #include "common/bt_target.h"
28 #if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
29 
30 #include "osi/allocator.h"
31 #include "bta/bta_api.h"
32 #include "bta/bta_sys.h"
33 #include "bta/bta_av_api.h"
34 #include "bta_av_int.h"
35 #include <string.h>
36 
37 /*****************************************************************************
38 **  Constants
39 *****************************************************************************/
40 
41 static const tBTA_SYS_REG bta_av_reg = {
42     bta_av_hdl_event,
43     BTA_AvDisable
44 };
45 
46 /*******************************************************************************
47 **
48 ** Function         BTA_AvEnable
49 **
50 ** Description      Enable the advanced audio/video service. When the enable
51 **                  operation is complete the callback function will be
52 **                  called with a BTA_AV_ENABLE_EVT. This function must
53 **                  be called before other function in the AV API are
54 **                  called.
55 **
56 ** Returns          void
57 **
58 *******************************************************************************/
BTA_AvEnable(tBTA_SEC sec_mask,tBTA_AV_FEAT features,tBTA_AV_CBACK * p_cback)59 void BTA_AvEnable(tBTA_SEC sec_mask, tBTA_AV_FEAT features, tBTA_AV_CBACK *p_cback)
60 {
61     tBTA_AV_API_ENABLE  *p_buf;
62 
63     /* register with BTA system manager */
64     bta_sys_register(BTA_ID_AV, &bta_av_reg);
65 
66     if ((p_buf = (tBTA_AV_API_ENABLE *) osi_malloc(sizeof(tBTA_AV_API_ENABLE))) != NULL) {
67         p_buf->hdr.event = BTA_AV_API_ENABLE_EVT;
68         p_buf->p_cback  = p_cback;
69         p_buf->features = features;
70         p_buf->sec_mask = sec_mask;
71         bta_sys_sendmsg(p_buf);
72     }
73 }
74 
75 /*******************************************************************************
76 **
77 ** Function         BTA_AvDisable
78 **
79 ** Description      Disable the advanced audio/video service.
80 **
81 ** Returns          void
82 **
83 *******************************************************************************/
BTA_AvDisable(void)84 void BTA_AvDisable(void)
85 {
86     BT_HDR  *p_buf;
87 
88     bta_sys_deregister(BTA_ID_AV);
89     if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
90         p_buf->event = BTA_AV_API_DISABLE_EVT;
91         bta_sys_sendmsg(p_buf);
92     }
93 }
94 
95 /*******************************************************************************
96 **
97 ** Function         BTA_AvRegister
98 **
99 ** Description      Register the audio or video service to stack. When the
100 **                  operation is complete the callback function will be
101 **                  called with a BTA_AV_REGISTER_EVT. This function must
102 **                  be called before AVDT stream is open.
103 **
104 **
105 ** Returns          void
106 **
107 *******************************************************************************/
BTA_AvRegister(tBTA_AV_CHNL chnl,const char * p_service_name,UINT8 app_id,tBTA_AV_DATA_CBACK * p_data_cback,tBTA_AV_CO_FUNCTS * bta_av_cos,tBTA_AVRC_CO_FUNCTS * bta_avrc_cos,UINT8 tsep)108 void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id,
109                     tBTA_AV_DATA_CBACK *p_data_cback, tBTA_AV_CO_FUNCTS *bta_av_cos,
110                     tBTA_AVRC_CO_FUNCTS *bta_avrc_cos, UINT8 tsep)
111 {
112     tBTA_AV_API_REG  *p_buf;
113 
114 
115     if ((p_buf = (tBTA_AV_API_REG *) osi_malloc(sizeof(tBTA_AV_API_REG))) != NULL) {
116         p_buf->hdr.layer_specific   = chnl;
117         p_buf->hdr.event = BTA_AV_API_REGISTER_EVT;
118         if (p_service_name) {
119             BCM_STRNCPY_S(p_buf->p_service_name, p_service_name, BTA_SERVICE_NAME_LEN);
120             p_buf->p_service_name[BTA_SERVICE_NAME_LEN - 1] = 0;
121         } else {
122             p_buf->p_service_name[0] = 0;
123         }
124         p_buf->app_id = app_id;
125         p_buf->p_app_data_cback = p_data_cback;
126         p_buf->bta_av_cos = bta_av_cos;
127         p_buf->bta_avrc_cos = bta_avrc_cos;
128         p_buf->tsep = tsep;
129         bta_sys_sendmsg(p_buf);
130     }
131 }
132 
133 /*******************************************************************************
134 **
135 ** Function         BTA_AvDeregister
136 **
137 ** Description      Deregister the audio or video service
138 **
139 ** Returns          void
140 **
141 *******************************************************************************/
BTA_AvDeregister(tBTA_AV_HNDL hndl)142 void BTA_AvDeregister(tBTA_AV_HNDL hndl)
143 {
144     BT_HDR  *p_buf;
145 
146     if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
147         p_buf->layer_specific   = hndl;
148         p_buf->event = BTA_AV_API_DEREGISTER_EVT;
149         bta_sys_sendmsg(p_buf);
150     }
151 }
152 
153 /*******************************************************************************
154 **
155 ** Function         BTA_AvOpen
156 **
157 ** Description      Opens an advanced audio/video connection to a peer device.
158 **                  When connection is open callback function is called
159 **                  with a BTA_AV_OPEN_EVT.
160 **
161 ** Returns          void
162 **
163 *******************************************************************************/
BTA_AvOpen(BD_ADDR bd_addr,tBTA_AV_HNDL handle,BOOLEAN use_rc,tBTA_SEC sec_mask,UINT16 uuid)164 void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle, BOOLEAN use_rc, tBTA_SEC sec_mask,
165                 UINT16 uuid)
166 {
167     tBTA_AV_API_OPEN  *p_buf;
168 
169     if ((p_buf = (tBTA_AV_API_OPEN *) osi_malloc(sizeof(tBTA_AV_API_OPEN))) != NULL) {
170         p_buf->hdr.event = BTA_AV_API_OPEN_EVT;
171         p_buf->hdr.layer_specific   = handle;
172         bdcpy(p_buf->bd_addr, bd_addr);
173         p_buf->use_rc = use_rc;
174         p_buf->sec_mask = sec_mask;
175         p_buf->switch_res = BTA_AV_RS_NONE;
176         p_buf->uuid = uuid;
177         bta_sys_sendmsg(p_buf);
178     }
179 }
180 
181 /*******************************************************************************
182 **
183 ** Function         BTA_AvClose
184 **
185 ** Description      Close the current streams.
186 **
187 ** Returns          void
188 **
189 *******************************************************************************/
BTA_AvClose(tBTA_AV_HNDL handle)190 void BTA_AvClose(tBTA_AV_HNDL handle)
191 {
192     BT_HDR  *p_buf;
193 
194     if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
195         p_buf->event = BTA_AV_API_CLOSE_EVT;
196         p_buf->layer_specific   = handle;
197         bta_sys_sendmsg(p_buf);
198     }
199 }
200 
201 /*******************************************************************************
202 **
203 ** Function         BTA_AvDisconnect
204 **
205 ** Description      Close the connection to the address.
206 **
207 ** Returns          void
208 **
209 *******************************************************************************/
BTA_AvDisconnect(BD_ADDR bd_addr)210 void BTA_AvDisconnect(BD_ADDR bd_addr)
211 {
212     tBTA_AV_API_DISCNT  *p_buf;
213 
214     if ((p_buf = (tBTA_AV_API_DISCNT *) osi_malloc(sizeof(tBTA_AV_API_DISCNT))) != NULL) {
215         p_buf->hdr.event = BTA_AV_API_DISCONNECT_EVT;
216         bdcpy(p_buf->bd_addr, bd_addr);
217         bta_sys_sendmsg(p_buf);
218     }
219 }
220 
221 /*******************************************************************************
222 **
223 ** Function         BTA_AvStart
224 **
225 ** Description      Start audio/video stream data transfer.
226 **
227 ** Returns          void
228 **
229 *******************************************************************************/
BTA_AvStart(void)230 void BTA_AvStart(void)
231 {
232     BT_HDR  *p_buf;
233 
234     if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
235         p_buf->event = BTA_AV_API_START_EVT;
236         bta_sys_sendmsg(p_buf);
237     }
238 }
239 
240 /*******************************************************************************
241 **
242 ** Function         BTA_AvEnable_Sink
243 **
244 ** Description      Enable/Disable A2DP Sink..
245 **
246 ** Returns          void
247 **
248 *******************************************************************************/
BTA_AvEnable_Sink(int enable)249 void BTA_AvEnable_Sink(int enable)
250 {
251 #if (BTA_AV_SINK_INCLUDED == TRUE)
252     BT_HDR  *p_buf;
253     if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
254         p_buf->event = BTA_AV_API_SINK_ENABLE_EVT;
255         p_buf->layer_specific = enable;
256         bta_sys_sendmsg(p_buf);
257     }
258 #else
259     return;
260 #endif
261 }
262 
263 /*******************************************************************************
264 **
265 ** Function         BTA_AvStop
266 **
267 ** Description      Stop audio/video stream data transfer.
268 **                  If suspend is TRUE, this function sends AVDT suspend signal
269 **                  to the connected peer(s).
270 **
271 ** Returns          void
272 **
273 *******************************************************************************/
BTA_AvStop(BOOLEAN suspend)274 void BTA_AvStop(BOOLEAN suspend)
275 {
276     tBTA_AV_API_STOP  *p_buf;
277 
278     if ((p_buf = (tBTA_AV_API_STOP *) osi_malloc(sizeof(tBTA_AV_API_STOP))) != NULL) {
279         p_buf->hdr.event = BTA_AV_API_STOP_EVT;
280         p_buf->flush   = TRUE;
281         p_buf->suspend = suspend;
282         bta_sys_sendmsg(p_buf);
283     }
284 }
285 
286 /*******************************************************************************
287 **
288 ** Function         BTA_AvReconfig
289 **
290 ** Description      Reconfigure the audio/video stream.
291 **                  If suspend is TRUE, this function tries the suspend/reconfigure
292 **                  procedure first.
293 **                  If suspend is FALSE or when suspend/reconfigure fails,
294 **                  this function closes and re-opens the AVDT connection.
295 **
296 ** Returns          void
297 **
298 *******************************************************************************/
BTA_AvReconfig(tBTA_AV_HNDL hndl,BOOLEAN suspend,UINT8 sep_info_idx,UINT8 * p_codec_info,UINT8 num_protect,UINT8 * p_protect_info)299 void BTA_AvReconfig(tBTA_AV_HNDL hndl, BOOLEAN suspend, UINT8 sep_info_idx,
300                     UINT8 *p_codec_info, UINT8 num_protect, UINT8 *p_protect_info)
301 {
302     tBTA_AV_API_RCFG  *p_buf;
303 
304     if ((p_buf = (tBTA_AV_API_RCFG *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_RCFG) + num_protect))) != NULL) {
305         p_buf->hdr.layer_specific   = hndl;
306         p_buf->hdr.event    = BTA_AV_API_RECONFIG_EVT;
307         p_buf->num_protect  = num_protect;
308         p_buf->suspend      = suspend;
309         p_buf->sep_info_idx = sep_info_idx;
310         p_buf->p_protect_info = (UINT8 *)(p_buf + 1);
311         memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE);
312         memcpy(p_buf->p_protect_info, p_protect_info, num_protect);
313         bta_sys_sendmsg(p_buf);
314     }
315 }
316 
317 /*******************************************************************************
318 **
319 ** Function         BTA_AvProtectReq
320 **
321 ** Description      Send a content protection request.  This function can only
322 **                  be used if AV is enabled with feature BTA_AV_FEAT_PROTECT.
323 **
324 ** Returns          void
325 **
326 *******************************************************************************/
BTA_AvProtectReq(tBTA_AV_HNDL hndl,UINT8 * p_data,UINT16 len)327 void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len)
328 {
329     tBTA_AV_API_PROTECT_REQ  *p_buf;
330 
331     if ((p_buf = (tBTA_AV_API_PROTECT_REQ *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_PROTECT_REQ) + len))) != NULL) {
332         p_buf->hdr.layer_specific   = hndl;
333         p_buf->hdr.event = BTA_AV_API_PROTECT_REQ_EVT;
334         p_buf->len       = len;
335         if (p_data == NULL) {
336             p_buf->p_data = NULL;
337         } else {
338             p_buf->p_data = (UINT8 *) (p_buf + 1);
339             memcpy(p_buf->p_data, p_data, len);
340         }
341         bta_sys_sendmsg(p_buf);
342     }
343 }
344 
345 /*******************************************************************************
346 **
347 ** Function         BTA_AvProtectRsp
348 **
349 ** Description      Send a content protection response.  This function must
350 **                  be called if a BTA_AV_PROTECT_REQ_EVT is received.
351 **                  This function can only be used if AV is enabled with
352 **                  feature BTA_AV_FEAT_PROTECT.
353 **
354 ** Returns          void
355 **
356 *******************************************************************************/
BTA_AvProtectRsp(tBTA_AV_HNDL hndl,UINT8 error_code,UINT8 * p_data,UINT16 len)357 void BTA_AvProtectRsp(tBTA_AV_HNDL hndl, UINT8 error_code, UINT8 *p_data, UINT16 len)
358 {
359     tBTA_AV_API_PROTECT_RSP  *p_buf;
360 
361     if ((p_buf = (tBTA_AV_API_PROTECT_RSP *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_PROTECT_RSP) + len))) != NULL) {
362         p_buf->hdr.layer_specific   = hndl;
363         p_buf->hdr.event    = BTA_AV_API_PROTECT_RSP_EVT;
364         p_buf->len          = len;
365         p_buf->error_code   = error_code;
366         if (p_data == NULL) {
367             p_buf->p_data = NULL;
368         } else {
369             p_buf->p_data = (UINT8 *) (p_buf + 1);
370             memcpy(p_buf->p_data, p_data, len);
371         }
372         bta_sys_sendmsg(p_buf);
373     }
374 }
375 
376 /*******************************************************************************
377 **
378 ** Function         BTA_AvRemoteCmd
379 **
380 ** Description      Send a remote control command.  This function can only
381 **                  be used if AV is enabled with feature BTA_AV_FEAT_RCCT.
382 **
383 ** Returns          void
384 **
385 *******************************************************************************/
BTA_AvRemoteCmd(UINT8 rc_handle,UINT8 label,tBTA_AV_RC rc_id,tBTA_AV_STATE key_state)386 void BTA_AvRemoteCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_RC rc_id, tBTA_AV_STATE key_state)
387 {
388     tBTA_AV_API_REMOTE_CMD  *p_buf;
389 
390     if ((p_buf = (tBTA_AV_API_REMOTE_CMD *) osi_malloc(sizeof(tBTA_AV_API_REMOTE_CMD))) != NULL) {
391         p_buf->hdr.event = BTA_AV_API_REMOTE_CMD_EVT;
392         p_buf->hdr.layer_specific   = rc_handle;
393         p_buf->msg.op_id = rc_id;
394         p_buf->msg.state = key_state;
395         p_buf->msg.p_pass_data = NULL;
396         p_buf->msg.pass_len = 0;
397         p_buf->label = label;
398         bta_sys_sendmsg(p_buf);
399     }
400 }
401 
402 /*******************************************************************************
403 **
404 ** Function         BTA_AvVendorCmd
405 **
406 ** Description      Send a vendor dependent remote control command.  This
407 **                  function can only be used if AV is enabled with feature
408 **                  BTA_AV_FEAT_VENDOR.
409 **
410 ** Returns          void
411 **
412 *******************************************************************************/
BTA_AvVendorCmd(UINT8 rc_handle,UINT8 label,tBTA_AV_CODE cmd_code,UINT8 * p_data,UINT16 len)413 void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code, UINT8 *p_data, UINT16 len)
414 {
415     tBTA_AV_API_VENDOR  *p_buf;
416 
417     if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL) {
418         p_buf->hdr.event = BTA_AV_API_VENDOR_CMD_EVT;
419         p_buf->hdr.layer_specific   = rc_handle;
420         p_buf->msg.hdr.ctype = cmd_code;
421         p_buf->msg.hdr.subunit_type = AVRC_SUB_PANEL;
422         p_buf->msg.hdr.subunit_id = 0;
423         p_buf->msg.company_id = p_bta_av_cfg->company_id;
424         p_buf->label = label;
425         p_buf->msg.vendor_len = len;
426         if (p_data == NULL) {
427             p_buf->msg.p_vendor_data = NULL;
428         } else {
429             p_buf->msg.p_vendor_data = (UINT8 *) (p_buf + 1);
430             memcpy(p_buf->msg.p_vendor_data, p_data, len);
431         }
432         bta_sys_sendmsg(p_buf);
433     }
434 }
435 
436 /*******************************************************************************
437 **
438 ** Function         BTA_AvVendorRsp
439 **
440 ** Description      Send a vendor dependent remote control response.
441 **                  This function must be called if a BTA_AV_VENDOR_CMD_EVT
442 **                  is received. This function can only be used if AV is
443 **                  enabled with feature BTA_AV_FEAT_VENDOR.
444 **
445 ** Returns          void
446 **
447 *******************************************************************************/
BTA_AvVendorRsp(UINT8 rc_handle,UINT8 label,tBTA_AV_CODE rsp_code,UINT8 * p_data,UINT16 len,UINT32 company_id)448 void BTA_AvVendorRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code, UINT8 *p_data, UINT16 len, UINT32 company_id)
449 {
450     tBTA_AV_API_VENDOR  *p_buf;
451 
452     if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL) {
453         p_buf->hdr.event = BTA_AV_API_VENDOR_RSP_EVT;
454         p_buf->hdr.layer_specific   = rc_handle;
455         p_buf->msg.hdr.ctype = rsp_code;
456         p_buf->msg.hdr.subunit_type = AVRC_SUB_PANEL;
457         p_buf->msg.hdr.subunit_id = 0;
458         if (company_id) {
459             p_buf->msg.company_id = company_id;
460         } else {
461             p_buf->msg.company_id = p_bta_av_cfg->company_id;
462         }
463         p_buf->label = label;
464         p_buf->msg.vendor_len = len;
465         if (p_data == NULL) {
466             p_buf->msg.p_vendor_data = NULL;
467         } else {
468             p_buf->msg.p_vendor_data = (UINT8 *) (p_buf + 1);
469             memcpy(p_buf->msg.p_vendor_data, p_data, len);
470         }
471         bta_sys_sendmsg(p_buf);
472     }
473 }
474 
475 /*******************************************************************************
476 **
477 ** Function         BTA_AvOpenRc
478 **
479 ** Description      Open an AVRCP connection toward the device with the
480 **                  specified handle
481 **
482 ** Returns          void
483 **
484 *******************************************************************************/
BTA_AvOpenRc(tBTA_AV_HNDL handle)485 void BTA_AvOpenRc(tBTA_AV_HNDL handle)
486 {
487     tBTA_AV_API_OPEN_RC  *p_buf;
488 
489     if ((p_buf = (tBTA_AV_API_OPEN_RC *) osi_malloc(sizeof(tBTA_AV_API_OPEN_RC))) != NULL) {
490         p_buf->hdr.event = BTA_AV_API_RC_OPEN_EVT;
491         p_buf->hdr.layer_specific   = handle;
492         bta_sys_sendmsg(p_buf);
493     }
494 }
495 
496 /*******************************************************************************
497 **
498 ** Function         BTA_AvCloseRc
499 **
500 ** Description      Close an AVRCP connection
501 **
502 ** Returns          void
503 **
504 *******************************************************************************/
BTA_AvCloseRc(UINT8 rc_handle)505 void BTA_AvCloseRc(UINT8 rc_handle)
506 {
507     tBTA_AV_API_CLOSE_RC  *p_buf;
508 
509     if ((p_buf = (tBTA_AV_API_CLOSE_RC *) osi_malloc(sizeof(tBTA_AV_API_CLOSE_RC))) != NULL) {
510         p_buf->hdr.event = BTA_AV_API_RC_CLOSE_EVT;
511         p_buf->hdr.layer_specific   = rc_handle;
512         bta_sys_sendmsg(p_buf);
513     }
514 }
515 
516 /*******************************************************************************
517 **
518 ** Function         BTA_AvMetaRsp
519 **
520 ** Description      Send a Metadata/Advanced Control response. The message contained
521 **                  in p_pkt can be composed with AVRC utility functions.
522 **                  This function can only be used if AV is enabled with feature
523 **                  BTA_AV_FEAT_METADATA.
524 **
525 ** Returns          void
526 **
527 *******************************************************************************/
BTA_AvMetaRsp(UINT8 rc_handle,UINT8 label,tBTA_AV_CODE rsp_code,BT_HDR * p_pkt)528 void BTA_AvMetaRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
529                    BT_HDR *p_pkt)
530 {
531     tBTA_AV_API_META_RSP  *p_buf;
532 
533     if ((p_buf = (tBTA_AV_API_META_RSP *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_META_RSP)))) != NULL) {
534         p_buf->hdr.event = BTA_AV_API_META_RSP_EVT;
535         p_buf->hdr.layer_specific   = rc_handle;
536         p_buf->rsp_code = rsp_code;
537         p_buf->p_pkt = p_pkt;
538         p_buf->is_rsp = TRUE;
539         p_buf->label = label;
540 
541         bta_sys_sendmsg(p_buf);
542     } else if (p_pkt) {
543         osi_free(p_pkt);
544     }
545 }
546 
547 /*******************************************************************************
548 **
549 ** Function         BTA_AvMetaCmd
550 **
551 ** Description      Send a Metadata/Advanced Control command. The message contained
552 **                  in p_pkt can be composed with AVRC utility functions.
553 **                  This function can only be used if AV is enabled with feature
554 **                  BTA_AV_FEAT_METADATA.
555 **                  This message is sent only when the peer supports the TG role.
556 *8                  The only command makes sense right now is the absolute volume command.
557 **
558 ** Returns          void
559 **
560 *******************************************************************************/
BTA_AvMetaCmd(UINT8 rc_handle,UINT8 label,tBTA_AV_CMD cmd_code,BT_HDR * p_pkt)561 void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p_pkt)
562 {
563     tBTA_AV_API_META_RSP  *p_buf;
564 
565     if ((p_buf = (tBTA_AV_API_META_RSP *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_META_RSP)))) != NULL) {
566         p_buf->hdr.event = BTA_AV_API_META_RSP_EVT;
567         p_buf->hdr.layer_specific   = rc_handle;
568         p_buf->p_pkt = p_pkt;
569         p_buf->rsp_code = cmd_code;
570         p_buf->is_rsp = FALSE;
571         p_buf->label = label;
572 
573         bta_sys_sendmsg(p_buf);
574     }
575 }
576 
577 #endif /* BTA_AV_INCLUDED */
578