• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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