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