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