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 "bt_types.h"
27 #include "bt_target.h"
28 #include "bt_utils.h"
29 #include "bt_common.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
38 tAVCT_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 *******************************************************************************/
AVCT_Register(UINT16 mtu,UINT16 mtu_br,UINT8 sec_mask)55 void 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 *******************************************************************************/
AVCT_Deregister(void)109 void 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 *******************************************************************************/
AVCT_CreateConn(UINT8 * p_handle,tAVCT_CC * p_cc,BD_ADDR peer_addr)133 UINT16 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 *******************************************************************************/
AVCT_RemoveConn(UINT8 handle)196 UINT16 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 *******************************************************************************/
AVCT_CreateBrowse(UINT8 handle,UINT8 role)237 UINT16 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) || (p_ccb->p_lcb->allocated == 0))
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 *******************************************************************************/
AVCT_RemoveBrowse(UINT8 handle)314 UINT16 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 *******************************************************************************/
AVCT_GetBrowseMtu(UINT8 handle)349 UINT16 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 *******************************************************************************/
AVCT_GetPeerMtu(UINT8 handle)375 UINT16 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 *******************************************************************************/
AVCT_MsgReq(UINT8 handle,UINT8 label,UINT8 cr,BT_HDR * p_msg)413 UINT16 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         osi_free(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         osi_free(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                 osi_free(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