/* Copyright Statement: * * * * This software/firmware and related documentation ("MediaTek Software") are * * protected under relevant copyright laws. The information contained herein * * is confidential and proprietary to MediaTek Inc. and/or its licensors. * * Without the prior written permission of MediaTek inc. and/or its licensors, * * any reproduction, modification, use or disclosure of MediaTek Software, * * and information contained herein, in whole or in part, shall be strictly prohibited. * * * * MediaTek Inc. (C) 2016. All rights reserved. * * * * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES * * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") * * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON * * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, * * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. * * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE * * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR * * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH * * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES * * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES * * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK * * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR * * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND * * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, * * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, * * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO * * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. * * * * The following software/firmware and/or related documentation ("MediaTek Software") * * have been modified by MediaTek Inc. All revisions are subject to any receiver's * * applicable license agreements with MediaTek Inc. * */ #include "bta_dm_api.h" #include "bta/ag/bta_ag_int.h" #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sco.h" #include "stack/include/btm_api.h" #include "mediatek/stack/include/mtk_btm_int.h" #include "stack/include/acl_api.h" extern tBTM_CB btm_cb; /******************************************************************************/ /* L O C A L D A T A D E F I N I T I O N S */ /******************************************************************************/ /******************************************************************************* * * Function btm_is_sco_active_or_establishing_by_bdaddr * * Description This function is called to see if a SCO connection is active * or establisting for a bd address. * * Returns bool * ******************************************************************************/ bool btm_is_sco_active_or_establishing_by_bdaddr(const RawAddress& remote_bda) { #if (BTM_MAX_SCO_LINKS > 0) uint8_t xx; tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; /* If any SCO is being established or establishing to the remote BD address, refuse this */ for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { if (p->esco.data.bd_addr == remote_bda && (p->state != SCO_ST_UNUSED && p->state != SCO_ST_LISTENING)) { return (true); } } #endif return (false); } /******************************************************************************* * * Function btm_sco_preemption_conn_req * * Description Send preemption connection request to hfp stack * * * Returns void * ******************************************************************************/ void btm_sco_preemption_conn_req(const RawAddress& bda, const DEV_CLASS& dev_class, uint8_t link_type,uint16_t sco_index,tBTM_ESCO_CBACK* p_esco_cback) { tBTM_ESCO_CONN_REQ_EVT_DATA evt_data = {}; /* Notify upper layer of connect indication */ evt_data.bd_addr = bda; memcpy(evt_data.dev_class, dev_class, DEV_CLASS_LEN); evt_data.link_type = link_type; evt_data.sco_inx = sco_index; tBTM_ESCO_EVT_DATA btm_esco_evt_data = {}; btm_esco_evt_data.conn_evt = evt_data; p_esco_cback(BTM_ESCO_CONN_REQ_EVT, &btm_esco_evt_data); } /******************************************************************************* * * Function btm_is_any_sco_active * * Description This function is called to see if any SCO is already in use. * * * Returns bool * ******************************************************************************/ bool btm_is_any_sco_active(void) { #if (BTM_MAX_SCO_LINKS > 0) uint16_t xx; tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { if (p->state == SCO_ST_CONNECTED) return (true); } #endif return (false); } /******************************************************************************* * * Function btm_find_sco_idx_by_addr * * Description This function return the sco idx by request bd address. * * * Returns uint16_t * ******************************************************************************/ uint16_t btm_find_sco_idx_by_addr(const RawAddress& bda) { #if (BTM_MAX_SCO_LINKS > 0) uint16_t xx; tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { if(p->esco.data.bd_addr == bda) return xx; } #endif return BTM_MAX_SCO_LINKS; } /******************************************************************************* * * Function BTM_RegForEScoCback * * Description This function registers a SCO event callback with the * specified instance. It should be used to received * connection indication events and change of link parameter * events. * * Returns BTM_SUCCESS if the successful. * BTM_ILLEGAL_VALUE if there is an illegal sco_inx * ******************************************************************************/ tBTM_STATUS BTM_RegForEScoCback(uint16_t sco_inx,const RawAddress& bda,bool is_orig, tBTM_SCO_CB* p_conn_cb,tBTM_SCO_CB* p_disc_cb) { #if (BTM_MAX_SCO_LINKS > 0) tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx]; BTM_TRACE_DEBUG("%s: sco_inx = %x,pre is_orig %x,is_orig %x,pre p_conn_cb %x,pre p_disc_cb %x,p_conn_cb %x,p_disc_cb %x", __func__,sco_inx,p->is_orig ,is_orig,p->p_conn_cb,p->p_disc_cb,p_conn_cb,p_disc_cb); p->hci_handle = BTM_INVALID_SCO_INDEX; p->is_orig = is_orig; p->p_conn_cb = p_conn_cb; p->p_disc_cb = p_disc_cb; p->esco.data.bd_addr = bda; p->rem_bd_known = true; return (BTM_SUCCESS); #else return (BTM_MODE_UNSUPPORTED); #endif } /******************************************************************************* * * Function btm_sco_chk_pend_unpark * * Description This function is called by BTIF when there is a mode change * event to see if there are SCO commands waiting for the * unpark. * * Returns void * ******************************************************************************/ void btm_sco_chk_pend_unpark(uint8_t hci_status, uint16_t hci_handle, tBTM_PM_STATE state) { #if (BTM_MAX_SCO_LINKS > 0) tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0]; for (uint16_t xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { uint16_t acl_handle = BTM_GetHCIConnHandle(p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR); if ((p->state == SCO_ST_PEND_UNPARK) && (acl_handle == hci_handle)) { if (state == BTM_PM_ST_ACTIVE) { LOG(INFO) << __func__ << ": " << p->esco.data.bd_addr << " unparked, sending connection request, acl_handle=" << unsigned(acl_handle) << ", hci_status=" << unsigned(hci_status); if (btm_send_connect_request(acl_handle, &p->esco.setup) == BTM_CMD_STARTED) { p->state = SCO_ST_CONNECTING; } else { LOG(ERROR) << __func__ << ": failed to send connection request for " << p->esco.data.bd_addr; } } else { tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(bta_ag_idx_by_bdaddr(&p->esco.data.bd_addr)); if( p_scb != nullptr){ LOG(ERROR) << __func__ << ": We need to switch to active mode before creating SCO for" << p->esco.data.bd_addr; bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); } } } } #endif // BTM_MAX_SCO_LINKS }