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