bool BTM_SetSecurityLevel(bool is_originator, const char* p_name,
uint8_t service_id, uint16_t sec_level, uint16_t psm,
uint32_t mx_proto_id, uint32_t mx_chan_id) {
-#if (L2CAP_UCD_INCLUDED == TRUE)
- CONNECTION_TYPE conn_type;
-
- if (is_originator)
- conn_type = CONN_ORIENT_ORIG;
- else
- conn_type = CONN_ORIENT_TERM;
-
- return (btm_sec_set_security_level(conn_type, p_name, service_id, sec_level,
- psm, mx_proto_id, mx_chan_id));
-#else
return (btm_sec_set_security_level(is_originator, p_name, service_id,
sec_level, psm, mx_proto_id, mx_chan_id));
-#endif
}
/*******************************************************************************
uint16_t first_unused_record = BTM_NO_AVAIL_SEC_SERVICES;
bool record_allocated = false;
bool is_originator;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- bool is_ucd;
-
- if (conn_type & CONNECTION_TYPE_ORIG_MASK)
- is_originator = true;
- else
- is_originator = false;
-
- if (conn_type & CONNECTION_TYPE_CONNLESS_MASK) {
- is_ucd = true;
- } else {
- is_ucd = false;
- }
-#else
is_originator = conn_type;
-#endif
BTM_TRACE_API("%s : sec: 0x%x", __func__, sec_level);
BTM_SEC_SERVICE_NAME_LEN + 1);
#endif
/* clear out the old setting, just in case it exists */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (is_ucd) {
- p_srec->ucd_security_flags &= ~(
- BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_ENCRYPT |
- BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_MITM | BTM_SEC_FORCE_MASTER |
- BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE | BTM_SEC_ATTEMPT_SLAVE);
- } else
-#endif
{
p_srec->security_flags &= ~(
BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_ENCRYPT |
/* outgoing connections usually set the security level right before
* the connection is initiated.
* set it to be the outgoing service */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (is_ucd == false)
-#endif
- {
btm_cb.p_out_serv = p_srec;
- }
} else {
p_srec->term_mx_chan_id = mx_chan_id;
#if BTM_SEC_SERVICE_NAME_LEN > 0
BTM_SEC_SERVICE_NAME_LEN + 1);
#endif
/* clear out the old setting, just in case it exists */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (is_ucd) {
- p_srec->ucd_security_flags &=
- ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT |
- BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MITM | BTM_SEC_FORCE_MASTER |
- BTM_SEC_ATTEMPT_MASTER | BTM_SEC_FORCE_SLAVE |
- BTM_SEC_ATTEMPT_SLAVE | BTM_SEC_IN_MIN_16_DIGIT_PIN);
- } else
-#endif
{
p_srec->security_flags &=
~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT |
if (sec_level & BTM_SEC_IN_ENCRYPT) sec_level |= BTM_SEC_IN_AUTHENTICATE;
}
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (is_ucd) {
- p_srec->security_flags |= (uint16_t)(BTM_SEC_IN_USE);
- p_srec->ucd_security_flags |= (uint16_t)(sec_level | BTM_SEC_IN_USE);
- } else {
- p_srec->security_flags |= (uint16_t)(sec_level | BTM_SEC_IN_USE);
- }
-
- BTM_TRACE_API(
- "BTM_SEC_REG[%d]: id %d, conn_type 0x%x, psm 0x%04x, proto_id %d, "
- "chan_id %d",
- index, service_id, conn_type, psm, mx_proto_id, mx_chan_id);
-
- BTM_TRACE_API(
- " : security_flags: 0x%04x, ucd_security_flags: 0x%04x",
- p_srec->security_flags, p_srec->ucd_security_flags);
-
-#if BTM_SEC_SERVICE_NAME_LEN > 0
- BTM_TRACE_API(" : service name [%s] (up to %d chars saved)",
- p_name, BTM_SEC_SERVICE_NAME_LEN);
-#endif
-#else
p_srec->security_flags |= (uint16_t)(sec_level | BTM_SEC_IN_USE);
BTM_TRACE_API(
" : sec: 0x%x, service name [%s] (up to %d chars saved)",
p_srec->security_flags, p_name, BTM_SEC_SERVICE_NAME_LEN);
#endif
-#endif
return (record_allocated);
}
(!service_id || (service_id == p_srec->service_id))) {
BTM_TRACE_API("BTM_SEC_CLR[%d]: id %d", i, service_id);
p_srec->security_flags = 0;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- p_srec->ucd_security_flags = 0;
-#endif
num_freed++;
}
}
BT_TRANSPORT_BR_EDR; /* should check PSM range in LE connection oriented
L2CAP connection */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (conn_type & CONNECTION_TYPE_ORIG_MASK)
- is_originator = true;
- else
- is_originator = false;
-
- BTM_TRACE_DEBUG("%s() conn_type: 0x%x, 0x%x", __func__, conn_type,
- p_ref_data);
-#else
is_originator = conn_type;
BTM_TRACE_DEBUG("%s() is_originator:%d, 0x%x", __func__, is_originator,
p_ref_data);
-#endif
/* Find or get oldest record */
p_dev_rec = btm_find_or_alloc_dev(bd_addr);
(*p_callback)(&bd_addr, transport, p_ref_data, BTM_SUCCESS_NO_SECURITY);
return (BTM_SUCCESS);
}
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (conn_type & CONNECTION_TYPE_CONNLESS_MASK) {
- if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- security_required = btm_sec_set_serv_level4_flags(
- p_serv_rec->ucd_security_flags, is_originator);
- } else {
- security_required = p_serv_rec->ucd_security_flags;
- }
-
- rc = BTM_CMD_STARTED;
- if (is_originator) {
- if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) ==
- BTM_SEC_OUT_AUTHENTICATE) &&
- (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) ==
- (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) &&
- (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) ||
- ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_FLAGS) &&
- (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED)))) {
- rc = BTM_SUCCESS;
- }
- } else {
- if (((security_required & BTM_SEC_IN_FLAGS) == 0) ||
- ((((security_required & BTM_SEC_IN_FLAGS) ==
- BTM_SEC_IN_AUTHENTICATE) &&
- (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
- ((((security_required & BTM_SEC_IN_FLAGS) ==
- (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) &&
- (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) ||
- ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_FLAGS) &&
- (p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED)))) {
- // Check for 16 digits (or MITM)
- if (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) == 0) ||
- (((security_required & BTM_SEC_IN_MIN_16_DIGIT_PIN) ==
- BTM_SEC_IN_MIN_16_DIGIT_PIN) &&
- btm_dev_16_digit_authenticated(p_dev_rec))) {
- rc = BTM_SUCCESS;
- }
- }
- }
-
- if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) &&
- (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) {
- rc = BTM_CMD_STARTED;
- }
-
- if (rc == BTM_SUCCESS) {
- if (p_callback)
- (*p_callback)(&bd_addr, transport, (void*)p_ref_data, BTM_SUCCESS);
-
- return (BTM_SUCCESS);
- }
- } else
-#endif
- {
- if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
- security_required = btm_sec_set_serv_level4_flags(
- p_serv_rec->security_flags, is_originator);
- } else {
- security_required = p_serv_rec->security_flags;
- }
+ if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
+ security_required = btm_sec_set_serv_level4_flags(
+ p_serv_rec->security_flags, is_originator);
+ } else {
+ security_required = p_serv_rec->security_flags;
}
BTM_TRACE_DEBUG(
p_dev_rec->p_ref_data = p_ref_data;
p_dev_rec->is_originator = is_originator;
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (conn_type & CONNECTION_TYPE_CONNLESS_MASK)
- p_dev_rec->is_ucd = true;
- else
- p_dev_rec->is_ucd = false;
-#endif
-
/* If there are multiple service records used through the same PSM */
/* leave security decision for the multiplexor on the top */
-#if (L2CAP_UCD_INCLUDED == TRUE)
- if (((btm_sec_find_next_serv(p_serv_rec)) != NULL) &&
- (!(conn_type & CONNECTION_TYPE_CONNLESS_MASK))) /* if not UCD */
-#else
- if ((btm_sec_find_next_serv(p_serv_rec)) != NULL)
-#endif
- {
+ if ((btm_sec_find_next_serv(p_serv_rec)) != NULL) {
BTM_TRACE_DEBUG("no next_serv sm4:0x%x, chk:%d", p_dev_rec->sm4,
chk_acp_auth_done);
if (!BTM_SEC_IS_SM4(p_dev_rec->sm4)) {
* authenticated connections, hence we cannot distinguish here.
*/
-#if (L2CAP_UCD_INCLUDED == TRUE)
- /* if incoming UCD packet, discard it */
- if (!p_dev_rec->is_originator && (p_dev_rec->is_ucd == true))
- return (BTM_FAILED_ON_SECURITY);
-#endif
-
BTM_TRACE_EVENT("Security Manager: Start authentication");
/*
(!p_dev_rec->is_originator &&
(p_dev_rec->security_required & BTM_SEC_IN_ENCRYPT))) &&
(p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)) {
-#if (L2CAP_UCD_INCLUDED == TRUE)
- /* if incoming UCD packet, discard it */
- if (!p_dev_rec->is_originator && (p_dev_rec->is_ucd == true))
- return (BTM_FAILED_ON_SECURITY);
-#endif
BTM_TRACE_EVENT("Security Manager: Start encryption");
uint16_t psm) {
tBTM_SEC_SERV_REC* p_serv_rec = &btm_cb.sec_serv_rec[0];
int i;
- bool is_originator;
-
-#if (L2CAP_UCD_INCLUDED == TRUE)
-
- if (conn_type & CONNECTION_TYPE_ORIG_MASK)
- is_originator = true;
- else
- is_originator = false;
-#else
- is_originator = conn_type;
-#endif
+ bool is_originator = conn_type;
if (is_originator && btm_cb.p_out_serv && btm_cb.p_out_serv->psm == psm) {
/* If this is outgoing connection and the PSM matches p_out_serv,
+++ /dev/null
-/******************************************************************************
- *
- * Copyright (C) 1999-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * This file contains the L2CAP UCD code
- *
- ******************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "bt_common.h"
-#include "bt_types.h"
-#include "btm_api.h"
-#include "btm_int.h"
-#include "btu.h"
-#include "hcidefs.h"
-#include "hcimsgs.h"
-#include "l2c_int.h"
-#include "l2cdefs.h"
-
-#if (L2CAP_UCD_INCLUDED == TRUE)
-
-static bool l2c_ucd_connect(const RawAddress& rem_bda);
-
-/*******************************************************************************
- *
- * Function l2c_ucd_discover_cback
- *
- * Description UCD Discover callback
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_discover_cback(const RawAddress& rem_bda, uint8_t info_type,
- uint32_t data) {
- tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
- uint16_t xx;
-
- L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_discover_cback");
-
- for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
- if (p_rcb->in_use) {
- /* if this application is waiting UCD reception info */
- if ((info_type == L2CAP_UCD_INFO_TYPE_RECEPTION) &&
- (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION)) {
- p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(rem_bda, info_type, data);
- p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_RECEPTION);
- }
-
- /* if this application is waiting UCD MTU info */
- if ((info_type == L2CAP_UCD_INFO_TYPE_MTU) &&
- (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU)) {
- p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(rem_bda, info_type, data);
- p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_MTU);
- }
- }
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_data_ind_cback
- *
- * Description UCD Data callback
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_data_ind_cback(const RawAddress& rem_bda, BT_HDR* p_buf) {
- uint8_t* p;
- uint16_t psm;
- tL2C_RCB* p_rcb;
-
- L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_data_ind_cback");
-
- p = (uint8_t*)(p_buf + 1) + p_buf->offset;
- STREAM_TO_UINT16(psm, p)
-
- p_buf->offset += L2CAP_UCD_OVERHEAD;
- p_buf->len -= L2CAP_UCD_OVERHEAD;
-
- p_rcb = l2cu_find_rcb_by_psm(psm);
- if (p_rcb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x",
- psm);
- osi_free(p_buf);
- } else {
- p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf);
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_congestion_status_cback
- *
- * Description UCD Congestion Status callback
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_congestion_status_cback(const RawAddress& rem_bda,
- bool is_congested) {
- tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
- uint16_t xx;
-
- L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_congestion_status_cback");
-
- for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
- if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED)) {
- if (p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
- L2CAP_TRACE_DEBUG(
- "L2CAP - Calling UCDCongestionStatus_Cb (%d), PSM=0x%04x, BDA: "
- "%08x%04x,",
- is_congested, p_rcb->psm, (rem_bda[0] << 24) + (rem_bda[1] << 16) +
- (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(rem_bda,
- is_congested);
- }
- }
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_disconnect_ind_cback
- *
- * Description UCD disconnect callback (Prevent to access null pointer)
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_disconnect_ind_cback(uint16_t cid, bool result) {
- /* do nothing */
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_config_ind_cback
- *
- * Description UCD config callback (This prevent to access null pointer)
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_config_ind_cback(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
- /* do nothing */
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_config_cfm_cback
- *
- * Description UCD config callback (This prevent to access null pointer)
- *
- * Returns void
- *
- ******************************************************************************/
-static void l2c_ucd_config_cfm_cback(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
- /* do nothing */
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdRegister
- *
- * Description Register PSM on UCD.
- *
- * Parameters: tL2CAP_UCD_CB_INFO
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-bool L2CA_UcdRegister(uint16_t psm, tL2CAP_UCD_CB_INFO* p_cb_info) {
- tL2C_RCB* p_rcb;
-
- L2CAP_TRACE_API("L2CA_UcdRegister() PSM: 0x%04x", psm);
-
- if ((!p_cb_info->pL2CA_UCD_Discover_Cb) || (!p_cb_info->pL2CA_UCD_Data_Cb)) {
- L2CAP_TRACE_ERROR("L2CAP - no callback registering PSM(0x%04x) on UCD",
- psm);
- return (false);
- }
-
- p_rcb = l2cu_find_rcb_by_psm(psm);
- if (p_rcb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - no RCB for L2CA_UcdRegister, PSM: 0x%04x", psm);
- return (false);
- }
-
- p_rcb->ucd.state = L2C_UCD_STATE_W4_DATA;
- p_rcb->ucd.cb_info = *p_cb_info;
-
- /* check if master rcb is created for UCD */
- p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
- if (p_rcb == NULL) {
- p_rcb = l2cu_allocate_rcb(L2C_UCD_RCB_ID);
- if (p_rcb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - no RCB available for L2CA_UcdRegister");
- return (false);
- } else {
- /* these callback functions will forward data to each UCD application */
- p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb = l2c_ucd_discover_cback;
- p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb = l2c_ucd_data_ind_cback;
- p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb =
- l2c_ucd_congestion_status_cback;
-
- memset(&p_rcb->api, 0, sizeof(tL2CAP_APPL_INFO));
- p_rcb->api.pL2CA_DisconnectInd_Cb = l2c_ucd_disconnect_ind_cback;
-
- /* This will make L2CAP check UCD congestion callback */
- p_rcb->api.pL2CA_CongestionStatus_Cb = NULL;
-
- /* do nothing but prevent crash */
- p_rcb->api.pL2CA_ConfigInd_Cb = l2c_ucd_config_ind_cback;
- p_rcb->api.pL2CA_ConfigCfm_Cb = l2c_ucd_config_cfm_cback;
- }
- }
-
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdDeregister
- *
- * Description Deregister PSM on UCD.
- *
- * Parameters: PSM
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-bool L2CA_UcdDeregister(uint16_t psm) {
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
- uint16_t xx;
-
- L2CAP_TRACE_API("L2CA_UcdDeregister() PSM: 0x%04x", psm);
-
- p_rcb = l2cu_find_rcb_by_psm(psm);
- if (p_rcb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - no RCB for L2CA_UcdDeregister, PSM: 0x%04x",
- psm);
- return (false);
- }
-
- p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
-
- /* check this was the last UCD registration */
- p_rcb = &l2cb.rcb_pool[0];
-
- for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
- if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED))
- return (true);
- }
-
- /* delete master rcb for UCD */
- p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
- if (p_rcb != NULL) {
- l2cu_release_rcb(p_rcb);
- }
-
- /* delete CCB for UCD */
- p_ccb = l2cb.ccb_pool;
- for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) {
- if ((p_ccb->in_use) && (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)) {
- l2cu_release_ccb(p_ccb);
- }
- p_ccb++;
- }
-
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdDiscover
- *
- * Description Discover UCD of remote device.
- *
- * Parameters: PSM
- * BD_ADDR of remote device
- * info_type : L2CAP_UCD_INFO_TYPE_RECEPTION
- * L2CAP_UCD_INFO_TYPE_MTU
- *
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-bool L2CA_UcdDiscover(uint16_t psm, const RawAddress& rem_bda,
- uint8_t info_type) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
-
- L2CAP_TRACE_API(
- "L2CA_UcdDiscover() PSM: 0x%04x BDA: %08x%04x, InfoType=0x%02x", psm,
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5], info_type);
-
- /* Fail if the PSM is not registered */
- if (((p_rcb = l2cu_find_rcb_by_psm(psm)) == NULL) ||
- (p_rcb->ucd.state == L2C_UCD_STATE_UNUSED)) {
- L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_UcdDiscover, PSM: 0x%04x",
- psm);
- return (false);
- }
-
- /* First, see if we already have a link to the remote */
- /* then find the channel control block for UCD. */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
- NULL)) {
- if (l2c_ucd_connect(rem_bda) == false) {
- return (false);
- }
- }
-
- /* set waiting flags in rcb */
-
- if (info_type & L2CAP_UCD_INFO_TYPE_RECEPTION)
- p_rcb->ucd.state |= L2C_UCD_STATE_W4_RECEPTION;
-
- if (info_type & L2CAP_UCD_INFO_TYPE_MTU)
- p_rcb->ucd.state |= L2C_UCD_STATE_W4_MTU;
-
- /* if link is already established */
- if ((p_lcb) && (p_lcb->link_state == LST_CONNECTED)) {
- if (!p_ccb) {
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
- }
- l2c_ucd_check_pending_info_req(p_ccb);
- }
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdDataWrite
- *
- * Description Send UCD to remote device
- *
- * Parameters: PSM
- * BD Address of remote
- * Pointer to buffer of type BT_HDR
- * flags : L2CAP_FLUSHABLE_CH_BASED
- * L2CAP_FLUSHABLE_PKT
- * L2CAP_NON_FLUSHABLE_PKT
- *
- * Return value L2CAP_DW_SUCCESS, if data accepted
- * L2CAP_DW_FAILED, if error
- *
- ******************************************************************************/
-uint16_t L2CA_UcdDataWrite(uint16_t psm, const RawAddress& rem_bda,
- BT_HDR* p_buf, uint16_t flags) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
- uint8_t* p;
-
- L2CAP_TRACE_API(
- "L2CA_UcdDataWrite() PSM: 0x%04x BDA: %08x%04x", psm,
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- /* Fail if the PSM is not registered */
- if (((p_rcb = l2cu_find_rcb_by_psm(psm)) == NULL) ||
- (p_rcb->ucd.state == L2C_UCD_STATE_UNUSED)) {
- L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x",
- psm);
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
-
- /* First, see if we already have a link to the remote */
- /* then find the channel control block for UCD */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
- NULL)) {
- if (l2c_ucd_connect(rem_bda) == false) {
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
-
- /* If we still don't have lcb and ccb after connect attempt, then can't
- * proceed */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
- NULL)) {
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
- }
-
- /* write PSM */
- p_buf->offset -= L2CAP_UCD_OVERHEAD;
- p_buf->len += L2CAP_UCD_OVERHEAD;
- p = (uint8_t*)(p_buf + 1) + p_buf->offset;
-
- UINT16_TO_STREAM(p, psm);
-
- /* UCD MTU check */
- if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu)) {
- L2CAP_TRACE_WARNING(
- "L2CAP - Handle: 0x%04x UCD bigger than peer's UCD mtu size cannot be "
- "sent",
- p_lcb->handle);
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
-
- /* If already congested, do not accept any more packets */
- if (p_ccb->cong_sent) {
- L2CAP_TRACE_ERROR(
- "L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: "
- "%u buff_quota: %u",
- p_lcb->handle, (fixed_queue_length(p_ccb->xmit_hold_q) +
- fixed_queue_length(p_lcb->ucd_out_sec_pending_q)),
- p_ccb->buff_quota);
-
- osi_free(p_buf);
- return (L2CAP_DW_FAILED);
- }
-
- /* channel based, packet based flushable or non-flushable */
- p_buf->layer_specific = flags;
-
- l2c_csm_execute(p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf);
-
- if (p_ccb->cong_sent)
- return (L2CAP_DW_CONGESTED);
- else
- return (L2CAP_DW_SUCCESS);
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UcdSetIdleTimeout
- *
- * Description Set UCD Idle timeout.
- *
- * Parameters: BD Addr
- * Timeout in second
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-bool L2CA_UcdSetIdleTimeout(const RawAddress& rem_bda, uint16_t timeout) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
-
- L2CAP_TRACE_API(
- "L2CA_UcdSetIdleTimeout() Timeout: 0x%04x BDA: %08x%04x", timeout,
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- /* First, see if we already have a link to the remote */
- /* then find the channel control block. */
- if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
- NULL)) {
- L2CAP_TRACE_WARNING("L2CAP - no UCD channel");
- return (false);
- } else {
- p_ccb->fixed_chnl_idle_tout = timeout;
- return (true);
- }
-}
-
-/*******************************************************************************
- *
- * Function L2CA_UCDSetTxPriority
- *
- * Description Sets the transmission priority for a connectionless channel.
- *
- * Returns true if a valid channel, else false
- *
- ******************************************************************************/
-bool L2CA_UCDSetTxPriority(const RawAddress& rem_bda,
- tL2CAP_CHNL_PRIORITY priority) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
-
- L2CAP_TRACE_API(
- "L2CA_UCDSetTxPriority() priority: 0x%02x BDA: %08x%04x", priority,
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR);
- if (p_lcb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_UCDSetTxPriority");
- return (false);
- }
-
- /* Find the channel control block */
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
- if (p_ccb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_UCDSetTxPriority");
- return (false);
- }
-
- /* it will update the order of CCB in LCB by priority and update round robin
- * service variables */
- l2cu_change_pri_ccb(p_ccb, priority);
-
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_connect
- *
- * Description Connect UCD to remote device.
- *
- * Parameters: BD_ADDR of remote device
- *
- * Return value: true if successs
- *
- ******************************************************************************/
-static bool l2c_ucd_connect(const RawAddress& rem_bda) {
- tL2C_LCB* p_lcb;
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
-
- L2CAP_TRACE_DEBUG(
- "l2c_ucd_connect() BDA: %08x%04x",
- (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
- (rem_bda[4] << 8) + rem_bda[5]);
-
- /* Fail if we have not established communications with the controller */
- if (!BTM_IsDeviceUp()) {
- L2CAP_TRACE_WARNING("l2c_ucd_connect - BTU not ready");
- return (false);
- }
-
- /* First, see if we already have a link to the remote */
- p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR);
- if (p_lcb == NULL) {
- /* No link. Get an LCB and start link establishment */
- if (((p_lcb = l2cu_allocate_lcb(rem_bda, false, BT_TRANSPORT_BR_EDR)) ==
- NULL) ||
- (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == false)) {
- L2CAP_TRACE_WARNING("L2CAP - conn not started l2c_ucd_connect");
- return (false);
- }
- } else if (p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE)) {
- if (!(p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) {
- L2CAP_TRACE_WARNING(
- "L2CAP - UCD is not supported by peer, l2c_ucd_connect");
- return (false);
- }
- }
-
- /* Find the channel control block. */
- p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
- if (p_ccb == NULL) {
- /* Allocate a channel control block */
- p_ccb = l2cu_allocate_ccb(p_lcb, 0);
- if (p_ccb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no CCB for l2c_ucd_connect");
- return (false);
- } else {
- /* Set CID for the connection */
- p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
- p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
-
- /* Set the default idle timeout value to use */
- p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
-
- /* Set the default channel priority value to use */
- l2cu_change_pri_ccb(p_ccb, L2CAP_UCD_CH_PRIORITY);
-
- p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
- if (p_rcb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no UCD registered, l2c_ucd_connect");
- return (false);
- }
- /* Save UCD registration info */
- p_ccb->p_rcb = p_rcb;
-
- /* There is no configuration, so if the link is up, the channel is up */
- if (p_lcb->link_state == LST_CONNECTED) {
- p_ccb->chnl_state = CST_OPEN;
- }
- }
- }
-
- return (true);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_delete_sec_pending_q
- *
- * Description discard all of UCD packets in security pending queue
- *
- * Returns None
- *
- ******************************************************************************/
-void l2c_ucd_delete_sec_pending_q(tL2C_LCB* p_lcb) {
- /* clean up any security pending UCD */
- while (!fixed_queue_is_empty(p_lcb->ucd_out_sec_pending_q))
- osi_free(fixed_queue_try_dequeue(p_lcb->ucd_out_sec_pending_q));
- fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL);
- p_lcb->ucd_out_sec_pending_q = NULL;
-
- while (!fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q))
- osi_free(fixed_queue_try_dequeue(p_lcb->ucd_in_sec_pending_q));
- fixed_queue_free(p_lcb->ucd_in_sec_pending_q);
- p_lcb->ucd_in_sec_pending_q = NULL;
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_check_pending_info_req
- *
- * Description check if any application is waiting for UCD information
- *
- * Return true if any pending UCD info request
- *
- ******************************************************************************/
-bool l2c_ucd_check_pending_info_req(tL2C_CCB* p_ccb) {
- tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
- uint16_t xx;
- bool pending = false;
-
- if (p_ccb == NULL) {
- L2CAP_TRACE_ERROR("L2CAP - NULL p_ccb in l2c_ucd_check_pending_info_req");
- return (false);
- }
-
- for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
- if (p_rcb->in_use) {
- /* if application is waiting UCD reception info */
- if (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION) {
- /* if this information is available */
- if (p_ccb->p_lcb->info_rx_bits &
- (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE)) {
- if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) {
- L2CAP_TRACE_WARNING(
- "L2CAP - UCD is not supported by peer, "
- "l2c_ucd_check_pending_info_req");
-
- l2c_ucd_delete_sec_pending_q(p_ccb->p_lcb);
- l2cu_release_ccb(p_ccb);
- }
-
- p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(
- p_ccb->p_lcb->remote_bd_addr, L2CAP_UCD_INFO_TYPE_RECEPTION,
- p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION);
- } else {
- pending = true;
- if (p_ccb->p_lcb->w4_info_rsp == false) {
- l2cu_send_peer_info_req(p_ccb->p_lcb,
- L2CAP_EXTENDED_FEATURES_INFO_TYPE);
- }
- }
- }
-
- /* if application is waiting for UCD MTU */
- if (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU) {
- /* if this information is available */
- if (p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_CONNLESS_MTU_INFO_TYPE)) {
- p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(
- p_ccb->p_lcb->remote_bd_addr, L2CAP_UCD_INFO_TYPE_MTU,
- p_ccb->p_lcb->ucd_mtu);
- } else {
- pending = true;
- if (p_ccb->p_lcb->w4_info_rsp == false) {
- l2cu_send_peer_info_req(p_ccb->p_lcb, L2CAP_CONNLESS_MTU_INFO_TYPE);
- }
- }
- }
- }
- }
- return (pending);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_enqueue_pending_out_sec_q
- *
- * Description enqueue outgoing UCD packet into security pending queue
- * and check congestion
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB* p_ccb, void* p_data) {
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_out_sec_pending_q, p_data);
- l2cu_check_channel_congestion(p_ccb);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_check_pending_out_sec_q
- *
- * Description check outgoing security
- *
- * Return true if any UCD packet for security
- *
- ******************************************************************************/
-bool l2c_ucd_check_pending_out_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_peek_first(p_ccb->p_lcb->ucd_out_sec_pending_q);
-
- if (p_buf != NULL) {
- uint16_t psm;
- uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
-
- STREAM_TO_UINT16(psm, p)
-
- p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
- btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, psm,
- p_ccb->p_lcb->handle, CONNLESS_ORIG,
- &l2c_link_sec_comp, p_ccb);
-
- return (true);
- }
- return (false);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_send_pending_out_sec_q
- *
- * Description dequeue UCD packet from security pending queue and
- * enqueue it into CCB
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_send_pending_out_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
-
- if (p_buf != NULL) {
- l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_buf);
- l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_discard_pending_out_sec_q
- *
- * Description dequeue UCD packet from security pending queue and
- * discard it.
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
-
- /* we may need to report to application */
- osi_free(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_check_pending_in_sec_q
- *
- * Description check incoming security
- *
- * Return true if any UCD packet for security
- *
- ******************************************************************************/
-bool l2c_ucd_check_pending_in_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
-
- if (p_buf != NULL) {
- uint16_t psm;
- uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
- STREAM_TO_UINT16(psm, p)
-
- p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
- btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, psm,
- p_ccb->p_lcb->handle, CONNLESS_TERM,
- &l2c_link_sec_comp, p_ccb);
-
- return (true);
- }
- return (false);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_send_pending_in_sec_q
- *
- * Description dequeue UCD packet from security pending queue and
- * send it to application
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_send_pending_in_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q)
-
- if (p_buf != NULL) {
- p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(p_ccb->p_lcb->remote_bd_addr,
- (BT_HDR*)p_buf);
- }
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_discard_pending_in_sec_q
- *
- * Description dequeue UCD packet from security pending queue and
- * discard it.
- *
- * Return None
- *
- ******************************************************************************/
-void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB* p_ccb) {
- BT_HDR* p_buf =
- (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
- osi_free(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_check_rx_pkts
- *
- * Description Check if UCD reception is registered.
- * Process received UCD packet if application is expecting.
- *
- * Return true if UCD reception is registered
- *
- ******************************************************************************/
-bool l2c_ucd_check_rx_pkts(tL2C_LCB* p_lcb, BT_HDR* p_msg) {
- tL2C_CCB* p_ccb;
- tL2C_RCB* p_rcb;
-
- if (((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) !=
- NULL) ||
- ((p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID)) != NULL)) {
- if (p_ccb == NULL) {
- /* Allocate a channel control block */
- p_ccb = l2cu_allocate_ccb(p_lcb, 0);
- if (p_ccb == NULL) {
- L2CAP_TRACE_WARNING("L2CAP - no CCB for UCD reception");
- osi_free(p_msg);
- return true;
- } else {
- /* Set CID for the connection */
- p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
- p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
-
- /* Set the default idle timeout value to use */
- p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
-
- /* Set the default channel priority value to use */
- l2cu_change_pri_ccb(p_ccb, L2CAP_UCD_CH_PRIORITY);
-
- /* Save registration info */
- p_ccb->p_rcb = p_rcb;
-
- p_ccb->chnl_state = CST_OPEN;
- }
- }
- l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
- return true;
- } else
- return false;
-}
-
-/*******************************************************************************
- *
- * Function l2c_ucd_process_event
- *
- * Description This is called from main state machine when LCID is
- * connectionless. Process the event if it is for UCD.
- *
- * Return true if the event is consumed by UCD
- * false if the event needs to be processed by the main state
- * machine
- *
- ******************************************************************************/
-bool l2c_ucd_process_event(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
- /* if the event is not processed by this function, this variable will be set
- * to false */
- bool done = true;
-
- switch (p_ccb->chnl_state) {
- case CST_CLOSED:
- switch (event) {
- case L2CEVT_LP_CONNECT_CFM: /* Link came up */
- /* check if waiting for UCD info */
- if (!l2c_ucd_check_pending_info_req(p_ccb)) {
- /* check if any outgoing UCD packet is waiting security check */
- if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
- p_ccb->chnl_state = CST_OPEN;
- }
- }
- break;
-
- case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
- break;
-
- case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
- break;
-
- case L2CEVT_L2CAP_INFO_RSP:
- /* check if waiting for UCD info */
- if (!l2c_ucd_check_pending_info_req(p_ccb)) {
- /* check if any outgoing UCD packet is waiting security check */
- if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
- p_ccb->chnl_state = CST_OPEN;
- }
- }
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
- break;
-
- case CST_ORIG_W4_SEC_COMP:
- switch (event) {
- case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
- /* check if any outgoing UCD packet is waiting security check */
- if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
- p_ccb->chnl_state = CST_OPEN;
- }
- break;
-
- case L2CEVT_SEC_COMP: /* Security completed success */
- p_ccb->chnl_state = CST_OPEN;
- l2c_ucd_send_pending_out_sec_q(p_ccb);
-
- if (!fixed_queue_is_empty(p_ccb->p_lcb->ucd_out_sec_pending_q)) {
- /* start a timer to send next UCD packet in OPEN state */
- /* it will prevent stack overflow */
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 0, l2c_ccb_timer_timeout,
- p_ccb);
- } else {
- /* start a timer for idle timeout of UCD */
- period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, timeout_ms,
- l2c_ccb_timer_timeout, p_ccb);
- }
- break;
-
- case L2CEVT_SEC_COMP_NEG:
- p_ccb->chnl_state = CST_OPEN;
- l2c_ucd_discard_pending_out_sec_q(p_ccb);
-
- /* start a timer for idle timeout of UCD */
- period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, timeout_ms,
- l2c_ccb_timer_timeout, p_ccb);
- break;
-
- case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
- break;
-
- case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
- break;
-
- case L2CEVT_L2CAP_INFO_RSP:
- /* check if waiting for UCD info */
- l2c_ucd_check_pending_info_req(p_ccb);
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
- break;
-
- case CST_TERM_W4_SEC_COMP:
- switch (event) {
- case L2CEVT_SEC_COMP:
- p_ccb->chnl_state = CST_OPEN;
- l2c_ucd_send_pending_in_sec_q(p_ccb);
-
- if (!fixed_queue_is_empty(p_ccb->p_lcb->ucd_in_sec_pending_q)) {
- /* start a timer to check next UCD packet in OPEN state */
- /* it will prevent stack overflow */
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 0, l2c_ccb_timer_timeout,
- p_ccb);
- } else {
- /* start a timer for idle timeout of UCD */
- period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, timeout_ms,
- l2c_ccb_timer_timeout, p_ccb);
- }
- break;
-
- case L2CEVT_SEC_COMP_NEG:
- if (((tL2C_CONN_INFO*)p_data)->status == BTM_DELAY_CHECK) {
- done = false;
- break;
- }
- p_ccb->chnl_state = CST_OPEN;
- l2c_ucd_discard_pending_in_sec_q(p_ccb);
-
- /* start a timer for idle timeout of UCD */
- period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, timeout_ms,
- l2c_ccb_timer_timeout, p_ccb);
- break;
-
- case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
- break;
-
- case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
- break;
-
- case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
- /* check if any incoming UCD packet is waiting security check */
- if (!l2c_ucd_check_pending_in_sec_q(p_ccb)) {
- p_ccb->chnl_state = CST_OPEN;
- }
- break;
-
- case L2CEVT_L2CAP_INFO_RSP:
- /* check if waiting for UCD info */
- l2c_ucd_check_pending_info_req(p_ccb);
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
- break;
-
- case CST_OPEN:
- switch (event) {
- case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- /* stop idle timer of UCD */
- alarm_cancel(p_ccb->l2c_ccb_timer);
-
- fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
- l2c_ucd_check_pending_in_sec_q(p_ccb);
- break;
-
- case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- /* stop idle timer of UCD */
- alarm_cancel(p_ccb->l2c_ccb_timer);
-
- l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
-
- /* success changes state, failure stays in current state */
- l2c_ucd_check_pending_out_sec_q(p_ccb);
- break;
-
- case L2CEVT_TIMEOUT:
- /* check if any UCD packet is waiting security check */
- if ((!l2c_ucd_check_pending_in_sec_q(p_ccb)) &&
- (!l2c_ucd_check_pending_out_sec_q(p_ccb))) {
- l2cu_release_ccb(p_ccb);
- }
- break;
-
- case L2CEVT_L2CAP_INFO_RSP:
- /* check if waiting for UCD info */
- l2c_ucd_check_pending_info_req(p_ccb);
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
- break;
-
- default:
- done = false; /* main state machine continues to process event */
- break;
- }
-
- return done;
-}
-#endif /* (L2CAP_UCD_INCLUDED == TRUE) */