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