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