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