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