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