blob: 9407da55615d2c2f1752fbe14c4c8dc3aa687182 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 1999-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 file contains the L2CAP UCD code
22 *
23 ******************************************************************************/
24
25#include <stdlib.h>
26#include <string.h>
27#include <stdio.h>
28
Pavlin Radoslavov258c2532015-09-27 20:59:05 -070029#include "bt_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080030#include "bt_types.h"
31#include "hcidefs.h"
32#include "hcimsgs.h"
33#include "l2cdefs.h"
34#include "l2c_int.h"
35#include "btu.h"
36#include "btm_api.h"
37#include "btm_int.h"
38
39#if (L2CAP_UCD_INCLUDED == TRUE)
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -080040
41extern fixed_queue_t *btu_bta_alarm_queue;
42
Marie Janssend19e0782016-07-15 12:48:27 -070043static bool l2c_ucd_connect ( BD_ADDR rem_bda );
The Android Open Source Project5738f832012-12-12 16:00:35 -080044
45/*******************************************************************************
46**
47** Function l2c_ucd_discover_cback
48**
49** Description UCD Discover callback
50**
51** Returns void
52**
53*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -070054static void l2c_ucd_discover_cback (BD_ADDR rem_bda, uint8_t info_type, uint32_t data)
The Android Open Source Project5738f832012-12-12 16:00:35 -080055{
56 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
Marie Janssend19e0782016-07-15 12:48:27 -070057 uint16_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -080058
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -070059 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_discover_cback");
The Android Open Source Project5738f832012-12-12 16:00:35 -080060
61 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++)
62 {
63 if (p_rcb->in_use)
64 {
65 /* if this application is waiting UCD reception info */
66 if (( info_type == L2CAP_UCD_INFO_TYPE_RECEPTION )
67 && ( p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION ))
68 {
69 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (rem_bda, info_type, data);
70 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_RECEPTION);
71 }
72
73 /* if this application is waiting UCD MTU info */
74 if (( info_type == L2CAP_UCD_INFO_TYPE_MTU )
75 && ( p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU ))
76 {
77 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (rem_bda, info_type, data);
78 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_MTU);
79 }
80 }
81 }
82}
83
84/*******************************************************************************
85**
86** Function l2c_ucd_data_ind_cback
87**
88** Description UCD Data callback
89**
90** Returns void
91**
92*******************************************************************************/
93static void l2c_ucd_data_ind_cback (BD_ADDR rem_bda, BT_HDR *p_buf)
94{
Marie Janssend19e0782016-07-15 12:48:27 -070095 uint8_t *p;
96 uint16_t psm;
The Android Open Source Project5738f832012-12-12 16:00:35 -080097 tL2C_RCB *p_rcb;
98
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -070099 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_data_ind_cback");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800100
Marie Janssend19e0782016-07-15 12:48:27 -0700101 p = (uint8_t *)(p_buf + 1) + p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800102 STREAM_TO_UINT16(psm, p)
103
104 p_buf->offset += L2CAP_UCD_OVERHEAD;
105 p_buf->len -= L2CAP_UCD_OVERHEAD;
106
107 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
108 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700109 L2CAP_TRACE_ERROR ("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x", psm);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800110 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800111 }
112 else
113 {
114 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf);
115 }
116}
117
118/*******************************************************************************
119**
120** Function l2c_ucd_congestion_status_cback
121**
122** Description UCD Congestion Status callback
123**
124** Returns void
125**
126*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700127static void l2c_ucd_congestion_status_cback (BD_ADDR rem_bda, bool is_congested)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800128{
129 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
Marie Janssend19e0782016-07-15 12:48:27 -0700130 uint16_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800131
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700132 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_congestion_status_cback");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800133
134 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++)
135 {
136 if (( p_rcb->in_use )
137 &&( p_rcb->ucd.state != L2C_UCD_STATE_UNUSED ))
138 {
139 if ( p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb )
140 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700141 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCDCongestionStatus_Cb (%d), PSM=0x%04x, BDA: %08x%04x,",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800142 is_congested, p_rcb->psm,
143 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
144 (rem_bda[4]<<8)+rem_bda[5]);
145
146 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ( rem_bda, is_congested );
147 }
148 }
149 }
150}
151
152/*******************************************************************************
153**
154** Function l2c_ucd_disconnect_ind_cback
155**
156** Description UCD disconnect callback (This prevent to access null pointer)
157**
158** Returns void
159**
160*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700161static void l2c_ucd_disconnect_ind_cback (uint16_t cid, bool result)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800162{
163 /* do nothing */
164}
165
166/*******************************************************************************
167**
168** Function l2c_ucd_config_ind_cback
169**
170** Description UCD config callback (This prevent to access null pointer)
171**
172** Returns void
173**
174*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700175static void l2c_ucd_config_ind_cback (uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800176{
177 /* do nothing */
178}
179
180/*******************************************************************************
181**
182** Function l2c_ucd_config_cfm_cback
183**
184** Description UCD config callback (This prevent to access null pointer)
185**
186** Returns void
187**
188*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700189static void l2c_ucd_config_cfm_cback (uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800190{
191 /* do nothing */
192}
193
194/*******************************************************************************
195**
196** Function L2CA_UcdRegister
197**
198** Description Register PSM on UCD.
199**
200** Parameters: tL2CAP_UCD_CB_INFO
201**
Marie Janssend19e0782016-07-15 12:48:27 -0700202** Return value: true if successs
The Android Open Source Project5738f832012-12-12 16:00:35 -0800203**
204*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700205bool L2CA_UcdRegister ( uint16_t psm, tL2CAP_UCD_CB_INFO *p_cb_info )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800206{
207 tL2C_RCB *p_rcb;
208
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700209 L2CAP_TRACE_API ("L2CA_UcdRegister() PSM: 0x%04x", psm);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800210
211 if ((!p_cb_info->pL2CA_UCD_Discover_Cb)
212 || (!p_cb_info->pL2CA_UCD_Data_Cb))
213 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700214 L2CAP_TRACE_ERROR ("L2CAP - no callback registering PSM(0x%04x) on UCD", psm);
Marie Janssend19e0782016-07-15 12:48:27 -0700215 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800216 }
217
218 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
219 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700220 L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdRegister, PSM: 0x%04x", psm);
Marie Janssend19e0782016-07-15 12:48:27 -0700221 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800222 }
223
224 p_rcb->ucd.state = L2C_UCD_STATE_W4_DATA;
225 p_rcb->ucd.cb_info = *p_cb_info;
226
227 /* check if master rcb is created for UCD */
228 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL)
229 {
230 if ((p_rcb = l2cu_allocate_rcb (L2C_UCD_RCB_ID)) == NULL)
231 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700232 L2CAP_TRACE_ERROR ("L2CAP - no RCB available for L2CA_UcdRegister");
Marie Janssend19e0782016-07-15 12:48:27 -0700233 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800234 }
235 else
236 {
237 /* these callback functions will forward data to each UCD application */
238 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb = l2c_ucd_discover_cback;
239 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb = l2c_ucd_data_ind_cback;
240 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb = l2c_ucd_congestion_status_cback;
241
242 memset (&p_rcb->api, 0, sizeof(tL2CAP_APPL_INFO));
243 p_rcb->api.pL2CA_DisconnectInd_Cb = l2c_ucd_disconnect_ind_cback;
244
245 /* This will make L2CAP check UCD congestion callback */
246 p_rcb->api.pL2CA_CongestionStatus_Cb = NULL;
247
248 /* do nothing but prevent crash */
249 p_rcb->api.pL2CA_ConfigInd_Cb = l2c_ucd_config_ind_cback;
250 p_rcb->api.pL2CA_ConfigCfm_Cb = l2c_ucd_config_cfm_cback;
251 }
252 }
253
Marie Janssend19e0782016-07-15 12:48:27 -0700254 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800255}
256
257/*******************************************************************************
258**
259** Function L2CA_UcdDeregister
260**
261** Description Deregister PSM on UCD.
262**
263** Parameters: PSM
264**
Marie Janssend19e0782016-07-15 12:48:27 -0700265** Return value: true if successs
The Android Open Source Project5738f832012-12-12 16:00:35 -0800266**
267*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700268bool L2CA_UcdDeregister ( uint16_t psm )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800269{
270 tL2C_CCB *p_ccb;
271 tL2C_RCB *p_rcb;
Marie Janssend19e0782016-07-15 12:48:27 -0700272 uint16_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800273
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700274 L2CAP_TRACE_API ("L2CA_UcdDeregister() PSM: 0x%04x", psm);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800275
276 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
277 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700278 L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdDeregister, PSM: 0x%04x", psm);
Marie Janssend19e0782016-07-15 12:48:27 -0700279 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800280 }
281
282 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
283
284 /* check this was the last UCD registration */
285 p_rcb = &l2cb.rcb_pool[0];
286
287 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++)
288 {
289 if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED))
Marie Janssend19e0782016-07-15 12:48:27 -0700290 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800291 }
292
293 /* delete master rcb for UCD */
294 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL)
295 {
296 l2cu_release_rcb (p_rcb);
297 }
298
299 /* delete CCB for UCD */
300 p_ccb = l2cb.ccb_pool;
301 for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ )
302 {
303 if (( p_ccb->in_use )
304 &&( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ))
305 {
306 l2cu_release_ccb (p_ccb);
307 }
308 p_ccb++;
309 }
310
Marie Janssend19e0782016-07-15 12:48:27 -0700311 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800312}
313
314/*******************************************************************************
315**
316** Function L2CA_UcdDiscover
317**
318** Description Discover UCD of remote device.
319**
320** Parameters: PSM
321** BD_ADDR of remote device
322** info_type : L2CAP_UCD_INFO_TYPE_RECEPTION
323** L2CAP_UCD_INFO_TYPE_MTU
324**
325**
Marie Janssend19e0782016-07-15 12:48:27 -0700326** Return value: true if successs
The Android Open Source Project5738f832012-12-12 16:00:35 -0800327**
328*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700329bool L2CA_UcdDiscover ( uint16_t psm, BD_ADDR rem_bda, uint8_t info_type )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800330{
331 tL2C_LCB *p_lcb;
332 tL2C_CCB *p_ccb;
333 tL2C_RCB *p_rcb;
334
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700335 L2CAP_TRACE_API ("L2CA_UcdDiscover() PSM: 0x%04x BDA: %08x%04x, InfoType=0x%02x", psm,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800336 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
337 (rem_bda[4]<<8)+rem_bda[5], info_type);
338
339 /* Fail if the PSM is not registered */
340 if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
341 ||( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED ))
342 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700343 L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDiscover, PSM: 0x%04x", psm);
Marie Janssend19e0782016-07-15 12:48:27 -0700344 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800345 }
346
347 /* First, see if we already have a link to the remote */
348 /* then find the channel control block for UCD. */
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700349 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800350 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
351 {
Marie Janssend19e0782016-07-15 12:48:27 -0700352 if ( l2c_ucd_connect (rem_bda) == false )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800353 {
Marie Janssend19e0782016-07-15 12:48:27 -0700354 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800355 }
356 }
357
358 /* set waiting flags in rcb */
359
360 if ( info_type & L2CAP_UCD_INFO_TYPE_RECEPTION )
361 p_rcb->ucd.state |= L2C_UCD_STATE_W4_RECEPTION;
362
363 if ( info_type & L2CAP_UCD_INFO_TYPE_MTU )
364 p_rcb->ucd.state |= L2C_UCD_STATE_W4_MTU;
365
366 /* if link is already established */
367 if ((p_lcb)&&(p_lcb->link_state == LST_CONNECTED))
368 {
369 if (!p_ccb)
370 {
371 p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID);
372 }
373 l2c_ucd_check_pending_info_req(p_ccb);
374 }
Marie Janssend19e0782016-07-15 12:48:27 -0700375 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800376}
377
378/*******************************************************************************
379**
380** Function L2CA_UcdDataWrite
381**
382** Description Send UCD to remote device
383**
384** Parameters: PSM
385** BD Address of remote
386** Pointer to buffer of type BT_HDR
387** flags : L2CAP_FLUSHABLE_CH_BASED
388** L2CAP_FLUSHABLE_PKT
389** L2CAP_NON_FLUSHABLE_PKT
390**
391** Return value L2CAP_DW_SUCCESS, if data accepted
392** L2CAP_DW_FAILED, if error
393**
394*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700395uint16_t L2CA_UcdDataWrite (uint16_t psm, BD_ADDR rem_bda, BT_HDR *p_buf, uint16_t flags)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800396{
397 tL2C_LCB *p_lcb;
398 tL2C_CCB *p_ccb;
399 tL2C_RCB *p_rcb;
Marie Janssend19e0782016-07-15 12:48:27 -0700400 uint8_t *p;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800401
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700402 L2CAP_TRACE_API ("L2CA_UcdDataWrite() PSM: 0x%04x BDA: %08x%04x", psm,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800403 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
404 (rem_bda[4]<<8)+rem_bda[5]);
405
406 /* Fail if the PSM is not registered */
407 if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
408 ||( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED ))
409 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700410 L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x", psm);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800411 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800412 return (L2CAP_DW_FAILED);
413 }
414
415 /* First, see if we already have a link to the remote */
416 /* then find the channel control block for UCD */
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700417 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800418 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
419 {
Marie Janssend19e0782016-07-15 12:48:27 -0700420 if ( l2c_ucd_connect (rem_bda) == false )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800421 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800422 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800423 return (L2CAP_DW_FAILED);
424 }
425
426 /* If we still don't have lcb and ccb after connect attempt, then can't proceed */
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700427 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800428 || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
429 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800430 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800431 return (L2CAP_DW_FAILED);
432 }
433 }
434
435 /* write PSM */
436 p_buf->offset -= L2CAP_UCD_OVERHEAD;
437 p_buf->len += L2CAP_UCD_OVERHEAD;
Marie Janssend19e0782016-07-15 12:48:27 -0700438 p = (uint8_t *)(p_buf + 1) + p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800439
440 UINT16_TO_STREAM (p, psm);
441
442 /* UCD MTU check */
443 if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu))
444 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700445 L2CAP_TRACE_WARNING ("L2CAP - Handle: 0x%04x UCD bigger than peer's UCD mtu size cannot be sent", p_lcb->handle);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800446 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800447 return (L2CAP_DW_FAILED);
448 }
449
450 /* If already congested, do not accept any more packets */
451 if (p_ccb->cong_sent)
452 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700453 L2CAP_TRACE_ERROR ("L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: %u buff_quota: %u",
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700454 p_lcb->handle,
455 (fixed_queue_length(p_ccb->xmit_hold_q) +
456 fixed_queue_length(p_lcb->ucd_out_sec_pending_q)),
457 p_ccb->buff_quota);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800458
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800459 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800460 return (L2CAP_DW_FAILED);
461 }
462
463 /* channel based, packet based flushable or non-flushable */
464 p_buf->layer_specific = flags;
465
466 l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf);
467
468 if (p_ccb->cong_sent)
469 return (L2CAP_DW_CONGESTED);
470 else
471 return (L2CAP_DW_SUCCESS);
472}
473
474/*******************************************************************************
475**
476** Function L2CA_UcdSetIdleTimeout
477**
478** Description Set UCD Idle timeout.
479**
480** Parameters: BD Addr
481** Timeout in second
482**
Marie Janssend19e0782016-07-15 12:48:27 -0700483** Return value: true if successs
The Android Open Source Project5738f832012-12-12 16:00:35 -0800484**
485*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700486bool L2CA_UcdSetIdleTimeout ( BD_ADDR rem_bda, uint16_t timeout )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800487{
488 tL2C_LCB *p_lcb;
489 tL2C_CCB *p_ccb;
490
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700491 L2CAP_TRACE_API ("L2CA_UcdSetIdleTimeout() Timeout: 0x%04x BDA: %08x%04x", timeout,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800492 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
493 (rem_bda[4]<<8)+rem_bda[5]);
494
495 /* First, see if we already have a link to the remote */
496 /* then find the channel control block. */
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700497 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800498 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
499 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700500 L2CAP_TRACE_WARNING ("L2CAP - no UCD channel");
Marie Janssend19e0782016-07-15 12:48:27 -0700501 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800502 }
503 else
504 {
505 p_ccb->fixed_chnl_idle_tout = timeout;
Marie Janssend19e0782016-07-15 12:48:27 -0700506 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800507 }
508}
509
510/*******************************************************************************
511**
512** Function L2CA_UCDSetTxPriority
513**
514** Description Sets the transmission priority for a connectionless channel.
515**
Marie Janssend19e0782016-07-15 12:48:27 -0700516** Returns true if a valid channel, else false
The Android Open Source Project5738f832012-12-12 16:00:35 -0800517**
518*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700519bool L2CA_UCDSetTxPriority ( BD_ADDR rem_bda, tL2CAP_CHNL_PRIORITY priority )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800520{
521 tL2C_LCB *p_lcb;
522 tL2C_CCB *p_ccb;
523
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700524 L2CAP_TRACE_API ("L2CA_UCDSetTxPriority() priority: 0x%02x BDA: %08x%04x", priority,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800525 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
526 (rem_bda[4]<<8)+rem_bda[5]);
527
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700528 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800529 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700530 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_UCDSetTxPriority");
Marie Janssend19e0782016-07-15 12:48:27 -0700531 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800532 }
533
534 /* Find the channel control block */
535 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)
536 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700537 L2CAP_TRACE_WARNING ("L2CAP - no CCB for L2CA_UCDSetTxPriority");
Marie Janssend19e0782016-07-15 12:48:27 -0700538 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800539 }
540
541 /* it will update the order of CCB in LCB by priority and update round robin service variables */
542 l2cu_change_pri_ccb (p_ccb, priority);
543
Marie Janssend19e0782016-07-15 12:48:27 -0700544 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800545}
546
547/*******************************************************************************
548**
549** Function l2c_ucd_connect
550**
551** Description Connect UCD to remote device.
552**
553** Parameters: BD_ADDR of remote device
554**
Marie Janssend19e0782016-07-15 12:48:27 -0700555** Return value: true if successs
The Android Open Source Project5738f832012-12-12 16:00:35 -0800556**
557*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700558static bool l2c_ucd_connect ( BD_ADDR rem_bda )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800559{
560 tL2C_LCB *p_lcb;
561 tL2C_CCB *p_ccb;
562 tL2C_RCB *p_rcb;
563
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700564 L2CAP_TRACE_DEBUG ("l2c_ucd_connect() BDA: %08x%04x",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800565 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
566 (rem_bda[4]<<8)+rem_bda[5]);
567
568 /* Fail if we have not established communications with the controller */
569 if (!BTM_IsDeviceUp())
570 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700571 L2CAP_TRACE_WARNING ("l2c_ucd_connect - BTU not ready");
Marie Janssend19e0782016-07-15 12:48:27 -0700572 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800573 }
574
575 /* First, see if we already have a link to the remote */
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700576 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800577 {
578 /* No link. Get an LCB and start link establishment */
Marie Janssend19e0782016-07-15 12:48:27 -0700579 if ( ((p_lcb = l2cu_allocate_lcb (rem_bda, false, BT_TRANSPORT_BR_EDR)) == NULL)
580 || (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == false) )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800581 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700582 L2CAP_TRACE_WARNING ("L2CAP - conn not started l2c_ucd_connect");
Marie Janssend19e0782016-07-15 12:48:27 -0700583 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800584 }
585 }
586 else if ( p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE) )
587 {
588 if (!(p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION))
589 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700590 L2CAP_TRACE_WARNING ("L2CAP - UCD is not supported by peer, l2c_ucd_connect");
Marie Janssend19e0782016-07-15 12:48:27 -0700591 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800592 }
593 }
594
595 /* Find the channel control block. */
596 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)
597 {
598 /* Allocate a channel control block */
599 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL)
600 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700601 L2CAP_TRACE_WARNING ("L2CAP - no CCB for l2c_ucd_connect");
Marie Janssend19e0782016-07-15 12:48:27 -0700602 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800603 }
604 else
605 {
606 /* Set CID for the connection */
607 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
608 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
609
610 /* Set the default idle timeout value to use */
611 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
612
613 /* Set the default channel priority value to use */
614 l2cu_change_pri_ccb (p_ccb, L2CAP_UCD_CH_PRIORITY);
615
616 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL)
617 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700618 L2CAP_TRACE_WARNING ("L2CAP - no UCD registered, l2c_ucd_connect");
Marie Janssend19e0782016-07-15 12:48:27 -0700619 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800620 }
621 /* Save UCD registration info */
622 p_ccb->p_rcb = p_rcb;
623
624 /* There is no configuration, so if the link is up, the channel is up */
625 if (p_lcb->link_state == LST_CONNECTED)
626 {
627 p_ccb->chnl_state = CST_OPEN;
628 }
629 }
630 }
631
Marie Janssend19e0782016-07-15 12:48:27 -0700632 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800633}
634
635/*******************************************************************************
636**
637** Function l2c_ucd_delete_sec_pending_q
638**
639** Description discard all of UCD packets in security pending queue
640**
641** Returns None
642**
643*******************************************************************************/
644void l2c_ucd_delete_sec_pending_q(tL2C_LCB *p_lcb)
645{
646 /* clean up any security pending UCD */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700647 while (! fixed_queue_is_empty(p_lcb->ucd_out_sec_pending_q))
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800648 osi_free(fixed_queue_try_dequeue(p_lcb->ucd_out_sec_pending_q));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700649 fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL);
650 p_lcb->ucd_out_sec_pending_q = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800651
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700652 while (! fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q))
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800653 osi_free(fixed_queue_try_dequeue(p_lcb->ucd_in_sec_pending_q));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700654 fixed_queue_free(p_lcb->ucd_in_sec_pending_q);
655 p_lcb->ucd_in_sec_pending_q = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800656}
657
658/*******************************************************************************
659**
660** Function l2c_ucd_check_pending_info_req
661**
662** Description check if any application is waiting for UCD information
663**
Marie Janssend19e0782016-07-15 12:48:27 -0700664** Return true if any pending UCD info request
The Android Open Source Project5738f832012-12-12 16:00:35 -0800665**
666*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700667bool l2c_ucd_check_pending_info_req(tL2C_CCB *p_ccb)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800668{
669 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
Marie Janssend19e0782016-07-15 12:48:27 -0700670 uint16_t xx;
671 bool pending = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800672
673 if (p_ccb == NULL)
674 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700675 L2CAP_TRACE_ERROR ("L2CAP - NULL p_ccb in l2c_ucd_check_pending_info_req");
Marie Janssend19e0782016-07-15 12:48:27 -0700676 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800677 }
678
679 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++)
680 {
681 if (p_rcb->in_use)
682 {
683 /* if application is waiting UCD reception info */
684 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION)
685 {
686 /* if this information is available */
687 if ( p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE) )
688 {
689 if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION))
690 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700691 L2CAP_TRACE_WARNING ("L2CAP - UCD is not supported by peer, l2c_ucd_check_pending_info_req");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800692
693 l2c_ucd_delete_sec_pending_q(p_ccb->p_lcb);
694 l2cu_release_ccb (p_ccb);
695 }
696
697 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (p_ccb->p_lcb->remote_bd_addr,
698 L2CAP_UCD_INFO_TYPE_RECEPTION,
699 p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION);
700 }
701 else
702 {
Marie Janssend19e0782016-07-15 12:48:27 -0700703 pending = true;
704 if (p_ccb->p_lcb->w4_info_rsp == false)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800705 {
706 l2cu_send_peer_info_req (p_ccb->p_lcb, L2CAP_EXTENDED_FEATURES_INFO_TYPE);
707 }
708 }
709 }
710
711 /* if application is waiting for UCD MTU */
712 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU)
713 {
714 /* if this information is available */
715 if ( p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_CONNLESS_MTU_INFO_TYPE))
716 {
717 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (p_ccb->p_lcb->remote_bd_addr,
718 L2CAP_UCD_INFO_TYPE_MTU,
719 p_ccb->p_lcb->ucd_mtu);
720 }
721 else
722 {
Marie Janssend19e0782016-07-15 12:48:27 -0700723 pending = true;
724 if (p_ccb->p_lcb->w4_info_rsp == false)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800725 {
726 l2cu_send_peer_info_req (p_ccb->p_lcb, L2CAP_CONNLESS_MTU_INFO_TYPE);
727 }
728 }
729 }
730 }
731 }
732 return (pending);
733}
734
735/*******************************************************************************
736**
737** Function l2c_ucd_enqueue_pending_out_sec_q
738**
739** Description enqueue outgoing UCD packet into security pending queue
740** and check congestion
741**
742** Return None
743**
744*******************************************************************************/
745void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB *p_ccb, void *p_data)
746{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700747 fixed_queue_enqueue(p_ccb->p_lcb->ucd_out_sec_pending_q, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800748 l2cu_check_channel_congestion (p_ccb);
749}
750
751/*******************************************************************************
752**
753** Function l2c_ucd_check_pending_out_sec_q
754**
755** Description check outgoing security
756**
Marie Janssend19e0782016-07-15 12:48:27 -0700757** Return true if any UCD packet for security
The Android Open Source Project5738f832012-12-12 16:00:35 -0800758**
759*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700760bool l2c_ucd_check_pending_out_sec_q(tL2C_CCB *p_ccb)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800761{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700762 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->p_lcb->ucd_out_sec_pending_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800763
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700764 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800765 {
Marie Janssend19e0782016-07-15 12:48:27 -0700766 uint16_t psm;
767 uint8_t *p = (uint8_t *)(p_buf + 1) + p_buf->offset;
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700768
The Android Open Source Project5738f832012-12-12 16:00:35 -0800769 STREAM_TO_UINT16(psm, p)
770
771 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
772 btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm,
773 p_ccb->p_lcb->handle, CONNLESS_ORIG, &l2c_link_sec_comp, p_ccb);
774
Marie Janssend19e0782016-07-15 12:48:27 -0700775 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800776 }
Marie Janssend19e0782016-07-15 12:48:27 -0700777 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800778}
779
780/*******************************************************************************
781**
782** Function l2c_ucd_send_pending_out_sec_q
783**
784** Description dequeue UCD packet from security pending queue and
785** enqueue it into CCB
786**
787** Return None
788**
789*******************************************************************************/
790void l2c_ucd_send_pending_out_sec_q(tL2C_CCB *p_ccb)
791{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700792 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800793
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700794 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800795 {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800796 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_buf);
797 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
798 }
799}
800
801/*******************************************************************************
802**
803** Function l2c_ucd_discard_pending_out_sec_q
804**
805** Description dequeue UCD packet from security pending queue and
806** discard it.
807**
808** Return None
809**
810*******************************************************************************/
811void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB *p_ccb)
812{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700813 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800814
815 /* we may need to report to application */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800816 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800817}
818
819/*******************************************************************************
820**
821** Function l2c_ucd_check_pending_in_sec_q
822**
823** Description check incoming security
824**
Marie Janssend19e0782016-07-15 12:48:27 -0700825** Return true if any UCD packet for security
The Android Open Source Project5738f832012-12-12 16:00:35 -0800826**
827*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700828bool l2c_ucd_check_pending_in_sec_q(tL2C_CCB *p_ccb)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800829{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700830 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800831
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700832 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800833 {
Marie Janssend19e0782016-07-15 12:48:27 -0700834 uint16_t psm;
835 uint8_t *p = (uint8_t *)(p_buf + 1) + p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800836 STREAM_TO_UINT16(psm, p)
837
838 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
839 btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm,
840 p_ccb->p_lcb->handle, CONNLESS_TERM, &l2c_link_sec_comp, p_ccb);
841
Marie Janssend19e0782016-07-15 12:48:27 -0700842 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800843 }
Marie Janssend19e0782016-07-15 12:48:27 -0700844 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800845}
846
847/*******************************************************************************
848**
849** Function l2c_ucd_send_pending_in_sec_q
850**
851** Description dequeue UCD packet from security pending queue and
852** send it to application
853**
854** Return None
855**
856*******************************************************************************/
857void l2c_ucd_send_pending_in_sec_q(tL2C_CCB *p_ccb)
858{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700859 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800860
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700861 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800862 {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800863 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(p_ccb->p_lcb->remote_bd_addr, (BT_HDR *)p_buf);
864 }
865}
866
867/*******************************************************************************
868**
869** Function l2c_ucd_discard_pending_in_sec_q
870**
871** Description dequeue UCD packet from security pending queue and
872** discard it.
873**
874** Return None
875**
876*******************************************************************************/
877void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB *p_ccb)
878{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700879 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800880 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800881}
882
883/*******************************************************************************
884**
885** Function l2c_ucd_check_rx_pkts
886**
887** Description Check if UCD reception is registered.
888** Process received UCD packet if application is expecting.
889**
Marie Janssend19e0782016-07-15 12:48:27 -0700890** Return true if UCD reception is registered
The Android Open Source Project5738f832012-12-12 16:00:35 -0800891**
892*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700893bool l2c_ucd_check_rx_pkts(tL2C_LCB *p_lcb, BT_HDR *p_msg)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800894{
895 tL2C_CCB *p_ccb;
896 tL2C_RCB *p_rcb;
897
898 if (((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) != NULL)
899 ||((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL))
900 {
901 if (p_ccb == NULL)
902 {
903 /* Allocate a channel control block */
904 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL)
905 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700906 L2CAP_TRACE_WARNING ("L2CAP - no CCB for UCD reception");
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800907 osi_free(p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700908 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800909 }
910 else
911 {
912 /* Set CID for the connection */
913 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
914 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
915
916 /* Set the default idle timeout value to use */
917 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
918
919 /* Set the default channel priority value to use */
920 l2cu_change_pri_ccb (p_ccb, L2CAP_UCD_CH_PRIORITY);
921
922 /* Save registration info */
923 p_ccb->p_rcb = p_rcb;
924
925 p_ccb->chnl_state = CST_OPEN;
926 }
927 }
928 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700929 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800930 }
931 else
Marie Janssend19e0782016-07-15 12:48:27 -0700932 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800933}
934
935/*******************************************************************************
936**
937** Function l2c_ucd_process_event
938**
939** Description This is called from main state machine when LCID is connectionless
940** Process the event if it is for UCD.
941**
Marie Janssend19e0782016-07-15 12:48:27 -0700942** Return true if the event is consumed by UCD
943** false if the event needs to be processed by main state machine
The Android Open Source Project5738f832012-12-12 16:00:35 -0800944**
945*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700946bool l2c_ucd_process_event(tL2C_CCB *p_ccb, uint16_t event, void *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800947{
Marie Janssend19e0782016-07-15 12:48:27 -0700948 /* if the event is not processed by this function, this variable will be set to false */
949 bool done = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800950
951 switch (p_ccb->chnl_state)
952 {
953 case CST_CLOSED:
954 switch (event)
955 {
956 case L2CEVT_LP_CONNECT_CFM: /* Link came up */
957 /* check if waiting for UCD info */
958 if (!l2c_ucd_check_pending_info_req (p_ccb))
959 {
960 /* check if any outgoing UCD packet is waiting security check */
961 if (!l2c_ucd_check_pending_out_sec_q(p_ccb))
962 {
963 p_ccb->chnl_state = CST_OPEN;
964 }
965 }
966 break;
967
968 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700969 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800970 break;
971
972 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
973 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
974 break;
975
976 case L2CEVT_L2CAP_INFO_RSP:
977 /* check if waiting for UCD info */
978 if (!l2c_ucd_check_pending_info_req (p_ccb))
979 {
980 /* check if any outgoing UCD packet is waiting security check */
981 if (!l2c_ucd_check_pending_out_sec_q(p_ccb))
982 {
983 p_ccb->chnl_state = CST_OPEN;
984 }
985 }
986 break;
987
988 default:
Marie Janssend19e0782016-07-15 12:48:27 -0700989 done = false; /* main state machine continues to process event */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800990 break;
991 }
992 break;
993
994 case CST_ORIG_W4_SEC_COMP:
995 switch (event)
996 {
997 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
998 /* check if any outgoing UCD packet is waiting security check */
999 if (!l2c_ucd_check_pending_out_sec_q(p_ccb))
1000 {
1001 p_ccb->chnl_state = CST_OPEN;
1002 }
1003 break;
1004
1005 case L2CEVT_SEC_COMP: /* Security completed success */
1006 p_ccb->chnl_state = CST_OPEN;
1007 l2c_ucd_send_pending_out_sec_q(p_ccb);
1008
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001009 if (! fixed_queue_is_empty(p_ccb->p_lcb->ucd_out_sec_pending_q))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001010 {
1011 /* start a timer to send next UCD packet in OPEN state */
1012 /* it will prevent stack overflow */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001013 alarm_set_on_queue(p_ccb->l2c_ccb_timer, 0,
1014 l2c_ccb_timer_timeout, p_ccb,
1015 btu_general_alarm_queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001016 }
1017 else
1018 {
1019 /* start a timer for idle timeout of UCD */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001020 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1021 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1022 l2c_ccb_timer_timeout, p_ccb,
1023 btu_general_alarm_queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001024 }
1025 break;
1026
1027 case L2CEVT_SEC_COMP_NEG:
1028 p_ccb->chnl_state = CST_OPEN;
1029 l2c_ucd_discard_pending_out_sec_q(p_ccb);
1030
1031 /* start a timer for idle timeout of UCD */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001032 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1033 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1034 l2c_ccb_timer_timeout, p_ccb,
1035 btu_general_alarm_queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001036 break;
1037
1038 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1039 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1040 break;
1041
1042 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001043 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001044 break;
1045
1046 case L2CEVT_L2CAP_INFO_RSP:
1047 /* check if waiting for UCD info */
1048 l2c_ucd_check_pending_info_req (p_ccb);
1049 break;
1050
1051 default:
Marie Janssend19e0782016-07-15 12:48:27 -07001052 done = false; /* main state machine continues to process event */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001053 break;
1054 }
1055 break;
1056
1057
1058 case CST_TERM_W4_SEC_COMP:
1059 switch (event)
1060 {
1061 case L2CEVT_SEC_COMP:
1062 p_ccb->chnl_state = CST_OPEN;
1063 l2c_ucd_send_pending_in_sec_q (p_ccb);
1064
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001065 if (! fixed_queue_is_empty(p_ccb->p_lcb->ucd_in_sec_pending_q))
The Android Open Source Project5738f832012-12-12 16:00:35 -08001066 {
1067 /* start a timer to check next UCD packet in OPEN state */
1068 /* it will prevent stack overflow */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001069 alarm_set_on_queue(p_ccb->l2c_ccb_timer, 0,
1070 l2c_ccb_timer_timeout, p_ccb,
1071 btu_general_alarm_queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001072 }
1073 else
1074 {
1075 /* start a timer for idle timeout of UCD */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001076 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1077 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1078 l2c_ccb_timer_timeout, p_ccb,
1079 btu_general_alarm_queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001080 }
1081 break;
1082
1083 case L2CEVT_SEC_COMP_NEG:
1084 if (((tL2C_CONN_INFO *)p_data)->status == BTM_DELAY_CHECK)
1085 {
Marie Janssend19e0782016-07-15 12:48:27 -07001086 done = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001087 break;
1088 }
1089 p_ccb->chnl_state = CST_OPEN;
1090 l2c_ucd_discard_pending_in_sec_q (p_ccb);
1091
1092 /* start a timer for idle timeout of UCD */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001093 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1094 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1095 l2c_ccb_timer_timeout, p_ccb,
1096 btu_general_alarm_queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001097 break;
1098
1099 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1100 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1101 break;
1102
1103 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001104 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001105 break;
1106
1107 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
1108 /* check if any incoming UCD packet is waiting security check */
1109 if (!l2c_ucd_check_pending_in_sec_q(p_ccb))
1110 {
1111 p_ccb->chnl_state = CST_OPEN;
1112 }
1113 break;
1114
1115 case L2CEVT_L2CAP_INFO_RSP:
1116 /* check if waiting for UCD info */
1117 l2c_ucd_check_pending_info_req (p_ccb);
1118 break;
1119
1120 default:
Marie Janssend19e0782016-07-15 12:48:27 -07001121 done = false; /* main state machine continues to process event */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001122 break;
1123 }
1124 break;
1125
1126 case CST_OPEN:
1127 switch (event)
1128 {
1129 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1130 /* stop idle timer of UCD */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001131 alarm_cancel(p_ccb->l2c_ccb_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001132
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001133 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001134 l2c_ucd_check_pending_in_sec_q (p_ccb);
1135 break;
1136
1137 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1138 /* stop idle timer of UCD */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001139 alarm_cancel(p_ccb->l2c_ccb_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001140
1141 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1142
1143 /* coverity[check_return] */ /* coverity[unchecked_value] */
1144 /* success changes state, failure stays in current state */
1145 l2c_ucd_check_pending_out_sec_q (p_ccb);
1146 break;
1147
1148 case L2CEVT_TIMEOUT:
1149 /* check if any UCD packet is waiting security check */
1150 if ((!l2c_ucd_check_pending_in_sec_q(p_ccb))
1151 &&(!l2c_ucd_check_pending_out_sec_q(p_ccb)))
1152 {
1153 l2cu_release_ccb (p_ccb);
1154 }
1155 break;
1156
1157 case L2CEVT_L2CAP_INFO_RSP:
1158 /* check if waiting for UCD info */
1159 l2c_ucd_check_pending_info_req (p_ccb);
1160 break;
1161
1162 default:
Marie Janssend19e0782016-07-15 12:48:27 -07001163 done = false; /* main state machine continues to process event */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001164 break;
1165 }
1166 break;
1167
1168 default:
Marie Janssend19e0782016-07-15 12:48:27 -07001169 done = false; /* main state machine continues to process event */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001170 break;
1171 }
1172
1173 return done;
1174}
1175#endif /* (L2CAP_UCD_INCLUDED == TRUE) */