Files
2026-08-24 10:03:24 +08:00

239 lines
8.1 KiB
C
Executable File

/* 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) 2014. 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "bt_mtk.h"
#ifndef MTK_LINUX
#include <cutils/properties.h>
#endif
/**************************************************************************
* G L O B A L V A R I A B L E S *
***************************************************************************/
bt_vendor_callbacks_t *bt_vnd_cbacks = NULL;
static int bt_fd = -1;
/**************************************************************************
* F U N C T I O N D E C L A R A T I O N S *
***************************************************************************/
extern BOOL BT_InitDevice(
UINT32 chipId,
PUCHAR pucNvRamData,
UINT32 u4Baud,
UINT32 u4HostBaud,
UINT32 u4FlowControl,
SETUP_UART_PARAM_T setup_uart_param
);
extern BOOL BT_DeinitDevice(VOID);
extern VOID BT_Cleanup(VOID);
/**************************************************************************
* F U N C T I O N S *
***************************************************************************/
static BOOL is_memzero(unsigned char *buf, int size)
{
int i;
for (i = 0; i < size; i++) {
if (*(buf+i) != 0) return FALSE;
}
return TRUE;
}
/* Register callback functions to libbt-hci.so */
void set_callbacks(const bt_vendor_callbacks_t *p_cb)
{
bt_vnd_cbacks = (bt_vendor_callbacks_t *)p_cb;
}
/* Cleanup callback functions previously registered */
void clean_callbacks(void)
{
bt_vnd_cbacks = NULL;
}
/* Initialize UART port */
int init_uart(void)
{
int retry = 50;
LOG_TRC();
if (bt_fd >= 0) {
LOG_WAN("Previous serial port is not closed\n");
close_uart();
}
while(1) {
bt_fd = open("/dev/stpbt", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (bt_fd < 0) {
LOG_ERROR("Can't open serial port, Retry\n");
usleep(200000);/*200ms*/
if (retry <= 0)
break;
retry--;
} else
break;
}
if (bt_fd < 0) {
LOG_ERROR("Can't open serial port\n");
return -1;
}
return bt_fd;
}
/* Close UART port previously opened */
void close_uart(void)
{
if (bt_fd >= 0) close(bt_fd);
bt_fd = -1;
}
#ifdef MTK_LINUX
/* This function no need in 7663 Linux-base project */
#else
static int bt_get_combo_id(unsigned int *pChipId)
{
int chipId_ready_retry = 0;
char chipId_val[PROPERTY_VALUE_MAX];
do {
if (property_get("persist.mtk.wcn.combo.chipid", chipId_val, NULL) &&
0 != strcmp(chipId_val, "-1")) {
*pChipId = (unsigned int)strtoul(chipId_val, NULL, 16);
break;
}
else {
chipId_ready_retry ++;
usleep(500000);
}
} while(chipId_ready_retry < 10);
LOG_DBG("Get combo chip id retry %d\n", chipId_ready_retry);
if (chipId_ready_retry >= 10) {
LOG_DBG("Invalid combo chip id!\n");
return -1;
}
else {
LOG_DBG("Combo chip id %x\n", *pChipId);
return 0;
}
}
#endif
/* MTK specific chip initialize process */
int mtk_fw_cfg(void)
{
unsigned int chipId = 0x7662;
unsigned char ucNvRamData[64] = {0};
unsigned int speed, flow_control;
SETUP_UART_PARAM_T uart_setup_callback = NULL;
LOG_TRC();
LOG_WAN("[BDAddr %02x-%02x-%02x-%02x-%02x-%02x][Voice %02x %02x][Codec %02x %02x %02x %02x] \
[Radio %02x %02x %02x %02x %02x %02x][Sleep %02x %02x %02x %02x %02x %02x %02x][BtFTR %02x %02x] \
[TxPWOffset %02x %02x %02x][CoexAdjust %02x %02x %02x %02x %02x %02x]\n",
ucNvRamData[0], ucNvRamData[1], ucNvRamData[2], ucNvRamData[3], ucNvRamData[4], ucNvRamData[5],
ucNvRamData[6], ucNvRamData[7],
ucNvRamData[8], ucNvRamData[9], ucNvRamData[10], ucNvRamData[11],
ucNvRamData[12], ucNvRamData[13], ucNvRamData[14], ucNvRamData[15], ucNvRamData[16], ucNvRamData[17],
ucNvRamData[18], ucNvRamData[19], ucNvRamData[20], ucNvRamData[21], ucNvRamData[22], ucNvRamData[23], ucNvRamData[24],
ucNvRamData[25], ucNvRamData[26],
ucNvRamData[27], ucNvRamData[28], ucNvRamData[29],
ucNvRamData[30], ucNvRamData[31], ucNvRamData[32], ucNvRamData[33], ucNvRamData[34], ucNvRamData[35]);
return (BT_InitDevice(
chipId,
ucNvRamData,
speed,
speed,
flow_control,
uart_setup_callback) == TRUE ? 0 : -1);
}
/* MTK specific deinitialize process */
int mtk_prepare_off(void)
{
/*
* On KK, BlueDroid adds BT_VND_OP_EPILOG procedure when BT disable:
* - 1. BT_VND_OP_EPILOG;
* - 2. In vendor epilog_cb, send EXIT event to bt_hc_worker_thread;
* - 3. Wait for bt_hc_worker_thread exit;
* - 4. userial close;
* - 5. vendor cleanup;
* - 6. Set power off.
* On L, the disable flow is modified as below:
* - 1. userial Rx thread exit;
* - 2. BT_VND_OP_EPILOG;
* - 3. Write reactor->event_fd to trigger bt_hc_worker_thread exit
* (not wait to vendor epilog_cb and do nothing in epilog_cb);
* - 4. Wait for bt_hc_worker_thread exit;
* - 5. userial close;
* - 6. Set power off;
* - 7. vendor cleanup.
*
* It seems BlueDroid does not expect Tx/Rx interaction with chip during
* BT_VND_OP_EPILOG procedure, and also does not need to do it in a new
* thread context (NE may occur in __pthread_start if bt_hc_worker_thread
* has already exited).
* So BT_VND_OP_EPILOG procedure may be not for chip deinitialization,
* do nothing, just notify success.
*
* [FIXME!!]How to do if chip deinit is needed?
*/
//return (BT_DeinitDevice() == TRUE ? 0 : -1);
if (bt_vnd_cbacks) {
bt_vnd_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
}
return 0;
}
/* Cleanup driver resources, e.g thread exit */
void clean_resource(void)
{
BT_Cleanup();
}