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