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,const RawAddress & peer_addr)132 uint16_t AVCT_CreateConn(uint8_t* p_handle, tAVCT_CC* p_cc,
133 const RawAddress& peer_addr) {
134 uint16_t result = AVCT_SUCCESS;
135 tAVCT_CCB* p_ccb;
136 tAVCT_LCB* p_lcb;
137
138 AVCT_TRACE_API("AVCT_CreateConn: %d, control:%d", p_cc->role, p_cc->control);
139
140 /* Allocate ccb; if no ccbs, return failure */
141 p_ccb = avct_ccb_alloc(p_cc);
142 if (p_ccb == NULL) {
143 result = AVCT_NO_RESOURCES;
144 } else {
145 /* get handle */
146 *p_handle = avct_ccb_to_idx(p_ccb);
147
148 /* if initiator connection */
149 if (p_cc->role == AVCT_INT) {
150 /* find link; if none allocate a new one */
151 p_lcb = avct_lcb_by_bd(peer_addr);
152 if (p_lcb == NULL) {
153 p_lcb = avct_lcb_alloc(peer_addr);
154 if (p_lcb == NULL) {
155 /* no link resources; free ccb as well */
156 avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
157 result = AVCT_NO_RESOURCES;
158 }
159 }
160 /* check if PID already in use */
161 else if (avct_lcb_has_pid(p_lcb, p_cc->pid)) {
162 avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
163 result = AVCT_PID_IN_USE;
164 }
165
166 if (result == AVCT_SUCCESS) {
167 /* bind lcb to ccb */
168 p_ccb->p_lcb = p_lcb;
169 AVCT_TRACE_DEBUG("ch_state: %d", p_lcb->ch_state);
170 tAVCT_LCB_EVT avct_lcb_evt;
171 avct_lcb_evt.p_ccb = p_ccb;
172 avct_lcb_event(p_lcb, AVCT_LCB_UL_BIND_EVT, &avct_lcb_evt);
173 }
174 }
175 }
176 return result;
177 }
178
179 /*******************************************************************************
180 *
181 * Function AVCT_RemoveConn
182 *
183 * Description Remove an AVCTP connection. This function is called when
184 * the application is no longer using a connection. If this
185 * is the last connection to a peer the L2CAP channel for AVCTP
186 * will be closed.
187 *
188 *
189 * Returns AVCT_SUCCESS if successful, otherwise error.
190 *
191 ******************************************************************************/
AVCT_RemoveConn(uint8_t handle)192 uint16_t AVCT_RemoveConn(uint8_t handle) {
193 uint16_t result = AVCT_SUCCESS;
194 tAVCT_CCB* p_ccb;
195
196 AVCT_TRACE_API("AVCT_RemoveConn");
197
198 /* map handle to ccb */
199 p_ccb = avct_ccb_by_idx(handle);
200 if (p_ccb == NULL) {
201 result = AVCT_BAD_HANDLE;
202 }
203 /* if connection not bound to lcb, dealloc */
204 else if (p_ccb->p_lcb == NULL) {
205 avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
206 }
207 /* send unbind event to lcb */
208 else {
209 tAVCT_LCB_EVT avct_lcb_evt;
210 avct_lcb_evt.p_ccb = p_ccb;
211 avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_UNBIND_EVT, &avct_lcb_evt);
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
227 * device.
228 *
229 *
230 * Returns AVCT_SUCCESS if successful, otherwise error.
231 *
232 ******************************************************************************/
AVCT_CreateBrowse(uint8_t handle,uint8_t role)233 uint16_t AVCT_CreateBrowse(uint8_t handle, uint8_t role) {
234 uint16_t result = AVCT_SUCCESS;
235 tAVCT_CCB* p_ccb;
236 tAVCT_BCB* p_bcb;
237 int index;
238
239 AVCT_TRACE_API("AVCT_CreateBrowse: %d", role);
240
241 /* map handle to ccb */
242 p_ccb = avct_ccb_by_idx(handle);
243 if (p_ccb == 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 */
256 if ((p_ccb->p_lcb == NULL) || (p_ccb->p_lcb->allocated == 0)) {
257 result = AVCT_NOT_OPEN;
258 } else {
259 /* find link; if none allocate a new one */
260 index = p_ccb->p_lcb->allocated;
261 if (index > AVCT_NUM_LINKS) {
262 result = AVCT_BAD_HANDLE;
263 } else {
264 p_bcb = &avct_cb.bcb[index - 1];
265 p_bcb->allocated = index;
266 }
267 }
268
269 if (result == AVCT_SUCCESS) {
270 /* bind bcb to ccb */
271 p_ccb->p_bcb = p_bcb;
272 p_bcb->peer_addr = p_ccb->p_lcb->peer_addr;
273 AVCT_TRACE_DEBUG("ch_state: %d", p_bcb->ch_state);
274 tAVCT_LCB_EVT avct_lcb_evt;
275 avct_lcb_evt.p_ccb = p_ccb;
276 avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, &avct_lcb_evt);
277 }
278 }
279
280 return result;
281 }
282
283 /*******************************************************************************
284 *
285 * Function AVCT_RemoveBrowse
286 *
287 * Description Remove an AVCTP Browse channel. This function is called
288 * when the application is no longer using a connection. If
289 * this is the last connection to a peer the L2CAP channel for
290 * AVCTP will be closed.
291 *
292 *
293 * Returns AVCT_SUCCESS if successful, otherwise error.
294 *
295 ******************************************************************************/
AVCT_RemoveBrowse(uint8_t handle)296 uint16_t AVCT_RemoveBrowse(uint8_t handle) {
297 uint16_t result = AVCT_SUCCESS;
298 tAVCT_CCB* p_ccb;
299
300 AVCT_TRACE_API("AVCT_RemoveBrowse");
301
302 /* map handle to ccb */
303 p_ccb = avct_ccb_by_idx(handle);
304 if (p_ccb == NULL) {
305 result = AVCT_BAD_HANDLE;
306 } else if (p_ccb->p_bcb != NULL)
307 /* send unbind event to bcb */
308 {
309 tAVCT_LCB_EVT avct_lcb_evt;
310 avct_lcb_evt.p_ccb = p_ccb;
311 avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, &avct_lcb_evt);
312 }
313
314 return result;
315 }
316
317 /*******************************************************************************
318 *
319 * Function AVCT_GetBrowseMtu
320 *
321 * Description Get the peer_mtu for the AVCTP Browse channel of the given
322 * connection.
323 *
324 * Returns the peer browsing channel MTU.
325 *
326 ******************************************************************************/
AVCT_GetBrowseMtu(uint8_t handle)327 uint16_t AVCT_GetBrowseMtu(uint8_t handle) {
328 uint16_t peer_mtu = AVCT_MIN_BROWSE_MTU;
329
330 tAVCT_CCB* p_ccb = avct_ccb_by_idx(handle);
331
332 if (p_ccb != NULL && p_ccb->p_bcb != NULL) {
333 peer_mtu = p_ccb->p_bcb->peer_mtu;
334 }
335
336 return peer_mtu;
337 }
338
339 /*******************************************************************************
340 *
341 * Function AVCT_GetPeerMtu
342 *
343 * Description Get the peer_mtu for the AVCTP channel of the given
344 * connection.
345 *
346 * Returns the peer MTU size.
347 *
348 ******************************************************************************/
AVCT_GetPeerMtu(uint8_t handle)349 uint16_t AVCT_GetPeerMtu(uint8_t handle) {
350 uint16_t peer_mtu = L2CAP_DEFAULT_MTU;
351 tAVCT_CCB* p_ccb;
352
353 /* map handle to ccb */
354 p_ccb = avct_ccb_by_idx(handle);
355 if (p_ccb != NULL) {
356 if (p_ccb->p_lcb) {
357 peer_mtu = p_ccb->p_lcb->peer_mtu;
358 }
359 }
360
361 return peer_mtu;
362 }
363
364 /*******************************************************************************
365 *
366 * Function AVCT_MsgReq
367 *
368 * Description Send an AVCTP message to a peer device. In calling
369 * AVCT_MsgReq(), the application should keep track of the
370 * congestion state of AVCTP as communicated with events
371 * AVCT_CONG_IND_EVT and AVCT_UNCONG_IND_EVT. If the
372 * application calls AVCT_MsgReq() when AVCTP is congested
373 * the message may be discarded. The application may make its
374 * first call to AVCT_MsgReq() after it receives an
375 * AVCT_CONNECT_CFM_EVT or AVCT_CONNECT_IND_EVT on control
376 * channel or AVCT_BROWSE_CONN_CFM_EVT or
377 * AVCT_BROWSE_CONN_IND_EVT on browsing channel.
378 *
379 * p_msg->layer_specific must be set to
380 * AVCT_DATA_CTRL for control channel traffic;
381 * AVCT_DATA_BROWSE for for browse channel traffic.
382 *
383 * Returns AVCT_SUCCESS if successful, otherwise error.
384 *
385 ******************************************************************************/
AVCT_MsgReq(uint8_t handle,uint8_t label,uint8_t cr,BT_HDR * p_msg)386 uint16_t AVCT_MsgReq(uint8_t handle, uint8_t label, uint8_t cr, BT_HDR* p_msg) {
387 uint16_t result = AVCT_SUCCESS;
388 tAVCT_CCB* p_ccb;
389 tAVCT_UL_MSG ul_msg;
390
391 AVCT_TRACE_API("%s", __func__);
392
393 /* verify p_msg parameter */
394 if (p_msg == NULL) {
395 return AVCT_NO_RESOURCES;
396 }
397 AVCT_TRACE_API("%s len: %d layer_specific: %d", __func__, p_msg->len,
398 p_msg->layer_specific);
399
400 /* map handle to ccb */
401 p_ccb = avct_ccb_by_idx(handle);
402 if (p_ccb == NULL) {
403 result = AVCT_BAD_HANDLE;
404 osi_free(p_msg);
405 }
406 /* verify channel is bound to link */
407 else if (p_ccb->p_lcb == NULL) {
408 result = AVCT_NOT_OPEN;
409 osi_free(p_msg);
410 }
411
412 if (result == AVCT_SUCCESS) {
413 ul_msg.p_buf = p_msg;
414 ul_msg.p_ccb = p_ccb;
415 ul_msg.label = label;
416 ul_msg.cr = cr;
417
418 /* send msg event to bcb */
419 if (p_msg->layer_specific == AVCT_DATA_BROWSE) {
420 if (p_ccb->p_bcb == NULL && (p_ccb->allocated & AVCT_ALOC_BCB) == 0) {
421 /* BCB channel is not open and not allocated */
422 result = AVCT_BAD_HANDLE;
423 osi_free(p_msg);
424 } else {
425 p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb);
426 tAVCT_LCB_EVT avct_lcb_evt;
427 avct_lcb_evt.ul_msg = ul_msg;
428 avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, &avct_lcb_evt);
429 }
430 }
431 /* send msg event to lcb */
432 else {
433 tAVCT_LCB_EVT avct_lcb_evt;
434 avct_lcb_evt.ul_msg = ul_msg;
435 avct_lcb_event(p_ccb->p_lcb, AVCT_LCB_UL_MSG_EVT, &avct_lcb_evt);
436 }
437 }
438 return result;
439 }
440