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
41extern fixed_queue_t* btu_bta_alarm_queue;
42
43static 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 ******************************************************************************/
54static 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 ******************************************************************************/
89static 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 ******************************************************************************/
121static 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 ******************************************************************************/
154static 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 ******************************************************************************/
167static 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 ******************************************************************************/
180static 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 ******************************************************************************/
195bool 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 ******************************************************************************/
255bool 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 ******************************************************************************/
312bool 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 ******************************************************************************/
376uint16_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 ******************************************************************************/
472bool 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 ******************************************************************************/
504bool 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 ******************************************************************************/
544static 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 ******************************************************************************/
624void 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 ******************************************************************************/
646bool 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 ******************************************************************************/
713void 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 ******************************************************************************/
727bool 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 ******************************************************************************/
757void 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 ******************************************************************************/
777void 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 ******************************************************************************/
794bool 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 ******************************************************************************/
823void 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 ******************************************************************************/
843void 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 ******************************************************************************/
859bool 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 ******************************************************************************/
908bool 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