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