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