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 *  This module contains API of the audio/video control transport protocol.
22 *
23 ******************************************************************************/
24
25#include <string.h>
26#include "data_types.h"
27#include "bt_target.h"
28#include "bt_utils.h"
29#include "gki.h"
30#include "l2c_api.h"
31#include "l2cdefs.h"
32#include "btm_api.h"
33#include "avct_api.h"
34#include "avct_int.h"
35
36/* Control block for AVCT */
37#if AVCT_DYNAMIC_MEMORY == FALSE
38tAVCT_CB avct_cb;
39#endif
40
41/*******************************************************************************
42**
43** Function         AVCT_Register
44**
45** Description      This is the system level registration function for the
46**                  AVCTP protocol.  This function initializes AVCTP and
47**                  prepares the protocol stack for its use.  This function
48**                  must be called once by the system or platform using AVCTP
49**                  before the other functions of the API an be used.
50**
51**
52** Returns          void
53**
54*******************************************************************************/
55void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask)
56{
57    UNUSED(mtu_br);
58
59    AVCT_TRACE_API("AVCT_Register");
60
61    /* register PSM with L2CAP */
62    L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_appl);
63
64    /* set security level */
65    BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
66    BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0);
67
68    /* initialize AVCTP data structures */
69    memset(&avct_cb, 0, sizeof(tAVCT_CB));
70
71#if (AVCT_BROWSE_INCLUDED == TRUE)
72    /* Include the browsing channel which uses eFCR */
73    L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_br_appl);
74
75    BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
76    BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP_BROWSE, sec_mask, AVCT_BR_PSM, 0, 0);
77
78    if (mtu_br < AVCT_MIN_BROWSE_MTU)
79        mtu_br = AVCT_MIN_BROWSE_MTU;
80    avct_cb.mtu_br = mtu_br;
81#endif
82
83#if defined(AVCT_INITIAL_TRACE_LEVEL)
84    avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
85#else
86    avct_cb.trace_level = BT_TRACE_LEVEL_NONE;
87#endif
88
89    if (mtu < AVCT_MIN_CONTROL_MTU)
90        mtu = AVCT_MIN_CONTROL_MTU;
91    /* store mtu */
92    avct_cb.mtu = mtu;
93}
94
95/*******************************************************************************
96**
97** Function         AVCT_Deregister
98**
99** Description      This function is called to deregister use AVCTP protocol.
100**                  It is called when AVCTP is no longer being used by any
101**                  application in the system.  Before this function can be
102**                  called, all connections must be removed with
103**                  AVCT_RemoveConn().
104**
105**
106** Returns          void
107**
108*******************************************************************************/
109void AVCT_Deregister(void)
110{
111    AVCT_TRACE_API("AVCT_Deregister");
112
113    /* deregister PSM with L2CAP */
114    L2CA_Deregister(AVCT_PSM);
115}
116
117/*******************************************************************************
118**
119** Function         AVCT_CreateConn
120**
121** Description      Create an AVCTP connection.  There are two types of
122**                  connections, initiator and acceptor, as determined by
123**                  the p_cc->role parameter.  When this function is called to
124**                  create an initiator connection, an AVCTP connection to
125**                  the peer device is initiated if one does not already exist.
126**                  If an acceptor connection is created, the connection waits
127**                  passively for an incoming AVCTP connection from a peer device.
128**
129**
130** Returns          AVCT_SUCCESS if successful, otherwise error.
131**
132*******************************************************************************/
133UINT16 AVCT_CreateConn(UINT8 *p_handle, tAVCT_CC *p_cc, BD_ADDR peer_addr)
134{
135    UINT16      result = AVCT_SUCCESS;
136    tAVCT_CCB   *p_ccb;
137    tAVCT_LCB   *p_lcb;
138
139    AVCT_TRACE_API("AVCT_CreateConn: %d, control:%d", p_cc->role, p_cc->control);
140
141    /* Allocate ccb; if no ccbs, return failure */
142    if ((p_ccb = avct_ccb_alloc(p_cc)) == NULL)
143    {
144        result = AVCT_NO_RESOURCES;
145    }
146    else
147    {
148        /* get handle */
149        *p_handle = avct_ccb_to_idx(p_ccb);
150
151        /* if initiator connection */
152        if (p_cc->role == AVCT_INT)
153        {
154            /* find link; if none allocate a new one */
155            if ((p_lcb = avct_lcb_by_bd(peer_addr)) == NULL)
156            {
157                if ((p_lcb = avct_lcb_alloc(peer_addr)) == NULL)
158                {
159                    /* no link resources; free ccb as well */
160                    avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
161                    result = AVCT_NO_RESOURCES;
162                }
163            }
164            /* check if PID already in use */
165            else if (avct_lcb_has_pid(p_lcb, p_cc->pid))
166            {
167                avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
168                result = AVCT_PID_IN_USE;
169            }
170
171            if (result == AVCT_SUCCESS)
172            {
173                /* bind lcb to ccb */
174                p_ccb->p_lcb = p_lcb;
175                AVCT_TRACE_DEBUG("ch_state: %d", p_lcb->ch_state);
176                avct_lcb_event(p_lcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
177            }
178        }
179    }
180    return result;
181}
182
183/*******************************************************************************
184**
185** Function         AVCT_RemoveConn
186**
187** Description      Remove an AVCTP connection.  This function is called when
188**                  the application is no longer using a connection.  If this
189**                  is the last connection to a peer the L2CAP channel for AVCTP
190**                  will be closed.
191**
192**
193** Returns          AVCT_SUCCESS if successful, otherwise error.
194**
195*******************************************************************************/
196UINT16 AVCT_RemoveConn(UINT8 handle)
197{
198    UINT16              result = AVCT_SUCCESS;
199    tAVCT_CCB           *p_ccb;
200
201    AVCT_TRACE_API("AVCT_RemoveConn");
202
203    /* map handle to ccb */
204    if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
205    {
206        result = AVCT_BAD_HANDLE;
207    }
208    /* if connection not bound to lcb, dealloc */
209    else if (p_ccb->p_lcb == NULL)
210    {
211        avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
212    }
213    /* send unbind event to lcb */
214    else
215    {
216        avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
217    }
218    return result;
219}
220
221/*******************************************************************************
222**
223** Function         AVCT_CreateBrowse
224**
225** Description      Create an AVCTP Browse channel.  There are two types of
226**                  connections, initiator and acceptor, as determined by
227**                  the role parameter.  When this function is called to
228**                  create an initiator connection, the Browse channel to
229**                  the peer device is initiated if one does not already exist.
230**                  If an acceptor connection is created, the connection waits
231**                  passively for an incoming AVCTP connection from a peer device.
232**
233**
234** Returns          AVCT_SUCCESS if successful, otherwise error.
235**
236*******************************************************************************/
237UINT16 AVCT_CreateBrowse (UINT8 handle, UINT8 role)
238{
239#if (AVCT_BROWSE_INCLUDED == TRUE)
240    UINT16      result = AVCT_SUCCESS;
241    tAVCT_CCB   *p_ccb;
242    tAVCT_BCB   *p_bcb;
243    int         index;
244
245    AVCT_TRACE_API("AVCT_CreateBrowse: %d", role);
246
247    /* map handle to ccb */
248    if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
249    {
250        return AVCT_BAD_HANDLE;
251    }
252    else
253    {
254        /* mark this CCB as supporting browsing channel */
255        if ((p_ccb->allocated & AVCT_ALOC_BCB) == 0)
256        {
257            p_ccb->allocated |= AVCT_ALOC_BCB;
258        }
259    }
260
261    /* if initiator connection */
262    if (role == AVCT_INT)
263    {
264        /* the link control block must exist before this function is called as INT. */
265        if (p_ccb->p_lcb == NULL)
266        {
267            result = AVCT_NOT_OPEN;
268        }
269        else
270        {
271            /* find link; if none allocate a new one */
272            index = p_ccb->p_lcb->allocated;
273            if (index > AVCT_NUM_LINKS)
274            {
275                result = AVCT_BAD_HANDLE;
276            }
277            else
278            {
279                p_bcb = &avct_cb.bcb[index - 1];
280                p_bcb->allocated = index;
281            }
282        }
283
284        if (result == AVCT_SUCCESS)
285        {
286            /* bind bcb to ccb */
287            p_ccb->p_bcb = p_bcb;
288            AVCT_TRACE_DEBUG("ch_state: %d", p_bcb->ch_state);
289            avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
290        }
291    }
292
293    return result;
294#else
295    UNUSED(handle);
296    UNUSED(role);
297    return AVCT_NO_RESOURCES;
298#endif
299}
300
301/*******************************************************************************
302**
303** Function         AVCT_RemoveBrowse
304**
305** Description      Remove an AVCTP Browse channel.  This function is called when
306**                  the application is no longer using a connection.  If this
307**                  is the last connection to a peer the L2CAP channel for AVCTP
308**                  will be closed.
309**
310**
311** Returns          AVCT_SUCCESS if successful, otherwise error.
312**
313*******************************************************************************/
314UINT16 AVCT_RemoveBrowse (UINT8 handle)
315{
316#if (AVCT_BROWSE_INCLUDED == TRUE)
317    UINT16              result = AVCT_SUCCESS;
318    tAVCT_CCB           *p_ccb;
319
320    AVCT_TRACE_API("AVCT_RemoveBrowse");
321
322    /* map handle to ccb */
323    if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
324    {
325        result = AVCT_BAD_HANDLE;
326    }
327    else if (p_ccb->p_bcb != NULL)
328    /* send unbind event to bcb */
329    {
330        avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb);
331    }
332    return result;
333#else
334    UNUSED(handle);
335    return AVCT_NO_RESOURCES;
336#endif
337}
338
339/*******************************************************************************
340**
341** Function         AVCT_GetBrowseMtu
342**
343** Description      Get the peer_mtu for the AVCTP Browse channel of the given
344**                  connection.
345**
346** Returns          the peer browsing channel MTU.
347**
348*******************************************************************************/
349UINT16 AVCT_GetBrowseMtu (UINT8 handle)
350{
351    UINT16  peer_mtu = AVCT_MIN_BROWSE_MTU;
352#if (AVCT_BROWSE_INCLUDED == TRUE)
353    tAVCT_CCB           *p_ccb;
354
355    if ((p_ccb = avct_ccb_by_idx(handle)) != NULL && p_ccb->p_bcb != NULL)
356    {
357        peer_mtu = p_ccb->p_bcb->peer_mtu;
358    }
359#else
360    UNUSED(handle);
361#endif
362    return peer_mtu;
363}
364
365/*******************************************************************************
366**
367** Function         AVCT_GetPeerMtu
368**
369** Description      Get the peer_mtu for the AVCTP channel of the given
370**                  connection.
371**
372** Returns          the peer MTU size.
373**
374*******************************************************************************/
375UINT16 AVCT_GetPeerMtu (UINT8 handle)
376{
377    UINT16      peer_mtu = L2CAP_DEFAULT_MTU;
378    tAVCT_CCB   *p_ccb;
379
380    /* map handle to ccb */
381    if ((p_ccb = avct_ccb_by_idx(handle)) != NULL)
382    {
383        if (p_ccb->p_lcb)
384        {
385            peer_mtu = p_ccb->p_lcb->peer_mtu;
386        }
387    }
388
389    return peer_mtu;
390}
391
392/*******************************************************************************
393**
394** Function         AVCT_MsgReq
395**
396** Description      Send an AVCTP message to a peer device.  In calling
397**                  AVCT_MsgReq(), the application should keep track of the
398**                  congestion state of AVCTP as communicated with events
399**                  AVCT_CONG_IND_EVT and AVCT_UNCONG_IND_EVT.   If the
400**                  application calls AVCT_MsgReq() when AVCTP is congested
401**                  the message may be discarded.  The application may make its
402**                  first call to AVCT_MsgReq() after it receives an
403**                  AVCT_CONNECT_CFM_EVT or AVCT_CONNECT_IND_EVT on control channel or
404**                  AVCT_BROWSE_CONN_CFM_EVT or AVCT_BROWSE_CONN_IND_EVT on browsing channel.
405**
406**                  p_msg->layer_specific must be set to
407**                  AVCT_DATA_CTRL for control channel traffic;
408**                  AVCT_DATA_BROWSE for for browse channel traffic.
409**
410** Returns          AVCT_SUCCESS if successful, otherwise error.
411**
412*******************************************************************************/
413UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg)
414{
415    UINT16          result = AVCT_SUCCESS;
416    tAVCT_CCB       *p_ccb;
417    tAVCT_UL_MSG    ul_msg;
418
419    AVCT_TRACE_API("AVCT_MsgReq");
420
421    /* verify p_msg parameter */
422    if (p_msg == NULL)
423    {
424        return AVCT_NO_RESOURCES;
425    }
426    AVCT_TRACE_API("len: %d", p_msg->len);
427
428    /* map handle to ccb */
429    if ((p_ccb = avct_ccb_by_idx(handle)) == NULL)
430    {
431        result = AVCT_BAD_HANDLE;
432        GKI_freebuf(p_msg);
433    }
434    /* verify channel is bound to link */
435    else if (p_ccb->p_lcb == NULL)
436    {
437        result = AVCT_NOT_OPEN;
438        GKI_freebuf(p_msg);
439    }
440
441    if (result == AVCT_SUCCESS)
442    {
443        ul_msg.p_buf = p_msg;
444        ul_msg.p_ccb = p_ccb;
445        ul_msg.label = label;
446        ul_msg.cr = cr;
447
448#if (AVCT_BROWSE_INCLUDED == TRUE)
449        /* send msg event to bcb */
450        if (p_msg->layer_specific == AVCT_DATA_BROWSE)
451        {
452            if (p_ccb->p_bcb == NULL && (p_ccb->allocated & AVCT_ALOC_BCB) == 0)
453            {
454                /* BCB channel is not open and not allocated */
455                result = AVCT_BAD_HANDLE;
456                GKI_freebuf(p_msg);
457            }
458            else
459            {
460                p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb);
461                avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
462            }
463        }
464        /* send msg event to lcb */
465        else
466#endif
467        {
468            avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
469        }
470    }
471    return result;
472}
473
474