/* 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. * */ /****************************************************************************** * * This file contains functions for the MTK defined interop function * ******************************************************************************/ #define LOG_TAG "bt_device_interop_mtk" #include #include #include #include "interop_mtk.h" #if MTK_INTEROP_CONF == 0 #if defined(MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) #include #include "btif_config.h" #include "btm_api.h" #include "interop_database_mtk.h" #include "osi/include/log.h" bt_status_t btmtk_get_device_name(const RawAddress* addr, BD_NAME bd_name) { if (addr) { std::string addrstr = addr->ToString(); const char* bdstr = addrstr.c_str(); int length = BD_NAME_LEN; bool ret = btif_config_get_str(bdstr, "Name", reinterpret_cast(bd_name), &length); return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; } return BT_STATUS_FAIL; } bool interop_mtk_match_addr(const char *section, const RawAddress* addr) { CHECK(addr); const size_t db_size = sizeof(mtk_interop_addr_db) / sizeof(mtk_interop_addr_entry_t); const mtk_interop_addr_entry_t* db = mtk_interop_addr_db; for (size_t i = 0; i != db_size; ++i) { if (strcmp(section, db[i].section.c_str()) == 0 && memcmp(addr, &db[i].addr, db[i].length) == 0) { LOG_INFO("%s() Device is a match for interop workaround %s.", __func__, section); return true; } } return false; } bool interop_mtk_match_name(const char *section, const char* name) { if (name != NULL && name[0] != '\0') { const size_t db_size = sizeof(mtk_interop_name_db) / sizeof(mtk_interop_name_entry_t); const mtk_interop_name_entry_t* db = mtk_interop_name_db; for (size_t i = 0; i != db_size; ++i) { if (strcmp(section, db[i].section.c_str()) == 0 && strlen(name) >= db[i].length && strncmp(name, db[i].name, db[i].length) == 0) { LOG_INFO("%s() Device is a match for interop workaround %s.", __func__, section); return true; } } const size_t partial_name_db_size = sizeof(mtk_interop_partial_name_db) / sizeof(mtk_interop_partial_name_entry_t); const mtk_interop_partial_name_entry_t* partial_name_db = mtk_interop_partial_name_db; for (size_t i = 0; i != partial_name_db_size; ++i) { if (strcmp(section, partial_name_db[i].section.c_str()) == 0 && strstr(name, partial_name_db[i].name) != NULL) { LOG_INFO("%s() Device is a match for interop workaround %s.", __func__, section); return true; } } return false; } return false; } bool interop_mtk_match_name(const char *section, const RawAddress* addr) { CHECK(addr); BD_NAME remote_name = {0}; // Get device name from config btmtk_get_device_name(addr, remote_name); if (remote_name[0] != '\0') return interop_mtk_match_name(section, reinterpret_cast(remote_name)); return false; } bool interop_mtk_match_addr_name(const char* section, const RawAddress* addr) { return interop_mtk_match_addr(section, addr) || interop_mtk_match_name(section, addr); } bool interop_mtk_match_lmp_ver(const char *section, const RawAddress* addr) { CHECK(addr); uint8_t lmp_ver = 0; uint16_t lmp_subver = 0; uint16_t mfct_set = 0; if (!BTM_ReadRemoteVersion(*addr, &lmp_ver, &mfct_set, &lmp_subver)) { LOG_INFO("%s() BTM_ReadRemoteVersion fail.", __func__); return false; } if (0 == lmp_ver && 0 == mfct_set && 0 == lmp_subver) { LOG_INFO("%s() remote version is 0.", __func__); return false; } const size_t db_size = sizeof(mtk_interop_ver_db) / sizeof(mtk_interop_ver_entry_t); const mtk_interop_ver_entry_t* db = mtk_interop_ver_db; for (size_t i = 0; i != db_size; ++i) { if (strcmp(section, db[i].section.c_str()) == 0 && lmp_ver == db[i].lmp_ver) { LOG_INFO("%s() Device is a match for interop workaround %s.", __func__, section); return true; } } return false; } bool interop_mtk_match_mfct(const char *section, const RawAddress* addr) { CHECK(addr); uint8_t lmp_ver = 0; uint16_t lmp_subver = 0; uint16_t mfct_set = 0; if (!BTM_ReadRemoteVersion(*addr, &lmp_ver, &mfct_set, &lmp_subver)) { LOG_INFO("%s() BTM_ReadRemoteVersion fail.", __func__); return false; } if (0 == lmp_ver && 0 == mfct_set && 0 == lmp_subver) { LOG_INFO("%s() remote version is 0.", __func__); return false; } const size_t db_size = sizeof(mtk_interop_ver_db) / sizeof(mtk_interop_ver_entry_t); const mtk_interop_ver_entry_t* db = mtk_interop_ver_db; for (size_t i = 0; i != db_size; ++i) { if (strcmp(section, db[i].section.c_str()) == 0 && mfct_set == db[i].mfct) { LOG_INFO("%s() Device is a match for interop workaround %s.", __func__, section); return true; } } return false; } bool interop_mtk_match_lmp_subver(const char *section, const RawAddress* addr) { CHECK(addr); uint8_t lmp_ver = 0; uint16_t mfct_set = 0; uint16_t lmp_subver = 0; if (!BTM_ReadRemoteVersion(*addr, &lmp_ver, &mfct_set, &lmp_subver)) { LOG_INFO("%s() BTM_ReadRemoteVersion fail.", __func__); return false; } if (0 == lmp_ver && 0 == mfct_set && 0 == lmp_subver) { LOG_INFO("%s() remote version is 0.", __func__); return false; } const size_t db_size = sizeof(mtk_interop_ver_db) / sizeof(mtk_interop_ver_entry_t); const mtk_interop_ver_entry_t* db = mtk_interop_ver_db; for (size_t i = 0; i != db_size; ++i) { if (strcmp(section, db[i].section.c_str()) == 0 && lmp_subver == db[i].lmp_subver) { LOG_INFO("%s() Device is a match for interop workaround %s.", __func__, section); return true; } } return false; } bool interop_mtk_match_ver(const char *section, const RawAddress* addr) { CHECK(addr); uint8_t lmp_ver = 0; uint16_t mfct_set = 0; uint16_t lmp_subver = 0; if (!BTM_ReadRemoteVersion(*addr, &lmp_ver, &mfct_set, &lmp_subver)) { LOG_INFO("%s() BTM_ReadRemoteVersion fail.", __func__); return false; } if (0 == lmp_ver && 0 == mfct_set && 0 == lmp_subver) { LOG_INFO("%s() remote version is 0.", __func__); return false; } const size_t db_size = sizeof(mtk_interop_ver_db) / sizeof(mtk_interop_ver_entry_t); const mtk_interop_ver_entry_t* db = mtk_interop_ver_db; for (size_t i = 0; i != db_size; ++i) { if (strcmp(section, db[i].section.c_str()) == 0 && lmp_ver == db[i].lmp_ver && mfct_set == db[i].mfct && lmp_subver == db[i].lmp_subver) { LOG_INFO("%s() Device is a match for interop workaround %s.", __func__, section); return true; } } return false; } bool interop_mtk_match_any(const char* section, const RawAddress* addr) { return interop_mtk_match_addr(section, addr) || interop_mtk_match_name(section, addr) || interop_mtk_match_ver(section, addr); } bool interop_mtk_set_addr(const char* section, const RawAddress* addr, int size) { LOG_INFO("%s() not supported.", __func__); return false; } bool interop_mtk_set_name(const char* section, const char* name) { LOG_INFO("%s() not supported.", __func__); return false; } bool interop_mtk_set_partial_name(const char* section, const char* name) { LOG_INFO("%s() not supported.", __func__); return false; } bool interop_mtk_set_ver(const char* section, const RawAddress* addr) { LOG_INFO("%s() not supported.", __func__); return false; } #endif /** M: New feature: framework get black list information {@ */ bool interop_mtk_match_addr_fwk(const char* section, const RawAddress* addr) { #if defined (MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) return interop_mtk_match_addr_name(section, addr); #else return false; #endif } bool interop_mtk_match_name_fwk(const char* section, const char* name) { #if defined (MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) return interop_mtk_match_name(section, name); #else return false; #endif } bool interop_mtk_match_addr_name_fwk(const char* section, const RawAddress* addr) { #if defined (MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) return interop_mtk_match_addr_name(section, addr); #else return false; #endif } bool interop_mtk_match_lmp_ver_fwk(const char* section, const RawAddress* addr) { #if defined (MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) return interop_mtk_match_lmp_ver(section, addr); #else return false; #endif } bool interop_mtk_match_mfct_fwk(const char* section, const RawAddress* addr) { #if defined (MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) return interop_mtk_match_mfct(section, addr); #else return false; #endif } bool interop_mtk_match_lmp_subver_fwk(const char* section, const RawAddress* addr) { #if defined (MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) return interop_mtk_match_lmp_subver(section, addr); #else return false; #endif } bool interop_mtk_match_ver_fwk(const char* section, const RawAddress* addr) { #if defined (MTK_INTEROP_EXTENSION) && (MTK_INTEROP_EXTENSION == TRUE) return interop_mtk_match_ver(section, addr); #else return false; #endif } static const btinterop_mtk_interface_t interop_if = { sizeof(btinterop_mtk_interface_t), interop_mtk_match_addr_fwk, interop_mtk_match_name_fwk, interop_mtk_match_addr_name_fwk, interop_mtk_match_lmp_ver_fwk, interop_mtk_match_mfct_fwk, interop_mtk_match_lmp_subver_fwk, interop_mtk_match_ver_fwk}; const btinterop_mtk_interface_t* btif_interop_mtk_get_interface() { return &interop_if; } /**@}*/ #endif