1 /******************************************************************************
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
29 #include "stack/bt_types.h"
30 #include "stack/hcidefs.h"
31 #include "stack/hcimsgs.h"
32 #include "stack/l2cdefs.h"
33 #include "l2c_int.h"
34 #include "stack/btu.h"
35 #include "stack/btm_api.h"
36 #include "btm_int.h"
37
38 #if (L2CAP_UCD_INCLUDED == TRUE)
39 static BOOLEAN l2c_ucd_connect ( BD_ADDR rem_bda );
40
41 /*******************************************************************************
42 **
43 ** Function l2c_ucd_discover_cback
44 **
45 ** Description UCD Discover callback
46 **
47 ** Returns void
48 **
49 *******************************************************************************/
l2c_ucd_discover_cback(BD_ADDR rem_bda,UINT8 info_type,UINT32 data)50 static void l2c_ucd_discover_cback (BD_ADDR rem_bda, UINT8 info_type, UINT32 data)
51 {
52 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
53 UINT16 xx;
54
55 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_discover_cback");
56
57 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
58 if (p_rcb->in_use) {
59 /* if this application is waiting UCD reception info */
60 if (( info_type == L2CAP_UCD_INFO_TYPE_RECEPTION )
61 && ( p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION )) {
62 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (rem_bda, info_type, data);
63 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_RECEPTION);
64 }
65
66 /* if this application is waiting UCD MTU info */
67 if (( info_type == L2CAP_UCD_INFO_TYPE_MTU )
68 && ( p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU )) {
69 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (rem_bda, info_type, data);
70 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_MTU);
71 }
72 }
73 }
74 }
75
76 /*******************************************************************************
77 **
78 ** Function l2c_ucd_data_ind_cback
79 **
80 ** Description UCD Data callback
81 **
82 ** Returns void
83 **
84 *******************************************************************************/
l2c_ucd_data_ind_cback(BD_ADDR rem_bda,BT_HDR * p_buf)85 static void l2c_ucd_data_ind_cback (BD_ADDR rem_bda, BT_HDR *p_buf)
86 {
87 UINT8 *p;
88 UINT16 psm;
89 tL2C_RCB *p_rcb;
90
91 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_data_ind_cback");
92
93 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
94 STREAM_TO_UINT16(psm, p)
95
96 p_buf->offset += L2CAP_UCD_OVERHEAD;
97 p_buf->len -= L2CAP_UCD_OVERHEAD;
98
99 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) {
100 L2CAP_TRACE_ERROR ("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x", psm);
101 osi_free (p_buf);
102 } else {
103 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf);
104 }
105 }
106
107 /*******************************************************************************
108 **
109 ** Function l2c_ucd_congestion_status_cback
110 **
111 ** Description UCD Congestion Status callback
112 **
113 ** Returns void
114 **
115 *******************************************************************************/
l2c_ucd_congestion_status_cback(BD_ADDR rem_bda,BOOLEAN is_congested)116 static void l2c_ucd_congestion_status_cback (BD_ADDR rem_bda, BOOLEAN is_congested)
117 {
118 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
119 UINT16 xx;
120
121 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_congestion_status_cback");
122
123 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
124 if (( p_rcb->in_use )
125 && ( p_rcb->ucd.state != L2C_UCD_STATE_UNUSED )) {
126 if ( p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
127 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCDCongestionStatus_Cb (%d), PSM=0x%04x, BDA: %08x%04x,",
128 is_congested, p_rcb->psm,
129 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
130 (rem_bda[4] << 8) + rem_bda[5]);
131
132 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ( rem_bda, is_congested );
133 }
134 }
135 }
136 }
137
138 /*******************************************************************************
139 **
140 ** Function l2c_ucd_disconnect_ind_cback
141 **
142 ** Description UCD disconnect callback (This prevent to access null pointer)
143 **
144 ** Returns void
145 **
146 *******************************************************************************/
l2c_ucd_disconnect_ind_cback(UINT16 cid,BOOLEAN result)147 static void l2c_ucd_disconnect_ind_cback (UINT16 cid, BOOLEAN result)
148 {
149 /* do nothing */
150 }
151
152 /*******************************************************************************
153 **
154 ** Function l2c_ucd_config_ind_cback
155 **
156 ** Description UCD config callback (This prevent to access null pointer)
157 **
158 ** Returns void
159 **
160 *******************************************************************************/
l2c_ucd_config_ind_cback(UINT16 cid,tL2CAP_CFG_INFO * p_cfg)161 static void l2c_ucd_config_ind_cback (UINT16 cid, tL2CAP_CFG_INFO *p_cfg)
162 {
163 /* do nothing */
164 }
165
166 /*******************************************************************************
167 **
168 ** Function l2c_ucd_config_cfm_cback
169 **
170 ** Description UCD config callback (This prevent to access null pointer)
171 **
172 ** Returns void
173 **
174 *******************************************************************************/
l2c_ucd_config_cfm_cback(UINT16 cid,tL2CAP_CFG_INFO * p_cfg)175 static void l2c_ucd_config_cfm_cback (UINT16 cid, tL2CAP_CFG_INFO *p_cfg)
176 {
177 /* do nothing */
178 }
179
180 /*******************************************************************************
181 **
182 ** Function L2CA_UcdRegister
183 **
184 ** Description Register PSM on UCD.
185 **
186 ** Parameters: tL2CAP_UCD_CB_INFO
187 **
188 ** Return value: TRUE if successs
189 **
190 *******************************************************************************/
L2CA_UcdRegister(UINT16 psm,tL2CAP_UCD_CB_INFO * p_cb_info)191 BOOLEAN L2CA_UcdRegister ( UINT16 psm, tL2CAP_UCD_CB_INFO *p_cb_info )
192 {
193 tL2C_RCB *p_rcb;
194
195 L2CAP_TRACE_API ("L2CA_UcdRegister() PSM: 0x%04x", psm);
196
197 if ((!p_cb_info->pL2CA_UCD_Discover_Cb)
198 || (!p_cb_info->pL2CA_UCD_Data_Cb)) {
199 L2CAP_TRACE_ERROR ("L2CAP - no callback registering PSM(0x%04x) on UCD", psm);
200 return (FALSE);
201 }
202
203 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) {
204 L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdRegister, PSM: 0x%04x", psm);
205 return (FALSE);
206 }
207
208 p_rcb->ucd.state = L2C_UCD_STATE_W4_DATA;
209 p_rcb->ucd.cb_info = *p_cb_info;
210
211 /* check if master rcb is created for UCD */
212 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL) {
213 if ((p_rcb = l2cu_allocate_rcb (L2C_UCD_RCB_ID)) == NULL) {
214 L2CAP_TRACE_ERROR ("L2CAP - no RCB available for L2CA_UcdRegister");
215 return (FALSE);
216 } else {
217 /* these callback functions will forward data to each UCD application */
218 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb = l2c_ucd_discover_cback;
219 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb = l2c_ucd_data_ind_cback;
220 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb = l2c_ucd_congestion_status_cback;
221
222 memset (&p_rcb->api, 0, sizeof(tL2CAP_APPL_INFO));
223 p_rcb->api.pL2CA_DisconnectInd_Cb = l2c_ucd_disconnect_ind_cback;
224
225 /* This will make L2CAP check UCD congestion callback */
226 p_rcb->api.pL2CA_CongestionStatus_Cb = NULL;
227
228 /* do nothing but prevent crash */
229 p_rcb->api.pL2CA_ConfigInd_Cb = l2c_ucd_config_ind_cback;
230 p_rcb->api.pL2CA_ConfigCfm_Cb = l2c_ucd_config_cfm_cback;
231 }
232 }
233
234 return (TRUE);
235 }
236
237 /*******************************************************************************
238 **
239 ** Function L2CA_UcdDeregister
240 **
241 ** Description Deregister PSM on UCD.
242 **
243 ** Parameters: PSM
244 **
245 ** Return value: TRUE if successs
246 **
247 *******************************************************************************/
L2CA_UcdDeregister_In_CCB_List(void * p_ccb_node,void * context)248 BOOLEAN L2CA_UcdDeregister_In_CCB_List (void *p_ccb_node, void * context)
249 {
250 p_ccb = (tL2C_CCB *)p_ccb_node;
251 if (( p_ccb->in_use )
252 && ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )) {
253 l2cu_release_ccb (p_ccb);
254 }
255 return false;
256 }
257
L2CA_UcdDeregister(UINT16 psm)258 BOOLEAN L2CA_UcdDeregister ( UINT16 psm )
259 {
260 tL2C_CCB *p_ccb;
261 tL2C_RCB *p_rcb;
262 UINT16 xx;
263
264 L2CAP_TRACE_API ("L2CA_UcdDeregister() PSM: 0x%04x", psm);
265
266 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) {
267 L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdDeregister, PSM: 0x%04x", psm);
268 return (FALSE);
269 }
270
271 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
272
273 /* check this was the last UCD registration */
274 p_rcb = &l2cb.rcb_pool[0];
275
276 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
277 if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED)) {
278 return (TRUE);
279 }
280 }
281
282 /* delete master rcb for UCD */
283 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL) {
284 l2cu_release_rcb (p_rcb);
285 }
286
287 /* delete CCB for UCD */
288 list_foreach(l2cb.p_ccb_pool, L2CA_UcdDeregister_In_CCB_List, NULL);
289 return (TRUE);
290 }
291
292 /*******************************************************************************
293 **
294 ** Function L2CA_UcdDiscover
295 **
296 ** Description Discover UCD of remote device.
297 **
298 ** Parameters: PSM
299 ** BD_ADDR of remote device
300 ** info_type : L2CAP_UCD_INFO_TYPE_RECEPTION
301 ** L2CAP_UCD_INFO_TYPE_MTU
302 **
303 **
304 ** Return value: TRUE if successs
305 **
306 *******************************************************************************/
L2CA_UcdDiscover(UINT16 psm,BD_ADDR rem_bda,UINT8 info_type)307 BOOLEAN L2CA_UcdDiscover ( UINT16 psm, BD_ADDR rem_bda, UINT8 info_type )
308 {
309 tL2C_LCB *p_lcb;
310 tL2C_CCB *p_ccb;
311 tL2C_RCB *p_rcb;
312
313 L2CAP_TRACE_API ("L2CA_UcdDiscover() PSM: 0x%04x BDA: %08x%04x, InfoType=0x%02x", psm,
314 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
315 (rem_bda[4] << 8) + rem_bda[5], info_type);
316
317 /* Fail if the PSM is not registered */
318 if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
319 || ( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED )) {
320 L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDiscover, PSM: 0x%04x", psm);
321 return (FALSE);
322 }
323
324 /* First, see if we already have a link to the remote */
325 /* then find the channel control block for UCD. */
326 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
327 || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) {
328 if ( l2c_ucd_connect (rem_bda) == FALSE ) {
329 return (FALSE);
330 }
331 }
332
333 /* set waiting flags in rcb */
334
335 if ( info_type & L2CAP_UCD_INFO_TYPE_RECEPTION ) {
336 p_rcb->ucd.state |= L2C_UCD_STATE_W4_RECEPTION;
337 }
338
339 if ( info_type & L2CAP_UCD_INFO_TYPE_MTU ) {
340 p_rcb->ucd.state |= L2C_UCD_STATE_W4_MTU;
341 }
342
343 /* if link is already established */
344 if ((p_lcb) && (p_lcb->link_state == LST_CONNECTED)) {
345 if (!p_ccb) {
346 p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID);
347 }
348 l2c_ucd_check_pending_info_req(p_ccb);
349 }
350 return (TRUE);
351 }
352
353 /*******************************************************************************
354 **
355 ** Function L2CA_UcdDataWrite
356 **
357 ** Description Send UCD to remote device
358 **
359 ** Parameters: PSM
360 ** BD Address of remote
361 ** Pointer to buffer of type BT_HDR
362 ** flags : L2CAP_FLUSHABLE_CH_BASED
363 ** L2CAP_FLUSHABLE_PKT
364 ** L2CAP_NON_FLUSHABLE_PKT
365 **
366 ** Return value L2CAP_DW_SUCCESS, if data accepted
367 ** L2CAP_DW_FAILED, if error
368 **
369 *******************************************************************************/
L2CA_UcdDataWrite(UINT16 psm,BD_ADDR rem_bda,BT_HDR * p_buf,UINT16 flags)370 UINT16 L2CA_UcdDataWrite (UINT16 psm, BD_ADDR rem_bda, BT_HDR *p_buf, UINT16 flags)
371 {
372 tL2C_LCB *p_lcb;
373 tL2C_CCB *p_ccb;
374 tL2C_RCB *p_rcb;
375 UINT8 *p;
376
377 L2CAP_TRACE_API ("L2CA_UcdDataWrite() PSM: 0x%04x BDA: %08x%04x", psm,
378 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
379 (rem_bda[4] << 8) + rem_bda[5]);
380
381 /* Fail if the PSM is not registered */
382 if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
383 || ( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED )) {
384 L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x", psm);
385 osi_free (p_buf);
386 return (L2CAP_DW_FAILED);
387 }
388
389 /* First, see if we already have a link to the remote */
390 /* then find the channel control block for UCD */
391 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
392 || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) {
393 if ( l2c_ucd_connect (rem_bda) == FALSE ) {
394 osi_free (p_buf);
395 return (L2CAP_DW_FAILED);
396 }
397
398 /* If we still don't have lcb and ccb after connect attempt, then can't proceed */
399 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
400 || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) {
401 osi_free (p_buf);
402 return (L2CAP_DW_FAILED);
403 }
404 }
405
406 /* write PSM */
407 p_buf->offset -= L2CAP_UCD_OVERHEAD;
408 p_buf->len += L2CAP_UCD_OVERHEAD;
409 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
410
411 UINT16_TO_STREAM (p, psm);
412
413 /* UCD MTU check */
414 if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu)) {
415 L2CAP_TRACE_WARNING ("L2CAP - Handle: 0x%04x UCD bigger than peer's UCD mtu size cannot be sent", p_lcb->handle);
416 osi_free (p_buf);
417 return (L2CAP_DW_FAILED);
418 }
419
420 /* If already congested, do not accept any more packets */
421 if (p_ccb->cong_sent) {
422 L2CAP_TRACE_ERROR ("L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: %u buff_quota: %u",
423 p_lcb->handle,
424 (fixed_queue_length(p_ccb->xmit_hold_q) +
425 fixed_queue_length(p_lcb->ucd_out_sec_pending_q)),
426 p_ccb->buff_quota);
427
428 osi_free (p_buf);
429 return (L2CAP_DW_FAILED);
430 }
431
432 /* channel based, packet based flushable or non-flushable */
433 p_buf->layer_specific = flags;
434
435 l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf);
436
437 if (p_ccb->cong_sent) {
438 return (L2CAP_DW_CONGESTED);
439 } else {
440 return (L2CAP_DW_SUCCESS);
441 }
442 }
443
444 /*******************************************************************************
445 **
446 ** Function L2CA_UcdSetIdleTimeout
447 **
448 ** Description Set UCD Idle timeout.
449 **
450 ** Parameters: BD Addr
451 ** Timeout in second
452 **
453 ** Return value: TRUE if successs
454 **
455 *******************************************************************************/
L2CA_UcdSetIdleTimeout(BD_ADDR rem_bda,UINT16 timeout)456 BOOLEAN L2CA_UcdSetIdleTimeout ( BD_ADDR rem_bda, UINT16 timeout )
457 {
458 tL2C_LCB *p_lcb;
459 tL2C_CCB *p_ccb;
460
461 L2CAP_TRACE_API ("L2CA_UcdSetIdleTimeout() Timeout: 0x%04x BDA: %08x%04x", timeout,
462 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
463 (rem_bda[4] << 8) + rem_bda[5]);
464
465 /* First, see if we already have a link to the remote */
466 /* then find the channel control block. */
467 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
468 || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) {
469 L2CAP_TRACE_WARNING ("L2CAP - no UCD channel");
470 return (FALSE);
471 } else {
472 p_ccb->fixed_chnl_idle_tout = timeout;
473 return (TRUE);
474 }
475 }
476
477 /*******************************************************************************
478 **
479 ** Function L2CA_UCDSetTxPriority
480 **
481 ** Description Sets the transmission priority for a connectionless channel.
482 **
483 ** Returns TRUE if a valid channel, else FALSE
484 **
485 *******************************************************************************/
L2CA_UCDSetTxPriority(BD_ADDR rem_bda,tL2CAP_CHNL_PRIORITY priority)486 BOOLEAN L2CA_UCDSetTxPriority ( BD_ADDR rem_bda, tL2CAP_CHNL_PRIORITY priority )
487 {
488 tL2C_LCB *p_lcb;
489 tL2C_CCB *p_ccb;
490
491 L2CAP_TRACE_API ("L2CA_UCDSetTxPriority() priority: 0x%02x BDA: %08x%04x", priority,
492 (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 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) {
496 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_UCDSetTxPriority");
497 return (FALSE);
498 }
499
500 /* Find the channel control block */
501 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL) {
502 L2CAP_TRACE_WARNING ("L2CAP - no CCB for L2CA_UCDSetTxPriority");
503 return (FALSE);
504 }
505
506 /* it will update the order of CCB in LCB by priority and update round robin service variables */
507 l2cu_change_pri_ccb (p_ccb, priority);
508
509 return (TRUE);
510 }
511
512 /*******************************************************************************
513 **
514 ** Function l2c_ucd_connect
515 **
516 ** Description Connect UCD to remote device.
517 **
518 ** Parameters: BD_ADDR of remote device
519 **
520 ** Return value: TRUE if successs
521 **
522 *******************************************************************************/
l2c_ucd_connect(BD_ADDR rem_bda)523 static BOOLEAN l2c_ucd_connect ( BD_ADDR rem_bda )
524 {
525 tL2C_LCB *p_lcb;
526 tL2C_CCB *p_ccb;
527 tL2C_RCB *p_rcb;
528
529 L2CAP_TRACE_DEBUG ("l2c_ucd_connect() BDA: %08x%04x",
530 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
531 (rem_bda[4] << 8) + rem_bda[5]);
532
533 /* Fail if we have not established communications with the controller */
534 if (!BTM_IsDeviceUp()) {
535 L2CAP_TRACE_WARNING ("l2c_ucd_connect - BTU not ready");
536 return (FALSE);
537 }
538
539 /* First, see if we already have a link to the remote */
540 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) {
541 /* No link. Get an LCB and start link establishment */
542 if ( ((p_lcb = l2cu_allocate_lcb (rem_bda, FALSE, BT_TRANSPORT_BR_EDR)) == NULL)
543 || (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE) ) {
544 L2CAP_TRACE_WARNING ("L2CAP - conn not started l2c_ucd_connect");
545 return (FALSE);
546 }
547 } else if ( p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE) ) {
548 if (!(p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) {
549 L2CAP_TRACE_WARNING ("L2CAP - UCD is not supported by peer, l2c_ucd_connect");
550 return (FALSE);
551 }
552 }
553
554 /* Find the channel control block. */
555 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL) {
556 /* Allocate a channel control block */
557 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL) {
558 L2CAP_TRACE_WARNING ("L2CAP - no CCB for l2c_ucd_connect");
559 return (FALSE);
560 } else {
561 /* Set CID for the connection */
562 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
563 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
564
565 /* Set the default idle timeout value to use */
566 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
567
568 /* Set the default channel priority value to use */
569 l2cu_change_pri_ccb (p_ccb, L2CAP_UCD_CH_PRIORITY);
570
571 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL) {
572 L2CAP_TRACE_WARNING ("L2CAP - no UCD registered, l2c_ucd_connect");
573 return (FALSE);
574 }
575 /* Save UCD registration info */
576 p_ccb->p_rcb = p_rcb;
577
578 /* There is no configuration, so if the link is up, the channel is up */
579 if (p_lcb->link_state == LST_CONNECTED) {
580 p_ccb->chnl_state = CST_OPEN;
581 }
582 }
583 }
584
585 return (TRUE);
586 }
587
588 /*******************************************************************************
589 **
590 ** Function l2c_ucd_delete_sec_pending_q
591 **
592 ** Description discard all of UCD packets in security pending queue
593 **
594 ** Returns None
595 **
596 *******************************************************************************/
l2c_ucd_delete_sec_pending_q(tL2C_LCB * p_lcb)597 void l2c_ucd_delete_sec_pending_q(tL2C_LCB *p_lcb)
598 {
599 /* clean up any security pending UCD */
600 while (p_lcb->ucd_out_sec_pending_q.p_first) {
601 osi_free(fixed_queue_dequeue(p_lcb->ucd_out_sec_pending_q, 0));
602 }
603 fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL);
604 p_lcb->ucd_out_sec_pending_q = NULL;
605
606 while (! fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q)) {
607 osi_free(fixed_queue_dequeue(p_lcb->ucd_in_sec_pending_q, 0));
608 }
609 fixed_queue_free(p_lcb->ucd_in_sec_pending_q);
610 p_lcb->ucd_in_sec_pending_q = NULL;
611 }
612
613 /*******************************************************************************
614 **
615 ** Function l2c_ucd_check_pending_info_req
616 **
617 ** Description check if any application is waiting for UCD information
618 **
619 ** Return TRUE if any pending UCD info request
620 **
621 *******************************************************************************/
l2c_ucd_check_pending_info_req(tL2C_CCB * p_ccb)622 BOOLEAN l2c_ucd_check_pending_info_req(tL2C_CCB *p_ccb)
623 {
624 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
625 UINT16 xx;
626 BOOLEAN pending = FALSE;
627
628 if (p_ccb == NULL) {
629 L2CAP_TRACE_ERROR ("L2CAP - NULL p_ccb in l2c_ucd_check_pending_info_req");
630 return (FALSE);
631 }
632
633 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
634 if (p_rcb->in_use) {
635 /* if application is waiting UCD reception info */
636 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION) {
637 /* if this information is available */
638 if ( p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE) ) {
639 if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) {
640 L2CAP_TRACE_WARNING ("L2CAP - UCD is not supported by peer, l2c_ucd_check_pending_info_req");
641
642 l2c_ucd_delete_sec_pending_q(p_ccb->p_lcb);
643 l2cu_release_ccb (p_ccb);
644 }
645
646 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (p_ccb->p_lcb->remote_bd_addr,
647 L2CAP_UCD_INFO_TYPE_RECEPTION,
648 p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION);
649 } else {
650 pending = TRUE;
651 if (p_ccb->p_lcb->w4_info_rsp == FALSE) {
652 l2cu_send_peer_info_req (p_ccb->p_lcb, L2CAP_EXTENDED_FEATURES_INFO_TYPE);
653 }
654 }
655 }
656
657 /* if application is waiting for UCD MTU */
658 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU) {
659 /* if this information is available */
660 if ( p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_CONNLESS_MTU_INFO_TYPE)) {
661 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (p_ccb->p_lcb->remote_bd_addr,
662 L2CAP_UCD_INFO_TYPE_MTU,
663 p_ccb->p_lcb->ucd_mtu);
664 } else {
665 pending = TRUE;
666 if (p_ccb->p_lcb->w4_info_rsp == FALSE) {
667 l2cu_send_peer_info_req (p_ccb->p_lcb, L2CAP_CONNLESS_MTU_INFO_TYPE);
668 }
669 }
670 }
671 }
672 }
673 return (pending);
674 }
675
676 /*******************************************************************************
677 **
678 ** Function l2c_ucd_enqueue_pending_out_sec_q
679 **
680 ** Description enqueue outgoing UCD packet into security pending queue
681 ** and check congestion
682 **
683 ** Return None
684 **
685 *******************************************************************************/
l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB * p_ccb,void * p_data)686 void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB *p_ccb, void *p_data)
687 {
688 fixed_queue_enqueue(p_ccb->p_lcb->ucd_out_sec_pending_q, p_data, FIXED_QUEUE_MAX_TIMEOUT);
689 l2cu_check_channel_congestion (p_ccb);
690 }
691
692 /*******************************************************************************
693 **
694 ** Function l2c_ucd_check_pending_out_sec_q
695 **
696 ** Description check outgoing security
697 **
698 ** Return TRUE if any UCD packet for security
699 **
700 *******************************************************************************/
l2c_ucd_check_pending_out_sec_q(tL2C_CCB * p_ccb)701 BOOLEAN l2c_ucd_check_pending_out_sec_q(tL2C_CCB *p_ccb)
702 {
703 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->p_lcb->ucd_out_sec_pending_q);
704
705 if (p_buf != NULL) {
706 UINT16 psm;
707 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
708
709 STREAM_TO_UINT16(psm, p)
710
711 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
712 btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm,
713 p_ccb->p_lcb->handle, CONNLESS_ORIG, &l2c_link_sec_comp, p_ccb);
714
715 return (TRUE);
716 }
717 return (FALSE);
718 }
719
720 /*******************************************************************************
721 **
722 ** Function l2c_ucd_send_pending_out_sec_q
723 **
724 ** Description dequeue UCD packet from security pending queue and
725 ** enqueue it into CCB
726 **
727 ** Return None
728 **
729 *******************************************************************************/
l2c_ucd_send_pending_out_sec_q(tL2C_CCB * p_ccb)730 void l2c_ucd_send_pending_out_sec_q(tL2C_CCB *p_ccb)
731 {
732 BT_HDR *p_buf = (BT_HDR*)fixed_queue_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q, 0);
733
734 if (p_buf != NULL) {
735 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_buf);
736 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
737 }
738 }
739
740 /*******************************************************************************
741 **
742 ** Function l2c_ucd_discard_pending_out_sec_q
743 **
744 ** Description dequeue UCD packet from security pending queue and
745 ** discard it.
746 **
747 ** Return None
748 **
749 *******************************************************************************/
l2c_ucd_discard_pending_out_sec_q(tL2C_CCB * p_ccb)750 void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB *p_ccb)
751 {
752 BT_HDR *p_buf = (BT_HDR*)fixed_queue_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q, 0);
753
754 /* we may need to report to application */
755
756 if (p_buf) {
757 osi_free (p_buf);
758 }
759 }
760
761 /*******************************************************************************
762 **
763 ** Function l2c_ucd_check_pending_in_sec_q
764 **
765 ** Description check incoming security
766 **
767 ** Return TRUE if any UCD packet for security
768 **
769 *******************************************************************************/
l2c_ucd_check_pending_in_sec_q(tL2C_CCB * p_ccb)770 BOOLEAN l2c_ucd_check_pending_in_sec_q(tL2C_CCB *p_ccb)
771 {
772 BT_HDR *p_buf = (BT_HDR*)fixed_queue_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q, 0);
773
774 if (p_buf != NULL) {
775 UINT16 psm;
776 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
777 STREAM_TO_UINT16(psm, p)
778
779 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
780 btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm,
781 p_ccb->p_lcb->handle, CONNLESS_TERM, &l2c_link_sec_comp, p_ccb);
782
783 return (TRUE);
784 }
785 return (FALSE);
786 }
787
788 /*******************************************************************************
789 **
790 ** Function l2c_ucd_send_pending_in_sec_q
791 **
792 ** Description dequeue UCD packet from security pending queue and
793 ** send it to application
794 **
795 ** Return None
796 **
797 *******************************************************************************/
l2c_ucd_send_pending_in_sec_q(tL2C_CCB * p_ccb)798 void l2c_ucd_send_pending_in_sec_q(tL2C_CCB *p_ccb)
799 {
800 BT_HDR *p_buf = (BT_HDR*)fixed_queue_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q, 0)
801
802 if (p_buf != NULL) {
803 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(p_ccb->p_lcb->remote_bd_addr, (BT_HDR *)p_buf);
804 }
805 }
806
807 /*******************************************************************************
808 **
809 ** Function l2c_ucd_discard_pending_in_sec_q
810 **
811 ** Description dequeue UCD packet from security pending queue and
812 ** discard it.
813 **
814 ** Return None
815 **
816 *******************************************************************************/
l2c_ucd_discard_pending_in_sec_q(tL2C_CCB * p_ccb)817 void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB *p_ccb)
818 {
819 BT_HDR *p_buf = (BT_HDR*)fixed_queue_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q, 0);
820
821 if (p_buf) {
822 osi_free (p_buf);
823 }
824 }
825
826 /*******************************************************************************
827 **
828 ** Function l2c_ucd_check_rx_pkts
829 **
830 ** Description Check if UCD reception is registered.
831 ** Process received UCD packet if application is expecting.
832 **
833 ** Return TRUE if UCD reception is registered
834 **
835 *******************************************************************************/
l2c_ucd_check_rx_pkts(tL2C_LCB * p_lcb,BT_HDR * p_msg)836 BOOLEAN l2c_ucd_check_rx_pkts(tL2C_LCB *p_lcb, BT_HDR *p_msg)
837 {
838 tL2C_CCB *p_ccb;
839 tL2C_RCB *p_rcb;
840
841 if (((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) != NULL)
842 || ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL)) {
843 if (p_ccb == NULL) {
844 /* Allocate a channel control block */
845 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL) {
846 L2CAP_TRACE_WARNING ("L2CAP - no CCB for UCD reception");
847 osi_free (p_msg);
848 return TRUE;
849 } else {
850 /* Set CID for the connection */
851 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
852 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
853
854 /* Set the default idle timeout value to use */
855 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
856
857 /* Set the default channel priority value to use */
858 l2cu_change_pri_ccb (p_ccb, L2CAP_UCD_CH_PRIORITY);
859
860 /* Save registration info */
861 p_ccb->p_rcb = p_rcb;
862
863 p_ccb->chnl_state = CST_OPEN;
864 }
865 }
866 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
867 return TRUE;
868 } else {
869 return FALSE;
870 }
871 }
872
873 /*******************************************************************************
874 **
875 ** Function l2c_ucd_process_event
876 **
877 ** Description This is called from main state machine when LCID is connectionless
878 ** Process the event if it is for UCD.
879 **
880 ** Return TRUE if the event is consumed by UCD
881 ** FALSE if the event needs to be processed by main state machine
882 **
883 *******************************************************************************/
l2c_ucd_process_event(tL2C_CCB * p_ccb,UINT16 event,void * p_data)884 BOOLEAN l2c_ucd_process_event(tL2C_CCB *p_ccb, UINT16 event, void *p_data)
885 {
886 /* if the event is not processed by this function, this variable will be set to FALSE */
887 BOOLEAN done = TRUE;
888
889 switch (p_ccb->chnl_state) {
890 case CST_CLOSED:
891 switch (event) {
892 case L2CEVT_LP_CONNECT_CFM: /* Link came up */
893 /* check if waiting for UCD info */
894 if (!l2c_ucd_check_pending_info_req (p_ccb)) {
895 /* check if any outgoing UCD packet is waiting security check */
896 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
897 p_ccb->chnl_state = CST_OPEN;
898 }
899 }
900 break;
901
902 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
903 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data, FIXED_QUEUE_MAX_TIMEOUT);
904 break;
905
906 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
907 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
908 break;
909
910 case L2CEVT_L2CAP_INFO_RSP:
911 /* check if waiting for UCD info */
912 if (!l2c_ucd_check_pending_info_req (p_ccb)) {
913 /* check if any outgoing UCD packet is waiting security check */
914 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
915 p_ccb->chnl_state = CST_OPEN;
916 }
917 }
918 break;
919
920 default:
921 done = FALSE; /* main state machine continues to process event */
922 break;
923 }
924 break;
925
926 case CST_ORIG_W4_SEC_COMP:
927 switch (event) {
928 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
929 /* check if any outgoing UCD packet is waiting security check */
930 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
931 p_ccb->chnl_state = CST_OPEN;
932 }
933 break;
934
935 case L2CEVT_SEC_COMP: /* Security completed success */
936 p_ccb->chnl_state = CST_OPEN;
937 l2c_ucd_send_pending_out_sec_q(p_ccb);
938
939 if (! fixed_queue_is_empty(p_ccb->p_lcb->ucd_out_sec_pending_q))
940 {
941 /* start a timer to send next UCD packet in OPEN state */
942 /* it will prevent stack overflow */
943 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, 0);
944 } else {
945 /* start a timer for idle timeout of UCD */
946 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, p_ccb->fixed_chnl_idle_tout);
947 }
948 break;
949
950 case L2CEVT_SEC_COMP_NEG:
951 p_ccb->chnl_state = CST_OPEN;
952 l2c_ucd_discard_pending_out_sec_q(p_ccb);
953
954 /* start a timer for idle timeout of UCD */
955 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, p_ccb->fixed_chnl_idle_tout);
956 break;
957
958 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
959 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
960 break;
961
962 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
963 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data, FIXED_QUEUE_MAX_TIMEOUT);
964 break;
965
966 case L2CEVT_L2CAP_INFO_RSP:
967 /* check if waiting for UCD info */
968 l2c_ucd_check_pending_info_req (p_ccb);
969 break;
970
971 default:
972 done = FALSE; /* main state machine continues to process event */
973 break;
974 }
975 break;
976
977
978 case CST_TERM_W4_SEC_COMP:
979 switch (event) {
980 case L2CEVT_SEC_COMP:
981 p_ccb->chnl_state = CST_OPEN;
982 l2c_ucd_send_pending_in_sec_q (p_ccb);
983
984 if (! fixed_queue_is_empty(p_ccb->p_lcb->ucd_in_sec_pending_q)) {
985 /* start a timer to check next UCD packet in OPEN state */
986 /* it will prevent stack overflow */
987 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, 0);
988 } else {
989 /* start a timer for idle timeout of UCD */
990 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, p_ccb->fixed_chnl_idle_tout);
991 }
992 break;
993
994 case L2CEVT_SEC_COMP_NEG:
995 if (((tL2C_CONN_INFO *)p_data)->status == BTM_DELAY_CHECK) {
996 done = FALSE;
997 break;
998 }
999 p_ccb->chnl_state = CST_OPEN;
1000 l2c_ucd_discard_pending_in_sec_q (p_ccb);
1001
1002 /* start a timer for idle timeout of UCD */
1003 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, p_ccb->fixed_chnl_idle_tout);
1004 break;
1005
1006 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1007 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1008 break;
1009
1010 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1011 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data, FIXED_QUEUE_MAX_TIMEOUT);
1012 break;
1013
1014 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
1015 /* check if any incoming UCD packet is waiting security check */
1016 if (!l2c_ucd_check_pending_in_sec_q(p_ccb)) {
1017 p_ccb->chnl_state = CST_OPEN;
1018 }
1019 break;
1020
1021 case L2CEVT_L2CAP_INFO_RSP:
1022 /* check if waiting for UCD info */
1023 l2c_ucd_check_pending_info_req (p_ccb);
1024 break;
1025
1026 default:
1027 done = FALSE; /* main state machine continues to process event */
1028 break;
1029 }
1030 break;
1031
1032 case CST_OPEN:
1033 switch (event) {
1034 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1035 /* stop idle timer of UCD */
1036 btu_stop_timer (&p_ccb->timer_entry);
1037
1038 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data, FIXED_QUEUE_MAX_TIMEOUT);
1039 l2c_ucd_check_pending_in_sec_q (p_ccb);
1040 break;
1041
1042 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1043 /* stop idle timer of UCD */
1044 btu_stop_timer (&p_ccb->timer_entry);
1045
1046 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1047
1048 /* coverity[check_return] */ /* coverity[unchecked_value] */
1049 /* success changes state, failure stays in current state */
1050 l2c_ucd_check_pending_out_sec_q (p_ccb);
1051 break;
1052
1053 case L2CEVT_TIMEOUT:
1054 /* check if any UCD packet is waiting security check */
1055 if ((!l2c_ucd_check_pending_in_sec_q(p_ccb))
1056 && (!l2c_ucd_check_pending_out_sec_q(p_ccb))) {
1057 l2cu_release_ccb (p_ccb);
1058 }
1059 break;
1060
1061 case L2CEVT_L2CAP_INFO_RSP:
1062 /* check if waiting for UCD info */
1063 l2c_ucd_check_pending_info_req (p_ccb);
1064 break;
1065
1066 default:
1067 done = FALSE; /* main state machine continues to process event */
1068 break;
1069 }
1070 break;
1071
1072 default:
1073 done = FALSE; /* main state machine continues to process event */
1074 break;
1075 }
1076
1077 return done;
1078 }
1079 #endif /* (L2CAP_UCD_INCLUDED == TRUE) */
1080