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