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