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