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