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