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