• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 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 
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  ******************************************************************************/
AVCT_Deregister(void)108 void 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  ******************************************************************************/
AVCT_CreateConn(uint8_t * p_handle,tAVCT_CC * p_cc,const RawAddress & peer_addr)132 uint16_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  ******************************************************************************/
AVCT_RemoveConn(uint8_t handle)192 uint16_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  ******************************************************************************/
AVCT_CreateBrowse(uint8_t handle,uint8_t role)233 uint16_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  ******************************************************************************/
AVCT_RemoveBrowse(uint8_t handle)296 uint16_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  ******************************************************************************/
AVCT_GetBrowseMtu(uint8_t handle)327 uint16_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  ******************************************************************************/
AVCT_GetPeerMtu(uint8_t handle)349 uint16_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  ******************************************************************************/
AVCT_MsgReq(uint8_t handle,uint8_t label,uint8_t cr,BT_HDR * p_msg)386 uint16_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